Благодаря @ 1001 * превосходному ответу @ francis-gagné на другой вопрос у меня есть более четкое представление о том, как работает дисперсия.Например, тип, содержащий ссылку, является ковариантным по своему параметру времени жизни, как показано ниже.
struct Foo<'a> (PhantomData<&'a str>);
/// Foo is covariant over its lifetime parameter
pub fn test_foo<'a:'b, 'b:'c, 'c>() {
let fa: Foo<'a> = Foo(PhantomData);
let fb: Foo<'b> = Foo(PhantomData);
let fc: Foo<'c> = Foo(PhantomData);
let v: Vec<Foo<'b>> = vec![fa, fb]; // fc is not accepted
}
С другой стороны, функция, принимающая ссылку (или тип, содержащий ее), является контравариантной по своему параметру времени жизни..
struct Bar<'a> (PhantomData<fn(&'a str)>);
/// Bar is contravariant over its lifetime parameter
pub fn test_bar<'a:'b, 'b:'c, 'c>() {
let ba: Bar<'a> = Bar(PhantomData);
let bb: Bar<'b> = Bar(PhantomData);
let bc: Bar<'c> = Bar(PhantomData);
let v: Vec<Bar<'b>> = vec![bb, bc]; // ba is not accepted
}
Наконец, признак с параметром времени жизни инвариантен относительно своего параметра времени жизни.
pub trait Baz<'a> {}
impl<'a> Baz<'a> for () {}
/// Baz is invariant over its lifetime parameter
pub fn test_baz<'a:'b, 'b:'c, 'c>() {
let za: Box<dyn Baz<'a>> = Box::new(());
let zb: Box<dyn Baz<'b>> = Box::new(());
let zc: Box<dyn Baz<'c>> = Box::new(());
let v: Vec<Box<dyn Baz<'b>>> = vec![zb]; // za and zx are not accepted
}
Это имеет смысл, поскольку черта может быть реализованакак ковариантным, так и контравариантным типом, как показано ниже.
impl<'a> Baz<'a> for Foo<'a> {}
impl<'a> Baz<'a> for Bar<'a> {}
Мой вопрос: могу ли я заставить черту быть ковариантной в течение ее параметра времени жизни?Я ожидаю, что черта маркера, такая как:
trait Baz<'a>: Covariant<'a> {}
, сделает незаконной реализацию этой черты с контравариантным типом и позволит za
быть членом вектора v
в test_baz
функция выше.
Конечно, возможность сделать обратное (заставить черту быть противоположной) также может быть полезна ...
Примеры на игровой площадке