Skip to content

Commit ddae01c

Browse files
committed
wip2
1 parent 3175532 commit ddae01c

5 files changed

Lines changed: 708 additions & 587 deletions

File tree

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

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

166166
/** A type parameter. */
167167
abstract class TypeParameter extends TypeImpl {
168+
abstract AstNode getScope();
169+
168170
override TypeParameter getPositionalTypeParameter(int i) { none() }
169171

170172
abstract AstNode getDeclaringItem();
@@ -187,6 +189,12 @@ class TypeParameterType extends TypeParameter, TTypeParameterType {
187189

188190
Unified::TypeParameter getTypeParameter() { result = typeParam }
189191

192+
override AstNode getScope() {
193+
result = typeParam.getParent()
194+
or
195+
result.(ClassLikeDeclaration).resolve().getEnclosingClassResolved*() = typeParam.getParent()
196+
}
197+
190198
override ClassLikeDeclaration getDeclaringItem() { typeParam = result.getATypeParameter() }
191199

192200
override Identifier getNameNode() { result = typeParam.getNameNode() }
@@ -208,6 +216,8 @@ class AssociatedTypeParameterType extends TypeParameter, TAssociatedTypeParamete
208216

209217
Unified::AssociatedTypeDeclaration getAssociatedTypeDeclaration() { result = assocTypeDecl }
210218

219+
override AstNode getScope() { result.(ClassLikeDeclaration).resolve() = c }
220+
211221
override ClassLikeDeclaration getDeclaringItem() { result = c }
212222

213223
override Identifier getNameNode() { result = assocTypeDecl.getNameNode() }
@@ -233,6 +243,8 @@ class ParentTypeParameterType extends TypeParameter, TParentTypeParameterType {
233243

234244
ClassLikeDeclaration getParent() { isNestedType(c, result) }
235245

246+
override AstNode getScope() { none() }
247+
236248
override ClassLikeDeclaration getDeclaringItem() { result = c }
237249

238250
override Identifier getNameNode() { none() }
@@ -250,6 +262,8 @@ class UnknownTypeTypeParameter extends TypeParameter, TUnknownTypeTypeParameter
250262

251263
UnknownTypeTypeParameter() { this = TUnknownTypeTypeParameter(i) }
252264

265+
override AstNode getScope() { none() }
266+
253267
override AstNode getDeclaringItem() { none() }
254268

255269
override Identifier getNameNode() { none() }

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,8 @@ query predicate nonUniqueCertainType(AstNode n, TypePath path) {
1818
Consistency::nonUniqueCertainType(n, path) and
1919
n.fromSource()
2020
}
21+
22+
query predicate typeParameterEscape(AstNode n, TypePath path, TypeParameter tp) {
23+
tp = inferType(n, path) and
24+
forex(AstNode scope | tp.getScope() = scope | not n.getParent*() = scope)
25+
}

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

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,18 @@ private import TypeInferencePlugin as Plugin
55
private import codeql.unified.internal.StaticNameBinding
66
private import codeql.unified.internal.ExprPositions
77

8+
// private predicate isTypeParameterAlias(TypeAliasDeclaration alias, int i) {
9+
// exists(Unified::TypeParameter tp |
10+
// tp = alias.getTypeParameter(i) and
11+
// tp.getNameNode() = getTypeFromRef(alias.getType())
12+
// )
13+
// }
814
final class TypeMention = TypeMentionImpl;
915

1016
/** An AST node that mentions a type. */
1117
abstract private class TypeMentionImpl extends AstNode {
18+
abstract TypeMention resolve();
19+
1220
/**
1321
* Gets the type mentioned at the root of this type mention.
1422
*
@@ -131,15 +139,13 @@ abstract private class ExprTypeMentionImpl extends TypeMentionImpl, Expr {
131139
pragma[nomagic]
132140
private ClassLikeDeclaration getQualifierTypeAt(TypePath path) {
133141
result =
134-
this.getParentQualifier().getTypeAt(path).(ClassLikeDeclarationType).getClassLikeDeclaration()
142+
this.getParentQualifier().getTypeAt(path).(ClassLikeDeclarationType).getClassLikeDeclaration() and
143+
forall(TypeParameter tp | tp = path.getElement(_) | tp instanceof ParentTypeParameterType)
135144
}
136145

137146
pragma[nomagic]
138-
private predicate isNestedClass(
139-
ClassLikeDeclaration cls, ParentTypeParameterType tp, ClassLikeDeclaration parent
140-
) {
141-
cls = this.getClassLikeDeclaration() and
142-
tp = TParentTypeParameterType(cls) and
147+
private predicate isNestedClass(ParentTypeParameterType tp, ClassLikeDeclaration parent) {
148+
tp = TParentTypeParameterType(this.getClassLikeDeclaration()) and
143149
parent = tp.getParent()
144150
}
145151

@@ -149,12 +155,9 @@ abstract private class ExprTypeMentionImpl extends TypeMentionImpl, Expr {
149155
result = this.getTypeAtImpl(path)
150156
or
151157
// A mention of a nested type with an explicit qualifier
152-
exists(
153-
TypeMention qualifier, ClassLikeDeclaration cls, ParentTypeParameterType tp, TypePath prefix,
154-
TypePath suffix
155-
|
158+
exists(TypeMention qualifier, ParentTypeParameterType tp, TypePath prefix, TypePath suffix |
156159
qualifier = this.getParentQualifier() and
157-
this.isNestedClass(cls, tp, this.getQualifierTypeAt(prefix)) and
160+
this.isNestedClass(tp, this.getQualifierTypeAt(prefix)) and
158161
path = TypePath::cons(tp, suffix) and
159162
result = qualifier.getTypeAt(prefix.appendInverse(suffix))
160163
)
@@ -188,7 +191,11 @@ abstract private class ExprTypeMentionImpl extends TypeMentionImpl, Expr {
188191
pragma[nomagic]
189192
private ClassLikeDeclaration getImplicitEnclosingCand(ParentTypeParameterType tp) {
190193
not this.hasParentQualifier() and
191-
not this.getParent*() = any(TypeAliasDeclaration alias).getType() and
194+
not exists(TypeAliasDeclaration alias |
195+
this.getParent*() = alias.getType() //and
196+
// not this.getParent*() = any(GenericTypeExpr g).getATypeArgument() and
197+
// not this.getParent*() = any(TupleExpr t).getAnElement()
198+
) and
192199
tp = TParentTypeParameterType(this.getClassLikeDeclaration()) and
193200
result = this.getEnclosingClassResolved+()
194201
}
@@ -233,6 +240,8 @@ class AliasExprTypeMention extends ExprTypeMentionImpl {
233240
)
234241
}
235242

243+
override TypeMention resolve() { result = this }
244+
236245
override TypeMention getAlias() { result = alias.getType() }
237246

238247
override Type getType() { result = alias.getType().(TypeMention).getType() }
@@ -350,6 +359,8 @@ private class NonAliasExprTypeMention extends ExprTypeMentionImpl {
350359
)
351360
}
352361

362+
override TypeMention resolve() { result = this }
363+
353364
override TypeMention getAlias() { none() }
354365
}
355366

@@ -382,6 +393,16 @@ private class GenericTypeExprTypeMention extends TypeMentionImpl, GenericTypeExp
382393
)
383394
}
384395

396+
override TypeMention resolve() {
397+
exists(int i |
398+
this.getBase().(AliasExprTypeMention).isTypeParameterAlias(i) and
399+
result = this.getTypeArgument(i).(TypeMention).resolve()
400+
)
401+
or
402+
base = this.getBase() and
403+
result = this
404+
}
405+
385406
override Type getType() { result = base.getType() }
386407

387408
override TypeMention getAParentQualifierCand() { result = base.getAParentQualifierCand() }

‎unified/ql/test/library-tests/type-inference/nested_types.swift‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,15 @@ class Outer<TOuter> {
112112
}
113113
}
114114

115+
class Foo: Outer<String> {
116+
func f(x: Pair, y: Outer<Bool>.Pair) {
117+
var a = x.0.getInner() // $ target=Outer.Inner.getInner field=Tuple2.0 type=a:Int
118+
var b = x.0.getOuter() // $ target=Outer.Inner.getOuter field=Tuple2.0 $ MISSING: type=b:String
119+
var c = y.0.getInner() // $ target=Outer.Inner.getInner field=Tuple2.0 type=c:Int
120+
var d = y.0.getOuter() // $ target=Outer.Inner.getOuter field=Tuple2.0 $ MISSING: type=d:Bool
121+
}
122+
}
123+
115124
func extractInner<Ta, Tb>(_ inner: Outer<Ta>.Inner<Tb>) -> Tb {
116125
return inner.getInner() // $ target=Outer.Inner.getInner
117126
}

0 commit comments

Comments
 (0)