From 32a0cfeb485f2c1bbfe52eaa9e119e974e38f21f Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 22 Aug 2016 08:30:07 +0000 Subject: [PATCH] Avoid reporting multiple ambiguity errors for a single use of a name. --- src/librustc_resolve/lib.rs | 30 ++++++++++++++-------- src/test/compile-fail/imports/duplicate.rs | 13 ++++++++++ 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d77258f44eb9..a881feaa4d35 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1065,6 +1065,7 @@ pub struct Resolver<'a> { pub maybe_unused_trait_imports: NodeSet, privacy_errors: Vec>, + ambiguity_errors: Vec<(Span, Name, &'a NameBinding<'a>)>, arenas: &'a ResolverArenas<'a>, dummy_binding: &'a NameBinding<'a>, @@ -1218,6 +1219,7 @@ impl<'a> Resolver<'a> { maybe_unused_trait_imports: NodeSet(), privacy_errors: Vec::new(), + ambiguity_errors: Vec::new(), arenas: arenas, dummy_binding: arenas.alloc_name_binding(NameBinding { @@ -1245,7 +1247,7 @@ impl<'a> Resolver<'a> { visit::walk_crate(self, krate); check_unused::check_crate(self, krate); - self.report_privacy_errors(); + self.report_errors(); } fn new_module(&self, parent_link: ParentLink<'a>, def: Option, normal_ancestor_id: NodeId) @@ -1276,14 +1278,8 @@ impl<'a> Resolver<'a> { self.add_to_glob_map(directive.id, name); } - if let Some((b1, b2)) = binding.ambiguity() { - let msg1 = format!("`{}` could resolve to the name imported here", name); - let msg2 = format!("`{}` could also resolve to the name imported here", name); - self.session.struct_span_err(span, &format!("`{}` is ambiguous", name)) - .span_note(b1.span, &msg1) - .span_note(b2.span, &msg2) - .note(&format!("Consider adding an explicit import of `{}` to disambiguate", name)) - .emit(); + if binding.ambiguity().is_some() { + self.ambiguity_errors.push((span, name, binding)); return true; } @@ -3289,9 +3285,21 @@ impl<'a> Resolver<'a> { vis.is_accessible_from(module.normal_ancestor_id, self) } - fn report_privacy_errors(&self) { - if self.privacy_errors.len() == 0 { return } + fn report_errors(&self) { let mut reported_spans = FnvHashSet(); + + for &(span, name, binding) in &self.ambiguity_errors { + if !reported_spans.insert(span) { continue } + let (b1, b2) = binding.ambiguity().unwrap(); + let msg1 = format!("`{}` could resolve to the name imported here", name); + let msg2 = format!("`{}` could also resolve to the name imported here", name); + self.session.struct_span_err(span, &format!("`{}` is ambiguous", name)) + .span_note(b1.span, &msg1) + .span_note(b2.span, &msg2) + .note(&format!("Consider adding an explicit import of `{}` to disambiguate", name)) + .emit(); + } + for &PrivacyError(span, name, binding) in &self.privacy_errors { if !reported_spans.insert(span) { continue } if binding.is_extern_crate() { diff --git a/src/test/compile-fail/imports/duplicate.rs b/src/test/compile-fail/imports/duplicate.rs index 05c0d9cd38e8..70936b254464 100644 --- a/src/test/compile-fail/imports/duplicate.rs +++ b/src/test/compile-fail/imports/duplicate.rs @@ -50,3 +50,16 @@ fn main() { g::foo(); //~ ERROR `foo` is ambiguous //~| NOTE Consider adding an explicit import of `foo` to disambiguate } + +mod ambiguous_module_errors { + pub mod m1 { pub use super::m1 as foo; } + pub mod m2 { pub use super::m2 as foo; } + + use self::m1::*; //~ NOTE + use self::m2::*; //~ NOTE + + fn f() { + foo::bar(); //~ ERROR `foo` is ambiguous + //~| NOTE + } +}