Report duplicate definition in impls with overlap check.
This commit is contained in:
parent
4891d57f7a
commit
112ce80726
10 changed files with 66 additions and 74 deletions
|
@ -58,6 +58,37 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
||||||
== item2.ident(self.tcx).normalize_to_macros_2_0()
|
== item2.ident(self.tcx).normalize_to_macros_2_0()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_for_duplicate_items_in_impl(&self, impl_: DefId) {
|
||||||
|
let impl_items = self.tcx.associated_items(impl_);
|
||||||
|
|
||||||
|
let mut seen_items = FxHashMap::default();
|
||||||
|
for impl_item in impl_items.in_definition_order() {
|
||||||
|
let span = self.tcx.def_span(impl_item.def_id);
|
||||||
|
let ident = impl_item.ident(self.tcx);
|
||||||
|
|
||||||
|
let norm_ident = ident.normalize_to_macros_2_0();
|
||||||
|
match seen_items.entry(norm_ident) {
|
||||||
|
Entry::Occupied(entry) => {
|
||||||
|
let former = entry.get();
|
||||||
|
let mut err = struct_span_err!(
|
||||||
|
self.tcx.sess,
|
||||||
|
span,
|
||||||
|
E0592,
|
||||||
|
"duplicate definitions with name `{}`",
|
||||||
|
ident,
|
||||||
|
);
|
||||||
|
err.span_label(span, format!("duplicate definitions for `{}`", ident));
|
||||||
|
err.span_label(*former, format!("other definition for `{}`", ident));
|
||||||
|
|
||||||
|
err.emit();
|
||||||
|
}
|
||||||
|
Entry::Vacant(entry) => {
|
||||||
|
entry.insert(span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check_for_common_items_in_impls(
|
fn check_for_common_items_in_impls(
|
||||||
&self,
|
&self,
|
||||||
impl1: DefId,
|
impl1: DefId,
|
||||||
|
@ -133,12 +164,6 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
||||||
|
|
||||||
let impls = self.tcx.inherent_impls(id.def_id);
|
let impls = self.tcx.inherent_impls(id.def_id);
|
||||||
|
|
||||||
// If there is only one inherent impl block,
|
|
||||||
// there is nothing to overlap check it with
|
|
||||||
if impls.len() <= 1 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let overlap_mode = OverlapMode::get(self.tcx, id.def_id.to_def_id());
|
let overlap_mode = OverlapMode::get(self.tcx, id.def_id.to_def_id());
|
||||||
|
|
||||||
let impls_items = impls
|
let impls_items = impls
|
||||||
|
@ -152,6 +177,8 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
||||||
const ALLOCATING_ALGO_THRESHOLD: usize = 500;
|
const ALLOCATING_ALGO_THRESHOLD: usize = 500;
|
||||||
if impls.len() < ALLOCATING_ALGO_THRESHOLD {
|
if impls.len() < ALLOCATING_ALGO_THRESHOLD {
|
||||||
for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() {
|
for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() {
|
||||||
|
self.check_for_duplicate_items_in_impl(impl1_def_id);
|
||||||
|
|
||||||
for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] {
|
for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] {
|
||||||
if self.impls_have_common_items(impl_items1, impl_items2) {
|
if self.impls_have_common_items(impl_items1, impl_items2) {
|
||||||
self.check_for_overlapping_inherent_impls(
|
self.check_for_overlapping_inherent_impls(
|
||||||
|
@ -290,6 +317,8 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
||||||
impl_blocks.sort_unstable();
|
impl_blocks.sort_unstable();
|
||||||
for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() {
|
for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() {
|
||||||
let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx];
|
let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx];
|
||||||
|
self.check_for_duplicate_items_in_impl(impl1_def_id);
|
||||||
|
|
||||||
for &impl2_items_idx in impl_blocks[(i + 1)..].iter() {
|
for &impl2_items_idx in impl_blocks[(i + 1)..].iter() {
|
||||||
let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx];
|
let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx];
|
||||||
if self.impls_have_common_items(impl_items1, impl_items2) {
|
if self.impls_have_common_items(impl_items1, impl_items2) {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
use crate::constrained_generic_params as cgp;
|
use crate::constrained_generic_params as cgp;
|
||||||
use min_specialization::check_min_specialization;
|
use min_specialization::check_min_specialization;
|
||||||
|
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::struct_span_err;
|
use rustc_errors::struct_span_err;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
|
@ -19,8 +19,6 @@ use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
|
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
|
||||||
|
|
||||||
mod min_specialization;
|
mod min_specialization;
|
||||||
|
|
||||||
/// Checks that all the type/lifetime parameters on an impl also
|
/// Checks that all the type/lifetime parameters on an impl also
|
||||||
|
@ -59,7 +57,6 @@ fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||||
for id in module.items() {
|
for id in module.items() {
|
||||||
if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
|
if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
|
||||||
enforce_impl_params_are_constrained(tcx, id.def_id.def_id);
|
enforce_impl_params_are_constrained(tcx, id.def_id.def_id);
|
||||||
enforce_impl_items_are_distinct(tcx, id.def_id.def_id);
|
|
||||||
if min_specialization {
|
if min_specialization {
|
||||||
check_min_specialization(tcx, id.def_id.def_id);
|
check_min_specialization(tcx, id.def_id.def_id);
|
||||||
}
|
}
|
||||||
|
@ -194,38 +191,3 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enforce that we do not have two items in an impl with the same name.
|
|
||||||
fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
|
|
||||||
if tcx.impl_trait_ref(impl_def_id).is_some() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut seen_type_items = FxHashMap::default();
|
|
||||||
let mut seen_value_items = FxHashMap::default();
|
|
||||||
for &impl_item_ref in tcx.associated_item_def_ids(impl_def_id) {
|
|
||||||
let impl_item = tcx.associated_item(impl_item_ref);
|
|
||||||
let seen_items = match impl_item.kind {
|
|
||||||
ty::AssocKind::Type => &mut seen_type_items,
|
|
||||||
_ => &mut seen_value_items,
|
|
||||||
};
|
|
||||||
let span = tcx.def_span(impl_item_ref);
|
|
||||||
let ident = impl_item.ident(tcx);
|
|
||||||
match seen_items.entry(ident.normalize_to_macros_2_0()) {
|
|
||||||
Occupied(entry) => {
|
|
||||||
let mut err = struct_span_err!(
|
|
||||||
tcx.sess,
|
|
||||||
span,
|
|
||||||
E0201,
|
|
||||||
"duplicate definitions with name `{}`:",
|
|
||||||
ident
|
|
||||||
);
|
|
||||||
err.span_label(*entry.get(), format!("previous definition of `{}` here", ident));
|
|
||||||
err.span_label(span, "duplicate definition");
|
|
||||||
err.emit();
|
|
||||||
}
|
|
||||||
Vacant(entry) => {
|
|
||||||
entry.insert(span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
error[E0201]: duplicate definitions with name `bar`:
|
error[E0592]: duplicate definitions with name `bar`
|
||||||
--> $DIR/associated-item-duplicate-names-2.rs:5:5
|
--> $DIR/associated-item-duplicate-names-2.rs:5:5
|
||||||
|
|
|
|
||||||
LL | const bar: bool = true;
|
LL | const bar: bool = true;
|
||||||
| --------------- previous definition of `bar` here
|
| --------------- other definition for `bar`
|
||||||
LL | fn bar() {}
|
LL | fn bar() {}
|
||||||
| ^^^^^^^^ duplicate definition
|
| ^^^^^^^^ duplicate definitions for `bar`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0201`.
|
For more information about this error, try `rustc --explain E0592`.
|
||||||
|
|
|
@ -3,7 +3,7 @@ struct Foo;
|
||||||
impl Foo {
|
impl Foo {
|
||||||
fn orange(&self) {}
|
fn orange(&self) {}
|
||||||
fn orange(&self) {}
|
fn orange(&self) {}
|
||||||
//~^ ERROR duplicate definition
|
//~^ ERROR duplicate definitions with name `orange` [E0592]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
11
src/test/ui/associated-item/impl-duplicate-methods.stderr
Normal file
11
src/test/ui/associated-item/impl-duplicate-methods.stderr
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
error[E0592]: duplicate definitions with name `orange`
|
||||||
|
--> $DIR/impl-duplicate-methods.rs:5:5
|
||||||
|
|
|
||||||
|
LL | fn orange(&self) {}
|
||||||
|
| ---------------- other definition for `orange`
|
||||||
|
LL | fn orange(&self) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^ duplicate definitions for `orange`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0592`.
|
|
@ -2,7 +2,7 @@ struct Foo(u8);
|
||||||
|
|
||||||
impl Foo {
|
impl Foo {
|
||||||
fn bar(&self) -> bool { self.0 > 5 }
|
fn bar(&self) -> bool { self.0 > 5 }
|
||||||
fn bar() {} //~ ERROR E0201
|
fn bar() {} //~ ERROR E0592
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Baz {
|
trait Baz {
|
||||||
|
|
|
@ -21,14 +21,15 @@ LL | type Quux = u32;
|
||||||
LL | type Quux = u32;
|
LL | type Quux = u32;
|
||||||
| ^^^^^^^^^^^^^^^^ duplicate definition
|
| ^^^^^^^^^^^^^^^^ duplicate definition
|
||||||
|
|
||||||
error[E0201]: duplicate definitions with name `bar`:
|
error[E0592]: duplicate definitions with name `bar`
|
||||||
--> $DIR/E0201.rs:5:5
|
--> $DIR/E0201.rs:5:5
|
||||||
|
|
|
|
||||||
LL | fn bar(&self) -> bool { self.0 > 5 }
|
LL | fn bar(&self) -> bool { self.0 > 5 }
|
||||||
| --------------------- previous definition of `bar` here
|
| --------------------- other definition for `bar`
|
||||||
LL | fn bar() {}
|
LL | fn bar() {}
|
||||||
| ^^^^^^^^ duplicate definition
|
| ^^^^^^^^ duplicate definitions for `bar`
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0201`.
|
Some errors have detailed explanations: E0201, E0592.
|
||||||
|
For more information about an error, try `rustc --explain E0201`.
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
error[E0201]: duplicate definitions with name `orange`:
|
|
||||||
--> $DIR/impl-duplicate-methods.rs:5:5
|
|
||||||
|
|
|
||||||
LL | fn orange(&self) {}
|
|
||||||
| ---------------- previous definition of `orange` here
|
|
||||||
LL | fn orange(&self) {}
|
|
||||||
| ^^^^^^^^^^^^^^^^ duplicate definition
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0201`.
|
|
|
@ -1,12 +1,12 @@
|
||||||
error[E0201]: duplicate definitions with name `bar`:
|
error[E0592]: duplicate definitions with name `bar`
|
||||||
--> $DIR/issue-4265.rs:10:5
|
--> $DIR/issue-4265.rs:10:5
|
||||||
|
|
|
|
||||||
LL | fn bar() {
|
LL | fn bar() {
|
||||||
| -------- previous definition of `bar` here
|
| -------- other definition for `bar`
|
||||||
...
|
...
|
||||||
LL | fn bar() {
|
LL | fn bar() {
|
||||||
| ^^^^^^^^ duplicate definition
|
| ^^^^^^^^ duplicate definitions for `bar`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0201`.
|
For more information about this error, try `rustc --explain E0592`.
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
error[E0201]: duplicate definitions with name `bar`:
|
error[E0592]: duplicate definitions with name `bar`
|
||||||
--> $DIR/method-macro-backtrace.rs:22:5
|
--> $DIR/method-macro-backtrace.rs:22:5
|
||||||
|
|
|
|
||||||
LL | fn bar(&self) { }
|
LL | fn bar(&self) { }
|
||||||
| ------------- previous definition of `bar` here
|
| ------------- other definition for `bar`
|
||||||
LL | fn bar(&self) { }
|
LL | fn bar(&self) { }
|
||||||
| ^^^^^^^^^^^^^ duplicate definition
|
| ^^^^^^^^^^^^^ duplicate definitions for `bar`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0201`.
|
For more information about this error, try `rustc --explain E0592`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue