Skip to content

Commit 04b0ed6

Browse files
committed
Rust: Refactor using shared constraint satisfaction
1 parent 8a3f62b commit 04b0ed6

File tree

4 files changed

+59
-95
lines changed

4 files changed

+59
-95
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ private predicate assocFunctionInfo(
822822
) {
823823
f = i.getASuccessor(name) and
824824
arity = f.getParamList().getNumberOfParams() and
825-
t.appliesTo(f, pos, i)
825+
t.appliesTo(f, i, pos)
826826
}
827827

828828
/**
@@ -1622,7 +1622,7 @@ private module MethodResolution {
16221622
predicate toCheck(ImplOrTraitItemNode i, Function f, FunctionPosition pos, AssocFunctionType t) {
16231623
exists(TypePath path, Type t0 |
16241624
FunctionOverloading::functionResolutionDependsOnArgument(i, f, pos, path, t0) and
1625-
t.appliesTo(f, pos, i) and
1625+
t.appliesTo(f, i, pos) and
16261626
// for now, we do not handle ambiguous targets when one of the types it iself
16271627
// a type parameter; we should be checking the constraints on that type parameter
16281628
// in this case
@@ -1855,7 +1855,7 @@ private module NonMethodResolution {
18551855
ImplItemNode impl, NonMethodFunction implFunction
18561856
) {
18571857
exists(TypePath path |
1858-
assocFunctionTypeAt(implFunction, impl, pos, path, type) and
1858+
type = assocFunctionTypeAt(implFunction, impl, pos, path) and
18591859
implFunction.implements(traitFunction) and
18601860
FunctionOverloading::traitTypeParameterOccurrence(trait, traitFunction, _, pos, path, _)
18611861
|
@@ -2069,7 +2069,7 @@ private module NonMethodResolution {
20692069

20702070
private module NonMethodArgsAreInstantiationsOfInput implements ArgsAreInstantiationsOfInputSig {
20712071
predicate toCheck(ImplOrTraitItemNode i, Function f, FunctionPosition pos, AssocFunctionType t) {
2072-
t.appliesTo(f, pos, i) and
2072+
t.appliesTo(f, i, pos) and
20732073
(
20742074
exists(Type t0 |
20752075
// for now, we do not handle ambiguous targets when one of the types it iself

rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ predicate traitTypeParameterOccurrence(
7979
TypeParameter tp
8080
) {
8181
f = trait.getASuccessor(functionName) and
82-
assocFunctionTypeAt(f, trait, pos, path, tp) and
82+
tp = assocFunctionTypeAt(f, trait, pos, path) and
8383
tp = trait.(TraitTypeAbstraction).getATypeParameter()
8484
}
8585

@@ -120,7 +120,7 @@ predicate functionResolutionDependsOnArgument(
120120
exists(TraitItemNode trait, string functionName |
121121
implHasSibling(impl, trait) and
122122
traitTypeParameterOccurrence(trait, _, functionName, pos, path, _) and
123-
assocFunctionTypeAt(f, impl, pos, path, type) and
123+
type = assocFunctionTypeAt(f, impl, pos, path) and
124124
f = impl.getASuccessor(functionName) and
125125
pos.isPosition()
126126
)

rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll

Lines changed: 52 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -72,28 +72,54 @@ module FunctionPositionMatchingInput {
7272
}
7373

7474
private newtype TAssocFunctionType =
75-
MkAssocFunctionType(Function f, FunctionPosition pos, ImplOrTraitItemNode i) {
76-
f = i.getAnAssocItem() and
77-
exists(pos.getTypeMention(f))
78-
} or
79-
MkInheritedAssocFunctionType(
80-
Function f, FunctionPosition pos, TypeMention parentMention, TraitItemNode parent,
81-
ImplOrTraitItemNode i
82-
) {
83-
exists(AssocFunctionType inherited |
84-
inherited.appliesTo(f, pos, parent) and
85-
f = i.getASuccessor(_)
75+
/** An associated function `f` that should be specialized for `i` at `pos`. */
76+
MkAssocFunctionType(Function f, ImplOrTraitItemNode i, FunctionPosition pos) {
77+
f = i.getASuccessor(_) and exists(pos.getTypeMention(f))
78+
}
79+
80+
bindingset[condition, constraint, tp]
81+
private Type traitConstraintTypeAt(
82+
TypeMention condition, TypeMention constraint, TypeParameter tp, TypePath path
83+
) {
84+
BaseTypes::conditionSatisfiesConstraintTypeAt(_, condition, constraint,
85+
TypePath::singleton(tp).appendInverse(path), result)
86+
}
87+
88+
/**
89+
* Gets if the type of the function `f` when specialized for `i` at position
90+
* `pos` at path `path`
91+
*/
92+
pragma[nomagic]
93+
Type assocFunctionTypeAt(Function f, ImplOrTraitItemNode i, FunctionPosition pos, TypePath path) {
94+
exists(MkAssocFunctionType(f, i, pos)) and
95+
(
96+
// No specialization needed when the function is directly in the trait or
97+
// impl block or the declared type is not a type parameter
98+
(i.getAnAssocItem() = f or not result instanceof TypeParameter) and
99+
result = pos.getTypeMention(f).resolveTypeAt(path)
100+
or
101+
not i.getAnAssocItem() = f and
102+
exists(TypePath prefix, TypePath suffix, TypeParameter tp |
103+
path = prefix.append(suffix) and
104+
tp = pos.getTypeMention(f).resolveTypeAt(prefix)
86105
|
87-
parent = i.(ImplItemNode).resolveTraitTy() and
88-
parentMention = i.(ImplItemNode).getTraitPath()
89-
or
90-
parent = i.(TraitItemNode).resolveBound(parentMention)
106+
if tp = TSelfTypeParameter(_)
107+
then result = resolveImplOrTraitType(i, suffix)
108+
else
109+
exists(TraitItemNode trait, TypeMention condition, TypeMention constraint |
110+
trait.getAnAssocItem() = f and
111+
BaseTypes::rootTypesSatisfaction(_, TTrait(trait), _, condition, constraint) and
112+
result = traitConstraintTypeAt(condition, constraint, tp, suffix)
113+
|
114+
condition = i.(Trait) or condition = i.(Impl).getSelfTy()
115+
)
91116
)
92-
}
117+
)
118+
}
93119

94120
/**
95-
* The type of an associated function at a given position, when viewed as a member
96-
* of a given trait or `impl` block.
121+
* The type of an associated function at a given position, when its implicit
122+
* `Self` type parameter is specialized to a given trait or `impl` block.
97123
*
98124
* Example:
99125
*
@@ -126,64 +152,13 @@ private newtype TAssocFunctionType =
126152
* `self4` | `impl T2 for X` | `X`
127153
* `self5` | `impl T2 for X` | `X`
128154
*/
129-
class AssocFunctionType extends TAssocFunctionType {
130-
private predicate isFunctionType(Function f, FunctionPosition pos, ImplOrTraitItemNode i) {
131-
this = MkAssocFunctionType(f, pos, i)
132-
}
133-
134-
private predicate isInheritedFunctionType(
135-
Function f, FunctionPosition pos, TypeMention parentMention, TraitItemNode parent,
136-
ImplOrTraitItemNode i
137-
) {
138-
this = MkInheritedAssocFunctionType(f, pos, parentMention, parent, i)
139-
}
140-
155+
class AssocFunctionType extends MkAssocFunctionType {
141156
/**
142157
* Holds if this function type applies to the function `f` at position `pos`,
143158
* when viewed as a member of the `impl` or trait item `i`.
144159
*/
145-
predicate appliesTo(Function f, FunctionPosition pos, ImplOrTraitItemNode i) {
146-
this.isFunctionType(f, pos, i)
147-
or
148-
this.isInheritedFunctionType(f, pos, _, _, i)
149-
}
150-
151-
/** Gets the type at the given path. */
152-
pragma[nomagic]
153-
Type getDeclaredTypeAt(TypePath path) {
154-
exists(Function f, FunctionPosition pos |
155-
this.isFunctionType(f, pos, _) and
156-
result = pos.getTypeMention(f).resolveTypeAt(path)
157-
)
158-
or
159-
exists(
160-
Function f, FunctionPosition pos, TypeMention parentMention, TraitItemNode parent,
161-
AssocFunctionType parentType, ImplOrTraitItemNode i
162-
|
163-
this.isInheritedFunctionType(f, pos, parentMention, parent, i) and
164-
parentType.appliesTo(f, pos, parent)
165-
|
166-
result = parentType.getDeclaredTypeAt(path) and
167-
not result instanceof TypeParameter
168-
or
169-
exists(TypePath prefix, TypePath suffix | path = prefix.append(suffix) |
170-
parentType.hasSelfTypeParameterAt(prefix) and
171-
result = resolveImplOrTraitType(i, suffix)
172-
or
173-
exists(TypeParameter tp |
174-
tp = parentType.getTypeParameterAt(prefix) and
175-
result = parentMention.resolveTypeAt(TypePath::singleton(tp).appendInverse(suffix))
176-
)
177-
)
178-
)
179-
}
180-
181-
pragma[nomagic]
182-
private TypeParameter getTypeParameterAt(TypePath path) { result = this.getDeclaredTypeAt(path) }
183-
184-
pragma[nomagic]
185-
private predicate hasSelfTypeParameterAt(TypePath path) {
186-
this.getTypeParameterAt(path) = TSelfTypeParameter(_)
160+
predicate appliesTo(Function f, ImplOrTraitItemNode i, FunctionPosition pos) {
161+
this = MkAssocFunctionType(f, i, pos)
187162
}
188163

189164
/**
@@ -196,7 +171,10 @@ class AssocFunctionType extends TAssocFunctionType {
196171
* traits when matching.
197172
*/
198173
Type getTypeAt(TypePath path) {
199-
exists(Type t | t = this.getDeclaredTypeAt(path) |
174+
exists(Function f, FunctionPosition pos, ImplOrTraitItemNode i, Type t |
175+
this.appliesTo(f, i, pos) and
176+
t = assocFunctionTypeAt(f, i, pos, path)
177+
|
200178
not t instanceof SelfTypeParameter and
201179
result = t
202180
or
@@ -206,7 +184,7 @@ class AssocFunctionType extends TAssocFunctionType {
206184

207185
private TypeMention getTypeMention() {
208186
exists(Function f, FunctionPosition pos |
209-
this.appliesTo(f, pos, _) and
187+
this.appliesTo(f, _, pos) and
210188
result = pos.getTypeMention(f)
211189
)
212190
}
@@ -216,20 +194,6 @@ class AssocFunctionType extends TAssocFunctionType {
216194
Location getLocation() { result = this.getTypeMention().getLocation() }
217195
}
218196

219-
/**
220-
* Holds if the type of the function `f` at position `pos` and path `path` inside
221-
* `i` is `type`.
222-
*/
223-
pragma[nomagic]
224-
predicate assocFunctionTypeAt(
225-
Function f, ImplOrTraitItemNode i, FunctionPosition pos, TypePath path, Type type
226-
) {
227-
exists(AssocFunctionType aft |
228-
aft.appliesTo(f, pos, i) and
229-
type = aft.getDeclaredTypeAt(path)
230-
)
231-
}
232-
233197
private Trait getALookupTrait(Type t) {
234198
result = t.(TypeParamTypeParameter).getTypeParam().(TypeParamItemNode).resolveABound()
235199
or

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
717717
}
718718

719719
/** Provides logic related to base types. */
720-
private module BaseTypes {
720+
module BaseTypes {
721721
/**
722722
* Holds if, when `tm1` is considered an instantiation of `tm2`, then at
723723
* the type parameter `tp` it has the type `t` at `path`.

0 commit comments

Comments
 (0)