I decided to poke at the edges of what higher-ranked type bounds can and can’t do, and I thought the results might be interesting to some people here. In particular, the behaviors for impl Trait
and dyn Trait
are a bit surprising.
trait Trait where for<'a> &'a Self: Trait {
fn foo(self)->() where Self:Sized {()}
}
// This is ok
impl<'a, 'b, T:?Sized> Trait for &'a &'b T where &'b T:Trait {}
// This complains of not being general enough
// impl<'a, 'b:'a, T:?Sized> Trait for &'a &'b T where &'b T:Trait {}
// All of these are ok
impl<'a, T> Trait for &'a Vec<T> {}
impl<T> Trait for Vec<T> {}
impl<'a, T> Trait for &'a [T] {}
// This works (with arbitrary numbers of `&`s)
fn f1(x:&Vec<()>) {
x.foo();
}
// Typechecker infinite recursion
//fn f2(x:&impl Trait) {
// x.foo()
//}
// This works, so Trait is object safe
fn f3(x:Vec<()>) {
let _:&dyn Trait = &x;
}
// Complains that `foo` cannot be invoked on a trait object
// but `dyn Trait` implements `Trait`
// which means `&dyn Trait` (which is Sized) *must* implement Trait per the where clause
//fn f3(x:&dyn Trait) {
// (&&x).foo()
//}
Errors:
Compiling playground v0.0.1 (/playground)
warning: function is never used: `f1`
--> src/lib.rs:17:4
|
17 | fn f1(x:&Vec<()>) {
| ^^
|
= note: `#[warn(dead_code)]` on by default
warning: function is never used: `f3`
--> src/lib.rs:27:4
|
27 | fn f3(x:Vec<()>) {
| ^^
warning: 2 warnings emitted
Finished dev [unoptimized + debuginfo] target(s) in 0.31s