@@ -112,13 +112,18 @@ abstract class ItemNode extends Locatable {
112
112
result = this .( SourceFileItemNode ) .getSuper ( )
113
113
}
114
114
115
+ pragma [ nomagic]
116
+ private ItemNode getAChildSuccessor ( string name ) {
117
+ this = result .getImmediateParent ( ) and
118
+ name = result .getName ( )
119
+ }
120
+
115
121
cached
116
122
ItemNode getASuccessorRec ( string name ) {
117
123
Stages:: PathResolutionStage:: ref ( ) and
118
124
sourceFileEdge ( this , name , result )
119
125
or
120
- this = result .getImmediateParent ( ) and
121
- name = result .getName ( )
126
+ result = this .getAChildSuccessor ( name )
122
127
or
123
128
fileImportEdge ( this , name , result )
124
129
or
@@ -224,6 +229,38 @@ abstract class ItemNode extends Locatable {
224
229
result .( CrateItemNode ) .isPotentialDollarCrateTarget ( )
225
230
}
226
231
232
+ /**
233
+ * Holds if the successor `item` with the name `name` is not available locally
234
+ * for unqualified paths.
235
+ *
236
+ * This has the effect that a path of the form `name` inside `this` will not
237
+ * resolve to `item`.
238
+ */
239
+ pragma [ nomagic]
240
+ predicate excludedLocally ( string name , ItemNode item ) {
241
+ // Associated items in an impl or trait block are not directly available
242
+ // inside the block, they require a qualified path with a `Self` prefix.
243
+ item = this .getAChildSuccessor ( name ) and
244
+ this instanceof ImplOrTraitItemNode and
245
+ item instanceof AssocItemNode
246
+ }
247
+
248
+ /**
249
+ * Holds if the successor `item` with the name `name` is not available
250
+ * externally for qualified paths that resolve to this item.
251
+ *
252
+ * This has the effect that a path of the form `Qualifier::name`, where
253
+ * `Qualifier` resolves to this item, will not resolve to `item`.
254
+ */
255
+ pragma [ nomagic]
256
+ predicate excludedExternally ( string name , ItemNode item ) {
257
+ // Type parameters for an `impl` or trait block are not available outside of
258
+ // the block.
259
+ item = this .getAChildSuccessor ( name ) and
260
+ this instanceof ImplOrTraitItemNode and
261
+ item instanceof TypeParamItemNode
262
+ }
263
+
227
264
pragma [ nomagic]
228
265
private predicate hasSourceFunction ( string name ) {
229
266
this .getASuccessorFull ( name ) .( Function ) .fromSource ( )
@@ -1145,7 +1182,9 @@ pragma[nomagic]
1145
1182
private predicate declares ( ItemNode item , Namespace ns , string name ) {
1146
1183
exists ( ItemNode child | child .getImmediateParent ( ) = item |
1147
1184
child .getName ( ) = name and
1148
- child .getNamespace ( ) = ns
1185
+ child .getNamespace ( ) = ns and
1186
+ // If `item` is excluded locally then it does not declare `name`.
1187
+ not item .excludedLocally ( name , child )
1149
1188
or
1150
1189
useTreeDeclares ( child .( Use ) .getUseTree ( ) , name ) and
1151
1190
exists ( ns ) // `use foo::bar` can refer to both a value and a type
@@ -1193,38 +1232,27 @@ private ItemNode getOuterScope(ItemNode i) {
1193
1232
result = i .getImmediateParent ( )
1194
1233
}
1195
1234
1196
- pragma [ nomagic]
1197
- private ItemNode getAdjustedEnclosing ( ItemNode encl0 , Namespace ns ) {
1198
- // functions in `impl` blocks need to use explicit `Self::` to access other
1199
- // functions in the `impl` block
1200
- if encl0 instanceof ImplOrTraitItemNode and ns .isValue ( )
1201
- then result = encl0 .getImmediateParent ( )
1202
- else result = encl0
1203
- }
1204
-
1205
1235
/**
1206
1236
* Holds if the unqualified path `p` references an item named `name`, and `name`
1207
1237
* may be looked up in the `ns` namespace inside enclosing item `encl`.
1208
1238
*/
1209
1239
pragma [ nomagic]
1210
1240
private predicate unqualifiedPathLookup ( ItemNode encl , string name , Namespace ns , RelevantPath p ) {
1211
- exists ( ItemNode encl0 | encl = getAdjustedEnclosing ( encl0 , ns ) |
1212
- // lookup in the immediately enclosing item
1213
- p .isUnqualified ( name ) and
1214
- encl0 .getADescendant ( ) = p and
1215
- exists ( ns ) and
1216
- not name = [ "crate" , "$crate" , "super" , "self" ]
1217
- or
1218
- // lookup in an outer scope, but only if the item is not declared in inner scope
1219
- exists ( ItemNode mid |
1220
- unqualifiedPathLookup ( mid , name , ns , p ) and
1221
- not declares ( mid , ns , name ) and
1222
- not (
1223
- name = "Self" and
1224
- mid = any ( ImplOrTraitItemNode i ) .getAnItemInSelfScope ( )
1225
- ) and
1226
- encl0 = getOuterScope ( mid )
1227
- )
1241
+ // lookup in the immediately enclosing item
1242
+ p .isUnqualified ( name ) and
1243
+ encl .getADescendant ( ) = p and
1244
+ exists ( ns ) and
1245
+ not name = [ "crate" , "$crate" , "super" , "self" ]
1246
+ or
1247
+ // lookup in an outer scope, but only if the item is not declared in inner scope
1248
+ exists ( ItemNode mid |
1249
+ unqualifiedPathLookup ( mid , name , ns , p ) and
1250
+ not declares ( mid , ns , name ) and
1251
+ not (
1252
+ name = "Self" and
1253
+ mid = any ( ImplOrTraitItemNode i ) .getAnItemInSelfScope ( )
1254
+ ) and
1255
+ encl = getOuterScope ( mid )
1228
1256
)
1229
1257
}
1230
1258
@@ -1245,10 +1273,10 @@ private predicate sourceFileHasCratePathTc(ItemNode i1, ItemNode i2) =
1245
1273
1246
1274
/**
1247
1275
* Holds if the unqualified path `p` references a keyword item named `name`, and
1248
- * `name` may be looked up in the `ns` namespace inside enclosing item `encl`.
1276
+ * `name` may be looked up inside enclosing item `encl`.
1249
1277
*/
1250
1278
pragma [ nomagic]
1251
- private predicate keywordLookup ( ItemNode encl , string name , Namespace ns , RelevantPath p ) {
1279
+ private predicate keywordLookup ( ItemNode encl , string name , RelevantPath p ) {
1252
1280
// For `($)crate`, jump directly to the root module
1253
1281
exists ( ItemNode i | p .isCratePath ( name , i ) |
1254
1282
encl instanceof SourceFile and
@@ -1259,18 +1287,17 @@ private predicate keywordLookup(ItemNode encl, string name, Namespace ns, Releva
1259
1287
or
1260
1288
name = [ "super" , "self" ] and
1261
1289
p .isUnqualified ( name ) and
1262
- exists ( ItemNode encl0 |
1263
- encl0 .getADescendant ( ) = p and
1264
- encl = getAdjustedEnclosing ( encl0 , ns )
1265
- )
1290
+ encl .getADescendant ( ) = p
1266
1291
}
1267
1292
1268
1293
pragma [ nomagic]
1269
1294
private ItemNode unqualifiedPathLookup ( RelevantPath p , Namespace ns ) {
1270
- exists ( ItemNode encl , string name | result = getASuccessorFull ( encl , name , ns ) |
1295
+ exists ( ItemNode encl , string name |
1296
+ result = getASuccessorFull ( encl , name , ns ) and not encl .excludedLocally ( name , result )
1297
+ |
1271
1298
unqualifiedPathLookup ( encl , name , ns , p )
1272
1299
or
1273
- keywordLookup ( encl , name , ns , p )
1300
+ keywordLookup ( encl , name , p ) and exists ( ns )
1274
1301
)
1275
1302
}
1276
1303
@@ -1291,7 +1318,8 @@ private ItemNode resolvePath0(RelevantPath path, Namespace ns) {
1291
1318
or
1292
1319
exists ( ItemNode q , string name |
1293
1320
q = resolvePathQualifier ( path , name ) and
1294
- result = getASuccessorFull ( q , name , ns )
1321
+ result = getASuccessorFull ( q , name , ns ) and
1322
+ not q .excludedExternally ( name , result )
1295
1323
)
1296
1324
or
1297
1325
result = resolveUseTreeListItem ( _, _, path ) and
0 commit comments