@@ -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
}
@@ -1158,6 +1157,7 @@ enum NameBindingKind<'a> {
1158
1157
used : Cell < bool > ,
1159
1158
} ,
1160
1159
Ambiguity {
1160
+ kind : AmbiguityKind ,
1161
1161
b1 : & ' a NameBinding < ' a > ,
1162
1162
b2 : & ' a NameBinding < ' a > ,
1163
1163
}
@@ -1175,10 +1175,61 @@ struct UseError<'a> {
1175
1175
better : bool ,
1176
1176
}
1177
1177
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
+
1178
1226
struct AmbiguityError < ' a > {
1227
+ kind : AmbiguityKind ,
1179
1228
ident : Ident ,
1180
1229
b1 : & ' a NameBinding < ' a > ,
1181
1230
b2 : & ' a NameBinding < ' a > ,
1231
+ misc1 : AmbiguityErrorMisc ,
1232
+ misc2 : AmbiguityErrorMisc ,
1182
1233
}
1183
1234
1184
1235
impl < ' a > NameBinding < ' a > {
@@ -1231,6 +1282,9 @@ impl<'a> NameBinding<'a> {
1231
1282
subclass : ImportDirectiveSubclass :: ExternCrate { .. } , ..
1232
1283
} , ..
1233
1284
} => true ,
1285
+ NameBindingKind :: Module (
1286
+ & ModuleData { kind : ModuleKind :: Def ( Def :: Mod ( def_id) , _) , .. }
1287
+ ) => def_id. index == CRATE_DEF_INDEX ,
1234
1288
_ => false ,
1235
1289
}
1236
1290
}
@@ -1276,6 +1330,10 @@ impl<'a> NameBinding<'a> {
1276
1330
if self . is_extern_crate ( ) { "extern crate" } else { self . def ( ) . kind_name ( ) }
1277
1331
}
1278
1332
1333
+ fn article ( & self ) -> & ' static str {
1334
+ if self . is_extern_crate ( ) { "an" } else { self . def ( ) . article ( ) }
1335
+ }
1336
+
1279
1337
// Suppose that we resolved macro invocation with `invoc_parent_expansion` to binding `binding`
1280
1338
// at some expansion round `max(invoc, binding)` when they both emerged from macros.
1281
1339
// 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> {
1826
1884
self . record_use ( ident, ns, binding)
1827
1885
}
1828
1886
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
+ } ) ;
1831
1893
true
1832
1894
}
1833
1895
_ => false
@@ -1965,7 +2027,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
1965
2027
}
1966
2028
if ns == TypeNS && is_known_tool ( ident. name ) {
1967
2029
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 ) ;
1969
2031
return Some ( LexicalScopeBinding :: Item ( binding) ) ;
1970
2032
}
1971
2033
if let Some ( prelude) = self . prelude {
@@ -4565,37 +4627,79 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
4565
4627
}
4566
4628
}
4567
4629
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 )
4584
4635
} else {
4585
- None
4636
+ ( b1 , b2 , misc1 , misc2 , false )
4586
4637
} ;
4587
4638
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( ) ) ;
4589
4642
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
+ }
4595
4699
} ;
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" ) ;
4599
4703
err. emit ( ) ;
4600
4704
}
4601
4705
@@ -4614,9 +4718,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
4614
4718
) ;
4615
4719
}
4616
4720
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 ) ;
4620
4724
}
4621
4725
}
4622
4726
@@ -4794,7 +4898,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
4794
4898
} ;
4795
4899
let crate_root = self . get_module ( DefId { krate : crate_id, index : CRATE_DEF_INDEX } ) ;
4796
4900
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 ( ) )
4798
4902
. to_name_binding ( self . arenas ) )
4799
4903
}
4800
4904
} )
0 commit comments