diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 9c8c9ba505612..859fbd974fedc 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -34,9 +34,7 @@ use CrateCtxt; use rustc::infer::{self, InferCtxt, TypeOrigin, new_infer_ctxt}; use std::cell::RefCell; use std::rc::Rc; -use syntax::ast; use syntax::codemap::Span; -use syntax::errors::DiagnosticBuilder; use util::nodemap::{DefIdMap, FnvHashMap}; use rustc::dep_graph::DepNode; use rustc::hir::map as hir_map; @@ -517,13 +515,6 @@ fn enforce_trait_manually_implementable(tcx: &TyCtxt, sp: Span, trait_def_id: De err.emit(); } -// Factored out into helper because the error cannot be defined in multiple locations. -pub fn report_duplicate_item<'tcx>(tcx: &TyCtxt<'tcx>, sp: Span, name: ast::Name) - -> DiagnosticBuilder<'tcx> -{ - struct_span_err!(tcx.sess, sp, E0201, "duplicate definitions with name `{}`:", name) -} - pub fn check_coherence(crate_context: &CrateCtxt) { let _task = crate_context.tcx.dep_graph.in_task(DepNode::Coherence); let infcx = new_infer_ctxt(crate_context.tcx, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 6d95586bed019..95958d78067da 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -63,7 +63,6 @@ use lint; use hir::def::Def; use hir::def_id::DefId; use constrained_type_params as ctp; -use coherence; use middle::lang_items::SizedTraitLangItem; use middle::resolve_lifetime; use middle::const_val::ConstVal; @@ -80,13 +79,14 @@ use rscope::*; use rustc::dep_graph::DepNode; use rustc::hir::map as hir_map; use util::common::{ErrorReported, MemoizationMap}; -use util::nodemap::{FnvHashMap, FnvHashSet}; +use util::nodemap::FnvHashMap; use write_ty_to_tcx; use rustc_const_math::ConstInt; use std::cell::RefCell; use std::collections::HashSet; +use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::rc::Rc; use syntax::abi; @@ -742,16 +742,27 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { // Convert all the associated consts. // Also, check if there are any duplicate associated items - let mut seen_type_items = FnvHashSet(); - let mut seen_value_items = FnvHashSet(); + let mut seen_type_items = FnvHashMap(); + let mut seen_value_items = FnvHashMap(); for impl_item in impl_items { let seen_items = match impl_item.node { hir::ImplItemKind::Type(_) => &mut seen_type_items, _ => &mut seen_value_items, }; - if !seen_items.insert(impl_item.name) { - coherence::report_duplicate_item(tcx, impl_item.span, impl_item.name).emit(); + match seen_items.entry(impl_item.name) { + Occupied(entry) => { + let mut err = struct_span_err!(tcx.sess, impl_item.span, E0201, + "duplicate definitions with name `{}`:", + impl_item.name); + span_note!(&mut err, *entry.get(), + "previous definition of `{}` here", + impl_item.name); + err.emit(); + } + Vacant(entry) => { + entry.insert(impl_item.span); + } } if let hir::ImplItemKind::Const(ref ty, _) = impl_item.node { diff --git a/src/test/compile-fail/impl-duplicate-methods.rs b/src/test/compile-fail/impl-duplicate-methods.rs index 148958ae12897..981eddc9dd96b 100644 --- a/src/test/compile-fail/impl-duplicate-methods.rs +++ b/src/test/compile-fail/impl-duplicate-methods.rs @@ -9,9 +9,10 @@ // except according to those terms. struct Foo; + impl Foo { - fn orange(&self){} - fn orange(&self){} //~ ERROR duplicate definitions + fn orange(&self) {} //~ NOTE previous definition of `orange` here + fn orange(&self) {} //~ ERROR duplicate definitions with name `orange` } fn main() {}