diff --git a/src/librustc_typeck/check/impl_item_duplicate.rs b/src/librustc_typeck/check/impl_item_duplicate.rs new file mode 100644 index 000000000000..4111fa9a2c0d --- /dev/null +++ b/src/librustc_typeck/check/impl_item_duplicate.rs @@ -0,0 +1,46 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::hir; +use rustc_data_structures::fx::FxHashMap; +use std::collections::hash_map::Entry::{Occupied, Vacant}; + +use CrateCtxt; + +/// Enforce that we do not have two items in an impl with the same name. +pub fn enforce_impl_items_are_distinct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + impl_item_ids: &[hir::ImplItemId]) +{ + let tcx = ccx.tcx; + let mut seen_type_items = FxHashMap(); + let mut seen_value_items = FxHashMap(); + for &impl_item_id in impl_item_ids { + let impl_item = tcx.map.impl_item(impl_item_id); + let seen_items = match impl_item.node { + hir::ImplItemKind::Type(_) => &mut seen_type_items, + _ => &mut seen_value_items, + }; + 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); + err.span_label(*entry.get(), + &format!("previous definition of `{}` here", + impl_item.name)); + err.span_label(impl_item.span, &format!("duplicate definition")); + err.emit(); + } + Vacant(entry) => { + entry.insert(impl_item.span); + } + } + } +} diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 12a1cc8279fd..7c21ddbe4019 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -143,6 +143,7 @@ mod closure; mod callee; mod compare_method; mod intrinsic; +mod impl_item_duplicate; mod impl_parameters_used; mod op; @@ -834,6 +835,8 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { impl_def_id, impl_item_ids); + impl_item_duplicate::enforce_impl_items_are_distinct(ccx, + impl_item_ids); } hir::ItemTrait(..) => { let def_id = ccx.tcx.map.local_def_id(it.id); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index fc1977424556..c20e1d1d4d74 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -77,7 +77,6 @@ use CrateCtxt; use rustc_const_math::ConstInt; use std::cell::RefCell; -use std::collections::hash_map::Entry::{Occupied, Vacant}; use syntax::{abi, ast, attr}; use syntax::parse::token::{self, keywords}; @@ -732,7 +731,11 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { ref generics, ref opt_trait_ref, ref selfty, - ref impl_item_ids) => { + ref _impl_item_ids /* [1] */) => { + // [1]: We really don't want to be inspecting the details + // of impl-items here; it creates bad edges in the + // incr. comp. graph. + // Create generics from the generics specified in the impl head. debug!("convert: ast_generics={:?}", generics); let def_id = ccx.tcx.map.local_def_id(it.id); @@ -763,35 +766,6 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { &mut ctp::parameters_for_impl(selfty, trait_ref)); tcx.predicates.borrow_mut().insert(def_id, ty_predicates.clone()); - - - // Convert all the associated consts. - // Also, check if there are any duplicate associated items - let mut seen_type_items = FxHashMap(); - let mut seen_value_items = FxHashMap(); - - for &impl_item_id in impl_item_ids { - let impl_item = tcx.map.impl_item(impl_item_id); - let seen_items = match impl_item.node { - hir::ImplItemKind::Type(_) => &mut seen_type_items, - _ => &mut seen_value_items, - }; - 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); - err.span_label(*entry.get(), - &format!("previous definition of `{}` here", - impl_item.name)); - err.span_label(impl_item.span, &format!("duplicate definition")); - err.emit(); - } - Vacant(entry) => { - entry.insert(impl_item.span); - } - } - } }, hir::ItemTrait(.., ref trait_items) => { let trait_def = trait_def_of_item(ccx, it);