For example, is there some way of doing this:
use std::marker::PhantomFn;
trait Valid : PhantomFn<Self> {}
trait Invalid : PhantomFn<Self> {}
struct Foo;
impl Foo {
fn as_trait<T: ?Sized>(&self) -> &T where Self: T {
return self as &T;
}
}
impl Valid for Foo {}
fn main() {
let foo = Foo;
// Should return a trait reference &Valid
let _ = foo.as_trait::<Valid>();
// Should fail to compile because Invalid is not implemented for Foo
let _ = foo.as_trait::<Invalid>();
}
i.e. restrict a generic to be only for traits where the trait is implemented on Self.
I don't believe it's possible to be generic over traits right now (and I haven't heard any plans to make it so), so
Foo: T
with a genericT
will not be valid.When you use a trait name in a position where a type is expected, it's treated as a trait object type rather than a trait. Thus,
foo.as_trait::<Valid>()
instantiates the type variableT
as the trait object typeValid
(which is allowed since you specified?Sized
). Then, inSelf: T
,T
is a type rather than a trait, so it's the wrong kind of thing.The compiler will tell you the same thing in fewer words: