Skip to content

Commit 8d94920

Browse files
committed
Rust: Rework call resolution and type inference for calls
1 parent 39872dd commit 8d94920

File tree

8 files changed

+2580
-1550
lines changed

8 files changed

+2580
-1550
lines changed

rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
1212
* the canonical path `path` and the method name `method`, and if it borrows its
1313
* first `borrows` arguments.
1414
*/
15-
private predicate isOverloaded(string op, int arity, string path, string method, int borrows) {
15+
predicate isOverloaded(string op, int arity, string path, string method, int borrows) {
1616
arity = 1 and
1717
(
1818
// Negation

rust/ql/lib/codeql/rust/elements/internal/UnionImpl.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ module Impl {
2121
* ```
2222
*/
2323
class Union extends Generated::Union {
24+
/** Gets the record field named `name`, if any. */
25+
pragma[nomagic]
26+
StructField getStructField(string name) {
27+
result = this.getStructFieldList().getAField() and
28+
result.getName().getText() = name
29+
}
30+
2431
override string toStringImpl() { result = "union " + this.getName().getText() }
2532
}
2633
}

rust/ql/lib/codeql/rust/frameworks/stdlib/Stdlib.qll

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,83 @@ class StringStruct extends Struct {
213213
pragma[nomagic]
214214
StringStruct() { this.getCanonicalPath() = "alloc::string::String" }
215215
}
216+
217+
/**
218+
* The [`Deref` trait][1].
219+
*
220+
* [1]: https://doc.rust-lang.org/core/ops/trait.Deref.html
221+
*/
222+
class DerefTrait extends Trait {
223+
pragma[nomagic]
224+
DerefTrait() { this.getCanonicalPath() = "core::ops::deref::Deref" }
225+
226+
/** Gets the `deref` function. */
227+
Function getDerefFunction() { result = this.(TraitItemNode).getAssocItem("deref") }
228+
229+
/** Gets the `Target` associated type. */
230+
pragma[nomagic]
231+
TypeAlias getTargetType() {
232+
result = this.getAssocItemList().getAnAssocItem() and
233+
result.getName().getText() = "Target"
234+
}
235+
}
236+
237+
/**
238+
* The [`Index` trait][1].
239+
*
240+
* [1]: https://doc.rust-lang.org/std/ops/trait.Index.html
241+
*/
242+
class IndexTrait extends Trait {
243+
pragma[nomagic]
244+
IndexTrait() { this.getCanonicalPath() = "core::ops::index::Index" }
245+
246+
/** Gets the `index` function. */
247+
Function getIndexFunction() { result = this.(TraitItemNode).getAssocItem("index") }
248+
249+
/** Gets the `Output` associated type. */
250+
pragma[nomagic]
251+
TypeAlias getOutputType() {
252+
result = this.getAssocItemList().getAnAssocItem() and
253+
result.getName().getText() = "Output"
254+
}
255+
}
256+
257+
/**
258+
* The [`Box` struct][1].
259+
*
260+
* [1]: https://doc.rust-lang.org/std/boxed/struct.Box.html
261+
*/
262+
class BoxStruct extends Struct {
263+
pragma[nomagic]
264+
BoxStruct() { this.getCanonicalPath() = "alloc::boxed::Box" }
265+
}
266+
267+
/**
268+
* The [`Rc` struct][1].
269+
*
270+
* [1]: https://doc.rust-lang.org/std/rc/struct.Rc.html
271+
*/
272+
class RcStruct extends Struct {
273+
pragma[nomagic]
274+
RcStruct() { this.getCanonicalPath() = "alloc::rc::Rc" }
275+
}
276+
277+
/**
278+
* The [`Arc` struct][1].
279+
*
280+
* [1]: https://doc.rust-lang.org/std/sync/struct.Arc.html
281+
*/
282+
class ArcStruct extends Struct {
283+
pragma[nomagic]
284+
ArcStruct() { this.getCanonicalPath() = "alloc::sync::Arc" }
285+
}
286+
287+
/**
288+
* The [`Pin` struct][1].
289+
*
290+
* [1]: https://doc.rust-lang.org/std/pin/struct.Pin.html
291+
*/
292+
class PinStruct extends Struct {
293+
pragma[nomagic]
294+
PinStruct() { this.getCanonicalPath() = "core::pin::Pin" }
295+
}

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

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
810810
}
811811
}
812812

813-
final private class ImplTraitTypeReprItemNode extends TypeItemNode instanceof ImplTraitTypeRepr {
813+
final class ImplTraitTypeReprItemNode extends TypeItemNode instanceof ImplTraitTypeRepr {
814814
pragma[nomagic]
815815
Path getABoundPath() {
816816
result = super.getTypeBoundList().getABound().getTypeRepr().(PathTypeRepr).getPath()
@@ -1549,25 +1549,55 @@ signature predicate relevantTraitVisibleSig(Element element, Trait trait);
15491549
* at a given element.
15501550
*/
15511551
module TraitIsVisible<relevantTraitVisibleSig/2 relevantTraitVisible> {
1552-
/** Holds if the trait might be looked up in `encl`. */
1553-
private predicate traitLookup(ItemNode encl, Element element, Trait trait) {
1554-
// lookup in immediately enclosing item
1555-
relevantTraitVisible(element, trait) and
1556-
encl.getADescendant() = element
1552+
private newtype TNode =
1553+
TTrait(Trait t) { relevantTraitVisible(_, t) } or
1554+
TItemNode(ItemNode i) or
1555+
TElement(Element e) { relevantTraitVisible(e, _) }
1556+
1557+
private predicate isTrait(TNode n) { n instanceof TTrait }
1558+
1559+
private predicate step(TNode n1, TNode n2) {
1560+
exists(Trait t1, ItemNode i2 |
1561+
n1 = TTrait(t1) and
1562+
n2 = TItemNode(i2) and
1563+
t1 = i2.getASuccessor(_, _, _)
1564+
)
15571565
or
1558-
// lookup in an outer scope, but only if the trait is not declared in inner scope
1559-
exists(ItemNode mid |
1560-
traitLookup(mid, element, trait) and
1561-
not trait = mid.getASuccessor(_, _, _) and
1562-
encl = getOuterScope(mid)
1566+
exists(ItemNode i1, ItemNode i2 |
1567+
n1 = TItemNode(i1) and
1568+
n2 = TItemNode(i2) and
1569+
i1 = getOuterScope(i2)
1570+
)
1571+
or
1572+
exists(ItemNode i1, Element e2 |
1573+
n1 = TItemNode(i1) and
1574+
n2 = TElement(e2) and
1575+
i1.getADescendant() = e2
1576+
)
1577+
}
1578+
1579+
private predicate isElement(TNode n) { n instanceof TElement }
1580+
1581+
private predicate traitIsVisibleTC(TNode trait, TNode element) =
1582+
doublyBoundedFastTC(step/2, isTrait/1, isElement/1)(trait, element)
1583+
1584+
pragma[nomagic]
1585+
private predicate relevantTraitVisibleLift(TNode trait, TElement element) {
1586+
exists(Trait t, Element e |
1587+
trait = TTrait(t) and
1588+
element = TElement(e) and
1589+
relevantTraitVisible(e, t)
15631590
)
15641591
}
15651592

15661593
/** Holds if the trait `trait` is visible at `element`. */
15671594
pragma[nomagic]
15681595
predicate traitIsVisible(Element element, Trait trait) {
1569-
exists(ItemNode encl |
1570-
traitLookup(encl, element, trait) and trait = encl.getASuccessor(_, _, _)
1596+
exists(TNode t, TNode e |
1597+
traitIsVisibleTC(t, e) and
1598+
relevantTraitVisibleLift(t, e) and
1599+
t = TTrait(trait) and
1600+
e = TElement(element)
15711601
)
15721602
}
15731603
}
@@ -1914,7 +1944,7 @@ private predicate builtin(string name, ItemNode i) {
19141944

19151945
/** Provides predicates for debugging the path resolution implementation. */
19161946
private module Debug {
1917-
private Locatable getRelevantLocatable() {
1947+
Locatable getRelevantLocatable() {
19181948
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
19191949
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
19201950
filepath.matches("%/main.rs") and

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

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,14 @@ newtype TType =
4242
TStruct(Struct s) or
4343
TEnum(Enum e) or
4444
TTrait(Trait t) or
45+
TUnion(Union u) or
4546
TArrayType() or // todo: add size?
4647
TRefType() or // todo: add mut?
4748
TImplTraitType(ImplTraitTypeRepr impl) or
4849
TDynTraitType(Trait t) { t = any(DynTraitTypeRepr dt).getTrait() } or
4950
TSliceType() or
51+
TNeverType() or
52+
TPtrType() or
5053
TTupleTypeParameter(int arity, int i) { exists(TTuple(arity)) and i in [0 .. arity - 1] } or
5154
TTypeParamTypeParameter(TypeParam t) or
5255
TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or
@@ -57,7 +60,8 @@ newtype TType =
5760
} or
5861
TRefTypeParameter() or
5962
TSelfTypeParameter(Trait t) or
60-
TSliceTypeParameter()
63+
TSliceTypeParameter() or
64+
TPtrTypeParameter()
6165

6266
private predicate implTraitTypeParam(ImplTraitTypeRepr implTrait, int i, TypeParam tp) {
6367
implTrait.isInReturnPos() and
@@ -224,6 +228,31 @@ class TraitType extends Type, TTrait {
224228
override Location getLocation() { result = trait.getLocation() }
225229
}
226230

231+
/** A union type. */
232+
class UnionType extends StructOrEnumType, TUnion {
233+
private Union union;
234+
235+
UnionType() { this = TUnion(union) }
236+
237+
override ItemNode asItemNode() { result = union }
238+
239+
override StructField getStructField(string name) { result = union.getStructField(name) }
240+
241+
override TupleField getTupleField(int i) { none() }
242+
243+
override TypeParameter getPositionalTypeParameter(int i) {
244+
result = TTypeParamTypeParameter(union.getGenericParamList().getTypeParam(i))
245+
}
246+
247+
override TypeMention getTypeParameterDefault(int i) {
248+
result = union.getGenericParamList().getTypeParam(i).getDefaultType()
249+
}
250+
251+
override string toString() { result = union.getName().getText() }
252+
253+
override Location getLocation() { result = union.getLocation() }
254+
}
255+
227256
/**
228257
* An array type.
229258
*
@@ -374,6 +403,33 @@ class SliceType extends Type, TSliceType {
374403
override Location getLocation() { result instanceof EmptyLocation }
375404
}
376405

406+
class NeverType extends Type, TNeverType {
407+
override StructField getStructField(string name) { none() }
408+
409+
override TupleField getTupleField(int i) { none() }
410+
411+
override TypeParameter getPositionalTypeParameter(int i) { none() }
412+
413+
override string toString() { result = "!" }
414+
415+
override Location getLocation() { result instanceof EmptyLocation }
416+
}
417+
418+
class PtrType extends Type, TPtrType {
419+
override StructField getStructField(string name) { none() }
420+
421+
override TupleField getTupleField(int i) { none() }
422+
423+
override TypeParameter getPositionalTypeParameter(int i) {
424+
i = 0 and
425+
result = TPtrTypeParameter()
426+
}
427+
428+
override string toString() { result = "*" }
429+
430+
override Location getLocation() { result instanceof EmptyLocation }
431+
}
432+
377433
/** A type parameter. */
378434
abstract class TypeParameter extends Type {
379435
override StructField getStructField(string name) { none() }
@@ -529,6 +585,12 @@ class SliceTypeParameter extends TypeParameter, TSliceTypeParameter {
529585
override Location getLocation() { result instanceof EmptyLocation }
530586
}
531587

588+
class PtrTypeParameter extends TypeParameter, TPtrTypeParameter {
589+
override string toString() { result = "*T" }
590+
591+
override Location getLocation() { result instanceof EmptyLocation }
592+
}
593+
532594
/**
533595
* The implicit `Self` type parameter of a trait, that refers to the
534596
* implementing type of the trait.

0 commit comments

Comments
 (0)