Skip to content

Commit f8a0343

Browse files
committed
Rust: Type inference 2.0
1 parent 0f08ba6 commit f8a0343

17 files changed

Lines changed: 1874 additions & 2032 deletions

File tree

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

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import rust
3030
* The `backref` predicate starts with `1 = 1 or` to ensure that the predicate will be optimized down to a constant by the optimizer.
3131
*/
3232
module Stages {
33+
private import codeql.rust.internal.typeinference.TypeInference as TypeInference
34+
3335
/**
3436
* The abstract syntex tree (AST) stage.
3537
*/
@@ -126,35 +128,7 @@ module Stages {
126128
/**
127129
* The type inference stage.
128130
*/
129-
cached
130-
module TypeInferenceStage {
131-
private import codeql.rust.internal.typeinference.Type
132-
private import codeql.rust.internal.typeinference.TypeInference
133-
private import codeql.rust.dataflow.internal.ModelsAsData
134-
135-
/**
136-
* Always holds.
137-
* Ensures that a predicate is evaluated as part of the type inference stage.
138-
*/
139-
cached
140-
predicate ref() { 1 = 1 }
141-
142-
/**
143-
* DO NOT USE!
144-
*
145-
* Contains references to each predicate that use the above `ref` predicate.
146-
*/
147-
cached
148-
predicate backref() {
149-
1 = 1
150-
or
151-
exists(Type t)
152-
or
153-
exists(inferType(_))
154-
or
155-
mayInvokeCallback(_, _)
156-
}
157-
}
131+
module TypeInferenceStage = TypeInference::CachedStage;
158132

159133
/**
160134
* The data flow stage.

rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ module SatisfiesBlanketConstraint<
9696

9797
Type getTypeAt(TypePath path) {
9898
result = at.getTypeAt(blanketPath.appendInverse(path)) and
99-
not result = TNeverType() and
100-
not result = TUnknownType()
99+
not result instanceof PseudoType
101100
}
102101

103102
string toString() { result = at.toString() + " [blanket at " + blanketPath.toString() + "]" }

rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,7 @@ module ArgIsInstantiationOf<ArgSig Arg, IsInstantiationOfInputSig<Arg, AssocFunc
329329
private class ArgSubst extends ArgFinal {
330330
Type getTypeAt(TypePath path) {
331331
result = substituteLookupTraits0(this.getEnclosingItemNode(), super.getTypeAt(path)) and
332-
not result = TNeverType() and
333-
not result = TUnknownType()
332+
not result instanceof PseudoType
334333
}
335334
}
336335

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

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,13 @@ newtype TType =
3636
TTrait(Trait t) or
3737
TImplTraitType(ImplTraitTypeRepr impl) or
3838
TDynTraitType(Trait t) { t = any(DynTraitTypeRepr dt).getTrait() } or
39-
TNeverType() or
4039
TUnknownType() or
40+
TClosureParameterPseudoType(Param p) {
41+
exists(ClosureExpr ce |
42+
p = ce.getParam(_) and
43+
not p.hasTypeRepr()
44+
)
45+
} or
4146
TTypeParamTypeParameter(TypeParam t) or
4247
TAssociatedTypeTypeParameter(Trait trait, AssocType typeAlias) {
4348
getTraitAssocType(trait) = typeAlias
@@ -326,14 +331,6 @@ TypeParamTypeParameter getSliceTypeParameter() {
326331
result = any(SliceType t).getPositionalTypeParameter(0)
327332
}
328333

329-
class NeverType extends Type, TNeverType {
330-
override TypeParameter getPositionalTypeParameter(int i) { none() }
331-
332-
override string toString() { result = "!" }
333-
334-
override Location getLocation() { result instanceof EmptyLocation }
335-
}
336-
337334
abstract class PtrType extends StructType { }
338335

339336
pragma[nomagic]
@@ -355,6 +352,10 @@ class PtrConstType extends PtrType {
355352
override string toString() { result = "*const" }
356353
}
357354

355+
abstract class PseudoType extends Type {
356+
override TypeParameter getPositionalTypeParameter(int i) { none() }
357+
}
358+
358359
/**
359360
* A special pseudo type used to indicate that the actual type may have to be
360361
* inferred by propagating type information back into call arguments.
@@ -377,14 +378,24 @@ class PtrConstType extends PtrType {
377378
* into call arguments (including method call receivers), in order to avoid
378379
* combinatorial explosions.
379380
*/
380-
class UnknownType extends Type, TUnknownType {
381-
override TypeParameter getPositionalTypeParameter(int i) { none() }
382-
383-
override string toString() { result = "(context typed)" }
381+
class UnknownType extends PseudoType, TUnknownType {
382+
override string toString() { result = "(unknown type)" }
384383

385384
override Location getLocation() { result instanceof EmptyLocation }
386385
}
387386

387+
class ClosureParameterPseudoType extends PseudoType, TClosureParameterPseudoType {
388+
private Param param;
389+
390+
ClosureParameterPseudoType() { this = TClosureParameterPseudoType(param) }
391+
392+
Param getParam() { result = param }
393+
394+
override string toString() { result = "(closure parameter " + param + ")" }
395+
396+
override Location getLocation() { result = param.getLocation() }
397+
}
398+
388399
/** A type parameter. */
389400
abstract class TypeParameter extends Type {
390401
override TypeParameter getPositionalTypeParameter(int i) { none() }

0 commit comments

Comments
 (0)