Skip to content

Commit

Permalink
Add tests cases from review of rust-lang#132289
Browse files Browse the repository at this point in the history
  • Loading branch information
steffahn committed Jan 9, 2025
1 parent 8247594 commit 5e50518
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 0 deletions.
37 changes: 37 additions & 0 deletions tests/ui/coherence/auxiliary/pr_review_132289_2_lib.rs
Original file line number Diff line number Diff line change
@@ -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())
}
12 changes: 12 additions & 0 deletions tests/ui/coherence/auxiliary/pr_review_132289_3_lib.rs
Original file line number Diff line number Diff line change
@@ -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`
}
52 changes: 52 additions & 0 deletions tests/ui/coherence/pr-review-132289-1.rs
Original file line number Diff line number Diff line change
@@ -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]
}
26 changes: 26 additions & 0 deletions tests/ui/coherence/pr-review-132289-2.rs
Original file line number Diff line number Diff line change
@@ -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);
}
50 changes: 50 additions & 0 deletions tests/ui/coherence/pr-review-132289-3.rs
Original file line number Diff line number Diff line change
@@ -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
}
1 change: 1 addition & 0 deletions tests/ui/coherence/pr-review-132289-3.run.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello!

0 comments on commit 5e50518

Please sign in to comment.