Skip to content

Commit 02115f6

Browse files
committed
Rust: Implement type inference support for non-universal impl blocks
1 parent f3fa0e7 commit 02115f6

File tree

7 files changed

+1779
-1081
lines changed

7 files changed

+1779
-1081
lines changed

rust/ql/lib/codeql/rust/internal/PathResolution.qll

-55
Original file line numberDiff line numberDiff line change
@@ -413,61 +413,6 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
413413

414414
TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) }
415415

416-
pragma[nomagic]
417-
private TypeRepr getASelfTyArg() {
418-
result =
419-
this.getSelfPath().getSegment().getGenericArgList().getAGenericArg().(TypeArg).getTypeRepr()
420-
}
421-
422-
/**
423-
* Holds if this `impl` block is not fully parametric. That is, the implementing
424-
* type is generic and the implementation is not parametrically polymorphic in all
425-
* the implementing type's arguments.
426-
*
427-
* Examples:
428-
*
429-
* ```rust
430-
* impl Foo { ... } // fully parametric
431-
*
432-
* impl<T> Foo<T> { ... } // fully parametric
433-
*
434-
* impl Foo<i64> { ... } // not fully parametric
435-
*
436-
* impl<T> Foo<Foo<T>> { ... } // not fully parametric
437-
*
438-
* impl<T: Trait> Foo<T> { ... } // not fully parametric
439-
*
440-
* impl<T> Foo<T> where T: Trait { ... } // not fully parametric
441-
* ```
442-
*/
443-
pragma[nomagic]
444-
predicate isNotFullyParametric() {
445-
exists(TypeRepr arg | arg = this.getASelfTyArg() |
446-
not exists(resolveTypeParamPathTypeRepr(arg))
447-
or
448-
resolveTypeParamPathTypeRepr(arg).hasTraitBound()
449-
)
450-
}
451-
452-
/**
453-
* Holds if this `impl` block is fully parametric. Examples:
454-
*
455-
* ```rust
456-
* impl Foo { ... } // fully parametric
457-
*
458-
* impl<T> Foo<T> { ... } // fully parametric
459-
*
460-
* impl Foo<i64> { ... } // not fully parametric
461-
*
462-
* impl<T> Foo<Foo<T>> { ... } // not fully parametric
463-
*
464-
* impl<T: Trait> Foo<T> { ... } // not fully parametric
465-
*
466-
* impl<T> Foo<T> where T: Trait { ... } // not fully parametric
467-
* ```
468-
*/
469-
predicate isFullyParametric() { not this.isNotFullyParametric() }
470-
471416
override AssocItemNode getAnAssocItem() { result = super.getAssocItemList().getAnAssocItem() }
472417

473418
override string getName() { result = "(impl)" }

rust/ql/lib/codeql/rust/internal/Type.qll

+26-86
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ newtype TType =
2727
* types, such as traits and implementation blocks.
2828
*/
2929
abstract class Type extends TType {
30-
/** Gets the method `name` belonging to this type, if any. */
31-
pragma[nomagic]
32-
abstract Function getMethod(string name);
33-
3430
/** Gets the struct field `name` belonging to this type, if any. */
3531
pragma[nomagic]
3632
abstract StructField getStructField(string name);
@@ -45,25 +41,6 @@ abstract class Type extends TType {
4541
/** Gets a type parameter of this type. */
4642
final TypeParameter getATypeParameter() { result = this.getTypeParameter(_) }
4743

48-
/**
49-
* Gets an AST node that mentions a base type of this type, if any.
50-
*
51-
* Although Rust doesn't have traditional OOP-style inheritance, we model trait
52-
* bounds and `impl` blocks as base types. Example:
53-
*
54-
* ```rust
55-
* trait T1 {}
56-
*
57-
* trait T2 {}
58-
*
59-
* trait T3 : T1, T2 {}
60-
* // ^^ `this`
61-
* // ^^ `result`
62-
* // ^^ `result`
63-
* ```
64-
*/
65-
abstract TypeMention getABaseTypeMention();
66-
6744
/** Gets a textual representation of this type. */
6845
abstract string toString();
6946

@@ -73,21 +50,6 @@ abstract class Type extends TType {
7350

7451
abstract private class StructOrEnumType extends Type {
7552
abstract ItemNode asItemNode();
76-
77-
final override Function getMethod(string name) {
78-
result = this.asItemNode().getASuccessor(name) and
79-
exists(ImplOrTraitItemNode impl | result = impl.getAnAssocItem() |
80-
impl instanceof Trait
81-
or
82-
impl.(ImplItemNode).isFullyParametric()
83-
)
84-
}
85-
86-
/** Gets all of the fully parametric `impl` blocks that target this type. */
87-
final override ImplMention getABaseTypeMention() {
88-
this.asItemNode() = result.resolveSelfTy() and
89-
result.isFullyParametric()
90-
}
9153
}
9254

9355
/** A struct type. */
@@ -138,8 +100,6 @@ class TraitType extends Type, TTrait {
138100

139101
TraitType() { this = TTrait(trait) }
140102

141-
override Function getMethod(string name) { result = trait.(ItemNode).getASuccessor(name) }
142-
143103
override StructField getStructField(string name) { none() }
144104

145105
override TupleField getTupleField(int i) { none() }
@@ -151,14 +111,6 @@ class TraitType extends Type, TTrait {
151111
any(AssociatedTypeTypeParameter param | param.getTrait() = trait and param.getIndex() = i)
152112
}
153113

154-
pragma[nomagic]
155-
private TypeReprMention getABoundMention() {
156-
result = trait.getTypeBoundList().getABound().getTypeRepr()
157-
}
158-
159-
/** Gets any of the trait bounds of this trait. */
160-
override TypeMention getABaseTypeMention() { result = this.getABoundMention() }
161-
162114
override string toString() { result = trait.toString() }
163115

164116
override Location getLocation() { result = trait.getLocation() }
@@ -220,8 +172,6 @@ class ImplType extends Type, TImpl {
220172

221173
ImplType() { this = TImpl(impl) }
222174

223-
override Function getMethod(string name) { result = impl.(ItemNode).getASuccessor(name) }
224-
225175
override StructField getStructField(string name) { none() }
226176

227177
override TupleField getTupleField(int i) { none() }
@@ -230,9 +180,6 @@ class ImplType extends Type, TImpl {
230180
result = TTypeParamTypeParameter(impl.getGenericParamList().getTypeParam(i))
231181
}
232182

233-
/** Get the trait implemented by this `impl` block, if any. */
234-
override TypeMention getABaseTypeMention() { result = impl.getTrait() }
235-
236183
override string toString() { result = impl.toString() }
237184

238185
override Location getLocation() { result = impl.getLocation() }
@@ -247,8 +194,6 @@ class ImplType extends Type, TImpl {
247194
class ArrayType extends Type, TArrayType {
248195
ArrayType() { this = TArrayType() }
249196

250-
override Function getMethod(string name) { none() }
251-
252197
override StructField getStructField(string name) { none() }
253198

254199
override TupleField getTupleField(int i) { none() }
@@ -257,8 +202,6 @@ class ArrayType extends Type, TArrayType {
257202
none() // todo
258203
}
259204

260-
override TypeMention getABaseTypeMention() { none() }
261-
262205
override string toString() { result = "[]" }
263206

264207
override Location getLocation() { result instanceof EmptyLocation }
@@ -273,8 +216,6 @@ class ArrayType extends Type, TArrayType {
273216
class RefType extends Type, TRefType {
274217
RefType() { this = TRefType() }
275218

276-
override Function getMethod(string name) { none() }
277-
278219
override StructField getStructField(string name) { none() }
279220

280221
override TupleField getTupleField(int i) { none() }
@@ -284,17 +225,13 @@ class RefType extends Type, TRefType {
284225
i = 0
285226
}
286227

287-
override TypeMention getABaseTypeMention() { none() }
288-
289228
override string toString() { result = "&" }
290229

291230
override Location getLocation() { result instanceof EmptyLocation }
292231
}
293232

294233
/** A type parameter. */
295234
abstract class TypeParameter extends Type {
296-
override TypeMention getABaseTypeMention() { none() }
297-
298235
override StructField getStructField(string name) { none() }
299236

300237
override TupleField getTupleField(int i) { none() }
@@ -318,19 +255,9 @@ class TypeParamTypeParameter extends TypeParameter, TTypeParamTypeParameter {
318255

319256
TypeParam getTypeParam() { result = typeParam }
320257

321-
override Function getMethod(string name) {
322-
// NOTE: If the type parameter has trait bounds, then this finds methods
323-
// on the bounding traits.
324-
result = typeParam.(ItemNode).getASuccessor(name)
325-
}
326-
327258
override string toString() { result = typeParam.toString() }
328259

329260
override Location getLocation() { result = typeParam.getLocation() }
330-
331-
final override TypeMention getABaseTypeMention() {
332-
result = typeParam.getTypeBoundList().getABound().getTypeRepr()
333-
}
334261
}
335262

336263
/**
@@ -377,19 +304,13 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara
377304

378305
int getIndex() { traitAliasIndex(_, result, typeAlias) }
379306

380-
override Function getMethod(string name) { none() }
381-
382307
override string toString() { result = typeAlias.getName().getText() }
383308

384309
override Location getLocation() { result = typeAlias.getLocation() }
385-
386-
override TypeMention getABaseTypeMention() { none() }
387310
}
388311

389312
/** An implicit reference type parameter. */
390313
class RefTypeParameter extends TypeParameter, TRefTypeParameter {
391-
override Function getMethod(string name) { none() }
392-
393314
override string toString() { result = "&T" }
394315

395316
override Location getLocation() { result instanceof EmptyLocation }
@@ -409,15 +330,34 @@ class SelfTypeParameter extends TypeParameter, TSelfTypeParameter {
409330

410331
Trait getTrait() { result = trait }
411332

412-
override TypeMention getABaseTypeMention() { result = trait }
333+
override string toString() { result = "Self [" + trait.toString() + "]" }
334+
335+
override Location getLocation() { result = trait.getLocation() }
336+
}
337+
338+
/** A type abstraction. */
339+
abstract class TypeAbstraction extends AstNode {
340+
abstract TypeParameter getATypeParameter();
341+
}
413342

414-
override Function getMethod(string name) {
415-
// The `Self` type parameter is an implementation of the trait, so it has
416-
// all the trait's methods.
417-
result = trait.(ItemNode).getASuccessor(name)
343+
final class ImplTypeAbstraction extends TypeAbstraction, Impl {
344+
override TypeParamTypeParameter getATypeParameter() {
345+
result.getTypeParam() = this.getGenericParamList().getATypeParam()
418346
}
347+
}
419348

420-
override string toString() { result = "Self [" + trait.toString() + "]" }
349+
final class TraitTypeAbstraction extends TypeAbstraction, Trait {
350+
override TypeParamTypeParameter getATypeParameter() {
351+
result.getTypeParam() = this.getGenericParamList().getATypeParam()
352+
}
353+
}
421354

422-
override Location getLocation() { result = trait.getLocation() }
355+
final class TypeBoundTypeAbstraction extends TypeAbstraction, TypeBound {
356+
override TypeParamTypeParameter getATypeParameter() { none() }
357+
}
358+
359+
final class SelfTypeBoundTypeAbstraction extends TypeAbstraction, Name {
360+
SelfTypeBoundTypeAbstraction() { any(Trait trait).getName() = this }
361+
362+
override TypeParamTypeParameter getATypeParameter() { none() }
423363
}

0 commit comments

Comments
 (0)