Rust: Path resolution for trait items with default implementations

This commit is contained in:
Tom Hvitved
2025-02-20 12:56:32 +01:00
parent 1be903cb4f
commit 8f0aced868
3 changed files with 49 additions and 6 deletions

View File

@@ -132,8 +132,12 @@ abstract class ItemNode extends AstNode {
)
or
// a trait has access to the associated items of its supertraits
result = this.(TraitItemNode).resolveABound().getASuccessorRec(name) and
result instanceof AssocItemNode
this =
any(TraitItemNode trait |
result = trait.resolveABound().getASuccessorRec(name) and
result instanceof AssocItemNode and
not trait.declares(name)
)
or
// items made available by an implementation where `this` is the implementing type
exists(ItemNode node |
@@ -141,6 +145,15 @@ abstract class ItemNode extends AstNode {
result = node.getASuccessorRec(name) and
result instanceof AssocItemNode
)
or
// trait items with default implementations made available in an implementation
exists(ImplItemNode impl, ItemNode trait |
this = impl and
trait = impl.resolveTraitTy() and
result = trait.getASuccessorRec(name) and
result.(AssocItemNode).hasImplementation() and
not impl.declares(name)
)
}
/** Gets a successor named `name` of this item, if any. */
@@ -194,11 +207,16 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
}
/** An item that can occur in a trait or an `impl` block. */
abstract private class AssocItemNode extends ItemNode { }
abstract private class AssocItemNode extends ItemNode, AssocItem {
/** Holds if this associated item has an implementation. */
abstract predicate hasImplementation();
}
private class ConstItemNode extends AssocItemNode instanceof Const {
override string getName() { result = Const.super.getName().getText() }
override predicate hasImplementation() { super.hasBody() }
override Namespace getNamespace() { result.isValue() }
override Visibility getVisibility() { result = Const.super.getVisibility() }
@@ -222,9 +240,11 @@ private class VariantItemNode extends ItemNode instanceof Variant {
override Visibility getVisibility() { result = Variant.super.getVisibility() }
}
private class FunctionItemNode extends AssocItemNode instanceof Function {
class FunctionItemNode extends AssocItemNode instanceof Function {
override string getName() { result = Function.super.getName().getText() }
override predicate hasImplementation() { super.hasBody() }
override Namespace getNamespace() { result.isValue() }
override Visibility getVisibility() { result = Function.super.getVisibility() }
@@ -245,7 +265,19 @@ abstract private class ImplOrTraitItemNode extends ItemNode {
}
class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
ItemNode resolveSelfTy() { result = resolvePath(super.getSelfTy().(PathTypeRepr).getPath()) }
Path getSelfPath() { result = super.getSelfTy().(PathTypeRepr).getPath() }
Path getTraitPath() { result = super.getTrait().(PathTypeRepr).getPath() }
ItemNode resolveSelfTy() { result = resolvePath(this.getSelfPath()) }
TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) }
/** Holds if this `impl` block declares an associated item named `name`. */
pragma[nomagic]
predicate declares(string name) {
name = super.getAssocItemList().getAnAssocItem().(AssocItemNode).getName()
}
override string getName() { result = "(impl)" }
@@ -259,6 +291,8 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
private class MacroCallItemNode extends AssocItemNode instanceof MacroCall {
override string getName() { result = "(macro call)" }
override predicate hasImplementation() { none() }
override Namespace getNamespace() { none() }
override Visibility getVisibility() { none() }
@@ -293,6 +327,12 @@ class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
/** Holds if this trait declares an associated item named `name`. */
pragma[nomagic]
predicate declares(string name) {
name = super.getAssocItemList().getAnAssocItem().(AssocItemNode).getName()
}
override string getName() { result = Trait.super.getName().getText() }
override Namespace getNamespace() { result.isType() }
@@ -303,6 +343,8 @@ class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
class TypeAliasItemNode extends AssocItemNode instanceof TypeAlias {
override string getName() { result = TypeAlias.super.getName().getText() }
override predicate hasImplementation() { super.hasTypeRepr() }
override Namespace getNamespace() { result.isType() }
override Visibility getVisibility() { result = TypeAlias.super.getVisibility() }

View File

@@ -430,7 +430,7 @@ mod m16 {
>::f(&x); // $ MISSING: item=I93
S::g(&x); // $ item=I92
x.g(); // $ MISSING: item=I92
S::h(&x); // $ MISSING: item=I96
S::h(&x); // $ item=I96
x.h(); // $ MISSING: item=I96
S::c; // $ item=I95
<S // $ item=I90

View File

@@ -187,6 +187,7 @@ resolvePath
| main.rs:431:9:431:9 | S | main.rs:384:5:384:13 | struct S |
| main.rs:431:9:431:12 | ...::g | main.rs:397:9:400:9 | fn g |
| main.rs:433:9:433:9 | S | main.rs:384:5:384:13 | struct S |
| main.rs:433:9:433:12 | ...::h | main.rs:360:9:363:9 | fn h |
| main.rs:435:9:435:9 | S | main.rs:384:5:384:13 | struct S |
| main.rs:435:9:435:12 | ...::c | main.rs:402:9:403:9 | Const |
| main.rs:436:10:436:10 | S | main.rs:384:5:384:13 | struct S |