about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSeo Sanghyeon <sanxiyn@gmail.com>2016-04-20 22:00:33 +0900
committerSeo Sanghyeon <sanxiyn@gmail.com>2016-04-20 22:00:33 +0900
commitf5326858b7f023ddcac8c252de06165419e2d86c (patch)
treec6bc4041e80c06bff6719caf53b8c672232e3b58
parent3dd88f60de01774b9f9e29c0289a874a5dcaa1ce (diff)
downloadrust-f5326858b7f023ddcac8c252de06165419e2d86c.tar.gz
rust-f5326858b7f023ddcac8c252de06165419e2d86c.zip
Show previous definition of duplicate impl item
-rw-r--r--src/librustc_typeck/coherence/mod.rs9
-rw-r--r--src/librustc_typeck/collect.rs23
-rw-r--r--src/test/compile-fail/impl-duplicate-methods.rs5
3 files changed, 20 insertions, 17 deletions
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 9c8c9ba5056..859fbd974fe 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 6d95586bed0..95958d78067 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 148958ae128..981eddc9dd9 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() {}