diff --git a/tests/ui/coherence/auxiliary/pr_review_132289_2_lib.rs b/tests/ui/coherence/auxiliary/pr_review_132289_2_lib.rs new file mode 100644 index 000000000000..4b79147dce10 --- /dev/null +++ b/tests/ui/coherence/auxiliary/pr_review_132289_2_lib.rs @@ -0,0 +1,37 @@ +pub type A = &'static [usize; 1]; +pub type B = &'static [usize; 100]; + +pub trait Trait

{ + type Assoc; +} + +pub type Dyn

= dyn Trait; + +pub trait LocallyUnimplemented

{} + +impl Trait

for T +where + T: LocallyUnimplemented

, +{ + type Assoc = B; +} + +trait MakeArray { + fn make() -> &'static Arr; +} +impl MakeArray<[usize; N]> for () { + fn make() -> &'static [usize; N] { + &[1337; N] + } +} + +// it would be sound for this return type to be interpreted as being +// either of A or B, if that's what a soundness fix for overlap of +// dyn Trait's impls would entail + +// In this test, we check at the call-site that the interpretation +// is consistent across crates in this specific scenario. +pub fn function

() -> ( as Trait

>::Assoc, usize) { + let val = <() as MakeArray<_>>::make(); + (val, val.len()) +} diff --git a/tests/ui/coherence/auxiliary/pr_review_132289_3_lib.rs b/tests/ui/coherence/auxiliary/pr_review_132289_3_lib.rs new file mode 100644 index 000000000000..f90be3b2487e --- /dev/null +++ b/tests/ui/coherence/auxiliary/pr_review_132289_3_lib.rs @@ -0,0 +1,12 @@ +use std::ops::Index; + +pub trait Trait { + fn f(&self) + where + dyn Index<(), Output = ()>: Index<()>; + // rustc (correctly) determines ^^^^^^^^ this bound to be true +} + +pub fn call(x: &dyn Trait) { + x.f(); // so we can call `f` +} diff --git a/tests/ui/coherence/pr-review-132289-1.rs b/tests/ui/coherence/pr-review-132289-1.rs new file mode 100644 index 000000000000..ab3ed9655e07 --- /dev/null +++ b/tests/ui/coherence/pr-review-132289-1.rs @@ -0,0 +1,52 @@ +// This is a regression test for issues that came up during review of the (closed) +// PR #132289; this single-crate test case is +// the first example from @steffahn during review. +// https://github.com/rust-lang/rust/pull/132289#issuecomment-2564492153 + +//@ check-pass + +type A = &'static [usize; 1]; +type B = &'static [usize; 100]; + +type DynSomething = dyn Something; + +trait Super { + type Assoc; +} +impl Super for Foo { + type Assoc = A; +} + +trait IsDynSomething {} +impl IsDynSomething for DynSomething {} + +impl Super for T +where + T: IsDynSomething, +{ + type Assoc = B; +} + +trait Something: Super { + fn method(&self) -> Self::Assoc; +} + +struct Foo; +impl Something for Foo { + fn method(&self) -> Self::Assoc { + &[1337] + } +} + +fn main() { + let x = &Foo; + let y: &DynSomething = x; + + // no surprises here + let _arr1: A = x.method(); + + // this (`_arr2`) can't ever become B either, soundly + let _arr2: A = y.method(); + // there aren't any other arrays being defined anywhere in this + // test case, besides the length-1 one containing [1337] +} diff --git a/tests/ui/coherence/pr-review-132289-2.rs b/tests/ui/coherence/pr-review-132289-2.rs new file mode 100644 index 000000000000..95ad86c61ff1 --- /dev/null +++ b/tests/ui/coherence/pr-review-132289-2.rs @@ -0,0 +1,26 @@ +// This is a regression test for issues that came up during review of the (closed) +// PR #132289; this 2-crate test case is adapted from +// the second example from @steffahn during review. +// https://github.com/rust-lang/rust/pull/132289#issuecomment-2564587796 + +//@ run-pass +//@ aux-build: pr_review_132289_2_lib.rs + +extern crate pr_review_132289_2_lib; + +use pr_review_132289_2_lib::{function, Dyn, LocallyUnimplemented}; + +struct Param; + +impl LocallyUnimplemented for Dyn {} + +// it would be sound for `function::`'s return type to be +// either of A or B, if that's what a soundness fix for overlap of +// dyn Trait's impls would entail + +// In this test, we check at this call-site that the interpretation +// is consistent with the function definition's body. +fn main() { + let (arr, len) = function::(); + assert_eq!(arr.len(), len); +} diff --git a/tests/ui/coherence/pr-review-132289-3.rs b/tests/ui/coherence/pr-review-132289-3.rs new file mode 100644 index 000000000000..7e597baa6ec2 --- /dev/null +++ b/tests/ui/coherence/pr-review-132289-3.rs @@ -0,0 +1,50 @@ +// This is a regression test for issues that came up during review of the (closed) +// PR #132289; this 3-ish-crate (including std) test case is adapted from +// the third example from @steffahn during review. +// https://github.com/rust-lang/rust/pull/132289#issuecomment-2564599221 + +//@ run-pass +//@ check-run-results +//@ aux-build: pr_review_132289_3_lib.rs + +extern crate pr_review_132289_3_lib; + +use std::ops::Index; + +use pr_review_132289_3_lib::{call, Trait}; + +trait SubIndex: Index {} + +struct Param; + +trait Project { + type Ty: ?Sized; +} +impl Project for () { + type Ty = dyn SubIndex; +} + +impl Index for <() as Project>::Ty { + type Output = (); + + fn index(&self, _: Param) -> &() { + &() + } +} + +struct Struct; + +impl Trait for Struct { + fn f(&self) + where + // higher-ranked to allow potentially-false bounds + for<'a> dyn Index<(), Output = ()>: Index<()>, + // after #132289 rustc used to believe this bound false + { + println!("hello!"); + } +} + +fn main() { + call(&Struct); // <- would segfault if the method `f` wasn't part of the vtable +} diff --git a/tests/ui/coherence/pr-review-132289-3.run.stdout b/tests/ui/coherence/pr-review-132289-3.run.stdout new file mode 100644 index 000000000000..4effa19f4f75 --- /dev/null +++ b/tests/ui/coherence/pr-review-132289-3.run.stdout @@ -0,0 +1 @@ +hello!