Skip to content

Commit e387ca4

Browse files
authored
Merge pull request #22639 from hvitved/unified/type-inference
Unified: Type inference first version
2 parents 6d876f7 + 467664b commit e387ca4

42 files changed

Lines changed: 6328 additions & 75 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2579,7 +2579,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
25792579
or
25802580
exists(Parameter p, Variable v |
25812581
implicitParameterDecl(p, v) and
2582-
result = p.getType().getTypeAt(path) and
2582+
tm = p.getType() and
25832583
n = v.getAnAccess()
25842584
)
25852585
)
@@ -2606,6 +2606,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
26062606
or
26072607
exists(VariableDeclaration decl |
26082608
decl.preservesInitializerType() and
2609+
not exists(decl.getType()) and
26092610
n1 = decl.getInitializer() and
26102611
n2 = decl.getPattern()
26112612
)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* @name Type inference inconsistencies
3+
* @description Lists the type inference inconsistencies in the database. This query is intended for internal use.
4+
* @kind table
5+
* @id unified/diagnostics/type-inference-consistency
6+
*/
7+
8+
import codeql.unified.internal.typeinference.TypeInferenceConsistency

‎unified/ql/lib/codeql/Definitions.qll‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ private import codeql.unified.internal.NameBinding
1010
*/
1111
cached
1212
predicate definitionOf(Identifier reference, NameBinding definition, string kind) {
13-
definition = getStaticBindingTarget(reference) and
13+
definition = getStaticBindingTargetFromIdentifier(reference) and
1414
not reference instanceof NameBinding and
1515
kind = "name"
1616
}

‎unified/ql/lib/codeql/unified/internal/AnalysisQuality.qll‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module StaticNameResolutionStats implements EntityStatsSig {
1313
*/
1414
private predicate resolvesToValue(Identifier name) {
1515
exists(AstNode decl |
16-
decl = getStaticBindingTarget(name).getDeclaration() and
16+
decl = getStaticBindingTargetFromIdentifier(name).getDeclaration() and
1717
not decl instanceof ClassLikeDeclaration and
1818
not decl instanceof TypeAliasDeclaration and
1919
not decl instanceof TypeParameter and
@@ -49,7 +49,7 @@ module StaticNameResolutionStats implements EntityStatsSig {
4949
}
5050

5151
NameBindingNode getTarget() {
52-
result.asIdentifier() = getStaticBindingTarget(this)
52+
result.asIdentifier() = getStaticBindingTargetFromIdentifier(this)
5353
or
5454
result.isModuleScopeNode(_) and
5555
result.(NamespaceNode).ref().isIdentifier(this)

‎unified/ql/lib/codeql/unified/internal/ExprPositions.qll‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
private import unified
22
private import NameBinding as NameBinding
3+
private import ExprPositionsPlugin
34

45
/**
5-
* Holds if `expr` appears in the context of a type annotation.
6+
* Holds if `expr` appears in a context where it must refer to a type.
67
*/
78
predicate isInTypeContext(Expr expr) {
89
expr = any(TypeCastExpr n).getType()
@@ -27,8 +28,22 @@ predicate isInTypeContext(Expr expr) {
2728
or
2829
expr = any(AssociatedTypeDeclaration n).getBound()
2930
or
31+
expr = any(ClassLikeDeclaration c).getExtensionTarget()
32+
or
33+
expr = any(GenericTypeExpr gte).getATypeArgument()
34+
or
3035
expr.getParent() instanceof TypeConstraint
3136
or
37+
exists(Identifier id | id = NameBinding::getStaticBindingTargetFromRef(expr) |
38+
id = any(ClassLikeDeclaration c).getNameNode()
39+
or
40+
id = any(TypeAliasDeclaration t).getNameNode()
41+
or
42+
id = any(TypeParameter t).getNameNode()
43+
)
44+
or
45+
any(ExprPositionsPlugin p).isInTypeContext(expr)
46+
or
3247
isInTypeContext(expr.getEnclosingExpr())
3348
}
3449

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
private import unified
2+
private import codeql.util.Unit
3+
4+
private module Plugins {
5+
private import ExprPositionsPluginSwift
6+
}
7+
8+
class ExprPositionsPlugin extends Unit {
9+
predicate isInTypeContext(Expr e) { none() }
10+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
private import unified
2+
private import ExprPositionsPlugin
3+
4+
private class ExprPositionsPluginSwift extends ExprPositionsPlugin {
5+
override predicate isInTypeContext(Expr e) { e = any(GenericTypeExpr g).getBase() }
6+
}

‎unified/ql/lib/codeql/unified/internal/FacadeAst.qll‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,7 @@ module Unified {
150150
/** Gets a direct base class of this class. */
151151
ClassLikeDeclaration getABaseClass() {
152152
result.getNameNode() =
153-
NameBinding::getStaticBindingTarget(NameBinding::getIdentifierFromRef(this.getABaseType()
154-
.getType()))
153+
NameBinding::getStaticBindingTargetFromRef(this.getABaseType().getType())
155154
}
156155
}
157156

@@ -217,6 +216,12 @@ module Unified {
217216
}
218217
}
219218

219+
/** A tuple expression. */
220+
class TupleExpr extends G::TupleExpr {
221+
/** Gets the number of elements in this tuple expression. */
222+
int getNumberOfElements() { result = count(this.getAnElement()) }
223+
}
224+
220225
class TypeAliasDeclaration extends G::TypeAliasDeclaration {
221226
/** Gets the name of this type alias. */
222227
string getName() { result = this.getNameNode().getValue() }
@@ -274,4 +279,10 @@ module Unified {
274279
result = count(Argument arg | arg = this.getAnArgument() and arg.isPositional())
275280
}
276281
}
282+
283+
/** A function expression. */
284+
class FunctionExpr extends G::FunctionExpr {
285+
/** Gets the number of parameters of this function. */
286+
int getNumberOfParameters() { result = count(this.getAParameter()) }
287+
}
277288
}

‎unified/ql/lib/codeql/unified/internal/StaticNameBinding.qll‎

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -717,14 +717,25 @@ module Public {
717717
}
718718
}
719719

720-
/** Gets the declaration being accessed by `access`, as determined by static name binding. */
721-
NameBinding getStaticBindingTarget(Identifier access) {
720+
/** Gets the declaration being accessed by identifier `i`, as determined by static name binding. */
721+
NameBinding getStaticBindingTargetFromIdentifier(Identifier i) {
722722
// For unqualified accesses, use the shadowing-aware lookup
723-
result = access.(UnqualifiedMemberAccess).getTarget()
723+
result = i.(UnqualifiedMemberAccess).getTarget()
724724
or
725725
// For others, just follow the name binding graph
726-
not access instanceof UnqualifiedMemberAccess and
727-
trackNameBinding(result).asIdentifier() = access
726+
not i instanceof UnqualifiedMemberAccess and
727+
trackNameBinding(result).asIdentifier() = i
728+
}
729+
730+
/**
731+
* Gets the declaration being accessed by `access`, as determined by static name binding.
732+
*
733+
* Unlike `getStaticBindingTargetFromIdentifier`, this works with any AST node that contains
734+
* a reference to an identifier, for example `x.foo` and `foo<Int>` resolve to whatever the
735+
* identifiers `foo` resolve to.
736+
*/
737+
NameBinding getStaticBindingTargetFromRef(AstNode access) {
738+
result = getStaticBindingTargetFromIdentifier(getIdentifierFromRef(access))
728739
}
729740

730741
/**
Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,7 @@
11
private import unified
22
private import AllDataFlow
3-
private import codeql.unified.internal.NameBinding as N
4-
5-
private Callable getCallableFromNameBinding(NameBinding binding) {
6-
binding = result.(FunctionDeclaration).getNameNode()
7-
}
3+
private import codeql.unified.internal.typeinference.TypeInference as T
84

95
DataFlowCallable viableCallable(DataFlowCall c) {
10-
exists(CallExpr call, Callable callable, NameBinding target |
11-
c.asExplicitCall() = call and
12-
target = N::getStaticBindingTarget(N::getIdentifierFromRef(call.getCallee())) and
13-
callable = getCallableFromNameBinding(target) and
14-
result.asSourceCallable() = callable
15-
)
6+
result.asSourceCallable() = T::resolveCallTarget(c.asExplicitCall())
167
}

0 commit comments

Comments
 (0)