Skip to content

Unsoundness due to variance of trait objects WRT associated types #71550

Closed
@trha

Description

@trha

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

A-trait-systemArea: Trait systemA-varianceArea: Variance (https://doc.rust-lang.org/nomicon/subtyping.html)C-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessICEBreaker-Cleanup-CrewHelping to "clean up" bugs with minimal examples and bisectionsP-criticalCritical priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions