diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index b8cdd67519bef..739a2354ed178 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -405,9 +405,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub(super) fn report_ambiguous_assoc_item( &self, - bound1: ty::PolyTraitRef<'tcx>, - bound2: ty::PolyTraitRef<'tcx>, - matching_candidates: impl Iterator>, + matching_candidates: &[ty::PolyTraitRef<'tcx>], qself: AssocItemQSelf, assoc_tag: ty::AssocTag, assoc_ident: Ident, @@ -439,7 +437,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // predicates!). // FIXME: Turn this into a structured, translatable & more actionable suggestion. let mut where_bounds = vec![]; - for bound in [bound1, bound2].into_iter().chain(matching_candidates) { + for &bound in matching_candidates { let bound_id = bound.def_id(); let assoc_item = tcx.associated_items(bound_id).find_by_ident_and_kind( tcx, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 943256ce07352..cd958eca4d011 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -24,6 +24,7 @@ use std::{assert_matches, slice}; use rustc_abi::FIRST_VARIANT; use rustc_ast::LitKind; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_data_structures::sso::SsoHashSet; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, StashKey, @@ -1262,6 +1263,74 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } + /// When there are multiple traits which contain an identically named + /// associated item, this function eliminates any traits which are a + /// supertrait of another candidate trait. + /// + /// This is the type-level analogue of + /// `rustc_hir_typeck::method::probe::ProbeContext::collapse_candidates_to_subtrait_pick`; + /// keep both implementations in sync. + /// + /// This implements RFC #3624. + fn collapse_candidates_to_subtrait_pick( + &self, + matching_candidates: &[ty::PolyTraitRef<'tcx>], + ) -> Option> { + if !self.tcx().features().supertrait_item_shadowing() { + return None; + } + + let mut child_trait = matching_candidates[0]; + let mut supertraits: SsoHashSet<_> = + traits::supertrait_def_ids(self.tcx(), child_trait.def_id()).collect(); + + let mut remaining_candidates: Vec<_> = matching_candidates[1..].iter().copied().collect(); + while !remaining_candidates.is_empty() { + let mut made_progress = false; + let mut next_round = vec![]; + + for remaining_trait in remaining_candidates { + if supertraits.contains(&remaining_trait.def_id()) { + made_progress = true; + continue; + } + + // This candidate is not a supertrait of the `child_trait`. + // Check if it's a subtrait of the `child_trait`, instead. + // If it is, then it must have been a subtrait of every + // other pick we've eliminated at this point. It will + // take over at this point. + let remaining_trait_supertraits: SsoHashSet<_> = + traits::supertrait_def_ids(self.tcx(), remaining_trait.def_id()).collect(); + if remaining_trait_supertraits.contains(&child_trait.def_id()) { + child_trait = remaining_trait; + supertraits = remaining_trait_supertraits; + made_progress = true; + continue; + } + + // Neither `child_trait` or the current candidate are + // supertraits of each other. + // Don't bail here, since we may be comparing two supertraits + // of a common subtrait. These two supertraits won't be related + // at all, but we will pick them up next round when we find their + // child as we continue iterating in this round. + next_round.push(remaining_trait); + } + + if made_progress { + // If we've made progress, iterate again. + remaining_candidates = next_round; + } else { + // Otherwise, we must have at least two candidates which + // are not related to each other at all. + return None; + } + } + + Some(child_trait) + } + /// Search for a single trait bound whose trait defines the associated item given by /// `assoc_ident`. /// @@ -1296,10 +1365,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; if let Some(bound2) = matching_candidates.next() { + let all_matching_candidates: Vec<_> = + [bound1, bound2].into_iter().chain(matching_candidates).collect(); + if let Some(bound) = self.collapse_candidates_to_subtrait_pick(&all_matching_candidates) + { + return Ok(bound); + } + return Err(self.report_ambiguous_assoc_item( - bound1, - bound2, - matching_candidates, + &all_matching_candidates, qself, assoc_tag, assoc_ident, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 4258896deec70..e464b61490f37 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -2359,6 +2359,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /// multiple conflicting picks if there is one pick whose trait container is a subtrait /// of the trait containers of all of the other picks. /// + /// This is the method-probe analogue of + /// `rustc_hir_analysis::hir_ty_lowering::HirTyLowerer::collapse_candidates_to_subtrait_pick`; + /// keep both implementations in sync. + /// /// This implements RFC #3624. fn collapse_candidates_to_subtrait_pick( &self, diff --git a/tests/ui/README.md b/tests/ui/README.md index f76cd507056fe..7ec7d6565c972 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -1341,6 +1341,10 @@ Generic collection of tests for suggestions, when no more specific directories a **FIXME**: Some overlap with `tests/ui/did_you_mean/`, that directory should probably be moved under here. +## `tests/ui/supertrait-shadowing/` + +Tests for supertrait item shadowing (RFC 3624). + ## `tests/ui/svh/`: Strict Version Hash Tests on the *Strict Version Hash* (SVH, also known as the "crate hash"). diff --git a/tests/ui/methods/supertrait-shadowing/assoc-const.rs b/tests/ui/methods/supertrait-shadowing/assoc-const.rs deleted file mode 100644 index 01d045b9fb74f..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/assoc-const.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ run-pass - -#![feature(supertrait_item_shadowing)] -#![allow(dead_code)] - -trait A { - const CONST: i32; -} -impl A for T { - const CONST: i32 = 1; -} - -trait B: A { - const CONST: i32; -} -impl B for T { - const CONST: i32 = 2; -} - -fn main() { - assert_eq!(i32::CONST, 2) -} diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs b/tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs deleted file mode 100644 index ce56c25df19ea..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs +++ /dev/null @@ -1,33 +0,0 @@ -//@ run-pass - -#![feature(supertrait_item_shadowing)] -#![warn(resolving_to_items_shadowing_supertrait_items)] -#![warn(shadowing_supertrait_items)] -#![allow(dead_code)] - -trait A { - fn hello(&self) -> &'static str { - "A" - } -} -impl A for T {} - -trait B { - fn hello(&self) -> &'static str { - "B" - } -} -impl B for T {} - -trait C: A + B { - fn hello(&self) -> &'static str { - //~^ WARN trait item `hello` from `C` shadows identically named item - "C" - } -} -impl C for T {} - -fn main() { - assert_eq!(().hello(), "C"); - //~^ WARN trait item `hello` from `C` shadows identically named item from supertrait -} diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-3.rs b/tests/ui/methods/supertrait-shadowing/common-ancestor-3.rs deleted file mode 100644 index b29f3c8d014ec..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/common-ancestor-3.rs +++ /dev/null @@ -1,43 +0,0 @@ -//@ run-pass - -#![feature(supertrait_item_shadowing)] -#![warn(resolving_to_items_shadowing_supertrait_items)] -#![warn(shadowing_supertrait_items)] -#![allow(dead_code)] - -trait A { - fn hello(&self) -> &'static str { - "A" - } -} -impl A for T {} - -trait B { - fn hello(&self) -> &'static str { - "B" - } -} -impl B for T {} - -trait C: A + B { - fn hello(&self) -> &'static str { - //~^ WARN trait item `hello` from `C` shadows identically named item - "C" - } -} -impl C for T {} - -// `D` extends `C` which extends `B` and `A` - -trait D: C { - fn hello(&self) -> &'static str { - //~^ WARN trait item `hello` from `D` shadows identically named item - "D" - } -} -impl D for T {} - -fn main() { - assert_eq!(().hello(), "D"); - //~^ WARN trait item `hello` from `D` shadows identically named item from supertrait -} diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr b/tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr deleted file mode 100644 index 28fe7f72f94c3..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr +++ /dev/null @@ -1,68 +0,0 @@ -warning: trait item `hello` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:23:5 - | -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: items from several supertraits are shadowed: `B` and `A` - --> $DIR/common-ancestor-3.rs:9:5 - | -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: the lint level is defined here - --> $DIR/common-ancestor-3.rs:5:9 - | -LL | #![warn(shadowing_supertrait_items)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: trait item `hello` from `D` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:33:5 - | -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: items from several supertraits are shadowed: `C`, `B`, and `A` - --> $DIR/common-ancestor-3.rs:9:5 - | -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: trait item `hello` from `D` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:41:19 - | -LL | assert_eq!(().hello(), "D"); - | ^^^^^ - | -note: item from `D` shadows a supertrait item - --> $DIR/common-ancestor-3.rs:33:5 - | -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: items from several supertraits are shadowed: `A`, `B`, and `C` - --> $DIR/common-ancestor-3.rs:9:5 - | -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: the lint level is defined here - --> $DIR/common-ancestor-3.rs:4:9 - | -LL | #![warn(resolving_to_items_shadowing_supertrait_items)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: 3 warnings emitted - diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor.rs b/tests/ui/methods/supertrait-shadowing/common-ancestor.rs deleted file mode 100644 index b288d6e22b8c3..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/common-ancestor.rs +++ /dev/null @@ -1,26 +0,0 @@ -//@ run-pass - -#![feature(supertrait_item_shadowing)] -#![warn(resolving_to_items_shadowing_supertrait_items)] -#![warn(shadowing_supertrait_items)] -#![allow(dead_code)] - -trait A { - fn hello(&self) -> &'static str { - "A" - } -} -impl A for T {} - -trait B: A { - fn hello(&self) -> &'static str { - //~^ WARN trait item `hello` from `B` shadows identically named item - "B" - } -} -impl B for T {} - -fn main() { - assert_eq!(().hello(), "B"); - //~^ WARN trait item `hello` from `B` shadows identically named item from supertrait -} diff --git a/tests/ui/methods/supertrait-shadowing/definition-site.rs b/tests/ui/methods/supertrait-shadowing/definition-site.rs deleted file mode 100644 index 248df032736f6..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/definition-site.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![feature(supertrait_item_shadowing)] -#![deny(shadowing_supertrait_items)] - -trait SuperSuper { - fn method(); -} - -trait Super: SuperSuper { - fn method(); - //~^ ERROR trait item `method` from `Super` shadows identically named item -} - -trait Sub: Super { - fn method(); - //~^ ERROR trait item `method` from `Sub` shadows identically named item -} - -fn main() {} diff --git a/tests/ui/methods/supertrait-shadowing/definition-site.stderr b/tests/ui/methods/supertrait-shadowing/definition-site.stderr deleted file mode 100644 index 1e35a753a9ebc..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/definition-site.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error: trait item `method` from `Super` shadows identically named item from supertrait - --> $DIR/definition-site.rs:9:5 - | -LL | fn method(); - | ^^^^^^^^^^^^ - | -note: item from `SuperSuper` is shadowed by a subtrait item - --> $DIR/definition-site.rs:5:5 - | -LL | fn method(); - | ^^^^^^^^^^^^ -note: the lint level is defined here - --> $DIR/definition-site.rs:2:9 - | -LL | #![deny(shadowing_supertrait_items)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: trait item `method` from `Sub` shadows identically named item from supertrait - --> $DIR/definition-site.rs:14:5 - | -LL | fn method(); - | ^^^^^^^^^^^^ - | -note: items from several supertraits are shadowed: `Super` and `SuperSuper` - --> $DIR/definition-site.rs:5:5 - | -LL | fn method(); - | ^^^^^^^^^^^^ -... -LL | fn method(); - | ^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.rs b/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.rs deleted file mode 100644 index b49476c7a4f68..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![feature(supertrait_item_shadowing)] - -trait A { - fn hello(&self) -> &'static str { - "A" - } -} -impl A for T {} - -trait B { - fn hello(&self) -> &'static str { - "B" - } -} -impl B for T {} - -trait C: A + B { - fn hello(&self) -> &'static str { - "C" - } -} -impl C for T {} - -// Since `D` is not a subtrait of `C`, -// we have no obvious lower bound. - -trait D: B { - fn hello(&self) -> &'static str { - "D" - } -} -impl D for T {} - -fn main() { - ().hello(); - //~^ ERROR multiple applicable items in scope -} diff --git a/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.stderr b/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.stderr deleted file mode 100644 index 745f61d00d660..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.stderr +++ /dev/null @@ -1,50 +0,0 @@ -error[E0034]: multiple applicable items in scope - --> $DIR/no-common-ancestor-2.rs:35:8 - | -LL | ().hello(); - | ^^^^^ multiple `hello` found - | -note: candidate #1 is defined in an impl of the trait `A` for the type `T` - --> $DIR/no-common-ancestor-2.rs:4:5 - | -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: candidate #2 is defined in an impl of the trait `B` for the type `T` - --> $DIR/no-common-ancestor-2.rs:11:5 - | -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: candidate #3 is defined in an impl of the trait `C` for the type `T` - --> $DIR/no-common-ancestor-2.rs:18:5 - | -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: candidate #4 is defined in an impl of the trait `D` for the type `T` - --> $DIR/no-common-ancestor-2.rs:28:5 - | -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: disambiguate the method for candidate #1 - | -LL - ().hello(); -LL + A::hello(&()); - | -help: disambiguate the method for candidate #2 - | -LL - ().hello(); -LL + B::hello(&()); - | -help: disambiguate the method for candidate #3 - | -LL - ().hello(); -LL + C::hello(&()); - | -help: disambiguate the method for candidate #4 - | -LL - ().hello(); -LL + D::hello(&()); - | - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/supertrait-shadowing/no-common-ancestor.rs b/tests/ui/methods/supertrait-shadowing/no-common-ancestor.rs deleted file mode 100644 index 03c822eb7375e..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/no-common-ancestor.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![feature(supertrait_item_shadowing)] - -trait A { - fn hello(&self) -> &'static str { - "A" - } -} -impl A for T {} - -trait B { - fn hello(&self) -> &'static str { - "B" - } -} -impl B for T {} - -fn main() { - ().hello(); - //~^ ERROR multiple applicable items in scope -} diff --git a/tests/ui/methods/supertrait-shadowing/no-common-ancestor.stderr b/tests/ui/methods/supertrait-shadowing/no-common-ancestor.stderr deleted file mode 100644 index 29cf7ff1dbb11..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/no-common-ancestor.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error[E0034]: multiple applicable items in scope - --> $DIR/no-common-ancestor.rs:18:8 - | -LL | ().hello(); - | ^^^^^ multiple `hello` found - | -note: candidate #1 is defined in an impl of the trait `A` for the type `T` - --> $DIR/no-common-ancestor.rs:4:5 - | -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: candidate #2 is defined in an impl of the trait `B` for the type `T` - --> $DIR/no-common-ancestor.rs:11:5 - | -LL | fn hello(&self) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: disambiguate the method for candidate #1 - | -LL - ().hello(); -LL + A::hello(&()); - | -help: disambiguate the method for candidate #2 - | -LL - ().hello(); -LL + B::hello(&()); - | - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/supertrait-shadowing/out-of-scope.rs b/tests/ui/methods/supertrait-shadowing/out-of-scope.rs deleted file mode 100644 index 4112634399b78..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/out-of-scope.rs +++ /dev/null @@ -1,23 +0,0 @@ -//@ run-pass - -#![allow(dead_code)] - -mod out_of_scope { - pub trait Subtrait: super::Supertrait { - fn hello(&self) -> &'static str { - "subtrait" - } - } - impl Subtrait for T {} -} - -trait Supertrait { - fn hello(&self) -> &'static str { - "supertrait" - } -} -impl Supertrait for T {} - -fn main() { - assert_eq!(().hello(), "supertrait"); -} diff --git a/tests/ui/methods/supertrait-shadowing/type-dependent.rs b/tests/ui/methods/supertrait-shadowing/type-dependent.rs deleted file mode 100644 index 4a5af1d598812..0000000000000 --- a/tests/ui/methods/supertrait-shadowing/type-dependent.rs +++ /dev/null @@ -1,28 +0,0 @@ -//@ run-pass - -// Makes sure we can shadow with type-dependent method syntax. - -#![feature(supertrait_item_shadowing)] -#![allow(dead_code)] - -trait A { - fn hello() -> &'static str { - "A" - } -} -impl A for T {} - -trait B: A { - fn hello() -> &'static str { - "B" - } -} -impl B for T {} - -fn foo() -> &'static str { - T::hello() -} - -fn main() { - assert_eq!(foo::<()>(), "B"); -} diff --git a/tests/ui/supertrait-shadowing/assoc-const.rs b/tests/ui/supertrait-shadowing/assoc-const.rs new file mode 100644 index 0000000000000..be0d990284b0c --- /dev/null +++ b/tests/ui/supertrait-shadowing/assoc-const.rs @@ -0,0 +1,31 @@ +//@ run-pass + +#![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] +#![allow(dead_code)] + +trait A { + const CONST: i32; +} +impl A for T { + const CONST: i32 = 1; +} + +trait B: A { + type const CONST: i32; +} +impl B for T { + type const CONST: i32 = 2; +} + +trait C: B {} +impl C for T {} + +fn main() { + assert_eq!(i32::CONST, 2); + generic::(); +} + +fn generic>() { + assert_eq!(T::CONST, 2); +} diff --git a/tests/ui/supertrait-shadowing/assoc-type-fail.rs b/tests/ui/supertrait-shadowing/assoc-type-fail.rs new file mode 100644 index 0000000000000..5df4edb7e96e2 --- /dev/null +++ b/tests/ui/supertrait-shadowing/assoc-type-fail.rs @@ -0,0 +1,47 @@ +#![feature(supertrait_item_shadowing)] +#![allow(dead_code)] + +use std::mem::size_of; + +trait A { + type Assoc; +} +impl A for X { + type Assoc = i8; +} + +trait B: A { + type Assoc; +} +impl B for X { + type Assoc = i16; +} + +trait C: B {} +impl C for X {} + +fn main() { + b_unbound::(); + c_unbound::(); + + b_assoc_is_a::(); + //~^ ERROR type mismatch resolving `::Assoc == i8` + c_assoc_is_a::(); + //~^ ERROR type mismatch resolving `::Assoc == i8` +} + +fn b_unbound() { + let _ = size_of::(); +} + +fn c_unbound() { + let _ = size_of::(); +} + +fn b_assoc_is_a>() { + let _ = size_of::(); +} + +fn c_assoc_is_a>() { + let _ = size_of::(); +} diff --git a/tests/ui/supertrait-shadowing/assoc-type-fail.stderr b/tests/ui/supertrait-shadowing/assoc-type-fail.stderr new file mode 100644 index 0000000000000..36a9bd082aaf6 --- /dev/null +++ b/tests/ui/supertrait-shadowing/assoc-type-fail.stderr @@ -0,0 +1,37 @@ +error[E0271]: type mismatch resolving `::Assoc == i8` + --> $DIR/assoc-type-fail.rs:27:20 + | +LL | b_assoc_is_a::(); + | ^^^ type mismatch resolving `::Assoc == i8` + | +note: expected this to be `i8` + --> $DIR/assoc-type-fail.rs:17:18 + | +LL | type Assoc = i16; + | ^^^ +note: required by a bound in `b_assoc_is_a` + --> $DIR/assoc-type-fail.rs:41:22 + | +LL | fn b_assoc_is_a>() { + | ^^^^^^^^^^ required by this bound in `b_assoc_is_a` + +error[E0271]: type mismatch resolving `::Assoc == i8` + --> $DIR/assoc-type-fail.rs:29:20 + | +LL | c_assoc_is_a::(); + | ^^^ type mismatch resolving `::Assoc == i8` + | +note: expected this to be `i8` + --> $DIR/assoc-type-fail.rs:17:18 + | +LL | type Assoc = i16; + | ^^^ +note: required by a bound in `c_assoc_is_a` + --> $DIR/assoc-type-fail.rs:45:22 + | +LL | fn c_assoc_is_a>() { + | ^^^^^^^^^^ required by this bound in `c_assoc_is_a` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/supertrait-shadowing/assoc-type-predicates.rs b/tests/ui/supertrait-shadowing/assoc-type-predicates.rs new file mode 100644 index 0000000000000..55d2b84a50f9a --- /dev/null +++ b/tests/ui/supertrait-shadowing/assoc-type-predicates.rs @@ -0,0 +1,45 @@ +//@ normalize-stderr: "assoc_type_predicates\[[^\]]+\]" -> "assoc_type_predicates[HASH]" + +#![feature(rustc_attrs)] +#![feature(supertrait_item_shadowing)] +#![allow(dead_code)] + +trait A { + type Assoc; +} +impl A for T { + type Assoc = i8; +} + +trait B: A { + type Assoc; +} +impl B for T { + type Assoc = i16; +} + +trait C: B {} +impl C for T {} + +#[rustc_dump_predicates] +fn a_bound>() {} +//~^ ERROR rustc_dump_predicates +//~| NOTE TraitPredicate( +//~| NOTE TraitPredicate( +//~| NOTE A::Assoc + +#[rustc_dump_predicates] +fn b_bound>() {} +//~^ ERROR rustc_dump_predicates +//~| NOTE TraitPredicate( +//~| NOTE TraitPredicate( +//~| NOTE B::Assoc + +#[rustc_dump_predicates] +fn c_bound>() {} +//~^ ERROR rustc_dump_predicates +//~| NOTE TraitPredicate( +//~| NOTE TraitPredicate( +//~| NOTE B::Assoc + +fn main() {} diff --git a/tests/ui/supertrait-shadowing/assoc-type-predicates.stderr b/tests/ui/supertrait-shadowing/assoc-type-predicates.stderr new file mode 100644 index 0000000000000..cad6c9342f2ba --- /dev/null +++ b/tests/ui/supertrait-shadowing/assoc-type-predicates.stderr @@ -0,0 +1,32 @@ +error: rustc_dump_predicates + --> $DIR/assoc-type-predicates.rs:25:1 + | +LL | fn a_bound>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: ProjectionPredicate(AliasTerm { args: [T/#0], kind: ProjectionTy { def_id: DefId(0:4 ~ assoc_type_predicates[HASH]::A::Assoc) }, .. }, Term::Ty(i8)), bound_vars: [] } + +error: rustc_dump_predicates + --> $DIR/assoc-type-predicates.rs:32:1 + | +LL | fn b_bound>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: ProjectionPredicate(AliasTerm { args: [T/#0], kind: ProjectionTy { def_id: DefId(0:9 ~ assoc_type_predicates[HASH]::B::Assoc) }, .. }, Term::Ty(i16)), bound_vars: [] } + +error: rustc_dump_predicates + --> $DIR/assoc-type-predicates.rs:39:1 + | +LL | fn c_bound>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: ProjectionPredicate(AliasTerm { args: [T/#0], kind: ProjectionTy { def_id: DefId(0:9 ~ assoc_type_predicates[HASH]::B::Assoc) }, .. }, Term::Ty(i16)), bound_vars: [] } + +error: aborting due to 3 previous errors + diff --git a/tests/ui/supertrait-shadowing/assoc-type.rs b/tests/ui/supertrait-shadowing/assoc-type.rs new file mode 100644 index 0000000000000..9e9799397c571 --- /dev/null +++ b/tests/ui/supertrait-shadowing/assoc-type.rs @@ -0,0 +1,53 @@ +//@ run-pass +//@ check-run-results + +#![feature(supertrait_item_shadowing)] +#![allow(dead_code)] + +use std::mem::size_of; + +trait A { + type Assoc; +} +impl A for T { + type Assoc = i8; +} + +trait B: A { + type Assoc; +} +impl B for T { + type Assoc = i16; +} + +trait C: B {} +impl C for T {} + +fn main() { + generic::(); + generic2::(); + generic3::(); + generic4::(); + generic5::(); +} + +fn generic() { + assert_eq!(size_of::(), 2); +} + +fn generic2>() { + assert_eq!(size_of::(), 1); +} + +fn generic3>() { + assert_eq!(size_of::(), 2); +} + +fn generic4>() { + assert_eq!(size_of::(), 2); +} + +fn generic5() { + assert_eq!(size_of::<::Assoc>(), 1); + assert_eq!(size_of::<::Assoc>(), 2); +} diff --git a/tests/ui/methods/supertrait-shadowing/auxiliary/shadowed_stability.rs b/tests/ui/supertrait-shadowing/auxiliary/shadowed_stability.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/auxiliary/shadowed_stability.rs rename to tests/ui/supertrait-shadowing/auxiliary/shadowed_stability.rs diff --git a/tests/ui/supertrait-shadowing/common-ancestor-2.rs b/tests/ui/supertrait-shadowing/common-ancestor-2.rs new file mode 100644 index 0000000000000..908c5d2bf2199 --- /dev/null +++ b/tests/ui/supertrait-shadowing/common-ancestor-2.rs @@ -0,0 +1,59 @@ +//@ run-pass + +#![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] +#![warn(resolving_to_items_shadowing_supertrait_items)] +#![warn(shadowing_supertrait_items)] +#![allow(dead_code)] + +use std::mem::size_of; + +trait A { + fn hello(&self) -> &'static str { + "A" + } + type Assoc; + const CONST: i32; +} +impl A for T { + type Assoc = i8; + const CONST: i32 = 1; +} + +trait B { + fn hello(&self) -> &'static str { + "B" + } + type Assoc; + const CONST: i32; +} +impl B for T { + type Assoc = i16; + const CONST: i32 = 2; +} + +trait C: A + B { + fn hello(&self) -> &'static str { + //~^ WARN trait item `hello` from `C` shadows identically named item + "C" + } + type Assoc; + //~^ WARN trait item `Assoc` from `C` shadows identically named item + type const CONST: i32; + //~^ WARN trait item `CONST` from `C` shadows identically named item +} +impl C for T { + type Assoc = i32; + type const CONST: i32 = 3; +} + +fn main() { + assert_eq!(().hello(), "C"); + //~^ WARN trait item `hello` from `C` shadows identically named item from supertrait + check::<()>(); +} + +fn check() { + assert_eq!(size_of::(), 4); + assert_eq!(T::CONST, 3); +} diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr b/tests/ui/supertrait-shadowing/common-ancestor-2.stderr similarity index 55% rename from tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr rename to tests/ui/supertrait-shadowing/common-ancestor-2.stderr index b0f61b46b6911..646726b835041 100644 --- a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr +++ b/tests/ui/supertrait-shadowing/common-ancestor-2.stderr @@ -1,11 +1,11 @@ warning: trait item `hello` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-2.rs:23:5 + --> $DIR/common-ancestor-2.rs:36:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: items from several supertraits are shadowed: `B` and `A` - --> $DIR/common-ancestor-2.rs:9:5 + --> $DIR/common-ancestor-2.rs:12:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,24 +13,54 @@ LL | fn hello(&self) -> &'static str { LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/common-ancestor-2.rs:5:9 + --> $DIR/common-ancestor-2.rs:6:9 | LL | #![warn(shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: trait item `Assoc` from `C` shadows identically named item from supertrait + --> $DIR/common-ancestor-2.rs:40:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `B` and `A` + --> $DIR/common-ancestor-2.rs:15:5 + | +LL | type Assoc; + | ^^^^^^^^^^ +... +LL | type Assoc; + | ^^^^^^^^^^ + +warning: trait item `CONST` from `C` shadows identically named item from supertrait + --> $DIR/common-ancestor-2.rs:42:5 + | +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `B` and `A` + --> $DIR/common-ancestor-2.rs:16:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +... +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + warning: trait item `hello` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-2.rs:31:19 + --> $DIR/common-ancestor-2.rs:51:19 | LL | assert_eq!(().hello(), "C"); | ^^^^^ | note: item from `C` shadows a supertrait item - --> $DIR/common-ancestor-2.rs:23:5 + --> $DIR/common-ancestor-2.rs:36:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: items from several supertraits are shadowed: `A` and `B` - --> $DIR/common-ancestor-2.rs:9:5 + --> $DIR/common-ancestor-2.rs:12:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -38,10 +68,10 @@ LL | fn hello(&self) -> &'static str { LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/common-ancestor-2.rs:4:9 + --> $DIR/common-ancestor-2.rs:5:9 | LL | #![warn(resolving_to_items_shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 2 warnings emitted +warning: 4 warnings emitted diff --git a/tests/ui/supertrait-shadowing/common-ancestor-3.rs b/tests/ui/supertrait-shadowing/common-ancestor-3.rs new file mode 100644 index 0000000000000..ade23ca88aec2 --- /dev/null +++ b/tests/ui/supertrait-shadowing/common-ancestor-3.rs @@ -0,0 +1,76 @@ +//@ run-pass + +#![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] +#![warn(resolving_to_items_shadowing_supertrait_items)] +#![warn(shadowing_supertrait_items)] +#![allow(dead_code)] + +use std::mem::size_of; + +trait A { + fn hello(&self) -> &'static str { + "A" + } + type Assoc; + const CONST: i32; +} +impl A for T { + type Assoc = i8; + const CONST: i32 = 1; +} + +trait B { + fn hello(&self) -> &'static str { + "B" + } + type Assoc; + const CONST: i32; +} +impl B for T { + type Assoc = i16; + const CONST: i32 = 2; +} + +trait C: A + B { + fn hello(&self) -> &'static str { + //~^ WARN trait item `hello` from `C` shadows identically named item + "C" + } + type Assoc; + //~^ WARN trait item `Assoc` from `C` shadows identically named item + type const CONST: i32; + //~^ WARN trait item `CONST` from `C` shadows identically named item +} +impl C for T { + type Assoc = i32; + type const CONST: i32 = 3; +} + +// `D` extends `C` which extends `B` and `A` + +trait D: C { + fn hello(&self) -> &'static str { + //~^ WARN trait item `hello` from `D` shadows identically named item + "D" + } + type Assoc; + //~^ WARN trait item `Assoc` from `D` shadows identically named item + type const CONST: i32; + //~^ WARN trait item `CONST` from `D` shadows identically named item +} +impl D for T { + type Assoc = i64; + type const CONST: i32 = 4; +} + +fn main() { + assert_eq!(().hello(), "D"); + //~^ WARN trait item `hello` from `D` shadows identically named item from supertrait + check::<()>(); +} + +fn check() { + assert_eq!(size_of::(), 8); + assert_eq!(T::CONST, 4); +} diff --git a/tests/ui/supertrait-shadowing/common-ancestor-3.stderr b/tests/ui/supertrait-shadowing/common-ancestor-3.stderr new file mode 100644 index 0000000000000..62132832da4ba --- /dev/null +++ b/tests/ui/supertrait-shadowing/common-ancestor-3.stderr @@ -0,0 +1,134 @@ +warning: trait item `hello` from `C` shadows identically named item from supertrait + --> $DIR/common-ancestor-3.rs:36:5 + | +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `B` and `A` + --> $DIR/common-ancestor-3.rs:12:5 + | +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/common-ancestor-3.rs:6:9 + | +LL | #![warn(shadowing_supertrait_items)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait item `Assoc` from `C` shadows identically named item from supertrait + --> $DIR/common-ancestor-3.rs:40:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `B` and `A` + --> $DIR/common-ancestor-3.rs:15:5 + | +LL | type Assoc; + | ^^^^^^^^^^ +... +LL | type Assoc; + | ^^^^^^^^^^ + +warning: trait item `CONST` from `C` shadows identically named item from supertrait + --> $DIR/common-ancestor-3.rs:42:5 + | +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `B` and `A` + --> $DIR/common-ancestor-3.rs:16:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +... +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + +warning: trait item `hello` from `D` shadows identically named item from supertrait + --> $DIR/common-ancestor-3.rs:53:5 + | +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `C`, `B`, and `A` + --> $DIR/common-ancestor-3.rs:12:5 + | +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait item `Assoc` from `D` shadows identically named item from supertrait + --> $DIR/common-ancestor-3.rs:57:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `C`, `B`, and `A` + --> $DIR/common-ancestor-3.rs:15:5 + | +LL | type Assoc; + | ^^^^^^^^^^ +... +LL | type Assoc; + | ^^^^^^^^^^ +... +LL | type Assoc; + | ^^^^^^^^^^ + +warning: trait item `CONST` from `D` shadows identically named item from supertrait + --> $DIR/common-ancestor-3.rs:59:5 + | +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `C`, `B`, and `A` + --> $DIR/common-ancestor-3.rs:16:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +... +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +... +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: trait item `hello` from `D` shadows identically named item from supertrait + --> $DIR/common-ancestor-3.rs:68:19 + | +LL | assert_eq!(().hello(), "D"); + | ^^^^^ + | +note: item from `D` shadows a supertrait item + --> $DIR/common-ancestor-3.rs:53:5 + | +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: items from several supertraits are shadowed: `A`, `B`, and `C` + --> $DIR/common-ancestor-3.rs:12:5 + | +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/common-ancestor-3.rs:5:9 + | +LL | #![warn(resolving_to_items_shadowing_supertrait_items)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 7 warnings emitted + diff --git a/tests/ui/supertrait-shadowing/common-ancestor.rs b/tests/ui/supertrait-shadowing/common-ancestor.rs new file mode 100644 index 0000000000000..903f85957870b --- /dev/null +++ b/tests/ui/supertrait-shadowing/common-ancestor.rs @@ -0,0 +1,47 @@ +//@ run-pass + +#![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] +#![warn(resolving_to_items_shadowing_supertrait_items)] +#![warn(shadowing_supertrait_items)] +#![allow(dead_code)] + +use std::mem::size_of; + +trait A { + fn hello(&self) -> &'static str { + "A" + } + type Assoc; + const CONST: i32; +} +impl A for T { + type Assoc = i8; + const CONST: i32 = 1; +} + +trait B: A { + fn hello(&self) -> &'static str { + //~^ WARN trait item `hello` from `B` shadows identically named item + "B" + } + type Assoc; + //~^ WARN trait item `Assoc` from `B` shadows identically named item + type const CONST: i32; + //~^ WARN trait item `CONST` from `B` shadows identically named item +} +impl B for T { + type Assoc = i16; + type const CONST: i32 = 2; +} + +fn main() { + assert_eq!(().hello(), "B"); + //~^ WARN trait item `hello` from `B` shadows identically named item from supertrait + check::<()>(); +} + +fn check() { + assert_eq!(size_of::(), 2); + assert_eq!(T::CONST, 2); +} diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor.stderr b/tests/ui/supertrait-shadowing/common-ancestor.stderr similarity index 56% rename from tests/ui/methods/supertrait-shadowing/common-ancestor.stderr rename to tests/ui/supertrait-shadowing/common-ancestor.stderr index 9afedeab5e2c2..9b13537cf800c 100644 --- a/tests/ui/methods/supertrait-shadowing/common-ancestor.stderr +++ b/tests/ui/supertrait-shadowing/common-ancestor.stderr @@ -1,41 +1,65 @@ warning: trait item `hello` from `B` shadows identically named item from supertrait - --> $DIR/common-ancestor.rs:16:5 + --> $DIR/common-ancestor.rs:24:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: item from `A` is shadowed by a subtrait item - --> $DIR/common-ancestor.rs:9:5 + --> $DIR/common-ancestor.rs:12:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/common-ancestor.rs:5:9 + --> $DIR/common-ancestor.rs:6:9 | LL | #![warn(shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: trait item `Assoc` from `B` shadows identically named item from supertrait + --> $DIR/common-ancestor.rs:28:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + | +note: item from `A` is shadowed by a subtrait item + --> $DIR/common-ancestor.rs:15:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + +warning: trait item `CONST` from `B` shadows identically named item from supertrait + --> $DIR/common-ancestor.rs:30:5 + | +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: item from `A` is shadowed by a subtrait item + --> $DIR/common-ancestor.rs:16:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + warning: trait item `hello` from `B` shadows identically named item from supertrait - --> $DIR/common-ancestor.rs:24:19 + --> $DIR/common-ancestor.rs:39:19 | LL | assert_eq!(().hello(), "B"); | ^^^^^ | note: item from `B` shadows a supertrait item - --> $DIR/common-ancestor.rs:16:5 + --> $DIR/common-ancestor.rs:24:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: item from `A` is shadowed by a subtrait item - --> $DIR/common-ancestor.rs:9:5 + --> $DIR/common-ancestor.rs:12:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/common-ancestor.rs:4:9 + --> $DIR/common-ancestor.rs:5:9 | LL | #![warn(resolving_to_items_shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 2 warnings emitted +warning: 4 warnings emitted diff --git a/tests/ui/supertrait-shadowing/definition-site.rs b/tests/ui/supertrait-shadowing/definition-site.rs new file mode 100644 index 0000000000000..3309ee97e9f00 --- /dev/null +++ b/tests/ui/supertrait-shadowing/definition-site.rs @@ -0,0 +1,28 @@ +#![feature(supertrait_item_shadowing)] +#![deny(shadowing_supertrait_items)] + +trait SuperSuper { + fn method(); + const CONST: i32; + type Assoc; +} + +trait Super: SuperSuper { + fn method(); + //~^ ERROR trait item `method` from `Super` shadows identically named item + const CONST: i32; + //~^ ERROR trait item `CONST` from `Super` shadows identically named item + type Assoc; + //~^ ERROR trait item `Assoc` from `Super` shadows identically named item +} + +trait Sub: Super { + fn method(); + //~^ ERROR trait item `method` from `Sub` shadows identically named item + const CONST: i32; + //~^ ERROR trait item `CONST` from `Sub` shadows identically named item + type Assoc; + //~^ ERROR trait item `Assoc` from `Sub` shadows identically named item +} + +fn main() {} diff --git a/tests/ui/supertrait-shadowing/definition-site.stderr b/tests/ui/supertrait-shadowing/definition-site.stderr new file mode 100644 index 0000000000000..faf01cc711c6a --- /dev/null +++ b/tests/ui/supertrait-shadowing/definition-site.stderr @@ -0,0 +1,88 @@ +error: trait item `method` from `Super` shadows identically named item from supertrait + --> $DIR/definition-site.rs:11:5 + | +LL | fn method(); + | ^^^^^^^^^^^^ + | +note: item from `SuperSuper` is shadowed by a subtrait item + --> $DIR/definition-site.rs:5:5 + | +LL | fn method(); + | ^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/definition-site.rs:2:9 + | +LL | #![deny(shadowing_supertrait_items)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: trait item `CONST` from `Super` shadows identically named item from supertrait + --> $DIR/definition-site.rs:13:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + | +note: item from `SuperSuper` is shadowed by a subtrait item + --> $DIR/definition-site.rs:6:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + +error: trait item `Assoc` from `Super` shadows identically named item from supertrait + --> $DIR/definition-site.rs:15:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + | +note: item from `SuperSuper` is shadowed by a subtrait item + --> $DIR/definition-site.rs:7:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + +error: trait item `method` from `Sub` shadows identically named item from supertrait + --> $DIR/definition-site.rs:20:5 + | +LL | fn method(); + | ^^^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `Super` and `SuperSuper` + --> $DIR/definition-site.rs:5:5 + | +LL | fn method(); + | ^^^^^^^^^^^^ +... +LL | fn method(); + | ^^^^^^^^^^^^ + +error: trait item `CONST` from `Sub` shadows identically named item from supertrait + --> $DIR/definition-site.rs:22:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `Super` and `SuperSuper` + --> $DIR/definition-site.rs:6:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +... +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + +error: trait item `Assoc` from `Sub` shadows identically named item from supertrait + --> $DIR/definition-site.rs:24:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `Super` and `SuperSuper` + --> $DIR/definition-site.rs:7:5 + | +LL | type Assoc; + | ^^^^^^^^^^ +... +LL | type Assoc; + | ^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.rs b/tests/ui/supertrait-shadowing/false-subtrait-after-inference.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.rs rename to tests/ui/supertrait-shadowing/false-subtrait-after-inference.rs diff --git a/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.stderr b/tests/ui/supertrait-shadowing/false-subtrait-after-inference.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.stderr rename to tests/ui/supertrait-shadowing/false-subtrait-after-inference.stderr diff --git a/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs b/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs new file mode 100644 index 0000000000000..957aabf5a51f8 --- /dev/null +++ b/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs @@ -0,0 +1,68 @@ +#![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] + +use std::mem::size_of; + +trait A { + fn hello(&self) -> &'static str { + "A" + } + type Assoc; + const CONST: i32; +} +impl A for T { + type Assoc = i8; + const CONST: i32 = 1; +} + +trait B { + fn hello(&self) -> &'static str { + "B" + } + type Assoc; + const CONST: i32; +} +impl B for T { + type Assoc = i16; + const CONST: i32 = 2; +} + +trait C: A + B { + fn hello(&self) -> &'static str { + "C" + } + type Assoc; + type const CONST: i32; +} +impl C for T { + type Assoc = i32; + type const CONST: i32 = 3; +} + +// Since `D` is not a subtrait of `C`, +// we have no obvious lower bound. + +trait D: B { + fn hello(&self) -> &'static str { + "D" + } + type Assoc; + type const CONST: i32; +} +impl D for T { + type Assoc = i64; + type const CONST: i32 = 4; +} + +fn main() { + ().hello(); + //~^ ERROR multiple applicable items in scope + check::<()>(); +} + +fn check() { + let _ = size_of::(); + //~^ ERROR ambiguous associated type `Assoc` in bounds of `T` + let _ = T::CONST; + //~^ ERROR multiple applicable items in scope +} diff --git a/tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr b/tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr new file mode 100644 index 0000000000000..987adcfbbe959 --- /dev/null +++ b/tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr @@ -0,0 +1,131 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/no-common-ancestor-2.rs:58:8 + | +LL | ().hello(); + | ^^^^^ multiple `hello` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/no-common-ancestor-2.rs:7:5 + | +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/no-common-ancestor-2.rs:19:5 + | +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #3 is defined in an impl of the trait `C` for the type `T` + --> $DIR/no-common-ancestor-2.rs:31:5 + | +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #4 is defined in an impl of the trait `D` for the type `T` + --> $DIR/no-common-ancestor-2.rs:46:5 + | +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: disambiguate the method for candidate #1 + | +LL - ().hello(); +LL + A::hello(&()); + | +help: disambiguate the method for candidate #2 + | +LL - ().hello(); +LL + B::hello(&()); + | +help: disambiguate the method for candidate #3 + | +LL - ().hello(); +LL + C::hello(&()); + | +help: disambiguate the method for candidate #4 + | +LL - ().hello(); +LL + D::hello(&()); + | + +error[E0221]: ambiguous associated type `Assoc` in bounds of `T` + --> $DIR/no-common-ancestor-2.rs:64:23 + | +LL | type Assoc; + | ---------- ambiguous `Assoc` from `A` +... +LL | type Assoc; + | ---------- ambiguous `Assoc` from `B` +... +LL | type Assoc; + | ---------- ambiguous `Assoc` from `C` +... +LL | type Assoc; + | ---------- ambiguous `Assoc` from `D` +... +LL | let _ = size_of::(); + | ^^^^^^^^ ambiguous associated type `Assoc` + | +help: use fully-qualified syntax to disambiguate + | +LL - let _ = size_of::(); +LL + let _ = size_of::<::Assoc>(); + | +help: use fully-qualified syntax to disambiguate + | +LL - let _ = size_of::(); +LL + let _ = size_of::<::Assoc>(); + | +help: use fully-qualified syntax to disambiguate + | +LL - let _ = size_of::(); +LL + let _ = size_of::<::Assoc>(); + | +help: use fully-qualified syntax to disambiguate + | +LL - let _ = size_of::(); +LL + let _ = size_of::<::Assoc>(); + | + +error[E0034]: multiple applicable items in scope + --> $DIR/no-common-ancestor-2.rs:66:16 + | +LL | let _ = T::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/no-common-ancestor-2.rs:11:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/no-common-ancestor-2.rs:23:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +note: candidate #3 is defined in the trait `C` + --> $DIR/no-common-ancestor-2.rs:35:5 + | +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ +note: candidate #4 is defined in the trait `D` + --> $DIR/no-common-ancestor-2.rs:50:5 + | +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL - let _ = T::CONST; +LL + let _ = ::CONST; + | +LL - let _ = T::CONST; +LL + let _ = ::CONST; + | +LL - let _ = T::CONST; +LL + let _ = ::CONST; + | +LL - let _ = T::CONST; +LL + let _ = ::CONST; + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0034, E0221. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/supertrait-shadowing/no-common-ancestor.rs b/tests/ui/supertrait-shadowing/no-common-ancestor.rs new file mode 100644 index 0000000000000..73209c015f8f5 --- /dev/null +++ b/tests/ui/supertrait-shadowing/no-common-ancestor.rs @@ -0,0 +1,41 @@ +#![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] + +use std::mem::size_of; + +trait A { + fn hello(&self) -> &'static str { + "A" + } + type Assoc; + const CONST: i32; +} +impl A for T { + type Assoc = i8; + const CONST: i32 = 1; +} + +trait B { + fn hello(&self) -> &'static str { + "B" + } + type Assoc; + const CONST: i32; +} +impl B for T { + type Assoc = i16; + const CONST: i32 = 2; +} + +fn main() { + ().hello(); + //~^ ERROR multiple applicable items in scope + check::<()>(); +} + +fn check() { + let _ = size_of::(); + //~^ ERROR ambiguous associated type `Assoc` in bounds of `T` + let _ = T::CONST; + //~^ ERROR multiple applicable items in scope +} diff --git a/tests/ui/supertrait-shadowing/no-common-ancestor.stderr b/tests/ui/supertrait-shadowing/no-common-ancestor.stderr new file mode 100644 index 0000000000000..78fd8f4670577 --- /dev/null +++ b/tests/ui/supertrait-shadowing/no-common-ancestor.stderr @@ -0,0 +1,79 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/no-common-ancestor.rs:31:8 + | +LL | ().hello(); + | ^^^^^ multiple `hello` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/no-common-ancestor.rs:7:5 + | +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/no-common-ancestor.rs:19:5 + | +LL | fn hello(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: disambiguate the method for candidate #1 + | +LL - ().hello(); +LL + A::hello(&()); + | +help: disambiguate the method for candidate #2 + | +LL - ().hello(); +LL + B::hello(&()); + | + +error[E0221]: ambiguous associated type `Assoc` in bounds of `T` + --> $DIR/no-common-ancestor.rs:37:23 + | +LL | type Assoc; + | ---------- ambiguous `Assoc` from `A` +... +LL | type Assoc; + | ---------- ambiguous `Assoc` from `B` +... +LL | let _ = size_of::(); + | ^^^^^^^^ ambiguous associated type `Assoc` + | +help: use fully-qualified syntax to disambiguate + | +LL - let _ = size_of::(); +LL + let _ = size_of::<::Assoc>(); + | +help: use fully-qualified syntax to disambiguate + | +LL - let _ = size_of::(); +LL + let _ = size_of::<::Assoc>(); + | + +error[E0034]: multiple applicable items in scope + --> $DIR/no-common-ancestor.rs:39:16 + | +LL | let _ = T::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/no-common-ancestor.rs:11:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/no-common-ancestor.rs:23:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL - let _ = T::CONST; +LL + let _ = ::CONST; + | +LL - let _ = T::CONST; +LL + let _ = ::CONST; + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0034, E0221. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/supertrait-shadowing/out-of-scope.rs b/tests/ui/supertrait-shadowing/out-of-scope.rs new file mode 100644 index 0000000000000..7b2322843f1c3 --- /dev/null +++ b/tests/ui/supertrait-shadowing/out-of-scope.rs @@ -0,0 +1,42 @@ +//@ run-pass + +#![feature(min_generic_const_args)] +#![allow(dead_code)] + +use std::mem::size_of; + +mod out_of_scope { + pub trait Subtrait: super::Supertrait { + fn hello(&self) -> &'static str { + "subtrait" + } + type Assoc; + type const CONST: i32; + } + impl Subtrait for T { + type Assoc = i16; + type const CONST: i32 = 2; + } +} + +trait Supertrait { + fn hello(&self) -> &'static str { + "supertrait" + } + type Assoc; + const CONST: i32; +} +impl Supertrait for T { + type Assoc = i8; + const CONST: i32 = 1; +} + +fn main() { + assert_eq!(().hello(), "supertrait"); + check::<()>(); +} + +fn check() { + assert_eq!(size_of::(), 1); + assert_eq!(T::CONST, 1); +} diff --git a/tests/ui/methods/supertrait-shadowing/trivially-false-subtrait.rs b/tests/ui/supertrait-shadowing/trivially-false-subtrait.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/trivially-false-subtrait.rs rename to tests/ui/supertrait-shadowing/trivially-false-subtrait.rs diff --git a/tests/ui/supertrait-shadowing/type-dependent.rs b/tests/ui/supertrait-shadowing/type-dependent.rs new file mode 100644 index 0000000000000..75272d101dd29 --- /dev/null +++ b/tests/ui/supertrait-shadowing/type-dependent.rs @@ -0,0 +1,51 @@ +//@ run-pass + +// Makes sure we can shadow with type-dependent associated item syntax. + +#![feature(min_generic_const_args)] +#![feature(supertrait_item_shadowing)] +#![allow(dead_code)] + +use std::mem::size_of; + +trait A { + fn hello() -> &'static str { + "A" + } + type Assoc; + const CONST: i32; +} +impl A for T { + type Assoc = i8; + const CONST: i32 = 1; +} + +trait B: A { + fn hello() -> &'static str { + "B" + } + type Assoc; + type const CONST: i32; +} +impl B for T { + type Assoc = i16; + type const CONST: i32 = 2; +} + +fn foo() -> &'static str { + T::hello() +} + +fn assoc() -> usize { + size_of::() +} + +fn konst() -> i32 { + T::CONST +} + +fn main() { + assert_eq!(foo::<()>(), "B"); + assert_eq!(assoc::<()>(), 2); + assert_eq!(konst::<()>(), 2); +} diff --git a/tests/ui/methods/supertrait-shadowing/unstable.off_normal.stderr b/tests/ui/supertrait-shadowing/unstable.off_normal.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/unstable.off_normal.stderr rename to tests/ui/supertrait-shadowing/unstable.off_normal.stderr diff --git a/tests/ui/methods/supertrait-shadowing/unstable.off_shadowing.stderr b/tests/ui/supertrait-shadowing/unstable.off_shadowing.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/unstable.off_shadowing.stderr rename to tests/ui/supertrait-shadowing/unstable.off_shadowing.stderr diff --git a/tests/ui/methods/supertrait-shadowing/unstable.on_normal.stderr b/tests/ui/supertrait-shadowing/unstable.on_normal.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/unstable.on_normal.stderr rename to tests/ui/supertrait-shadowing/unstable.on_normal.stderr diff --git a/tests/ui/methods/supertrait-shadowing/unstable.rs b/tests/ui/supertrait-shadowing/unstable.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/unstable.rs rename to tests/ui/supertrait-shadowing/unstable.rs