Closed
Description
IIUC currently a trait object is always covariant in its associated types, regardless of their positions.
trait Foo {
type A;
// `A` appears in contravariant position
fn foo(&self, _: Self::A) {}
}
impl Foo for () {
type A = &'static ();
}
fn bar<'a>(_: &'a dyn Foo<A = &'a ()>) {}
fn main() {
let x = ();
// Let 'x be the lifetime of `&x`
// 'static <: 'x
// `dyn Foo` covariant to `Foo::A`
// `&dyn Foo<A = &'static ()>` <: `&dyn Foo<A = &'x ()>`
bar(&x);
}
This makes it possible to pass a non-static reference to a function expecting a static reference:
use std::marker::PhantomData;
trait Foo {
type A;
type B;
fn foo(&self, x: Self::A) -> Self::B;
}
struct Bar<T>(PhantomData<T>);
impl<T: 'static> Foo for Bar<T> {
type A = &'static T;
type B = &'static T;
fn foo(&self, x: Self::A) -> Self::B {
x
}
}
fn bad<'a, T>(x: &dyn Foo<A = &'a T, B = &'static T>, k: &'a T) -> &'static T {
x.foo(k)
}
/// Extends the lifetime of an arbitrary reference.
fn extend<'a, T>(x: &'a T) -> &'static T {
bad(&Bar(PhantomData), x)
}
fn dangle_ref() -> &'static String {
let x = "hello world".to_string();
extend(&x)
}
fn main() {
// This segfaults.
println!("{}", dangle_ref());
}
Metadata
Metadata
Assignees
Labels
Area: Trait systemArea: Variance (https://doc.rust-lang.org/nomicon/subtyping.html)Category: This is a bug.Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessHelping to "clean up" bugs with minimal examples and bisectionsCritical priorityRelevant to the compiler team, which will review and decide on the PR/issue.Performance or correctness regression from one stable version to another.