Skip to content

Confusing Stacked Borrows error with #![feature(ptr_metadata)] #2087

Closed
@dimpolo

Description

@dimpolo

Sorry for the vague title.
I wasn't sure if this code was valid so I ran it through Miri.
This however led to even more confusion.
It seems as though I can convince Miri that this code is fine, by first calling a function with no observable side-effect.

I would be very thankful for an explanation (and even more thankful if someone want's to tell me if this code is fine 😃)

#![feature(ptr_metadata)]

use std::fmt::Debug;
use std::ptr;
use std::ptr::DynMetadata;

#[repr(C)]
struct Container<T: ?Sized> {
    vtable: DynMetadata<dyn Debug>,
    value: T,
}

impl<T: Debug + 'static> Container<T> {
    const fn new(value: T) -> Self {
        Container {
            vtable: ptr::metadata(ptr::null::<T>() as *const dyn Debug),
            value,
        }
    }

    const fn erase(&self) -> &Container<()> {
        let ptr = self as *const Container<T> as *const Container<()>;

        unsafe { &*ptr }
    }

    fn make_fat(&self) -> &Container<dyn Debug> {
        let fat_pointer = ptr::from_raw_parts(self as *const _ as *const (), self.vtable);
        unsafe { &*fat_pointer }
    }
}

fn main() {
    static CONTAINER: Container<i32> = Container::new(123);
    static ERASED: &Container<()> = CONTAINER.erase();

    // CONTAINER.make_fat(); uncomment this line to make Miri happy?

    ERASED.make_fat();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions