@@ -44,7 +44,7 @@ use crate::errors::{
4444use crate :: imports:: { Import , ImportKind } ;
4545use crate :: late:: { DiagMetadata , PatternSource , Rib } ;
4646use crate :: {
47- AmbiguityError , AmbiguityErrorMisc , AmbiguityKind , BindingError , BindingKey , Finalize ,
47+ AmbiguityError , AmbiguityKind , BindingError , BindingKey , Finalize ,
4848 ForwardGenericParamBanReason , HasGenericParams , LexicalScopeBinding , MacroRulesScope , Module ,
4949 ModuleKind , ModuleOrUniformRoot , NameBinding , NameBindingKind , ParentScope , PathResult ,
5050 PrivacyError , ResolutionError , Resolver , Scope , ScopeSet , Segment , UseError , Used ,
@@ -1968,23 +1968,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
19681968 true
19691969 }
19701970
1971- fn binding_description ( & self , b : NameBinding < ' _ > , ident : Ident , from_prelude : bool ) -> String {
1971+ fn binding_description ( & self , b : NameBinding < ' _ > , ident : Ident , scope : Scope < ' _ > ) -> String {
19721972 let res = b. res ( ) ;
19731973 if b. span . is_dummy ( ) || !self . tcx . sess . source_map ( ) . is_span_accessible ( b. span ) {
1974- // These already contain the "built-in" prefix or look bad with it.
1975- let add_built_in =
1976- !matches ! ( b. res( ) , Res :: NonMacroAttr ( ..) | Res :: PrimTy ( ..) | Res :: ToolMod ) ;
1977- let ( built_in, from) = if from_prelude {
1978- ( "" , " from prelude" )
1979- } else if b. is_extern_crate ( )
1980- && !b. is_import ( )
1981- && self . tcx . sess . opts . externs . get ( ident. as_str ( ) ) . is_some ( )
1982- {
1983- ( "" , " passed with `--extern`" )
1984- } else if add_built_in {
1985- ( " built-in" , "" )
1986- } else {
1987- ( "" , "" )
1974+ let ( built_in, from) = match scope {
1975+ Scope :: StdLibPrelude | Scope :: MacroUsePrelude => ( "" , " from prelude" ) ,
1976+ Scope :: ExternPreludeFlags
1977+ if self . tcx . sess . opts . externs . get ( ident. as_str ( ) ) . is_some ( ) =>
1978+ {
1979+ ( "" , " passed with `--extern`" )
1980+ }
1981+ _ => {
1982+ if matches ! ( res, Res :: NonMacroAttr ( ..) | Res :: PrimTy ( ..) | Res :: ToolMod ) {
1983+ // These already contain the "built-in" prefix or look bad with it.
1984+ ( "" , "" )
1985+ } else {
1986+ ( " built-in" , "" )
1987+ }
1988+ }
19881989 } ;
19891990
19901991 let a = if built_in. is_empty ( ) { res. article ( ) } else { "a" } ;
@@ -1996,22 +1997,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
19961997 }
19971998
19981999 fn ambiguity_diagnostic ( & self , ambiguity_error : & AmbiguityError < ' ra > ) -> errors:: Ambiguity {
1999- let AmbiguityError { kind, ident, b1, b2, misc1 , misc2 , .. } = * ambiguity_error;
2000+ let AmbiguityError { kind, ident, b1, b2, scope1 , scope2 , .. } = * ambiguity_error;
20002001 let extern_prelude_ambiguity = || {
2001- self . extern_prelude . get ( & Macros20NormalizedIdent :: new ( ident) ) . is_some_and ( |entry| {
2002- entry. item_binding . map ( |( b, _) | b) == Some ( b1)
2003- && entry. flag_binding . as_ref ( ) . and_then ( |pb| pb. get ( ) . 0 . binding ( ) ) == Some ( b2)
2004- } )
2002+ // Note: b1 may come from a module scope, as an extern crate item in module.
2003+ matches ! ( scope2, Scope :: ExternPreludeFlags )
2004+ && self
2005+ . extern_prelude
2006+ . get ( & Macros20NormalizedIdent :: new ( ident) )
2007+ . is_some_and ( |entry| entry. item_binding . map ( |( b, _) | b) == Some ( b1) )
20052008 } ;
2006- let ( b1, b2, misc1 , misc2 , swapped) = if b2. span . is_dummy ( ) && !b1. span . is_dummy ( ) {
2009+ let ( b1, b2, scope1 , scope2 , swapped) = if b2. span . is_dummy ( ) && !b1. span . is_dummy ( ) {
20072010 // We have to print the span-less alternative first, otherwise formatting looks bad.
2008- ( b2, b1, misc2 , misc1 , true )
2011+ ( b2, b1, scope2 , scope1 , true )
20092012 } else {
2010- ( b1, b2, misc1 , misc2 , false )
2013+ ( b1, b2, scope1 , scope2 , false )
20112014 } ;
20122015
2013- let could_refer_to = |b : NameBinding < ' _ > , misc : AmbiguityErrorMisc , also : & str | {
2014- let what = self . binding_description ( b, ident, misc == AmbiguityErrorMisc :: FromPrelude ) ;
2016+ let could_refer_to = |b : NameBinding < ' _ > , scope : Scope < ' ra > , also : & str | {
2017+ let what = self . binding_description ( b, ident, scope ) ;
20152018 let note_msg = format ! ( "`{ident}` could{also} refer to {what}" ) ;
20162019
20172020 let thing = b. res ( ) . descr ( ) ;
@@ -2029,12 +2032,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
20292032 {
20302033 help_msgs. push ( format ! ( "use `::{ident}` to refer to this {thing} unambiguously" ) )
20312034 }
2032- match misc {
2033- AmbiguityErrorMisc :: SuggestCrate => help_msgs
2034- . push ( format ! ( "use `crate::{ident}` to refer to this {thing} unambiguously" ) ) ,
2035- AmbiguityErrorMisc :: SuggestSelf => help_msgs
2036- . push ( format ! ( "use `self::{ident}` to refer to this {thing} unambiguously" ) ) ,
2037- AmbiguityErrorMisc :: FromPrelude | AmbiguityErrorMisc :: None => { }
2035+
2036+ if let Scope :: Module ( module, _) = scope {
2037+ if module == self . graph_root {
2038+ help_msgs. push ( format ! (
2039+ "use `crate::{ident}` to refer to this {thing} unambiguously"
2040+ ) ) ;
2041+ } else if module != self . empty_module && module. is_normal ( ) {
2042+ help_msgs. push ( format ! (
2043+ "use `self::{ident}` to refer to this {thing} unambiguously"
2044+ ) ) ;
2045+ }
20382046 }
20392047
20402048 (
@@ -2049,8 +2057,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
20492057 . collect :: < Vec < _ > > ( ) ,
20502058 )
20512059 } ;
2052- let ( b1_note, b1_help_msgs) = could_refer_to ( b1, misc1 , "" ) ;
2053- let ( b2_note, b2_help_msgs) = could_refer_to ( b2, misc2 , " also" ) ;
2060+ let ( b1_note, b1_help_msgs) = could_refer_to ( b1, scope1 , "" ) ;
2061+ let ( b2_note, b2_help_msgs) = could_refer_to ( b2, scope2 , " also" ) ;
20542062
20552063 errors:: Ambiguity {
20562064 ident,
0 commit comments