@@ -5,10 +5,8 @@ use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_
55use rustc_ast:: { MetaItemKind , NestedMetaItem } ;
66use rustc_ast_pretty:: pprust;
77use 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 } ;
1210use rustc_feature:: BUILTIN_ATTRIBUTES ;
1311use rustc_hir:: def:: Namespace :: { self , * } ;
1412use rustc_hir:: def:: { self , CtorKind , CtorOf , DefKind , NonMacroAttrKind , PerNS } ;
@@ -17,8 +15,9 @@ use rustc_hir::PrimTy;
1715use rustc_middle:: bug;
1816use rustc_middle:: ty:: TyCtxt ;
1917use rustc_session:: lint:: builtin:: ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE ;
18+ use rustc_session:: lint:: builtin:: AMBIGUOUS_GLOB_IMPORTS ;
2019use 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 } ;
2221use rustc_session:: Session ;
2322use rustc_span:: edit_distance:: find_best_match_for_name;
2423use rustc_span:: edition:: Edition ;
@@ -135,7 +134,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
135134 }
136135
137136 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+ }
139154 }
140155
141156 let mut reported_spans = FxHashSet :: default ( ) ;
@@ -1540,20 +1555,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15401555 }
15411556 }
15421557
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;
15451560 let ( b1, b2, misc1, misc2, swapped) = if b2. span . is_dummy ( ) && !b1. span . is_dummy ( ) {
15461561 // We have to print the span-less alternative first, otherwise formatting looks bad.
15471562 ( b2, b1, misc2, misc1, true )
15481563 } else {
15491564 ( b1, b2, misc1, misc2, false )
15501565 } ;
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 | {
15571567 let what = self . binding_description ( b, ident, misc == AmbiguityErrorMisc :: FromPrelude ) ;
15581568 let note_msg = format ! ( "`{ident}` could{also} refer to {what}" ) ;
15591569
@@ -1579,16 +1589,35 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15791589 AmbiguityErrorMisc :: FromPrelude | AmbiguityErrorMisc :: None => { }
15801590 }
15811591
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+ )
15871604 } ;
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+ }
15921621 }
15931622
15941623 /// If the binding refers to a tuple struct constructor with fields,
0 commit comments