Skip to content

Commit 1f2cc36

Browse files
committed
wip2
1 parent 4f453d8 commit 1f2cc36

File tree

3 files changed

+224
-217
lines changed

3 files changed

+224
-217
lines changed
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
private import rust
2+
private import TypeInference
3+
private import PathResolution
4+
private import Type
5+
private import TypeMention
6+
private import codeql.rust.elements.Call
7+
8+
private newtype TFunctionTypePosition =
9+
TArgumentFunctionTypePosition(ArgumentPosition pos) or
10+
TReturnFunctionTypePosition()
11+
12+
/**
13+
* A position of a type related to a function.
14+
*
15+
* Either `self`, `return`, or a positional parameter index.
16+
*/
17+
class FunctionTypePosition extends TFunctionTypePosition {
18+
predicate isSelf() { this.asArgumentPosition().isSelf() }
19+
20+
int asPositional() { result = this.asArgumentPosition().asPosition() }
21+
22+
predicate isPositional() { exists(this.asPositional()) }
23+
24+
ArgumentPosition asArgumentPosition() { this = TArgumentFunctionTypePosition(result) }
25+
26+
predicate isReturn() { this = TReturnFunctionTypePosition() }
27+
28+
/** Gets the corresponding position when `f` is invoked via a function call. */
29+
bindingset[f]
30+
FunctionTypePosition getFunctionCallAdjusted(Function f) {
31+
this.isReturn() and
32+
result = this
33+
or
34+
if f.hasSelfParam()
35+
then
36+
this.isSelf() and result.asPositional() = 0
37+
or
38+
result.asPositional() = this.asPositional() + 1
39+
else result = this
40+
}
41+
42+
TypeMention getTypeMention(Function f) {
43+
this.isSelf() and
44+
result = getSelfParamTypeMention(f.getSelfParam())
45+
or
46+
result = f.getParam(this.asPositional()).getTypeRepr()
47+
or
48+
this.isReturn() and
49+
result = f.getRetType().getTypeRepr()
50+
}
51+
52+
string toString() {
53+
result = this.asArgumentPosition().toString()
54+
or
55+
this.isReturn() and
56+
result = "(return)"
57+
}
58+
}
59+
60+
pragma[nomagic]
61+
predicate functionTypeAtPath(Function f, FunctionTypePosition pos, TypePath path, Type type) {
62+
type = pos.getTypeMention(f).resolveTypeAt(path)
63+
}
64+
65+
/**
66+
* A helper module for implementing `Matching(WithEnvironment)InputSig` with
67+
* `DeclarationPosition = AccessPosition = FunctionTypePosition`.
68+
*/
69+
module FunctionTypePositionMatchingInput {
70+
class DeclarationPosition = FunctionTypePosition;
71+
72+
class AccessPosition = DeclarationPosition;
73+
74+
predicate accessDeclarationPositionMatch(AccessPosition apos, DeclarationPosition dpos) {
75+
apos = dpos
76+
}
77+
}
78+
79+
private newtype TFunctionType =
80+
MkFunctionType(Function f, FunctionTypePosition pos, ImplOrTraitItemNode i) {
81+
f = i.getAnAssocItem() and
82+
exists(pos.getTypeMention(f))
83+
} or
84+
MkInheritedFunctionType(
85+
Function f, FunctionTypePosition pos, ImplOrTraitItemNode parent, ImplOrTraitItemNode i
86+
) {
87+
exists(FunctionType inherited |
88+
inherited.appliesTo(f, pos, parent) and
89+
f = i.getASuccessor(_)
90+
|
91+
parent = i.(ImplItemNode).resolveTraitTy()
92+
or
93+
parent = i.(TraitItemNode).resolveABound()
94+
)
95+
}
96+
97+
/**
98+
* The type of a function at a given position, when viewed as a member of a given
99+
* trait or `impl` block.
100+
*
101+
* Example:
102+
*
103+
* ```rust
104+
* trait T1 {
105+
* fn m1(self); // self1
106+
*
107+
* fn m2(self) { ... } // self2
108+
* }
109+
*
110+
* trait T2 : T1 {
111+
* fn m3(self); // self3
112+
* }
113+
*
114+
* impl T2 for X {
115+
* fn m1(self) { ... } // self4
116+
*
117+
* fn m3(self) { ... } // self5
118+
* }
119+
* ```
120+
*
121+
* param | `impl` or trait | type
122+
* ------- | --------------- | ----
123+
* `self1` | `trait T1` | `T1`
124+
* `self1` | `trait T2` | `T2`
125+
* `self2` | `trait T1` | `T1`
126+
* `self2` | `trait T2` | `T2`
127+
* `self2` | `impl T2 for X` | `X`
128+
* `self3` | `trait T2` | `T2`
129+
* `self4` | `impl T2 for X` | `X`
130+
* `self5` | `impl T2 for X` | `X`
131+
*/
132+
class FunctionType extends TFunctionType {
133+
private predicate asFunctionType(Function f, FunctionTypePosition pos, ImplOrTraitItemNode i) {
134+
this = MkFunctionType(f, pos, i)
135+
}
136+
137+
private predicate asInheritedFunctionType(
138+
Function f, FunctionTypePosition pos, ImplOrTraitItemNode parent, ImplOrTraitItemNode i
139+
) {
140+
this = MkInheritedFunctionType(f, pos, parent, i)
141+
}
142+
143+
/**
144+
* Holds if this function type applies to the function `f` at position `pos`,
145+
* when viewed as a member of the `impl` or trait item `i`.
146+
*/
147+
predicate appliesTo(Function f, FunctionTypePosition pos, ImplOrTraitItemNode i) {
148+
this.asFunctionType(f, pos, i)
149+
or
150+
this.asInheritedFunctionType(f, pos, _, i)
151+
}
152+
153+
pragma[nomagic]
154+
private Type getTypeAt0(TypePath path) {
155+
exists(Function f, FunctionTypePosition pos |
156+
this.asFunctionType(f, pos, _) and
157+
functionTypeAtPath(f, pos, path, result)
158+
)
159+
or
160+
exists(
161+
Function f, FunctionTypePosition pos, FunctionType parentType, ImplOrTraitItemNode parent,
162+
ImplOrTraitItemNode i
163+
|
164+
this.asInheritedFunctionType(f, pos, parent, i) and
165+
parentType.appliesTo(f, pos, parent)
166+
|
167+
result = parentType.getTypeAt0(path) and
168+
not result instanceof TSelfTypeParameter
169+
or
170+
exists(TypePath prefix, TypePath suffix |
171+
parentType.hasSelfTypeParameterAt(prefix) and
172+
result = resolveImplOrTraitType(i, suffix) and
173+
path = prefix.append(suffix)
174+
)
175+
)
176+
}
177+
178+
pragma[nomagic]
179+
private predicate hasSelfTypeParameterAt(TypePath path) {
180+
this.getTypeAt0(path) = TSelfTypeParameter(_)
181+
}
182+
183+
/**
184+
* Gets the type of this function at the given position and path.
185+
*
186+
* For functions belonging to a `trait`, we use the type of the trait itself instead
187+
* of the implicit `Self` type parameter, as otherwise any type will match.
188+
*
189+
* Calls will use `substituteLookupTraits` to map receiver types to the relevant
190+
* traits when matching.
191+
*/
192+
Type getTypeAt(TypePath path) {
193+
exists(Type t | t = this.getTypeAt0(path) |
194+
not t instanceof SelfTypeParameter and
195+
result = t
196+
or
197+
result = TTrait(t.(SelfTypeParameter).getTrait())
198+
)
199+
}
200+
201+
private AstNode getReportingNode() {
202+
exists(Function f, FunctionTypePosition pos | this.appliesTo(f, pos, _) |
203+
pos.isSelf() and
204+
result = f.getSelfParam()
205+
or
206+
result = f.getParam(pos.asPositional())
207+
or
208+
pos.isReturn() and
209+
result = f.getRetType().getTypeRepr()
210+
)
211+
}
212+
213+
string toString() { result = this.getReportingNode().toString() }
214+
215+
Location getLocation() { result = this.getReportingNode().getLocation() }
216+
}

0 commit comments

Comments
 (0)