@@ -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 }
@@ -1158,6 +1157,7 @@ enum NameBindingKind<'a> {
11581157 used : Cell < bool > ,
11591158 } ,
11601159 Ambiguity {
1160+ kind : AmbiguityKind ,
11611161 b1 : & ' a NameBinding < ' a > ,
11621162 b2 : & ' a NameBinding < ' a > ,
11631163 }
@@ -1175,10 +1175,61 @@ struct UseError<'a> {
11751175 better : bool ,
11761176}
11771177
1178+ #[ derive( Clone , Copy , PartialEq , Debug ) ]
1179+ enum AmbiguityKind {
1180+ Import ,
1181+ BuiltinAttr ,
1182+ DeriveHelper ,
1183+ LegacyHelperVsPrelude ,
1184+ LegacyVsModern ,
1185+ GlobVsOuter ,
1186+ GlobVsGlob ,
1187+ GlobVsExpanded ,
1188+ MoreExpandedVsOuter ,
1189+ }
1190+
1191+ impl AmbiguityKind {
1192+ fn descr ( self ) -> & ' static str {
1193+ match self {
1194+ AmbiguityKind :: Import =>
1195+ "name vs any other name during import resolution" ,
1196+ AmbiguityKind :: BuiltinAttr =>
1197+ "built-in attribute vs any other name" ,
1198+ AmbiguityKind :: DeriveHelper =>
1199+ "derive helper attribute vs any other name" ,
1200+ AmbiguityKind :: LegacyHelperVsPrelude =>
1201+ "legacy plugin helper attribute vs name from prelude" ,
1202+ AmbiguityKind :: LegacyVsModern =>
1203+ "`macro_rules` vs non-`macro_rules` from other module" ,
1204+ AmbiguityKind :: GlobVsOuter =>
1205+ "glob import vs any other name from outer scope during import/macro resolution" ,
1206+ AmbiguityKind :: GlobVsGlob =>
1207+ "glob import vs glob import in the same module" ,
1208+ AmbiguityKind :: GlobVsExpanded =>
1209+ "glob import vs macro-expanded name in the same \
1210+ module during import/macro resolution",
1211+ AmbiguityKind :: MoreExpandedVsOuter =>
1212+ "macro-expanded name vs less macro-expanded name \
1213+ from outer scope during import/macro resolution",
1214+ }
1215+ }
1216+ }
1217+
1218+ /// Miscellaneous bits of metadata for better ambiguity error reporting.
1219+ #[ derive( Clone , Copy , PartialEq ) ]
1220+ enum AmbiguityErrorMisc {
1221+ SuggestSelf ,
1222+ FromPrelude ,
1223+ None ,
1224+ }
1225+
11781226struct AmbiguityError < ' a > {
1227+ kind : AmbiguityKind ,
11791228 ident : Ident ,
11801229 b1 : & ' a NameBinding < ' a > ,
11811230 b2 : & ' a NameBinding < ' a > ,
1231+ misc1 : AmbiguityErrorMisc ,
1232+ misc2 : AmbiguityErrorMisc ,
11821233}
11831234
11841235impl < ' a > NameBinding < ' a > {
@@ -1231,6 +1282,9 @@ impl<'a> NameBinding<'a> {
12311282 subclass : ImportDirectiveSubclass :: ExternCrate { .. } , ..
12321283 } , ..
12331284 } => true ,
1285+ NameBindingKind :: Module (
1286+ & ModuleData { kind : ModuleKind :: Def ( Def :: Mod ( def_id) , _) , .. }
1287+ ) => def_id. index == CRATE_DEF_INDEX ,
12341288 _ => false ,
12351289 }
12361290 }
@@ -1276,6 +1330,10 @@ impl<'a> NameBinding<'a> {
12761330 if self . is_extern_crate ( ) { "extern crate" } else { self . def ( ) . kind_name ( ) }
12771331 }
12781332
1333+ fn article ( & self ) -> & ' static str {
1334+ if self . is_extern_crate ( ) { "an" } else { self . def ( ) . article ( ) }
1335+ }
1336+
12791337 // Suppose that we resolved macro invocation with `invoc_parent_expansion` to binding `binding`
12801338 // at some expansion round `max(invoc, binding)` when they both emerged from macros.
12811339 // Then this function returns `true` if `self` may emerge from a macro *after* that
@@ -1826,8 +1884,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
18261884 self . record_use ( ident, ns, binding)
18271885 }
18281886 NameBindingKind :: Import { .. } => false ,
1829- NameBindingKind :: Ambiguity { b1, b2 } => {
1830- self . ambiguity_errors . push ( AmbiguityError { ident, b1, b2 } ) ;
1887+ NameBindingKind :: Ambiguity { kind, b1, b2 } => {
1888+ self . ambiguity_errors . push ( AmbiguityError {
1889+ kind, ident, b1, b2,
1890+ misc1 : AmbiguityErrorMisc :: None ,
1891+ misc2 : AmbiguityErrorMisc :: None ,
1892+ } ) ;
18311893 true
18321894 }
18331895 _ => false
@@ -1965,7 +2027,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
19652027 }
19662028 if ns == TypeNS && is_known_tool ( ident. name ) {
19672029 let binding = ( Def :: ToolMod , ty:: Visibility :: Public ,
1968- ident . span , Mark :: root ( ) ) . to_name_binding ( self . arenas ) ;
2030+ DUMMY_SP , Mark :: root ( ) ) . to_name_binding ( self . arenas ) ;
19692031 return Some ( LexicalScopeBinding :: Item ( binding) ) ;
19702032 }
19712033 if let Some ( prelude) = self . prelude {
@@ -4565,37 +4627,79 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
45654627 }
45664628 }
45674629
4568- fn report_ambiguity_error ( & self , ident : Ident , b1 : & NameBinding , b2 : & NameBinding ) {
4569- let participle = |is_import : bool | if is_import { "imported" } else { "defined" } ;
4570- let msg1 =
4571- format ! ( "`{}` could refer to the name {} here" , ident, participle( b1. is_import( ) ) ) ;
4572- let msg2 =
4573- format ! ( "`{}` could also refer to the name {} here" , ident, participle( b2. is_import( ) ) ) ;
4574- let note = if b1. expansion != Mark :: root ( ) {
4575- Some ( if let Def :: Macro ( ..) = b1. def ( ) {
4576- format ! ( "macro-expanded {} do not shadow" ,
4577- if b1. is_import( ) { "macro imports" } else { "macros" } )
4578- } else {
4579- format ! ( "macro-expanded {} do not shadow when used in a macro invocation path" ,
4580- if b1. is_import( ) { "imports" } else { "items" } )
4581- } )
4582- } else if b1. is_glob_import ( ) {
4583- Some ( format ! ( "consider adding an explicit import of `{}` to disambiguate" , ident) )
4630+ fn report_ambiguity_error ( & self , ambiguity_error : & AmbiguityError ) {
4631+ let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = * ambiguity_error;
4632+ let ( b1, b2, misc1, misc2, swapped) = if b2. span . is_dummy ( ) && !b1. span . is_dummy ( ) {
4633+ // We have to print the span-less alternative first, otherwise formatting looks bad.
4634+ ( b2, b1, misc2, misc1, true )
45844635 } else {
4585- None
4636+ ( b1 , b2 , misc1 , misc2 , false )
45864637 } ;
45874638
4588- let mut err = struct_span_err ! ( self . session, ident. span, E0659 , "`{}` is ambiguous" , ident) ;
4639+ let mut err = struct_span_err ! ( self . session, ident. span, E0659 ,
4640+ "`{ident}` is ambiguous ({why})" ,
4641+ ident = ident, why = kind. descr( ) ) ;
45894642 err. span_label ( ident. span , "ambiguous name" ) ;
4590- err. span_note ( b1. span , & msg1) ;
4591- match b2. def ( ) {
4592- Def :: Macro ( ..) if b2. span . is_dummy ( ) =>
4593- err. note ( & format ! ( "`{}` is also a builtin macro" , ident) ) ,
4594- _ => err. span_note ( b2. span , & msg2) ,
4643+
4644+ let mut could_refer_to = |b : & NameBinding , misc : AmbiguityErrorMisc , also : & str | {
4645+ let what = if b. span . is_dummy ( ) {
4646+ let add_built_in = match b. def ( ) {
4647+ // These already contain the "built-in" prefix or look bad with it.
4648+ Def :: NonMacroAttr ( ..) | Def :: PrimTy ( ..) | Def :: ToolMod => false ,
4649+ _ => true ,
4650+ } ;
4651+ let ( built_in, from) = if misc == AmbiguityErrorMisc :: FromPrelude {
4652+ ( "" , " from prelude" )
4653+ } else if b. is_extern_crate ( ) && !b. is_import ( ) &&
4654+ self . session . opts . externs . get ( & ident. as_str ( ) ) . is_some ( ) {
4655+ ( "" , " passed with `--extern`" )
4656+ } else if add_built_in {
4657+ ( " built-in" , "" )
4658+ } else {
4659+ ( "" , "" )
4660+ } ;
4661+
4662+ let article = if built_in. is_empty ( ) { b. article ( ) } else { "a" } ;
4663+ format ! ( "{a}{built_in} {thing}{from}" ,
4664+ a = article, thing = b. descr( ) , built_in = built_in, from = from)
4665+ } else {
4666+ let participle = if b. is_import ( ) { "imported" } else { "defined" } ;
4667+ format ! ( "the {thing} {introduced} here" ,
4668+ thing = b. descr( ) , introduced = participle)
4669+ } ;
4670+ let note_msg = format ! ( "`{ident}` could{also} refer to {what}" ,
4671+ ident = ident, also = also, what = what) ;
4672+
4673+ let mut help_msgs = Vec :: new ( ) ;
4674+ if b. is_glob_import ( ) && ( kind == AmbiguityKind :: GlobVsGlob ||
4675+ kind == AmbiguityKind :: GlobVsExpanded ||
4676+ kind == AmbiguityKind :: GlobVsOuter &&
4677+ swapped != also. is_empty ( ) ) {
4678+ help_msgs. push ( format ! ( "consider adding an explicit import of \
4679+ `{ident}` to disambiguate", ident = ident) )
4680+ }
4681+ if b. is_extern_crate ( ) && self . session . rust_2018 ( ) {
4682+ help_msgs. push ( format ! ( "use `::{ident}` to refer to the {thing} unambiguously" ,
4683+ ident = ident, thing = b. descr( ) ) )
4684+ }
4685+ if misc == AmbiguityErrorMisc :: SuggestSelf {
4686+ help_msgs. push ( format ! ( "use `self::{ident}` to refer to the {thing} unambiguously" ,
4687+ ident = ident, thing = b. descr( ) ) )
4688+ }
4689+
4690+ if b. span . is_dummy ( ) {
4691+ err. note ( & note_msg) ;
4692+ } else {
4693+ err. span_note ( b. span , & note_msg) ;
4694+ }
4695+ for ( i, help_msg) in help_msgs. iter ( ) . enumerate ( ) {
4696+ let or = if i == 0 { "" } else { "or " } ;
4697+ err. help ( & format ! ( "{}{}" , or, help_msg) ) ;
4698+ }
45954699 } ;
4596- if let Some ( note ) = note {
4597- err . note ( & note ) ;
4598- }
4700+
4701+ could_refer_to ( b1 , misc1 , "" ) ;
4702+ could_refer_to ( b2 , misc2 , " also" ) ;
45994703 err. emit ( ) ;
46004704 }
46014705
@@ -4614,9 +4718,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
46144718 ) ;
46154719 }
46164720
4617- for & AmbiguityError { ident , b1 , b2 } in & self . ambiguity_errors {
4618- if reported_spans. insert ( ident. span ) {
4619- self . report_ambiguity_error ( ident , b1 , b2 ) ;
4721+ for ambiguity_error in & self . ambiguity_errors {
4722+ if reported_spans. insert ( ambiguity_error . ident . span ) {
4723+ self . report_ambiguity_error ( ambiguity_error ) ;
46204724 }
46214725 }
46224726
@@ -4794,7 +4898,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
47944898 } ;
47954899 let crate_root = self . get_module ( DefId { krate : crate_id, index : CRATE_DEF_INDEX } ) ;
47964900 self . populate_module_if_necessary ( & crate_root) ;
4797- Some ( ( crate_root, ty:: Visibility :: Public , ident . span , Mark :: root ( ) )
4901+ Some ( ( crate_root, ty:: Visibility :: Public , DUMMY_SP , Mark :: root ( ) )
47984902 . to_name_binding ( self . arenas ) )
47994903 }
48004904 } )
0 commit comments