@@ -25,7 +25,7 @@ use rustc_span::hygiene::MacroKind;
25
25
use rustc_span:: source_map:: SourceMap ;
26
26
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
27
27
use rustc_span:: { BytePos , Span , SyntaxContext } ;
28
- use thin_vec:: ThinVec ;
28
+ use thin_vec:: { thin_vec , ThinVec } ;
29
29
30
30
use crate :: errors:: {
31
31
AddedMacroUse , ChangeImportBinding , ChangeImportBindingSuggestion , ConsiderAddingADerive ,
@@ -1147,7 +1147,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1147
1147
namespace : Namespace ,
1148
1148
parent_scope : & ParentScope < ' a > ,
1149
1149
start_module : Module < ' a > ,
1150
- crate_name : Ident ,
1150
+ crate_path : ThinVec < ast :: PathSegment > ,
1151
1151
filter_fn : FilterFn ,
1152
1152
) -> Vec < ImportSuggestion >
1153
1153
where
@@ -1163,8 +1163,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1163
1163
Some ( x) => Some ( x) ,
1164
1164
} {
1165
1165
let in_module_is_extern = !in_module. def_id ( ) . is_local ( ) ;
1166
- // We have to visit module children in deterministic order to avoid
1167
- // instabilities in reported imports (#43552).
1168
1166
in_module. for_each_child ( self , |this, ident, ns, name_binding| {
1169
1167
// avoid non-importable candidates
1170
1168
if !name_binding. is_importable ( ) {
@@ -1214,12 +1212,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1214
1212
let res = name_binding. res ( ) ;
1215
1213
if filter_fn ( res) {
1216
1214
// create the path
1217
- let mut segms = path_segments. clone ( ) ;
1218
- if lookup_ident. span . at_least_rust_2018 ( ) {
1215
+ let mut segms = if lookup_ident. span . at_least_rust_2018 ( ) {
1219
1216
// crate-local absolute paths start with `crate::` in edition 2018
1220
1217
// FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
1221
- segms. insert ( 0 , ast:: PathSegment :: from_ident ( crate_name) ) ;
1222
- }
1218
+ crate_path. clone ( )
1219
+ } else {
1220
+ ThinVec :: new ( )
1221
+ } ;
1222
+ segms. append ( & mut path_segments. clone ( ) ) ;
1223
1223
1224
1224
segms. push ( ast:: PathSegment :: from_ident ( ident) ) ;
1225
1225
let path = Path { span : name_binding. span , segments : segms, tokens : None } ;
@@ -1318,18 +1318,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1318
1318
where
1319
1319
FilterFn : Fn ( Res ) -> bool ,
1320
1320
{
1321
+ let crate_path = thin_vec ! [ ast:: PathSegment :: from_ident( Ident :: with_dummy_span( kw:: Crate ) ) ] ;
1321
1322
let mut suggestions = self . lookup_import_candidates_from_module (
1322
1323
lookup_ident,
1323
1324
namespace,
1324
1325
parent_scope,
1325
1326
self . graph_root ,
1326
- Ident :: with_dummy_span ( kw :: Crate ) ,
1327
+ crate_path ,
1327
1328
& filter_fn,
1328
1329
) ;
1329
1330
1330
1331
if lookup_ident. span . at_least_rust_2018 ( ) {
1331
- let extern_prelude_names = self . extern_prelude . clone ( ) ;
1332
- for ( ident, _) in extern_prelude_names. into_iter ( ) {
1332
+ for ident in self . extern_prelude . clone ( ) . into_keys ( ) {
1333
1333
if ident. span . from_expansion ( ) {
1334
1334
// Idents are adjusted to the root context before being
1335
1335
// resolved in the extern prelude, so reporting this to the
@@ -1340,13 +1340,43 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1340
1340
}
1341
1341
let crate_id = self . crate_loader ( |c| c. maybe_process_path_extern ( ident. name ) ) ;
1342
1342
if let Some ( crate_id) = crate_id {
1343
- let crate_root = self . expect_module ( crate_id. as_def_id ( ) ) ;
1343
+ let crate_def_id = crate_id. as_def_id ( ) ;
1344
+ let crate_root = self . expect_module ( crate_def_id) ;
1345
+
1346
+ // Check if there's already an item in scope with the same name as the crate.
1347
+ // If so, we have to disambiguate the potential import suggestions by making
1348
+ // the paths *global* (i.e., by prefixing them with `::`).
1349
+ let needs_disambiguation =
1350
+ self . resolutions ( parent_scope. module ) . borrow ( ) . iter ( ) . any (
1351
+ |( key, name_resolution) | {
1352
+ if key. ns == TypeNS
1353
+ && key. ident == ident
1354
+ && let Some ( binding) = name_resolution. borrow ( ) . binding
1355
+ {
1356
+ match binding. res ( ) {
1357
+ // No disambiguation needed if the identically named item we
1358
+ // found in scope actually refers to the crate in question.
1359
+ Res :: Def ( _, def_id) => def_id != crate_def_id,
1360
+ Res :: PrimTy ( _) => true ,
1361
+ _ => false ,
1362
+ }
1363
+ } else {
1364
+ false
1365
+ }
1366
+ } ,
1367
+ ) ;
1368
+ let mut crate_path = ThinVec :: new ( ) ;
1369
+ if needs_disambiguation {
1370
+ crate_path. push ( ast:: PathSegment :: path_root ( rustc_span:: DUMMY_SP ) ) ;
1371
+ }
1372
+ crate_path. push ( ast:: PathSegment :: from_ident ( ident) ) ;
1373
+
1344
1374
suggestions. extend ( self . lookup_import_candidates_from_module (
1345
1375
lookup_ident,
1346
1376
namespace,
1347
1377
parent_scope,
1348
1378
crate_root,
1349
- ident ,
1379
+ crate_path ,
1350
1380
& filter_fn,
1351
1381
) ) ;
1352
1382
}
@@ -2554,7 +2584,7 @@ fn show_candidates(
2554
2584
2555
2585
candidates. iter ( ) . for_each ( |c| {
2556
2586
( if c. accessible { & mut accessible_path_strings } else { & mut inaccessible_path_strings } )
2557
- . push ( ( path_names_to_string ( & c. path ) , c. descr , c. did , & c. note , c. via_import ) )
2587
+ . push ( ( pprust :: path_to_string ( & c. path ) , c. descr , c. did , & c. note , c. via_import ) )
2558
2588
} ) ;
2559
2589
2560
2590
// we want consistent results across executions, but candidates are produced
0 commit comments