move duplicate checking into TypeCheck

This completes the effort to not touch the impl-items during
`Collect(Impl)`.
This commit is contained in:
Niko Matsakis 2016-11-08 20:27:28 -05:00
parent 29a39ab834
commit 4df5288971
3 changed files with 54 additions and 31 deletions

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
}
}
}
}

View file

@ -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);

View file

@ -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);