Rust: Resolve Self paths in type definitions

This commit is contained in:
Simon Friis Vindum
2026-02-02 13:29:26 +01:00
parent 95afe615b5
commit 99b498b891
3 changed files with 17 additions and 26 deletions

View File

@@ -119,6 +119,15 @@ private ItemNode getAChildSuccessor(ItemNode item, string name, SuccessorKind ki
if result.isPublic()
then kind.isBoth()
else kind.isInternal()
or
// `Self` has scoping rules similar to type parameters and can be considered
// an implicit type parameter child of the introducing item.
// - https://doc.rust-lang.org/stable/reference/paths.html#r-paths.qualifiers.type-self
// - https://doc.rust-lang.org/stable/reference/names/scopes.html#r-names.scopes.self
(item instanceof TypeItemTypeItemNode or item instanceof ImplOrTraitItemNode) and
name = "Self" and
kind.isInternal() and
result = item
}
private module UseOption = Option<Use>;
@@ -405,9 +414,6 @@ abstract class ItemNode extends Locatable {
this instanceof SourceFile and
builtin(name, result)
or
name = "Self" and
this = result.(ImplOrTraitItemNode).getAnItemInSelfScope()
or
name = "crate" and
this = result.(CrateItemNode).getASourceFile()
)
@@ -718,26 +724,12 @@ class FunctionItemNode extends AssocItemNode, ParameterizableItemNode instanceof
}
abstract class ImplOrTraitItemNode extends ItemNode {
/** Gets an item that may refer to this node using `Self`. */
pragma[nomagic]
ItemNode getAnItemInSelfScope() {
result = this
or
result.getImmediateParent() = this
or
exists(ItemNode mid |
mid = this.getAnItemInSelfScope() and
result.getImmediateParent() = mid and
not mid instanceof ImplOrTraitItemNode
)
}
/** Gets a `Self` path that refers to this item. */
cached
Path getASelfPath() {
Stages::PathResolutionStage::ref() and
isUnqualifiedSelfPath(result) and
result = this.getAnItemInSelfScope().getADescendant()
this = unqualifiedPathLookup(result, _, _)
}
/** Gets an associated item belonging to this trait or `impl` block. */
@@ -1610,11 +1602,7 @@ private predicate unqualifiedPathLookup(ItemNode ancestor, string name, Namespac
// lookup in an outer scope, but only if the item is not declared in inner scope
exists(ItemNode mid |
unqualifiedPathLookup(mid, name, ns, encl) and
not declares(mid, ns, name) and
not (
name = "Self" and
mid = any(ImplOrTraitItemNode i).getAnItemInSelfScope()
)
not declares(mid, ns, name)
|
ancestor = getOuterScope(mid)
or

View File

@@ -1060,12 +1060,12 @@ mod self_constructors {
mod self_types {
struct NonEmptyListStruct<T> {
head: T, // $ item=T
tail: Option<Box<Self>>, // $ item=Option item=Box MISSING: item=NonEmptyListStruct
tail: Option<Box<Self>>, // $ item=Option item=Box item=NonEmptyListStruct
}
enum NonEmptyListEnum<T> {
Single(T), // $ item=T
Cons(T, Box<Self>), // $ item=T item=Box MISSING: item=NonEmptyListEnum
Cons(T, Box<Self>), // $ item=T item=Box item=NonEmptyListEnum
}
#[rustfmt::skip]
@@ -1075,7 +1075,7 @@ mod self_types {
: Copy // $ item=Copy
> {
single: T, // $ item=T
cons: (T, &'a Self), // $ item=T MISSING: item=NonEmptyListUnion
cons: (T, &'a Self), // $ item=T item=NonEmptyListUnion
}
}

View File

@@ -536,12 +536,15 @@ resolvePath
| main.rs:1062:15:1062:15 | T | main.rs:1061:31:1061:31 | T |
| main.rs:1063:15:1063:31 | Option::<...> | {EXTERNAL LOCATION} | enum Option |
| main.rs:1063:22:1063:30 | Box::<...> | {EXTERNAL LOCATION} | struct Box |
| main.rs:1063:26:1063:29 | Self | main.rs:1061:5:1064:5 | struct NonEmptyListStruct |
| main.rs:1067:16:1067:16 | T | main.rs:1066:27:1066:27 | T |
| main.rs:1068:14:1068:14 | T | main.rs:1066:27:1066:27 | T |
| main.rs:1068:17:1068:25 | Box::<...> | {EXTERNAL LOCATION} | struct Box |
| main.rs:1068:21:1068:24 | Self | main.rs:1066:5:1069:5 | enum NonEmptyListEnum |
| main.rs:1075:13:1075:16 | Copy | {EXTERNAL LOCATION} | trait Copy |
| main.rs:1077:17:1077:17 | T | main.rs:1074:9:1074:9 | T |
| main.rs:1078:16:1078:16 | T | main.rs:1074:9:1074:9 | T |
| main.rs:1078:23:1078:26 | Self | main.rs:1071:5:1079:5 | union NonEmptyListUnion |
| main.rs:1083:5:1083:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:1083:5:1083:14 | ...::nested | my.rs:1:1:1:15 | mod nested |
| main.rs:1083:5:1083:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 |