Skip to content

Add tests cases from review of #132289 #135304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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!
Loading