@@ -5,10 +5,8 @@ use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_
5
5
use rustc_ast:: { MetaItemKind , NestedMetaItem } ;
6
6
use rustc_ast_pretty:: pprust;
7
7
use rustc_data_structures:: fx:: FxHashSet ;
8
- use rustc_errors:: {
9
- pluralize, Applicability , Diagnostic , DiagnosticBuilder , ErrorGuaranteed , MultiSpan ,
10
- } ;
11
- use rustc_errors:: { struct_span_err, SuggestionStyle } ;
8
+ use rustc_errors:: { pluralize, report_ambiguity_error, struct_span_err, SuggestionStyle } ;
9
+ use rustc_errors:: { Applicability , Diagnostic , DiagnosticBuilder , ErrorGuaranteed , MultiSpan } ;
12
10
use rustc_feature:: BUILTIN_ATTRIBUTES ;
13
11
use rustc_hir:: def:: Namespace :: { self , * } ;
14
12
use rustc_hir:: def:: { self , CtorKind , CtorOf , DefKind , NonMacroAttrKind , PerNS } ;
@@ -17,8 +15,9 @@ use rustc_hir::PrimTy;
17
15
use rustc_middle:: bug;
18
16
use rustc_middle:: ty:: TyCtxt ;
19
17
use rustc_session:: lint:: builtin:: ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE ;
18
+ use rustc_session:: lint:: builtin:: AMBIGUOUS_GLOB_IMPORTS ;
20
19
use rustc_session:: lint:: builtin:: MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS ;
21
- use rustc_session:: lint:: BuiltinLintDiagnostics ;
20
+ use rustc_session:: lint:: { AmbiguityErrorDiag , BuiltinLintDiagnostics } ;
22
21
use rustc_session:: Session ;
23
22
use rustc_span:: edit_distance:: find_best_match_for_name;
24
23
use rustc_span:: edition:: Edition ;
@@ -135,7 +134,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
135
134
}
136
135
137
136
for ambiguity_error in & self . ambiguity_errors {
138
- self . report_ambiguity_error ( ambiguity_error) ;
137
+ let diag = self . ambiguity_diagnostics ( ambiguity_error) ;
138
+ if ambiguity_error. warning {
139
+ let NameBindingKind :: Import { import, .. } = ambiguity_error. b1 . 0 . kind else {
140
+ unreachable ! ( )
141
+ } ;
142
+ self . lint_buffer . buffer_lint_with_diagnostic (
143
+ AMBIGUOUS_GLOB_IMPORTS ,
144
+ import. root_id ,
145
+ ambiguity_error. ident . span ,
146
+ diag. msg . to_string ( ) ,
147
+ BuiltinLintDiagnostics :: AmbiguousGlobImports { diag } ,
148
+ ) ;
149
+ } else {
150
+ let mut err = struct_span_err ! ( self . tcx. sess, diag. span, E0659 , "{}" , & diag. msg) ;
151
+ report_ambiguity_error ( & mut err, diag) ;
152
+ err. emit ( ) ;
153
+ }
139
154
}
140
155
141
156
let mut reported_spans = FxHashSet :: default ( ) ;
@@ -1540,20 +1555,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1540
1555
}
1541
1556
}
1542
1557
1543
- fn report_ambiguity_error ( & self , ambiguity_error : & AmbiguityError < ' _ > ) {
1544
- let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = * ambiguity_error;
1558
+ fn ambiguity_diagnostics ( & self , ambiguity_error : & AmbiguityError < ' _ > ) -> AmbiguityErrorDiag {
1559
+ let AmbiguityError { kind, ident, b1, b2, misc1, misc2, .. } = * ambiguity_error;
1545
1560
let ( b1, b2, misc1, misc2, swapped) = if b2. span . is_dummy ( ) && !b1. span . is_dummy ( ) {
1546
1561
// We have to print the span-less alternative first, otherwise formatting looks bad.
1547
1562
( b2, b1, misc2, misc1, true )
1548
1563
} else {
1549
1564
( b1, b2, misc1, misc2, false )
1550
1565
} ;
1551
-
1552
- let mut err = struct_span_err ! ( self . tcx. sess, ident. span, E0659 , "`{ident}` is ambiguous" ) ;
1553
- err. span_label ( ident. span , "ambiguous name" ) ;
1554
- err. note ( format ! ( "ambiguous because of {}" , kind. descr( ) ) ) ;
1555
-
1556
- let mut could_refer_to = |b : NameBinding < ' _ > , misc : AmbiguityErrorMisc , also : & str | {
1566
+ let could_refer_to = |b : NameBinding < ' _ > , misc : AmbiguityErrorMisc , also : & str | {
1557
1567
let what = self . binding_description ( b, ident, misc == AmbiguityErrorMisc :: FromPrelude ) ;
1558
1568
let note_msg = format ! ( "`{ident}` could{also} refer to {what}" ) ;
1559
1569
@@ -1579,16 +1589,35 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1579
1589
AmbiguityErrorMisc :: FromPrelude | AmbiguityErrorMisc :: None => { }
1580
1590
}
1581
1591
1582
- err. span_note ( b. span , note_msg) ;
1583
- for ( i, help_msg) in help_msgs. iter ( ) . enumerate ( ) {
1584
- let or = if i == 0 { "" } else { "or " } ;
1585
- err. help ( format ! ( "{}{}" , or, help_msg) ) ;
1586
- }
1592
+ (
1593
+ b. span ,
1594
+ note_msg,
1595
+ help_msgs
1596
+ . iter ( )
1597
+ . enumerate ( )
1598
+ . map ( |( i, help_msg) | {
1599
+ let or = if i == 0 { "" } else { "or " } ;
1600
+ format ! ( "{}{}" , or, help_msg)
1601
+ } )
1602
+ . collect :: < Vec < _ > > ( ) ,
1603
+ )
1587
1604
} ;
1588
-
1589
- could_refer_to ( b1, misc1, "" ) ;
1590
- could_refer_to ( b2, misc2, " also" ) ;
1591
- err. emit ( ) ;
1605
+ let ( b1_span, b1_note_msg, b1_help_msgs) = could_refer_to ( b1, misc1, "" ) ;
1606
+ let ( b2_span, b2_note_msg, b2_help_msgs) = could_refer_to ( b2, misc2, " also" ) ;
1607
+
1608
+ AmbiguityErrorDiag {
1609
+ msg : format ! ( "`{ident}` is ambiguous" ) ,
1610
+ span : ident. span ,
1611
+ label_span : ident. span ,
1612
+ label_msg : "ambiguous name" . to_string ( ) ,
1613
+ note_msg : format ! ( "ambiguous because of {}" , kind. descr( ) ) ,
1614
+ b1_span,
1615
+ b1_note_msg,
1616
+ b1_help_msgs,
1617
+ b2_span,
1618
+ b2_note_msg,
1619
+ b2_help_msgs,
1620
+ }
1592
1621
}
1593
1622
1594
1623
/// If the binding refers to a tuple struct constructor with fields,
0 commit comments