Skip to content
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

You can instantiate a dyn Trait that doesn't implement Trait #88904

Open
QuineDot opened this issue Sep 13, 2021 · 1 comment
Open

You can instantiate a dyn Trait that doesn't implement Trait #88904

QuineDot opened this issue Sep 13, 2021 · 1 comment
Labels
A-trait-objects Area: trait objects, vtable layout C-bug Category: This is a bug. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@QuineDot
Copy link

I tried this code:

pub trait Marker<'a> {}

pub trait Trait where for<'a> &'a Self: Marker<'a> {
    fn usable(&self) {}
}

impl<'a> Marker<'a> for &'a () {}
impl Trait for () {}

pub fn f() {
    // `(): Trait`
    let u = ();
    u.usable();

    // `dyn Trait` exists and `()` can coerce to it...
    let _t: &dyn Trait = &();
    // But `dyn Trait: !Trait`
    // _t.usable();
    // error[E0277]: the trait bound `for<'a> &'a T: Marker<'a>` is not satisfied
}

I expected to see this happen: The unsized coercion is denied (but see discussion below).

Instead, this happened: The unsized coercion happened and we end up with a dyn Trait which does not implement Trait.

Meta

This works on any stable version of Rust.

Notes

The failure to meet the trait bound is caught when you actually try to use the dyn Trait, at least trivially. I haven't found a way to weaponize this, but I haven't put any effort into doing so either.

dyn Trait implements Trait if you impl<'a> Marker<'a> for &'a (dyn Trait + 'static) {} in the example. However, the non-super-trait bound need not be a marker trait (it can have non-defaulted methods).

Related: Implied Bounds, #20671

Discussion

I'm filing this as a bug because the assertion that dyn Trait: Trait always holds has been expressed as a belief by Rust team members, e.g.

There are some possibilities in line with this assertion:

  • Unsized coercion checks the bounds and is denied in this case
  • Bounds that aren't super-traits make a trait object unsafe generally
  • Bounds that aren't super-traits don't apply to dyn Trait

However, another possibility is to generalize RFC 2027 and just accept the current behavior:

  • dyn Trait is always a valid type, as per RFC 2027
  • Unsized coercion is still dependent on all methods being either object safe or not applicable (where Self: Sized)
    • Though this could be relaxed too (if you're not object safe, dyn Trait just doesn't implement Trait)
  • If unsized coercion is possible, you can instantiate a dyn Trait, even if it doesn't implement Trait
  • Naturally, you can't use the Trait methods if it doesn't implement Trait

I'm sure there are a lot of subtleties and backwards-compatibility concerns in any of the possible approaches.

@QuineDot QuineDot added the C-bug Category: This is a bug. label Sep 13, 2021
@ChrisDenton ChrisDenton added the needs-triage-legacy Old issue that were never triaged. Remove this label once the issue has been sufficiently triaged. label Jul 16, 2023
@Jules-Bertholet
Copy link
Contributor

Jules-Bertholet commented Dec 16, 2023

Another method for doing this:

trait Super {
    type Assoc: ?Sized;
}

trait Sub: Super<Assoc = Self> {}

fn foo<T: Sub>(a: &T) {
    let b: &dyn Sub<Assoc = T> = a; // This line compiles
    bar(b) // This line does not
}

fn bar<T: Sub + ?Sized>(a: &T) {}

@rustbot label A-trait-objects T-types

@rustbot rustbot added A-trait-objects Area: trait objects, vtable layout T-types Relevant to the types team, which will review and decide on the PR/issue. labels Dec 16, 2023
@fmease fmease removed the needs-triage-legacy Old issue that were never triaged. Remove this label once the issue has been sufficiently triaged. label Jan 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-trait-objects Area: trait objects, vtable layout C-bug Category: This is a bug. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants