Skip to content

Inconsistent vtable layout with projections in supertrait bounds, making upcasting unsound #135315

Closed
@steffahn

Description

@steffahn
#![feature(trait_upcasting)]

trait Supertrait<T> {
    fn _print_numbers(&self, mem: &[usize; 100]) {
        println!("{mem:?}");
    }
}
impl<T> Supertrait<T> for () {}

trait Identity {
    type Selff;
}
impl<Selff> Identity for Selff {
    type Selff = Selff;
}

trait Middle<T>: Supertrait<()> + Supertrait<T> {
    fn say_hello(&self, _: &usize) {
        println!("Hello!");
    }
}
impl<T> Middle<T> for () {}

trait Trait: Middle<<() as Identity>::Selff> {}
impl Trait for () {}

fn main() {
    (&() as &dyn Trait as &dyn Middle<()>).say_hello(&0);
}

(playground)

example output (shortened):

[0, 2338324182462507040, 7738151096083899748, 438881233243824, 439624262586284, 439667212259195, 439765996507179…

so apparently, we're calling _print_numbers actually, because the vtable of dyn Trait and dyn Middle<()> aren't compatible.

@rustbot label F-trait_upcasting, I-unsound, T-compiler, requires-nightly, A-trait-objects, A-coercions

Metadata

Metadata

Labels

A-coercionsArea: implicit and explicit `expr as Type` coercionsA-dyn-traitArea: trait objects, vtable layoutC-bugCategory: This is a bug.F-trait_upcasting`#![feature(trait_upcasting)]`I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way.

Type

No type

Projects

Status

Completed

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions