diff options
| author | bors <bors@rust-lang.org> | 2023-07-29 06:04:41 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-07-29 06:04:41 +0000 |
| commit | 2dc661037d059bff1487b76ca949ced7b3cd46c9 (patch) | |
| tree | f5666979d20c236dfa502383e8a2cff8fde8bc2e /compiler | |
| parent | 5ed61a4378700aeb5af88385d9ae054c8adf2322 (diff) | |
| parent | 771c832338d57390018d41458a3223bc18eacedc (diff) | |
| download | rust-2dc661037d059bff1487b76ca949ced7b3cd46c9.tar.gz rust-2dc661037d059bff1487b76ca949ced7b3cd46c9.zip | |
Auto merge of #113099 - bvanjoi:fix-112713-2, r=petrochenkov
fix(resolve): update the ambiguity glob binding as warning recursively Fixes #47525 Fixes #56593, but `issue-56593-2.rs` is not fixed to ensure backward compatibility. Fixes #98467 Fixes #105235 Fixes #112713 This PR had added a field called `warn_ambiguous` in `NameBinding` which is only for back compatibly reason and used for lint. More details: https://github.com/rust-lang/rust/pull/112743 r? `@petrochenkov`
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_errors/src/lib.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/context.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_lint_defs/src/builtin.rs | 44 | ||||
| -rw-r--r-- | compiler/rustc_lint_defs/src/lib.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/build_reduced_graph.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 75 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/ident.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/imports.rs | 114 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 26 |
9 files changed, 256 insertions, 46 deletions
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index aa213cd0720..2181bd526eb 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1871,6 +1871,22 @@ pub fn add_elided_lifetime_in_path_suggestion( }); } +pub fn report_ambiguity_error<'a, G: EmissionGuarantee>( + db: &mut DiagnosticBuilder<'a, G>, + ambiguity: rustc_lint_defs::AmbiguityErrorDiag, +) { + db.span_label(ambiguity.label_span, ambiguity.label_msg); + db.note(ambiguity.note_msg); + db.span_note(ambiguity.b1_span, ambiguity.b1_note_msg); + for help_msg in ambiguity.b1_help_msgs { + db.help(help_msg); + } + db.span_note(ambiguity.b2_span, ambiguity.b2_note_msg); + for help_msg in ambiguity.b2_help_msgs { + db.help(help_msg); + } +} + #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum TerminalUrl { No, diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 65c56bff841..f7e56b30553 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -946,6 +946,9 @@ pub trait LintContext: Sized { Applicability::MachineApplicable, ); } + BuiltinLintDiagnostics::AmbiguousGlobImports { diag } => { + rustc_errors::report_ambiguity_error(db, diag); + } BuiltinLintDiagnostics::AmbiguousGlobReexports { name, namespace, first_reexport_span, duplicate_reexport_span } => { db.span_label(first_reexport_span, format!("the name `{name}` in the {namespace} namespace is first re-exported here")); db.span_label(duplicate_reexport_span, format!("but the name `{name}` in the {namespace} namespace is also re-exported here")); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index f1765d653b0..7e3b6e9e218 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3316,6 +3316,7 @@ declare_lint_pass! { // tidy-alphabetical-start ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_ASSOCIATED_ITEMS, + AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_GLOB_REEXPORTS, ARITHMETIC_OVERFLOW, ASM_SUB_REGISTER, @@ -4405,3 +4406,46 @@ declare_lint! { Warn, "unrecognized diagnostic attribute" } + +declare_lint! { + /// The `ambiguous_glob_imports` lint detects glob imports that should report ambiguity + /// errors, but previously didn't do that due to rustc bugs. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// + /// #![deny(ambiguous_glob_imports)] + /// pub fn foo() -> u32 { + /// use sub::*; + /// C + /// } + /// + /// mod sub { + /// mod mod1 { pub const C: u32 = 1; } + /// mod mod2 { pub const C: u32 = 2; } + /// + /// pub use mod1::*; + /// pub use mod2::*; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Previous versions of Rust compile it successfully because it + /// had lost the ambiguity error when resolve `use sub::mod2::*`. + /// + /// This is a [future-incompatible] lint to transition this to a + /// hard error in the future. + /// + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub AMBIGUOUS_GLOB_IMPORTS, + Warn, + "detects certain glob imports that require reporting an ambiguity error", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseError, + reference: "issue #114095 <https://github.com/rust-lang/rust/issues/114095>", + }; +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 10ebe29dfce..f350957f72f 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -467,6 +467,21 @@ impl<HCX> ToStableHashKey<HCX> for LintId { } } +#[derive(Debug)] +pub struct AmbiguityErrorDiag { + pub msg: String, + pub span: Span, + pub label_span: Span, + pub label_msg: String, + pub note_msg: String, + pub b1_span: Span, + pub b1_note_msg: String, + pub b1_help_msgs: Vec<String>, + pub b2_span: Span, + pub b2_note_msg: String, + pub b2_help_msgs: Vec<String>, +} + // This could be a closure, but then implementing derive trait // becomes hacky (and it gets allocated). #[derive(Debug)] @@ -530,6 +545,9 @@ pub enum BuiltinLintDiagnostics { vis_span: Span, ident_span: Span, }, + AmbiguousGlobImports { + diag: AmbiguityErrorDiag, + }, AmbiguousGlobReexports { /// The name for which collision(s) have occurred. name: String, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index ff63e4e33cb..5814e3d6c13 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -41,6 +41,7 @@ impl<'a, Id: Into<DefId>> ToNameBinding<'a> arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Module(self.0), ambiguity: None, + warn_ambiguity: false, vis: self.1.to_def_id(), span: self.2, expansion: self.3, @@ -53,6 +54,7 @@ impl<'a, Id: Into<DefId>> ToNameBinding<'a> for (Res, ty::Visibility<Id>, Span, arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Res(self.0), ambiguity: None, + warn_ambiguity: false, vis: self.1.to_def_id(), span: self.2, expansion: self.3, @@ -69,7 +71,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { { let binding = def.to_name_binding(self.arenas); let key = self.new_disambiguated_key(ident, ns); - if let Err(old_binding) = self.try_define(parent, key, binding) { + if let Err(old_binding) = self.try_define(parent, key, binding, false) { self.report_conflict(parent, ident, ns, old_binding, binding); } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 73cd596c076..97ac6891d82 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -5,10 +5,8 @@ use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_ use rustc_ast::{MetaItemKind, NestedMetaItem}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{ - pluralize, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, -}; -use rustc_errors::{struct_span_err, SuggestionStyle}; +use rustc_errors::{pluralize, report_ambiguity_error, struct_span_err, SuggestionStyle}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS}; @@ -17,8 +15,9 @@ use rustc_hir::PrimTy; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE; +use rustc_session::lint::builtin::AMBIGUOUS_GLOB_IMPORTS; use rustc_session::lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS; -use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_session::lint::{AmbiguityErrorDiag, BuiltinLintDiagnostics}; use rustc_session::Session; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; @@ -135,7 +134,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } for ambiguity_error in &self.ambiguity_errors { - self.report_ambiguity_error(ambiguity_error); + let diag = self.ambiguity_diagnostics(ambiguity_error); + if ambiguity_error.warning { + let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind else { + unreachable!() + }; + self.lint_buffer.buffer_lint_with_diagnostic( + AMBIGUOUS_GLOB_IMPORTS, + import.root_id, + ambiguity_error.ident.span, + diag.msg.to_string(), + BuiltinLintDiagnostics::AmbiguousGlobImports { diag }, + ); + } else { + let mut err = struct_span_err!(self.tcx.sess, diag.span, E0659, "{}", &diag.msg); + report_ambiguity_error(&mut err, diag); + err.emit(); + } } let mut reported_spans = FxHashSet::default(); @@ -1540,20 +1555,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError<'_>) { - let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = *ambiguity_error; + fn ambiguity_diagnostics(&self, ambiguity_error: &AmbiguityError<'_>) -> AmbiguityErrorDiag { + let AmbiguityError { kind, ident, b1, b2, misc1, misc2, .. } = *ambiguity_error; let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() { // We have to print the span-less alternative first, otherwise formatting looks bad. (b2, b1, misc2, misc1, true) } else { (b1, b2, misc1, misc2, false) }; - - let mut err = struct_span_err!(self.tcx.sess, ident.span, E0659, "`{ident}` is ambiguous"); - err.span_label(ident.span, "ambiguous name"); - err.note(format!("ambiguous because of {}", kind.descr())); - - let mut could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| { + let could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| { let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude); let note_msg = format!("`{ident}` could{also} refer to {what}"); @@ -1579,16 +1589,35 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { AmbiguityErrorMisc::FromPrelude | AmbiguityErrorMisc::None => {} } - err.span_note(b.span, note_msg); - for (i, help_msg) in help_msgs.iter().enumerate() { - let or = if i == 0 { "" } else { "or " }; - err.help(format!("{}{}", or, help_msg)); - } + ( + b.span, + note_msg, + help_msgs + .iter() + .enumerate() + .map(|(i, help_msg)| { + let or = if i == 0 { "" } else { "or " }; + format!("{}{}", or, help_msg) + }) + .collect::<Vec<_>>(), + ) }; - - could_refer_to(b1, misc1, ""); - could_refer_to(b2, misc2, " also"); - err.emit(); + let (b1_span, b1_note_msg, b1_help_msgs) = could_refer_to(b1, misc1, ""); + let (b2_span, b2_note_msg, b2_help_msgs) = could_refer_to(b2, misc2, " also"); + + AmbiguityErrorDiag { + msg: format!("`{ident}` is ambiguous"), + span: ident.span, + label_span: ident.span, + label_msg: "ambiguous name".to_string(), + note_msg: format!("ambiguous because of {}", kind.descr()), + b1_span, + b1_note_msg, + b1_help_msgs, + b2_span, + b2_note_msg, + b2_help_msgs, + } } /// If the binding refers to a tuple struct constructor with fields, diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index de431444769..00282df700b 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -677,6 +677,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ident: orig_ident, b1: innermost_binding, b2: binding, + warning: false, misc1: misc(innermost_flags), misc2: misc(flags), }); @@ -905,6 +906,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ident, b1: binding, b2: shadowed_glob, + warning: false, misc1: AmbiguityErrorMisc::None, misc2: AmbiguityErrorMisc::None, }); diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index f3cf61c5b93..e1dae57d34f 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -284,6 +284,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Import { binding, import, used: Cell::new(false) }, ambiguity: None, + warn_ambiguity: false, span: import.span, vis, expansion: import.parent_scope.expansion, @@ -291,16 +292,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } /// Define the name or return the existing binding if there is a collision. + /// `update` indicates if the definition is a redefinition of an existing binding. pub(crate) fn try_define( &mut self, module: Module<'a>, key: BindingKey, binding: NameBinding<'a>, + warn_ambiguity: bool, ) -> Result<(), NameBinding<'a>> { let res = binding.res(); self.check_reserved_macro_name(key.ident, res); self.set_binding_parent_module(binding, module); - self.update_resolution(module, key, |this, resolution| { + self.update_resolution(module, key, warn_ambiguity, |this, resolution| { if let Some(old_binding) = resolution.binding { if res == Res::Err && old_binding.res() != Res::Err { // Do not override real bindings with `Res::Err`s from error recovery. @@ -308,15 +311,42 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } match (old_binding.is_glob_import(), binding.is_glob_import()) { (true, true) => { - if res != old_binding.res() { - resolution.binding = Some(this.ambiguity( - AmbiguityKind::GlobVsGlob, - old_binding, - binding, - )); + // FIXME: remove `!binding.is_ambiguity()` after delete the warning ambiguity. + if !binding.is_ambiguity() + && let NameBindingKind::Import { import: old_import, .. } = old_binding.kind + && let NameBindingKind::Import { import, .. } = binding.kind + && old_import == import { + // We should replace the `old_binding` with `binding` regardless + // of whether they has same resolution or not when they are + // imported from the same glob-import statement. + // However we currently using `Some(old_binding)` for back compact + // purposes. + // This case can be removed after once `Undetermined` is prepared + // for glob-imports. + } else if res != old_binding.res() { + let binding = if warn_ambiguity { + this.warn_ambiguity( + AmbiguityKind::GlobVsGlob, + old_binding, + binding, + ) + } else { + this.ambiguity( + AmbiguityKind::GlobVsGlob, + old_binding, + binding, + ) + }; + resolution.binding = Some(binding); } else if !old_binding.vis.is_at_least(binding.vis, this.tcx) { // We are glob-importing the same item but with greater visibility. resolution.binding = Some(binding); + } else if binding.is_ambiguity() { + resolution.binding = + Some(self.arenas.alloc_name_binding(NameBindingData { + warn_ambiguity: true, + ..(*binding).clone() + })); } } (old_glob @ true, false) | (old_glob @ false, true) => { @@ -374,29 +404,52 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }) } + fn warn_ambiguity( + &self, + kind: AmbiguityKind, + primary_binding: NameBinding<'a>, + secondary_binding: NameBinding<'a>, + ) -> NameBinding<'a> { + self.arenas.alloc_name_binding(NameBindingData { + ambiguity: Some((secondary_binding, kind)), + warn_ambiguity: true, + ..(*primary_binding).clone() + }) + } + // Use `f` to mutate the resolution of the name in the module. // If the resolution becomes a success, define it in the module's glob importers. - fn update_resolution<T, F>(&mut self, module: Module<'a>, key: BindingKey, f: F) -> T + fn update_resolution<T, F>( + &mut self, + module: Module<'a>, + key: BindingKey, + warn_ambiguity: bool, + f: F, + ) -> T where F: FnOnce(&mut Resolver<'a, 'tcx>, &mut NameResolution<'a>) -> T, { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. - let (binding, t) = { + let (binding, t, warn_ambiguity) = { let resolution = &mut *self.resolution(module, key).borrow_mut(); let old_binding = resolution.binding(); let t = f(self, resolution); - if old_binding.is_none() && let Some(binding) = resolution.binding() { - (binding, t) + if let Some(binding) = resolution.binding() && old_binding != Some(binding) { + (binding, t, warn_ambiguity || old_binding.is_some()) } else { return t; } }; - // Define `binding` in `module`s glob importers. - for import in module.glob_importers.borrow_mut().iter() { + let Ok(glob_importers) = module.glob_importers.try_borrow_mut() else { + return t; + }; + + // Define or update `binding` in `module`s glob importers. + for import in glob_importers.iter() { let mut ident = key.ident; let scope = match ident.span.reverse_glob_adjust(module.expansion, import.span) { Some(Some(def)) => self.expn_def_scope(def), @@ -406,7 +459,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if self.is_accessible_from(binding.vis, scope) { let imported_binding = self.import(binding, *import); let key = BindingKey { ident, ..key }; - let _ = self.try_define(import.parent_scope.module, key, imported_binding); + let _ = self.try_define( + import.parent_scope.module, + key, + imported_binding, + warn_ambiguity, + ); } } @@ -425,7 +483,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let dummy_binding = self.import(dummy_binding, import); self.per_ns(|this, ns| { let key = BindingKey::new(target, ns); - let _ = this.try_define(import.parent_scope.module, key, dummy_binding); + let _ = this.try_define(import.parent_scope.module, key, dummy_binding, false); }); self.record_use(target, dummy_binding, false); } else if import.imported_module.get().is_none() { @@ -700,7 +758,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Segment::names_to_string(&import.module_path), module_to_string(import.parent_scope.module).unwrap_or_else(|| "???".to_string()), ); - let module = if let Some(module) = import.imported_module.get() { module } else { @@ -773,7 +830,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .emit(); } let key = BindingKey::new(target, ns); - this.update_resolution(parent, key, |_, resolution| { + this.update_resolution(parent, key, false, |_, resolution| { resolution.single_imports.remove(&import); }); } @@ -989,7 +1046,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { initial_binding.res() }); let res = binding.res(); - if res == Res::Err || !this.ambiguity_errors.is_empty() { + let has_ambiguity_error = this + .ambiguity_errors + .iter() + .filter(|error| !error.warning) + .next() + .is_some(); + if res == Res::Err || has_ambiguity_error { this.tcx .sess .delay_span_bug(import.span, "some error happened for an import"); @@ -1338,7 +1401,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; if self.is_accessible_from(binding.vis, scope) { let imported_binding = self.import(binding, import); - let _ = self.try_define(import.parent_scope.module, key, imported_binding); + let warn_ambiguity = self + .resolution(import.parent_scope.module, key) + .borrow() + .binding() + .is_some_and(|binding| binding.is_warn_ambiguity()); + let _ = self.try_define( + import.parent_scope.module, + key, + imported_binding, + warn_ambiguity, + ); } } @@ -1357,7 +1430,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module.for_each_child(self, |this, ident, _, binding| { let res = binding.res().expect_non_local(); - if res != def::Res::Err && !binding.is_ambiguity() { + let error_ambiguity = binding.is_ambiguity() && !binding.warn_ambiguity; + if res != def::Res::Err && !error_ambiguity { let mut reexport_chain = SmallVec::new(); let mut next_binding = binding; while let NameBindingKind::Import { binding, import, .. } = next_binding.kind { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index faa672db59c..91d89f44dbf 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -658,6 +658,7 @@ impl<'a> fmt::Debug for Module<'a> { struct NameBindingData<'a> { kind: NameBindingKind<'a>, ambiguity: Option<(NameBinding<'a>, AmbiguityKind)>, + warn_ambiguity: bool, expansion: LocalExpnId, span: Span, vis: ty::Visibility<DefId>, @@ -767,6 +768,7 @@ struct AmbiguityError<'a> { b2: NameBinding<'a>, misc1: AmbiguityErrorMisc, misc2: AmbiguityErrorMisc, + warning: bool, } impl<'a> NameBindingData<'a> { @@ -794,6 +796,14 @@ impl<'a> NameBindingData<'a> { } } + fn is_warn_ambiguity(&self) -> bool { + self.warn_ambiguity + || match self.kind { + NameBindingKind::Import { binding, .. } => binding.is_warn_ambiguity(), + _ => false, + } + } + fn is_possibly_imported_variant(&self) -> bool { match self.kind { NameBindingKind::Import { binding, .. } => binding.is_possibly_imported_variant(), @@ -1322,6 +1332,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { dummy_binding: arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Res(Res::Err), ambiguity: None, + warn_ambiguity: false, expansion: LocalExpnId::ROOT, span: DUMMY_SP, vis: ty::Visibility::Public, @@ -1685,6 +1696,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'a>, is_lexical_scope: bool) { + self.record_use_inner(ident, used_binding, is_lexical_scope, used_binding.warn_ambiguity); + } + + fn record_use_inner( + &mut self, + ident: Ident, + used_binding: NameBinding<'a>, + is_lexical_scope: bool, + warn_ambiguity: bool, + ) { if let Some((b2, kind)) = used_binding.ambiguity { let ambiguity_error = AmbiguityError { kind, @@ -1693,9 +1714,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { b2, misc1: AmbiguityErrorMisc::None, misc2: AmbiguityErrorMisc::None, + warning: warn_ambiguity, }; if !self.matches_previous_ambiguity_error(&ambiguity_error) { - // avoid duplicated span information to be emitt out + // avoid duplicated span information to be emit out self.ambiguity_errors.push(ambiguity_error); } } @@ -1715,7 +1737,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.used_imports.insert(id); } self.add_to_glob_map(import, ident); - self.record_use(ident, binding, false); + self.record_use_inner(ident, binding, false, warn_ambiguity || binding.warn_ambiguity); } } |
