@@ -391,14 +391,13 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
391
391
err
392
392
}
393
393
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) ) ;
400
399
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) ;
402
401
err. span_label ( binding. span , msg) ;
403
402
err
404
403
}
@@ -1195,6 +1194,7 @@ enum NameBindingKind<'a> {
1195
1194
used : Cell < bool > ,
1196
1195
} ,
1197
1196
Ambiguity {
1197
+ kind : AmbiguityKind ,
1198
1198
b1 : & ' a NameBinding < ' a > ,
1199
1199
b2 : & ' a NameBinding < ' a > ,
1200
1200
}
@@ -1212,10 +1212,61 @@ struct UseError<'a> {
1212
1212
better : bool ,
1213
1213
}
1214
1214
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
+
1215
1263
struct AmbiguityError < ' a > {
1264
+ kind : AmbiguityKind ,
1216
1265
ident : Ident ,
1217
1266
b1 : & ' a NameBinding < ' a > ,
1218
1267
b2 : & ' a NameBinding < ' a > ,
1268
+ misc1 : AmbiguityErrorMisc ,
1269
+ misc2 : AmbiguityErrorMisc ,
1219
1270
}
1220
1271
1221
1272
impl < ' a > NameBinding < ' a > {
@@ -1268,6 +1319,9 @@ impl<'a> NameBinding<'a> {
1268
1319
subclass : ImportDirectiveSubclass :: ExternCrate { .. } , ..
1269
1320
} , ..
1270
1321
} => true ,
1322
+ NameBindingKind :: Module (
1323
+ & ModuleData { kind : ModuleKind :: Def ( Def :: Mod ( def_id) , _) , .. }
1324
+ ) => def_id. index == CRATE_DEF_INDEX ,
1271
1325
_ => false ,
1272
1326
}
1273
1327
}
@@ -1313,6 +1367,10 @@ impl<'a> NameBinding<'a> {
1313
1367
if self . is_extern_crate ( ) { "extern crate" } else { self . def ( ) . kind_name ( ) }
1314
1368
}
1315
1369
1370
+ fn article ( & self ) -> & ' static str {
1371
+ if self . is_extern_crate ( ) { "an" } else { self . def ( ) . article ( ) }
1372
+ }
1373
+
1316
1374
// Suppose that we resolved macro invocation with `invoc_parent_expansion` to binding `binding`
1317
1375
// at some expansion round `max(invoc, binding)` when they both emerged from macros.
1318
1376
// 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> {
1885
1943
self . record_use ( ident, ns, binding)
1886
1944
}
1887
1945
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
+ } ) ;
1890
1952
true
1891
1953
}
1892
1954
_ => false
@@ -2024,7 +2086,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
2024
2086
}
2025
2087
if ns == TypeNS && is_known_tool ( ident. name ) {
2026
2088
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 ) ;
2028
2090
return Some ( LexicalScopeBinding :: Item ( binding) ) ;
2029
2091
}
2030
2092
if let Some ( prelude) = self . prelude {
@@ -4631,37 +4693,79 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
4631
4693
}
4632
4694
}
4633
4695
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 )
4650
4701
} else {
4651
- None
4702
+ ( b1 , b2 , misc1 , misc2 , false )
4652
4703
} ;
4653
4704
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( ) ) ;
4655
4708
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
+ }
4661
4765
} ;
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" ) ;
4665
4769
err. emit ( ) ;
4666
4770
}
4667
4771
@@ -4680,9 +4784,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
4680
4784
) ;
4681
4785
}
4682
4786
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 ) ;
4686
4790
}
4687
4791
}
4688
4792
@@ -4860,7 +4964,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
4860
4964
} ;
4861
4965
let crate_root = self . get_module ( DefId { krate : crate_id, index : CRATE_DEF_INDEX } ) ;
4862
4966
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 ( ) )
4864
4968
. to_name_binding ( self . arenas ) )
4865
4969
}
4866
4970
} )
0 commit comments