Open
Description
I would expect this code to compile:
#![allow(dead_code)]
#![allow(unused_variables)]
struct Covariant<'a> { y: &'a i32 }
struct Contravariant<'a> { y: fn(&'a i32) }
trait HasLifetime<'a> : 'a {}
impl<'a, T> HasLifetime<'a> for T where T: 'a {}
fn check_lifetime_bound<'a, T: 'a>(x: &T) {}
fn check_contra_rightway<'a>(x: Contravariant<'a>) {
let xref = &x;
let xstatic: &Contravariant<'static> = &x;
check_lifetime_bound::<'a>(&x);
check_lifetime_bound::<'a>(xref);
check_lifetime_bound::<'a>(xstatic);
check_lifetime_bound::<'static>(&x); // <-- this works, but...
check_lifetime_bound::<'static>(xref);
check_lifetime_bound::<'static>(xstatic);
let a: &HasLifetime<'static> = &x; // <-- this doesn't (BUG!)
let a: &HasLifetime<'static> = xstatic; // <-- nonetheless, this does work
// NB: Substituting Any for HasLifetime<'static> produces identical
// results.
}
fn check_co_wrongway<'a>(x: Covariant<'a>) {
let xref = &x;
// let xstatic: &Covariant<'static> = &x; <-- correctly fails
check_lifetime_bound::<'a>(&x);
check_lifetime_bound::<'a>(xref);
// check_lifetime_bound::<'static>(&x); <-- correctly fails
// check_lifetime_bound::<'static>(xref); <-- correctly fails
let a: &HasLifetime<'a> = &x;
}
fn check_co_rightway<'a>(x: Covariant<'static>, _: &'a i32) {
let xref = &x;
let xa: &Covariant<'a> = &x;
check_lifetime_bound::<'a>(&x);
check_lifetime_bound::<'a>(xref);
check_lifetime_bound::<'a>(xa);
check_lifetime_bound::<'static>(&x);
check_lifetime_bound::<'static>(xref);
// check_lifetime_bound::<'static>(xa); <-- this correctly fails
let a: &HasLifetime<'a> = &x;
let a: &HasLifetime<'a> = xref;
let a: &HasLifetime<'a> = xa;
// let bad: &HasLifetime<'static> = xa; <-- correctly fails
}
fn main() {}
Using rustc 1.11.0 (9b21dcd6a 2016-08-15)
, I get:
ref_life.rs:22:36: 22:38 error: the type `Contravariant<'a>` does not fulfill the required lifetime [E0477]
ref_life.rs:22 let a: &HasLifetime<'static> = &x; // <-- this doesn't (BUG!)
^~
ref_life.rs:22:36: 22:38 note: type must outlive the static lifetime
ref_life.rs:22:36: 22:38 error: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements [E0495]
ref_life.rs:22 let a: &HasLifetime<'static> = &x; // <-- this doesn't (BUG!)
^~
ref_life.rs:12:52: 28:2 note: first, the lifetime cannot outlive the lifetime 'a as defined on the block at 12:51...
ref_life.rs:12 fn check_contra_rightway<'a>(x: Contravariant<'a>) {
^
ref_life.rs:22:36: 22:38 note: ...so that the type `Contravariant<'a>` will meet its required lifetime bounds
ref_life.rs:22 let a: &HasLifetime<'static> = &x; // <-- this doesn't (BUG!)
^~
ref_life.rs:22:36: 22:38 note: but, the lifetime must be valid for the static lifetime...
ref_life.rs:22:36: 22:38 note: ...so that trait type parameters matches those specified on the impl (expected HasLifetime<'static>, found HasLifetime<'_>)
ref_life.rs:22 let a: &HasLifetime<'static> = &x; // <-- this doesn't (BUG!)
^~
error: aborting due to 2 previous errors
It seems that the rustc can match a covariant struct against a shorter lifetime bound when coercing to a trait object but that it can't match a contravariant struct against a longer timetime bound when coercing to a trait object, depite the fact that coercing directly works fine.
Metadata
Metadata
Assignees
Labels
Area: implicit and explicit `expr as Type` coercionsArea: trait objects, vtable layoutArea: Lifetimes / regionsArea: Variance (https://doc.rust-lang.org/nomicon/subtyping.html)Category: An issue proposing an enhancement or a PR with one.Relevant to the compiler team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.