Skip to content

Commit 3386439

Browse files
committed
Unified: Type inference first version
1 parent 202366e commit 3386439

30 files changed

Lines changed: 6133 additions & 41 deletions

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
/** Provides classes representing types without type arguments. */
2+
3+
import unified
4+
private import unified as Unified
5+
private import TypeInference
6+
private import codeql.unified.internal.StaticNameBinding
7+
8+
/**
9+
* Holds if `a` is an associated type of `c`, in which case we model it
10+
* as a type parameter.
11+
*
12+
* `inherited` indicates whether the associated type is declared in `c`
13+
* or inherited from a base class.
14+
*/
15+
private predicate associatedTypeParameter(
16+
ClassLikeDeclaration c, AssociatedTypeDeclaration a, boolean inherited
17+
) {
18+
a = c.getAMember() and
19+
inherited = false
20+
or
21+
exists(string name |
22+
associatedTypeParameterInherited(c, a, _, _, name) and
23+
not c.getAMember().(TypeAliasDeclaration).getName() = name and
24+
inherited = true
25+
)
26+
}
27+
28+
pragma[nomagic]
29+
predicate associatedTypeParameterInherited(
30+
ClassLikeDeclaration c, AssociatedTypeDeclaration a, ClassLikeDeclaration base, Expr baseRef,
31+
string name
32+
) {
33+
associatedTypeParameter(base, a, _) and
34+
baseRef = c.getABaseType().getType() and
35+
base.getNameNode() = getStaticBindingTarget(baseRef) and
36+
name = a.getName()
37+
}
38+
39+
cached
40+
newtype TType =
41+
TClassLikeDeclarationType(ClassLikeDeclaration c) {
42+
CachedStage::ref() and
43+
exists(c.getNameNode())
44+
} or
45+
TClosureParameterPseudoType(Parameter p) {
46+
exists(FunctionExpr fe |
47+
p = fe.getAParameter() and
48+
not exists(p.getType())
49+
)
50+
} or
51+
TTypeParameterType(Unified::TypeParameter tp) or
52+
TAssociatedTypeParameterType(
53+
ClassLikeDeclaration c, AssociatedTypeDeclaration a, boolean inherited
54+
) {
55+
associatedTypeParameter(c, a, inherited)
56+
} or
57+
TUnknownType() or
58+
TUnknownTypeTypeParameter(int i) { i in [0 .. 20] }
59+
60+
final class Type = TypeImpl;
61+
62+
/**
63+
* A type without type arguments.
64+
*/
65+
abstract private class TypeImpl extends TType {
66+
/**
67+
* Gets the `i`th positional type parameter of this type, if any.
68+
*
69+
* This excludes synthetic type parameters, such as associated types.
70+
*/
71+
abstract TypeParameter getPositionalTypeParameter(int i);
72+
73+
/**
74+
* Gets a type parameter of this type.
75+
*
76+
* This includes both positional type parameters and synthetic type parameters,
77+
* such as associated types.
78+
*/
79+
TypeParameter getATypeParameter() { result = this.getPositionalTypeParameter(_) }
80+
81+
/** Gets a textual representation of this type. */
82+
abstract string toString();
83+
84+
/** Gets the location of this type. */
85+
abstract Location getLocation();
86+
}
87+
88+
/**
89+
* A type representing a class-like declaration.
90+
*/
91+
class ClassLikeDeclarationType extends TypeImpl, TClassLikeDeclarationType {
92+
ClassLikeDeclaration c;
93+
94+
ClassLikeDeclarationType() { this = TClassLikeDeclarationType(c) }
95+
96+
ClassLikeDeclaration getClassLikeDeclaration() { result = c }
97+
98+
string getName() { result = c.getName() }
99+
100+
override TypeParameter getPositionalTypeParameter(int i) {
101+
result = TTypeParameterType(c.getTypeParameter(i))
102+
}
103+
104+
override TypeParameter getATypeParameter() {
105+
result = super.getATypeParameter()
106+
or
107+
result = TAssociatedTypeParameterType(c, _, _)
108+
}
109+
110+
override string toString() { result = c.getName() }
111+
112+
override Location getLocation() { result = c.getLocation() }
113+
}
114+
115+
/**
116+
* A pseudo type that does not correspond to any concrete type in the source code.
117+
*/
118+
abstract class PseudoType extends TypeImpl { }
119+
120+
/**
121+
* A type representing an unknown type.
122+
*/
123+
class UnknownType extends PseudoType, TUnknownType {
124+
override TypeParameter getPositionalTypeParameter(int i) { result = TUnknownTypeTypeParameter(i) }
125+
126+
override string toString() { result = "(unknown type)" }
127+
128+
override Location getLocation() { result instanceof EmptyLocation }
129+
}
130+
131+
/**
132+
* A type representing a closure parameter.
133+
*/
134+
class ClosureParameterPseudoType extends PseudoType, TClosureParameterPseudoType {
135+
private Parameter param;
136+
137+
ClosureParameterPseudoType() { this = TClosureParameterPseudoType(param) }
138+
139+
Parameter getParam() { result = param }
140+
141+
override TypeParameter getPositionalTypeParameter(int i) { none() }
142+
143+
override string toString() { result = "(closure parameter " + param + ")" }
144+
145+
override Location getLocation() { result = param.getLocation() }
146+
}
147+
148+
/** A type parameter. */
149+
abstract class TypeParameter extends TypeImpl {
150+
override TypeParameter getPositionalTypeParameter(int i) { none() }
151+
152+
abstract AstNode getDeclaringItem();
153+
}
154+
155+
private class IdAstNode =
156+
@unified_type_parameter or @unified_class_like_declaration or @unified_associated_type_declaration;
157+
158+
private predicate id(IdAstNode x, IdAstNode y) { x = y }
159+
160+
private predicate idOf(IdAstNode x, int y) = equivalenceRelation(id/2)(x, y)
161+
162+
int idOfTypeParameterAstNode(AstNode node) { idOf(node, result) }
163+
164+
/** A type parameter from source code. */
165+
class TypeParameterType extends TypeParameter, TTypeParameterType {
166+
private Unified::TypeParameter typeParam;
167+
168+
TypeParameterType() { this = TTypeParameterType(typeParam) }
169+
170+
Unified::TypeParameter getTypeParameter() { result = typeParam }
171+
172+
override ClassLikeDeclaration getDeclaringItem() { typeParam = result.getATypeParameter() }
173+
174+
override string toString() { result = typeParam.getName() }
175+
176+
override Location getLocation() { result = typeParam.getLocation() }
177+
}
178+
179+
/**
180+
* An associated type viewed as a type parameter.
181+
*/
182+
class AssociatedTypeParameterType extends TypeParameter, TAssociatedTypeParameterType {
183+
private Unified::ClassLikeDeclaration c;
184+
private Unified::AssociatedTypeDeclaration assocTypeDecl;
185+
private boolean inherited;
186+
187+
AssociatedTypeParameterType() { this = TAssociatedTypeParameterType(c, assocTypeDecl, inherited) }
188+
189+
Unified::AssociatedTypeDeclaration getAssociatedTypeDeclaration() { result = assocTypeDecl }
190+
191+
override ClassLikeDeclaration getDeclaringItem() { result = c }
192+
193+
override string toString() {
194+
if inherited = true
195+
then result = assocTypeDecl.getName() + " (inherited)"
196+
else result = assocTypeDecl.getName()
197+
}
198+
199+
override Location getLocation() {
200+
if inherited = true then result = c.getLocation() else result = assocTypeDecl.getLocation()
201+
}
202+
}
203+
204+
/**
205+
* A type parameter of the special `UnknownType`.
206+
*/
207+
class UnknownTypeTypeParameter extends TypeParameter, TUnknownTypeTypeParameter {
208+
private int i;
209+
210+
UnknownTypeTypeParameter() { this = TUnknownTypeTypeParameter(i) }
211+
212+
override AstNode getDeclaringItem() { none() }
213+
214+
override TypeParameter getPositionalTypeParameter(int j) { none() }
215+
216+
override string toString() { result = "unknown type parameter " + i }
217+
218+
override Location getLocation() { result instanceof EmptyLocation }
219+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
private import unified as Unified
2+
private import Type
3+
4+
/**
5+
* A type abstraction. I.e., a place in the program where type variables may
6+
* be introduced.
7+
*/
8+
abstract class TypeAbstraction extends AstNode {
9+
abstract TypeParameter getATypeParameter();
10+
}
11+
12+
/**
13+
* A class-like declaration. Unlike `ClassLikeDeclarationType`, this includes
14+
* declarations that do not define a new type, such as `extension`s in Swift.
15+
*/
16+
final class ClassLikeDeclarationTypeAbstraction extends TypeAbstraction instanceof Unified::ClassLikeDeclaration
17+
{
18+
override TypeParameter getATypeParameter() { this = result.getDeclaringItem() }
19+
}

0 commit comments

Comments
 (0)