@@ -391,14 +391,13 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
391391 err
392392 }
393393 ResolutionError :: BindingShadowsSomethingUnacceptable ( what_binding, name, binding) => {
394- let shadows_what = PathResolution :: new ( binding. def ( ) ) . kind_name ( ) ;
395- let mut err = struct_span_err ! ( resolver. session,
396- span,
397- E0530 ,
398- "{}s cannot shadow {}s" , what_binding, shadows_what) ;
399- err. span_label ( span, format ! ( "cannot be named the same as a {}" , shadows_what) ) ;
394+ let ( shadows_what, article) = ( binding. descr ( ) , binding. article ( ) ) ;
395+ let mut err = struct_span_err ! ( resolver. session, span, E0530 , "{}s cannot shadow {}s" ,
396+ what_binding, shadows_what) ;
397+ err. span_label ( span, format ! ( "cannot be named the same as {} {}" ,
398+ article, shadows_what) ) ;
400399 let participle = if binding. is_import ( ) { "imported" } else { "defined" } ;
401- let msg = format ! ( "a {} `{}` is {} here" , shadows_what, name, participle) ;
400+ let msg = format ! ( "{} {} `{}` is {} here" , article , shadows_what, name, participle) ;
402401 err. span_label ( binding. span , msg) ;
403402 err
404403 }
@@ -1195,6 +1194,7 @@ enum NameBindingKind<'a> {
11951194 used : Cell < bool > ,
11961195 } ,
11971196 Ambiguity {
1197+ kind : AmbiguityKind ,
11981198 b1 : & ' a NameBinding < ' a > ,
11991199 b2 : & ' a NameBinding < ' a > ,
12001200 }
@@ -1212,10 +1212,61 @@ struct UseError<'a> {
12121212 better : bool ,
12131213}
12141214
1215+ #[ derive( Clone , Copy , PartialEq , Debug ) ]
1216+ enum AmbiguityKind {
1217+ Import ,
1218+ BuiltinAttr ,
1219+ DeriveHelper ,
1220+ LegacyHelperVsPrelude ,
1221+ LegacyVsModern ,
1222+ GlobVsOuter ,
1223+ GlobVsGlob ,
1224+ GlobVsExpanded ,
1225+ MoreExpandedVsOuter ,
1226+ }
1227+
1228+ impl AmbiguityKind {
1229+ fn descr ( self ) -> & ' static str {
1230+ match self {
1231+ AmbiguityKind :: Import =>
1232+ "name vs any other name during import resolution" ,
1233+ AmbiguityKind :: BuiltinAttr =>
1234+ "built-in attribute vs any other name" ,
1235+ AmbiguityKind :: DeriveHelper =>
1236+ "derive helper attribute vs any other name" ,
1237+ AmbiguityKind :: LegacyHelperVsPrelude =>
1238+ "legacy plugin helper attribute vs name from prelude" ,
1239+ AmbiguityKind :: LegacyVsModern =>
1240+ "`macro_rules` vs non-`macro_rules` from other module" ,
1241+ AmbiguityKind :: GlobVsOuter =>
1242+ "glob import vs any other name from outer scope during import/macro resolution" ,
1243+ AmbiguityKind :: GlobVsGlob =>
1244+ "glob import vs glob import in the same module" ,
1245+ AmbiguityKind :: GlobVsExpanded =>
1246+ "glob import vs macro-expanded name in the same \
1247+ module during import/macro resolution",
1248+ AmbiguityKind :: MoreExpandedVsOuter =>
1249+ "macro-expanded name vs less macro-expanded name \
1250+ from outer scope during import/macro resolution",
1251+ }
1252+ }
1253+ }
1254+
1255+ /// Miscellaneous bits of metadata for better ambiguity error reporting.
1256+ #[ derive( Clone , Copy , PartialEq ) ]
1257+ enum AmbiguityErrorMisc {
1258+ SuggestSelf ,
1259+ FromPrelude ,
1260+ None ,
1261+ }
1262+
12151263struct AmbiguityError < ' a > {
1264+ kind : AmbiguityKind ,
12161265 ident : Ident ,
12171266 b1 : & ' a NameBinding < ' a > ,
12181267 b2 : & ' a NameBinding < ' a > ,
1268+ misc1 : AmbiguityErrorMisc ,
1269+ misc2 : AmbiguityErrorMisc ,
12191270}
12201271
12211272impl < ' a > NameBinding < ' a > {
@@ -1268,6 +1319,9 @@ impl<'a> NameBinding<'a> {
12681319 subclass : ImportDirectiveSubclass :: ExternCrate { .. } , ..
12691320 } , ..
12701321 } => true ,
1322+ NameBindingKind :: Module (
1323+ & ModuleData { kind : ModuleKind :: Def ( Def :: Mod ( def_id) , _) , .. }
1324+ ) => def_id. index == CRATE_DEF_INDEX ,
12711325 _ => false ,
12721326 }
12731327 }
@@ -1313,6 +1367,10 @@ impl<'a> NameBinding<'a> {
13131367 if self . is_extern_crate ( ) { "extern crate" } else { self . def ( ) . kind_name ( ) }
13141368 }
13151369
1370+ fn article ( & self ) -> & ' static str {
1371+ if self . is_extern_crate ( ) { "an" } else { self . def ( ) . article ( ) }
1372+ }
1373+
13161374 // Suppose that we resolved macro invocation with `invoc_parent_expansion` to binding `binding`
13171375 // at some expansion round `max(invoc, binding)` when they both emerged from macros.
13181376 // Then this function returns `true` if `self` may emerge from a macro *after* that
@@ -1885,8 +1943,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
18851943 self . record_use ( ident, ns, binding)
18861944 }
18871945 NameBindingKind :: Import { .. } => false ,
1888- NameBindingKind :: Ambiguity { b1, b2 } => {
1889- self . ambiguity_errors . push ( AmbiguityError { ident, b1, b2 } ) ;
1946+ NameBindingKind :: Ambiguity { kind, b1, b2 } => {
1947+ self . ambiguity_errors . push ( AmbiguityError {
1948+ kind, ident, b1, b2,
1949+ misc1 : AmbiguityErrorMisc :: None ,
1950+ misc2 : AmbiguityErrorMisc :: None ,
1951+ } ) ;
18901952 true
18911953 }
18921954 _ => false
@@ -2024,7 +2086,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
20242086 }
20252087 if ns == TypeNS && is_known_tool ( ident. name ) {
20262088 let binding = ( Def :: ToolMod , ty:: Visibility :: Public ,
2027- ident . span , Mark :: root ( ) ) . to_name_binding ( self . arenas ) ;
2089+ DUMMY_SP , Mark :: root ( ) ) . to_name_binding ( self . arenas ) ;
20282090 return Some ( LexicalScopeBinding :: Item ( binding) ) ;
20292091 }
20302092 if let Some ( prelude) = self . prelude {
@@ -4631,37 +4693,79 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
46314693 }
46324694 }
46334695
4634- fn report_ambiguity_error ( & self , ident : Ident , b1 : & NameBinding , b2 : & NameBinding ) {
4635- let participle = |is_import : bool | if is_import { "imported" } else { "defined" } ;
4636- let msg1 =
4637- format ! ( "`{}` could refer to the name {} here" , ident, participle( b1. is_import( ) ) ) ;
4638- let msg2 =
4639- format ! ( "`{}` could also refer to the name {} here" , ident, participle( b2. is_import( ) ) ) ;
4640- let note = if b1. expansion != Mark :: root ( ) {
4641- Some ( if let Def :: Macro ( ..) = b1. def ( ) {
4642- format ! ( "macro-expanded {} do not shadow" ,
4643- if b1. is_import( ) { "macro imports" } else { "macros" } )
4644- } else {
4645- format ! ( "macro-expanded {} do not shadow when used in a macro invocation path" ,
4646- if b1. is_import( ) { "imports" } else { "items" } )
4647- } )
4648- } else if b1. is_glob_import ( ) {
4649- Some ( format ! ( "consider adding an explicit import of `{}` to disambiguate" , ident) )
4696+ fn report_ambiguity_error ( & self , ambiguity_error : & AmbiguityError ) {
4697+ let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = * ambiguity_error;
4698+ let ( b1, b2, misc1, misc2, swapped) = if b2. span . is_dummy ( ) && !b1. span . is_dummy ( ) {
4699+ // We have to print the span-less alternative first, otherwise formatting looks bad.
4700+ ( b2, b1, misc2, misc1, true )
46504701 } else {
4651- None
4702+ ( b1 , b2 , misc1 , misc2 , false )
46524703 } ;
46534704
4654- let mut err = struct_span_err ! ( self . session, ident. span, E0659 , "`{}` is ambiguous" , ident) ;
4705+ let mut err = struct_span_err ! ( self . session, ident. span, E0659 ,
4706+ "`{ident}` is ambiguous ({why})" ,
4707+ ident = ident, why = kind. descr( ) ) ;
46554708 err. span_label ( ident. span , "ambiguous name" ) ;
4656- err. span_note ( b1. span , & msg1) ;
4657- match b2. def ( ) {
4658- Def :: Macro ( ..) if b2. span . is_dummy ( ) =>
4659- err. note ( & format ! ( "`{}` is also a builtin macro" , ident) ) ,
4660- _ => err. span_note ( b2. span , & msg2) ,
4709+
4710+ let mut could_refer_to = |b : & NameBinding , misc : AmbiguityErrorMisc , also : & str | {
4711+ let what = if b. span . is_dummy ( ) {
4712+ let add_built_in = match b. def ( ) {
4713+ // These already contain the "built-in" prefix or look bad with it.
4714+ Def :: NonMacroAttr ( ..) | Def :: PrimTy ( ..) | Def :: ToolMod => false ,
4715+ _ => true ,
4716+ } ;
4717+ let ( built_in, from) = if misc == AmbiguityErrorMisc :: FromPrelude {
4718+ ( "" , " from prelude" )
4719+ } else if b. is_extern_crate ( ) && !b. is_import ( ) &&
4720+ self . session . opts . externs . get ( & ident. as_str ( ) ) . is_some ( ) {
4721+ ( "" , " passed with `--extern`" )
4722+ } else if add_built_in {
4723+ ( " built-in" , "" )
4724+ } else {
4725+ ( "" , "" )
4726+ } ;
4727+
4728+ let article = if built_in. is_empty ( ) { b. article ( ) } else { "a" } ;
4729+ format ! ( "{a}{built_in} {thing}{from}" ,
4730+ a = article, thing = b. descr( ) , built_in = built_in, from = from)
4731+ } else {
4732+ let participle = if b. is_import ( ) { "imported" } else { "defined" } ;
4733+ format ! ( "the {thing} {introduced} here" ,
4734+ thing = b. descr( ) , introduced = participle)
4735+ } ;
4736+ let note_msg = format ! ( "`{ident}` could{also} refer to {what}" ,
4737+ ident = ident, also = also, what = what) ;
4738+
4739+ let mut help_msgs = Vec :: new ( ) ;
4740+ if b. is_glob_import ( ) && ( kind == AmbiguityKind :: GlobVsGlob ||
4741+ kind == AmbiguityKind :: GlobVsExpanded ||
4742+ kind == AmbiguityKind :: GlobVsOuter &&
4743+ swapped != also. is_empty ( ) ) {
4744+ help_msgs. push ( format ! ( "consider adding an explicit import of \
4745+ `{ident}` to disambiguate", ident = ident) )
4746+ }
4747+ if b. is_extern_crate ( ) && self . session . rust_2018 ( ) {
4748+ help_msgs. push ( format ! ( "use `::{ident}` to refer to the {thing} unambiguously" ,
4749+ ident = ident, thing = b. descr( ) ) )
4750+ }
4751+ if misc == AmbiguityErrorMisc :: SuggestSelf {
4752+ help_msgs. push ( format ! ( "use `self::{ident}` to refer to the {thing} unambiguously" ,
4753+ ident = ident, thing = b. descr( ) ) )
4754+ }
4755+
4756+ if b. span . is_dummy ( ) {
4757+ err. note ( & note_msg) ;
4758+ } else {
4759+ err. span_note ( b. span , & note_msg) ;
4760+ }
4761+ for ( i, help_msg) in help_msgs. iter ( ) . enumerate ( ) {
4762+ let or = if i == 0 { "" } else { "or " } ;
4763+ err. help ( & format ! ( "{}{}" , or, help_msg) ) ;
4764+ }
46614765 } ;
4662- if let Some ( note ) = note {
4663- err . note ( & note ) ;
4664- }
4766+
4767+ could_refer_to ( b1 , misc1 , "" ) ;
4768+ could_refer_to ( b2 , misc2 , " also" ) ;
46654769 err. emit ( ) ;
46664770 }
46674771
@@ -4680,9 +4784,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
46804784 ) ;
46814785 }
46824786
4683- for & AmbiguityError { ident , b1 , b2 } in & self . ambiguity_errors {
4684- if reported_spans. insert ( ident. span ) {
4685- self . report_ambiguity_error ( ident , b1 , b2 ) ;
4787+ for ambiguity_error in & self . ambiguity_errors {
4788+ if reported_spans. insert ( ambiguity_error . ident . span ) {
4789+ self . report_ambiguity_error ( ambiguity_error ) ;
46864790 }
46874791 }
46884792
@@ -4860,7 +4964,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
48604964 } ;
48614965 let crate_root = self . get_module ( DefId { krate : crate_id, index : CRATE_DEF_INDEX } ) ;
48624966 self . populate_module_if_necessary ( & crate_root) ;
4863- Some ( ( crate_root, ty:: Visibility :: Public , ident . span , Mark :: root ( ) )
4967+ Some ( ( crate_root, ty:: Visibility :: Public , DUMMY_SP , Mark :: root ( ) )
48644968 . to_name_binding ( self . arenas ) )
48654969 }
48664970 } )
0 commit comments