Can you restrict a generic to T where T is a trait

2019-07-24 12:23发布

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.

标签: rust
1条回答
Viruses.
2楼-- · 2019-07-24 12:53

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 generic T 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 variable T as the trait object type Valid (which is allowed since you specified ?Sized). Then, in Self: 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:

<anon>:9:53: 9:54 error: `T` is not a trait
<anon>:9     fn as_trait<T: ?Sized>(&self) -> &T where Self: T {
                                                             ^
查看更多
登录 后发表回答