Skip to content

Commit d58d89c

Browse files
committed
Type inference: Consistency check for escaping type parameters
1 parent 1e676e1 commit d58d89c

6 files changed

Lines changed: 56 additions & 9 deletions

File tree

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,8 @@ abstract class TypeParameter extends Type {
401401
override TypeParameter getPositionalTypeParameter(int i) { none() }
402402

403403
abstract ItemNode getDeclaringItem();
404+
405+
AstNode getScope() { result = this.getDeclaringItem() }
404406
}
405407

406408
private class RawTypeParameter = @type_param or @trait or @type_alias or @impl_trait_type_repr;
@@ -583,6 +585,8 @@ class ImplTraitTypeParameter extends TypeParameter, TImplTraitTypeParameter {
583585

584586
override ItemNode getDeclaringItem() { none() }
585587

588+
override AstNode getScope() { result = implTrait.getFunction() }
589+
586590
override string toString() { result = "impl(" + typeParam.toString() + ")" }
587591

588592
override Location getLocation() { result = typeParam.getLocation() }
@@ -633,6 +637,8 @@ class ImplTraitTypeTypeParameter extends ImplTraitType, TypeParameter {
633637

634638
override ItemNode getDeclaringItem() { none() }
635639

640+
override AstNode getScope() { result = function }
641+
636642
override Function getFunction() { result = function }
637643

638644
override TypeParameter getPositionalTypeParameter(int i) { none() }

‎rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll‎

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,7 +2272,11 @@ private module Input3 implements InputSig3 {
22722272
BoolType() { this.getTypeItem() instanceof Builtins::Bool }
22732273
}
22742274

2275-
class AstNode = Rust::AstNode;
2275+
class AstNode extends Rust::AstNode {
2276+
AstNode getParent() { result = this.getParentNode() }
2277+
}
2278+
2279+
AstNode getTypeParameterScope(TypeParameter tp) { result = tp.getScope() }
22762280

22772281
final class Expr = ExprImpl;
22782282

@@ -2286,13 +2290,13 @@ private module Input3 implements InputSig3 {
22862290
TypeMention getType() { result = this.getTypeRepr() }
22872291
}
22882292

2289-
class Switch extends Rust::MatchExpr {
2293+
class Switch extends Expr, Rust::MatchExpr {
22902294
Expr getExpr() { result = this.getScrutinee() }
22912295

22922296
Case getCase(int index) { result = this.getArm(index) }
22932297
}
22942298

2295-
class Case extends Rust::MatchArm {
2299+
class Case extends AstNode, Rust::MatchArm {
22962300
AstNode getAPattern() { result = this.getPat() }
22972301

22982302
AstNode getBody() { result = this.getExpr() }
@@ -2453,8 +2457,8 @@ private module Input3 implements InputSig3 {
24532457
// mutual recursion; resolving fields requires resolving types and vice versa
24542458
result =
24552459
[
2456-
resolveStructFieldExpr(this, _).(AstNode),
2457-
resolveTupleFieldExpr(this, _)
2460+
resolveStructFieldExpr(this, _).(Field),
2461+
resolveTupleFieldExpr(this, _).(Field)
24582462
]
24592463
}
24602464
}
@@ -2484,7 +2488,7 @@ private module Input3 implements InputSig3 {
24842488
)
24852489
}
24862490

2487-
class Return extends ReturnExpr {
2491+
class Return extends Expr, ReturnExpr {
24882492
Expr getExpr() { result = super.getExpr() }
24892493
}
24902494

@@ -2587,15 +2591,15 @@ private module Input3 implements InputSig3 {
25872591
override TypeItem getTypeItem() { result = this }
25882592

25892593
override Parameter getParameter(int i) {
2590-
result = [super.getTupleField(i).(AstNode), super.getNthStructField(i)]
2594+
result = [super.getTupleField(i).(Parameter), super.getNthStructField(i).(Parameter)]
25912595
}
25922596
}
25932597

25942598
private class VariantConstructor extends ConstructorImpl instanceof Variant {
25952599
override TypeItem getTypeItem() { result = super.getEnum() }
25962600

25972601
override Parameter getParameter(int i) {
2598-
result = [super.getTupleField(i).(AstNode), super.getNthStructField(i)]
2602+
result = [super.getTupleField(i).(Parameter), super.getNthStructField(i).(Parameter)]
25992603
}
26002604
}
26012605

@@ -3161,7 +3165,7 @@ module Consistency = M3::Consistency;
31613165

31623166
module CachedStage = M3::CachedStage;
31633167

3164-
private predicate typeTestAstNodeRepr(AstNode n, string repr) {
3168+
private predicate typeTestAstNodeRepr(Input3::AstNode n, string repr) {
31653169
repr = [n.toString(), n.(IdentPat).getName().getText()]
31663170
}
31673171

‎shared/typeinference/codeql/typeinference/internal/TypeInference.qll‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,13 +2140,24 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21402140

21412141
/** An AST node. */
21422142
class AstNode {
2143+
/** Gets the parent of this AST node, if any. */
2144+
AstNode getParent();
2145+
21432146
/** Gets a textual representation of this AST node. */
21442147
string toString();
21452148

21462149
/** Gets the location of this AST node. */
21472150
Location getLocation();
21482151
}
21492152

2153+
/**
2154+
* Gets the scope of type parameter `tp`.
2155+
*
2156+
* Only used in a consistency check to ensure that type parameters do not
2157+
* escape their scope.
2158+
*/
2159+
AstNode getTypeParameterScope(TypeParameter tp);
2160+
21502161
/** An expression. */
21512162
class Expr extends AstNode;
21522163

@@ -3754,6 +3765,11 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
37543765
Input3::inferTypeForDefaults(n, path) = t and
37553766
not inferType(n, path) = t
37563767
}
3768+
3769+
query predicate typeParameterEscape(AstNode n, TypePath path, TypeParameter tp) {
3770+
tp = inferType(n, path) and
3771+
not n.getParent*() = getTypeParameterScope(tp)
3772+
}
37573773
}
37583774

37593775
/**

‎unified/ql/lib/codeql/unified/internal/typeinference/Type.qll‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ class ClosureParameterPseudoType extends PseudoType, TClosureParameterPseudoType
204204

205205
/** A type parameter. */
206206
abstract class TypeParameter extends TypeImpl {
207+
abstract AstNode getScope();
208+
207209
override TypeParameter getPositionalTypeParameter(int i) { none() }
208210

209211
abstract AstNode getDeclaringItem();
@@ -227,6 +229,12 @@ class TypeParameterType extends TypeParameter, TTypeParameterType {
227229

228230
Unified::TypeParameter getTypeParameter() { result = typeParam }
229231

232+
override AstNode getScope() {
233+
result = typeParam.getParent()
234+
or
235+
result.(ClassLikeDeclaration).resolve().getEnclosingClassResolved*() = typeParam.getParent()
236+
}
237+
230238
override ClassLikeDeclaration getDeclaringItem() { typeParam = result.getATypeParameter() }
231239

232240
override Identifier getNameNode() { result = typeParam.getNameNode() }
@@ -248,6 +256,8 @@ class AssociatedTypeParameterType extends TypeParameter, TAssociatedTypeParamete
248256

249257
Unified::AssociatedTypeDeclaration getAssociatedTypeDeclaration() { result = assocTypeDecl }
250258

259+
override AstNode getScope() { result.(ClassLikeDeclaration).resolve() = c }
260+
251261
override ClassLikeDeclaration getDeclaringItem() { result = c }
252262

253263
override Identifier getNameNode() { result = assocTypeDecl.getNameNode() }
@@ -295,6 +305,8 @@ class ParentTypeParameterType extends TypeParameter, TParentTypeParameterType {
295305

296306
override Member getDeclaringItem() { result = m }
297307

308+
override AstNode getScope() { none() }
309+
298310
override Identifier getNameNode() { none() }
299311

300312
override string toString() { result = "(parent:" + m.getNameOrFallback() + ")" }
@@ -310,6 +322,8 @@ class UnknownTypeTypeParameter extends TypeParameter, TUnknownTypeTypeParameter
310322

311323
UnknownTypeTypeParameter() { this = TUnknownTypeTypeParameter(i) }
312324

325+
override AstNode getScope() { none() }
326+
313327
override AstNode getDeclaringItem() { none() }
314328

315329
override Identifier getNameNode() { none() }

‎unified/ql/lib/codeql/unified/internal/typeinference/TypeInference.qll‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ module Input3 implements InputSig3 {
143143

144144
class AstNode = Unified::AstNode;
145145

146+
AstNode getTypeParameterScope(TypeParameter tp) { result = tp.getScope() }
147+
146148
class Expr extends Unified::Expr {
147149
Expr() {
148150
isInAssignmentContext(this, _) or

‎unified/ql/lib/codeql/unified/internal/typeinference/TypeInferenceConsistency.qll‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,15 @@ import TypeInference::Consistency
1010

1111
query predicate illFormedTypeMention(TypeMention tm) {
1212
Consistency::illFormedTypeMention(tm) and
13+
// not tm.(AliasExprTypeMention).isTypeParameterAlias(_) and
1314
tm.fromSource()
1415
}
1516

1617
query predicate nonUniqueCertainType(AstNode n, TypePath path) {
1718
Consistency::nonUniqueCertainType(n, path) and
1819
n.fromSource()
1920
}
21+
22+
query predicate hasAliasType(AstNode n, TypePath path, AliasType alias) {
23+
alias = inferType(n, path)
24+
}

0 commit comments

Comments
 (0)