about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFrank Steffahn <fdsteffahn@gmail.com>2025-01-09 21:25:59 +0100
committerFrank Steffahn <fdsteffahn@gmail.com>2025-01-09 21:43:25 +0100
commit5e505189cd2b5355eb4b24bdce7aca7ca4e65189 (patch)
tree8cfd50e361fdd392f9d4cf379932b8c12014d895
parent824759493246ee383beb9cd5ceffa0e15deb9fa4 (diff)
downloadrust-5e505189cd2b5355eb4b24bdce7aca7ca4e65189.tar.gz
rust-5e505189cd2b5355eb4b24bdce7aca7ca4e65189.zip
Add tests cases from review of #132289
-rw-r--r--tests/ui/coherence/auxiliary/pr_review_132289_2_lib.rs37
-rw-r--r--tests/ui/coherence/auxiliary/pr_review_132289_3_lib.rs12
-rw-r--r--tests/ui/coherence/pr-review-132289-1.rs52
-rw-r--r--tests/ui/coherence/pr-review-132289-2.rs26
-rw-r--r--tests/ui/coherence/pr-review-132289-3.rs50
-rw-r--r--tests/ui/coherence/pr-review-132289-3.run.stdout1
6 files changed, 178 insertions, 0 deletions
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 00000000000..4b79147dce1
--- /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<P> {
+    type Assoc;
+}
+
+pub type Dyn<P> = dyn Trait<P, Assoc = A>;
+
+pub trait LocallyUnimplemented<P> {}
+
+impl<P, T: ?Sized> Trait<P> for T
+where
+    T: LocallyUnimplemented<P>,
+{
+    type Assoc = B;
+}
+
+trait MakeArray<Arr> {
+    fn make() -> &'static Arr;
+}
+impl<const N: usize> 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<P>() -> (<Dyn<P> as Trait<P>>::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 00000000000..f90be3b2487
--- /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 00000000000..ab3ed9655e0
--- /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<Assoc = A>;
+
+trait Super {
+    type Assoc;
+}
+impl Super for Foo {
+    type Assoc = A;
+}
+
+trait IsDynSomething {}
+impl IsDynSomething for DynSomething {}
+
+impl<T: ?Sized> 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 00000000000..95ad86c61ff
--- /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<Param> for Dyn<Param> {}
+
+// it would be sound for `function::<Param>`'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::<Param>();
+    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 00000000000..7e597baa6ec
--- /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<I>: Index<I> {}
+
+struct Param;
+
+trait Project {
+    type Ty: ?Sized;
+}
+impl Project for () {
+    type Ty = dyn SubIndex<Param, Output = ()>;
+}
+
+impl Index<Param> 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 00000000000..4effa19f4f7
--- /dev/null
+++ b/tests/ui/coherence/pr-review-132289-3.run.stdout
@@ -0,0 +1 @@
+hello!