pub trait RemoveT<TargetL, List> {
type AfterRemove;
fn remove_label(&self) -> Self::AfterRemove;}
impl<TargetL, List, T> RemoveT<TargetL, List> for T {
type AfterRemove = Nil;
fn remove_label(&self) -> Self::AfterRemove {
todo!()}}
// ================================================================================ test
pub struct Foo;
pub struct Nil;
fn main () {
let x = Vec::<i32>::new();
let y = (x as RemoveT<Foo, Vec<i32>>).remove_label();
}
Error:
Compiling playground v0.0.1 (/playground)
warning: trait objects without an explicit `dyn` are deprecated
--> src/main.rs:20:19
|
20 | let y = (x as RemoveT<Foo, Vec<i32>>).remove_label();
| ^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn RemoveT<Foo, Vec<i32>>`
|
= note: `#[warn(bare_trait_objects)]` on by default
error[E0191]: the value of the associated type `AfterRemove` (from trait `RemoveT`) must be specified
--> src/main.rs:20:19
|
2 | type AfterRemove;
| ----------------- `AfterRemove` defined here
...
20 | let y = (x as RemoveT<Foo, Vec<i32>>).remove_label();
| ^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated type: `RemoveT<Foo, Vec<i32>, AfterRemove = Type>`
error[E0620]: cast to unsized type: `Vec<i32>` as `dyn RemoveT<Foo, Vec<i32>>`
--> src/main.rs:20:13
|
20 | let y = (x as RemoveT<Foo, Vec<i32>>).remove_label();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider using a box or reference as appropriate
--> src/main.rs:20:14
|
20 | let y = (x as RemoveT<Foo, Vec<i32>>).remove_label();
| ^
error: aborting due to 2 previous errors; 1 warning emitted
Some errors have detailed explanations: E0191, E0620.
For more information about an error, try `rustc --explain E0191`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
Question: Why does this error? It is "clear" to me that we should have AfterRemove = Nil
If you callt like this, the type inference works properly:
fn main () {
let x = Vec::<i32>::new();
let y = RemoveT::<Foo, Vec<i32>>::remove_label(&x);
}
Trait objects always have to list associated types explicitly: The identity of the underlying type is lost when the trait object is generated, so it’s no longer possible to look up the associated types from the impl block.
as RemoveT<Foo, Vec<i32>> is a cast, and the RemoveT<Foo, Vec<i32>> is interpreted as a type, not a trait. The only way to interpret that as a type is as a trait object, and that's why the compiler is complaining it's missing the dyn keyword and that it is unsized. Calling a method that involves an associated type on a trait object also requires that the associated type is specified. It can't be inferred because it would change the type since dyn RemoveT<Foo, Vec<i32>> is not the same as dyn RemoveT<Foo, Vec<i32>, AfterRemove=Nil>.
Edit: To be clear, in expr as RemoveT<Foo, Vec<i32>> the as means a cast but when you do something like <Vec<i32> as RemoveT<Foo, Vec<i32>>>::remove_label(&x) then RemoveT<Foo, Vec<i32>> is interpreted as a trait and used to disambiguate the method call.