@@ -25,7 +25,7 @@ use rustc_span::hygiene::MacroKind;
2525use rustc_span:: source_map:: SourceMap ;
2626use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
2727use rustc_span:: { BytePos , Span , SyntaxContext } ;
28- use thin_vec:: ThinVec ;
28+ use thin_vec:: { thin_vec , ThinVec } ;
2929
3030use crate :: errors:: {
3131 AddedMacroUse , ChangeImportBinding , ChangeImportBindingSuggestion , ConsiderAddingADerive ,
@@ -1147,7 +1147,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
11471147 namespace : Namespace ,
11481148 parent_scope : & ParentScope < ' a > ,
11491149 start_module : Module < ' a > ,
1150- crate_name : Ident ,
1150+ crate_path : ThinVec < ast :: PathSegment > ,
11511151 filter_fn : FilterFn ,
11521152 ) -> Vec < ImportSuggestion >
11531153 where
@@ -1163,8 +1163,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
11631163 Some ( x) => Some ( x) ,
11641164 } {
11651165 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).
11681166 in_module. for_each_child ( self , |this, ident, ns, name_binding| {
11691167 // avoid non-importable candidates
11701168 if !name_binding. is_importable ( ) {
@@ -1214,12 +1212,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12141212 let res = name_binding. res ( ) ;
12151213 if filter_fn ( res) {
12161214 // 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 ( ) {
12191216 // crate-local absolute paths start with `crate::` in edition 2018
12201217 // 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 ( ) ) ;
12231223
12241224 segms. push ( ast:: PathSegment :: from_ident ( ident) ) ;
12251225 let path = Path { span : name_binding. span , segments : segms, tokens : None } ;
@@ -1318,18 +1318,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13181318 where
13191319 FilterFn : Fn ( Res ) -> bool ,
13201320 {
1321+ let crate_path = thin_vec ! [ ast:: PathSegment :: from_ident( Ident :: with_dummy_span( kw:: Crate ) ) ] ;
13211322 let mut suggestions = self . lookup_import_candidates_from_module (
13221323 lookup_ident,
13231324 namespace,
13241325 parent_scope,
13251326 self . graph_root ,
1326- Ident :: with_dummy_span ( kw :: Crate ) ,
1327+ crate_path ,
13271328 & filter_fn,
13281329 ) ;
13291330
13301331 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 ( ) {
13331333 if ident. span . from_expansion ( ) {
13341334 // Idents are adjusted to the root context before being
13351335 // resolved in the extern prelude, so reporting this to the
@@ -1340,13 +1340,43 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13401340 }
13411341 let crate_id = self . crate_loader ( |c| c. maybe_process_path_extern ( ident. name ) ) ;
13421342 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) if def_id != crate_def_id => true ,
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+
13441374 suggestions. extend ( self . lookup_import_candidates_from_module (
13451375 lookup_ident,
13461376 namespace,
13471377 parent_scope,
13481378 crate_root,
1349- ident ,
1379+ crate_path ,
13501380 & filter_fn,
13511381 ) ) ;
13521382 }
@@ -2541,7 +2571,7 @@ fn show_candidates(
25412571
25422572 candidates. iter ( ) . for_each ( |c| {
25432573 ( if c. accessible { & mut accessible_path_strings } else { & mut inaccessible_path_strings } )
2544- . push ( ( path_names_to_string ( & c. path ) , c. descr , c. did , & c. note , c. via_import ) )
2574+ . push ( ( pprust :: path_to_string ( & c. path ) , c. descr , c. did , & c. note , c. via_import ) )
25452575 } ) ;
25462576
25472577 // we want consistent results across executions, but candidates are produced
0 commit comments