Dyn compatibility error when using an associated type as a type parameter in the super-trait listing
I tried this code:
trait Super<T> {}
trait Foo: Super<<Self as Foo>::Bar> { type Bar; }
type BoxFoo = Box<Foo<Bar = u8>>;
The code should compile since Self::Bar is the type parameter, not Self.
Instead, it will fail with the following message:
the trait Foo cannot be made into an object
the trait cannot use Self as a type parameter in the supertrait listing
FYI the discussion that sparked this issue:
So this has to do with object safety -- any trait that references Self is not object safe because the true Self type is erased. However, the error doesn't seem appropriate in this case. I think this warrants a bug report at least to fix the error message, if not to relax the object safety check (because there could be something I don't see preventing it still... can't say I fully understand object safety).
Meta
rustc --version --verbose: rustc 1.17.0-nightly (b1e31766d 2017-03-03)
Current output:
error[E0038]: the trait `Foo` cannot be made into an object --> src/lib.rs:5:19 | 5 | type BoxFoo = Box<Foo<Bar = u8>>; | ^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clausesIt should at least point at
trait Foo's supertraits.Esteban Kuber at 2019-10-11 23:13:57
Output in #68377:
error[E0038]: the trait `Foo` cannot be made into an object --> file.rs:7:19 | 3 | trait Foo: Super<<Self as Foo>::Bar> { | --- ------------------------- ...because it cannot use `Self` as a type parameter in the supertraits or `where`-clauses | | | this trait cannot be made into an object... ... 7 | type BoxFoo = Box<dyn Foo<Bar = u8>>; | ^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an objectEsteban Kuber at 2020-02-02 21:03:13
I believe that we should change the implementation here
https://github.com/rust-lang/rust/blob/ed9749324aed9e97741abf569a022353e269a9df/compiler/rustc_trait_selection/src/traits/object_safety.rs#L287-L293
to account for
data=TraitPredicate(<Self as Super<<Self as Foo>::Bar>>, polarity:Positiveand explicitly allow it, by ignoring whenSelfis only referenced to access one of its currently defined associated types.Further changes would also be needed here
https://github.com/rust-lang/rust/blob/ed9749324aed9e97741abf569a022353e269a9df/compiler/rustc_hir_analysis/src/astconv/mod.rs#L1519-L1542
@rust-lang/lang, would this require team sign-off, or is the current behavior "accidental"/"incidental" and a change of behavior requires no "new rationale"?
I'm also intrigued on whether this test should have been rejected with a more targeted error, instead of E0038: https://github.com/rust-lang/rust/blob/eb4580a570069175e1290b294d91042a09f9fde3/src/test/ui/issues/issue-26056.rs
Esteban Kuber at 2022-12-13 02:14:47
@estebank
Self can appear in projections, but only as part of an "identity" trait-ref. i.e., if you hvae
trait Foo<A..Z>, then the trait ref has to be<Self as Foo<A..Z>>::Bar. This ensures that we can extract the associated type from the self type (which will be something likedyn Foo<A..Z, Bar=X>.I think such a PR does not require an FCP, but it's prob a good idea to nominate for @rust-lang/types approval or review. This feels to me like a 'nitty gritty' detail. I think in general @rust-lang/types is a good choice for that, and types team can escalate to lang if it seems like it requires a policy decision.
Niko Matsakis at 2022-12-13 11:30:11
This is a disparity between trait generic parameter and associated type. I very much doubt such disparity is intended in this scenario. Though not particularly damaging, it adds restrictions during high-level type designs.
trait Super<T> {} trait Foo<Bar>: Super<Bar> {} // Using a generic parameter does not break object safety type BoxFoo = Box<Foo<u8>>;ZhennanWu at 2023-07-05 00:27:10
I think such a PR does not require an FCP, but it's prob a good idea to nominate for @rust-lang/types approval or review. This feels to me like a 'nitty gritty' detail. I think in general @rust-lang/types is a good choice for that, and types team can escalate to lang if it seems like it requires a policy decision.
I quite strongly believe that a fix for this issue should require a types FCP. Changes to the stable behavior of the type system, especially if the changes are hanbdle some nitty gritty detail should go through a types FCP, see https://rust-lang.zulipchat.com/#narrow/stream/144729-t-types/topic/FCPs.20for.20type.20system.20hacks where we've previously discussed this question on zulip. Most unsound issues and weird backcompat hurdles tend to be caused by one (or the interaction of multiple) such nitty gritty detail(s). Even if the FCP only manages to force t-types members to look at the PR in more detail, this is still very clearly worth it to me.
lcnr at 2023-07-06 10:51:45