Skip to content

Stacked Borrows' interior mutability is per-location: enum discriminants can surprisingly change #204

Closed
@RalfJung

Description

@RalfJung

Stacked Borrows does per-location tracking of whether something has interior mutability. This means if the discriminant is stored on the same location as an UnsafeCell, it can surprisingly change:

/// Sets `x` to `None`.
fn evil<T>(x: &Option<Cell<&T>>) {
    assert_eq!(
        mem::size_of_val(x), mem::size_of_val(x.as_ref().unwrap()),
        "layout optimization did not kick in?",
    );
    unsafe { *(x as *const _ as *mut usize) = 0; }
}

fn main() {
    let my = Some(Cell::new(&0));
    evil(&my);
    dbg!(my);
}

This passes in Miri and prints "None".

Note that right now, this would pass in Miri even with no enum layout optimizations as I simplified the handling of interior mutability (see rust-lang/miri#931). The old, more precise handling was a total mess and basically impossible to reason about. But even the most precise handling I can imagine would still allow the code above.

Cc @nikomatsakis @eddyb

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-aliasing-modelTopic: Related to the aliasing model (e.g. Stacked/Tree Borrows)C-open-questionCategory: An open question that we should revisitTriagedVisited during a backlog bonanza meeting

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions