Report duplicate definitions in trait impls during resolution.
This commit is contained in:
parent
8796e7a9cf
commit
152cd63226
11 changed files with 142 additions and 30 deletions
|
@ -197,6 +197,9 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol
|
||||||
|
|
||||||
/// Enforce that we do not have two items in an impl with the same name.
|
/// 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) {
|
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_type_items = FxHashMap::default();
|
||||||
let mut seen_value_items = FxHashMap::default();
|
let mut seen_value_items = FxHashMap::default();
|
||||||
for &impl_item_ref in tcx.associated_item_def_ids(impl_def_id) {
|
for &impl_item_ref in tcx.associated_item_def_ids(impl_def_id) {
|
||||||
|
|
|
@ -1047,6 +1047,19 @@ impl<'a> Resolver<'a> {
|
||||||
err.span_label(trait_item_span, "item in trait");
|
err.span_label(trait_item_span, "item in trait");
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => {
|
||||||
|
let mut err = struct_span_err!(
|
||||||
|
self.session,
|
||||||
|
span,
|
||||||
|
E0201,
|
||||||
|
"duplicate definitions with name `{}`:",
|
||||||
|
name,
|
||||||
|
);
|
||||||
|
err.span_label(old_span, "previous definition here");
|
||||||
|
err.span_label(trait_item_span, "item in trait");
|
||||||
|
err.span_label(span, "duplicate definition");
|
||||||
|
err
|
||||||
|
}
|
||||||
ResolutionError::InvalidAsmSym => {
|
ResolutionError::InvalidAsmSym => {
|
||||||
let mut err = self.session.struct_span_err(span, "invalid `sym` operand");
|
let mut err = self.session.struct_span_err(span, "invalid `sym` operand");
|
||||||
err.span_label(span, "is a local variable");
|
err.span_label(span, "is a local variable");
|
||||||
|
|
|
@ -2619,8 +2619,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
this.with_current_self_type(self_type, |this| {
|
this.with_current_self_type(self_type, |this| {
|
||||||
this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
|
this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
|
||||||
debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
|
debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
|
||||||
|
let mut seen_trait_items = Default::default();
|
||||||
for item in impl_items {
|
for item in impl_items {
|
||||||
this.resolve_impl_item(&**item);
|
this.resolve_impl_item(&**item, &mut seen_trait_items);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2634,7 +2635,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_impl_item(&mut self, item: &'ast AssocItem) {
|
fn resolve_impl_item(
|
||||||
|
&mut self,
|
||||||
|
item: &'ast AssocItem,
|
||||||
|
seen_trait_items: &mut FxHashMap<DefId, Span>,
|
||||||
|
) {
|
||||||
use crate::ResolutionError::*;
|
use crate::ResolutionError::*;
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
AssocItemKind::Const(_, ty, default) => {
|
AssocItemKind::Const(_, ty, default) => {
|
||||||
|
@ -2647,6 +2652,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
&item.kind,
|
&item.kind,
|
||||||
ValueNS,
|
ValueNS,
|
||||||
item.span,
|
item.span,
|
||||||
|
seen_trait_items,
|
||||||
|i, s, c| ConstNotMemberOfTrait(i, s, c),
|
|i, s, c| ConstNotMemberOfTrait(i, s, c),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2687,6 +2693,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
&item.kind,
|
&item.kind,
|
||||||
ValueNS,
|
ValueNS,
|
||||||
item.span,
|
item.span,
|
||||||
|
seen_trait_items,
|
||||||
|i, s, c| MethodNotMemberOfTrait(i, s, c),
|
|i, s, c| MethodNotMemberOfTrait(i, s, c),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2715,6 +2722,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
&item.kind,
|
&item.kind,
|
||||||
TypeNS,
|
TypeNS,
|
||||||
item.span,
|
item.span,
|
||||||
|
seen_trait_items,
|
||||||
|i, s, c| TypeNotMemberOfTrait(i, s, c),
|
|i, s, c| TypeNotMemberOfTrait(i, s, c),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2736,6 +2744,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
kind: &AssocItemKind,
|
kind: &AssocItemKind,
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
seen_trait_items: &mut FxHashMap<DefId, Span>,
|
||||||
err: F,
|
err: F,
|
||||||
) where
|
) where
|
||||||
F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'a>,
|
F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'a>,
|
||||||
|
@ -2768,7 +2777,25 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = binding.res();
|
let res = binding.res();
|
||||||
let Res::Def(def_kind, _) = res else { bug!() };
|
let Res::Def(def_kind, id_in_trait) = res else { bug!() };
|
||||||
|
|
||||||
|
match seen_trait_items.entry(id_in_trait) {
|
||||||
|
Entry::Occupied(entry) => {
|
||||||
|
self.report_error(
|
||||||
|
span,
|
||||||
|
ResolutionError::TraitImplDuplicate {
|
||||||
|
name: ident.name,
|
||||||
|
old_span: *entry.get(),
|
||||||
|
trait_item_span: binding.span,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Entry::Vacant(entry) => {
|
||||||
|
entry.insert(span);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
match (def_kind, kind) {
|
match (def_kind, kind) {
|
||||||
(DefKind::AssocTy, AssocItemKind::TyAlias(..))
|
(DefKind::AssocTy, AssocItemKind::TyAlias(..))
|
||||||
| (DefKind::AssocFn, AssocItemKind::Fn(..))
|
| (DefKind::AssocFn, AssocItemKind::Fn(..))
|
||||||
|
|
|
@ -236,6 +236,8 @@ enum ResolutionError<'a> {
|
||||||
trait_item_span: Span,
|
trait_item_span: Span,
|
||||||
code: rustc_errors::DiagnosticId,
|
code: rustc_errors::DiagnosticId,
|
||||||
},
|
},
|
||||||
|
/// Error E0201: multiple impl items for the same trait item.
|
||||||
|
TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span },
|
||||||
/// Inline asm `sym` operand must refer to a `fn` or `static`.
|
/// Inline asm `sym` operand must refer to a `fn` or `static`.
|
||||||
InvalidAsmSym,
|
InvalidAsmSym,
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,5 @@ impl Foo for Baz {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x: Baz::Bar = 5;
|
let x: Baz::Bar = 5;
|
||||||
|
//~^ ERROR ambiguous associated type
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
error[E0201]: duplicate definitions with name `Bar`:
|
error[E0201]: duplicate definitions with name `Bar`:
|
||||||
--> $DIR/associated-item-duplicate-names-3.rs:14:5
|
--> $DIR/associated-item-duplicate-names-3.rs:14:5
|
||||||
|
|
|
|
||||||
|
LL | type Bar;
|
||||||
|
| --------- item in trait
|
||||||
|
...
|
||||||
LL | type Bar = i16;
|
LL | type Bar = i16;
|
||||||
| -------- previous definition of `Bar` here
|
| --------------- previous definition here
|
||||||
LL | type Bar = u16;
|
LL | type Bar = u16;
|
||||||
| ^^^^^^^^ duplicate definition
|
| ^^^^^^^^^^^^^^^ duplicate definition
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0223]: ambiguous associated type
|
||||||
|
--> $DIR/associated-item-duplicate-names-3.rs:18:12
|
||||||
|
|
|
||||||
|
LL | let x: Baz::Bar = 5;
|
||||||
|
| ^^^^^^^^ help: use fully-qualified syntax: `<Baz as Trait>::Bar`
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0201`.
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0201, E0223.
|
||||||
|
For more information about an error, try `rustc --explain E0201`.
|
||||||
|
|
|
@ -1,18 +1,24 @@
|
||||||
error[E0201]: duplicate definitions with name `Ty`:
|
error[E0201]: duplicate definitions with name `Ty`:
|
||||||
--> $DIR/associated-item-duplicate-names.rs:11:5
|
--> $DIR/associated-item-duplicate-names.rs:11:5
|
||||||
|
|
|
|
||||||
|
LL | type Ty;
|
||||||
|
| -------- item in trait
|
||||||
|
...
|
||||||
LL | type Ty = ();
|
LL | type Ty = ();
|
||||||
| ------- previous definition of `Ty` here
|
| ------------- previous definition here
|
||||||
LL | type Ty = usize;
|
LL | type Ty = usize;
|
||||||
| ^^^^^^^ duplicate definition
|
| ^^^^^^^^^^^^^^^^ duplicate definition
|
||||||
|
|
||||||
error[E0201]: duplicate definitions with name `BAR`:
|
error[E0201]: duplicate definitions with name `BAR`:
|
||||||
--> $DIR/associated-item-duplicate-names.rs:13:5
|
--> $DIR/associated-item-duplicate-names.rs:13:5
|
||||||
|
|
|
|
||||||
|
LL | const BAR: u32;
|
||||||
|
| --------------- item in trait
|
||||||
|
...
|
||||||
LL | const BAR: u32 = 7;
|
LL | const BAR: u32 = 7;
|
||||||
| -------------- previous definition of `BAR` here
|
| ------------------- previous definition here
|
||||||
LL | const BAR: u32 = 8;
|
LL | const BAR: u32 = 8;
|
||||||
| ^^^^^^^^^^^^^^ duplicate definition
|
| ^^^^^^^^^^^^^^^^^^^ duplicate definition
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,26 @@
|
||||||
|
error[E0201]: duplicate definitions with name `baz`:
|
||||||
|
--> $DIR/E0201.rs:17:5
|
||||||
|
|
|
||||||
|
LL | fn baz(&self) -> bool;
|
||||||
|
| ---------------------- item in trait
|
||||||
|
...
|
||||||
|
LL | fn baz(&self) -> bool { true }
|
||||||
|
| ------------------------------ previous definition here
|
||||||
|
LL | fn baz(&self) -> bool { self.0 > 5 }
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
|
||||||
|
|
||||||
|
error[E0201]: duplicate definitions with name `Quux`:
|
||||||
|
--> $DIR/E0201.rs:18:5
|
||||||
|
|
|
||||||
|
LL | type Quux;
|
||||||
|
| ---------- item in trait
|
||||||
|
...
|
||||||
|
LL | type Quux = u32;
|
||||||
|
| ---------------- previous definition here
|
||||||
|
...
|
||||||
|
LL | type Quux = u32;
|
||||||
|
| ^^^^^^^^^^^^^^^^ duplicate definition
|
||||||
|
|
||||||
error[E0201]: duplicate definitions with name `bar`:
|
error[E0201]: duplicate definitions with name `bar`:
|
||||||
--> $DIR/E0201.rs:5:5
|
--> $DIR/E0201.rs:5:5
|
||||||
|
|
|
|
||||||
|
@ -6,23 +29,6 @@ LL | fn bar(&self) -> bool { self.0 > 5 }
|
||||||
LL | fn bar() {}
|
LL | fn bar() {}
|
||||||
| ^^^^^^^^ duplicate definition
|
| ^^^^^^^^ duplicate definition
|
||||||
|
|
||||||
error[E0201]: duplicate definitions with name `baz`:
|
|
||||||
--> $DIR/E0201.rs:17:5
|
|
||||||
|
|
|
||||||
LL | fn baz(&self) -> bool { true }
|
|
||||||
| --------------------- previous definition of `baz` here
|
|
||||||
LL | fn baz(&self) -> bool { self.0 > 5 }
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ duplicate definition
|
|
||||||
|
|
||||||
error[E0201]: duplicate definitions with name `Quux`:
|
|
||||||
--> $DIR/E0201.rs:18:5
|
|
||||||
|
|
|
||||||
LL | type Quux = u32;
|
|
||||||
| --------- previous definition of `Quux` here
|
|
||||||
...
|
|
||||||
LL | type Quux = u32;
|
|
||||||
| ^^^^^^^^^ duplicate definition
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0201`.
|
For more information about this error, try `rustc --explain E0201`.
|
||||||
|
|
26
src/test/ui/hygiene/impl_items-2.rs
Normal file
26
src/test/ui/hygiene/impl_items-2.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#![feature(decl_macro)]
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
fn foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro trait_impl() {
|
||||||
|
fn foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that we error on multiple impl items that resolve to the same trait item.
|
||||||
|
impl Trait for i32 {
|
||||||
|
trait_impl!();
|
||||||
|
fn foo() {}
|
||||||
|
//~^ ERROR duplicate definitions with name `foo`: [E0201]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Type;
|
||||||
|
|
||||||
|
// Check that we do not error with inherent impls.
|
||||||
|
impl Type {
|
||||||
|
trait_impl!();
|
||||||
|
fn foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
15
src/test/ui/hygiene/impl_items-2.stderr
Normal file
15
src/test/ui/hygiene/impl_items-2.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0201]: duplicate definitions with name `foo`:
|
||||||
|
--> $DIR/impl_items-2.rs:14:5
|
||||||
|
|
|
||||||
|
LL | fn foo() {}
|
||||||
|
| ----------- item in trait
|
||||||
|
...
|
||||||
|
LL | fn foo() {}
|
||||||
|
| ----------- previous definition here
|
||||||
|
...
|
||||||
|
LL | fn foo() {}
|
||||||
|
| ^^^^^^^^^^^ duplicate definition
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0201`.
|
|
@ -1,10 +1,13 @@
|
||||||
error[E0201]: duplicate definitions with name `bar`:
|
error[E0201]: duplicate definitions with name `bar`:
|
||||||
--> $DIR/issue-8153.rs:11:5
|
--> $DIR/issue-8153.rs:11:5
|
||||||
|
|
|
|
||||||
|
LL | fn bar(&self) -> isize;
|
||||||
|
| ----------------------- item in trait
|
||||||
|
...
|
||||||
LL | fn bar(&self) -> isize {1}
|
LL | fn bar(&self) -> isize {1}
|
||||||
| ---------------------- previous definition of `bar` here
|
| -------------------------- previous definition here
|
||||||
LL | fn bar(&self) -> isize {2}
|
LL | fn bar(&self) -> isize {2}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue