Skip to content

Unexpected unsizing coercion introduced by unsafe block #128880

Open
@RalfJung

Description

@RalfJung

Consider this example:

pub fn testcase() -> *const dyn Bar {
    let baz: &dyn Baz = &1;
    // Unexpected coercion in the next line
    let baz_fake = unsafe { std::mem::transmute::<_, *const dyn Bar>(baz) };
    baz_fake
}

The initial MIR after MIR building is

    bb0: {
        StorageLive(_1);
        StorageLive(_2);
        StorageLive(_3);
        StorageLive(_4);
        StorageLive(_5);
        _5 = const 1_i32;
        _4 = &_5;
        _3 = &(*_4);
        _2 = move _3 as &dyn Baz (PointerCoercion(Unsize));
        StorageDead(_3);
        FakeRead(ForLet(None), _2);
        AscribeUserType(_2, o, UserTypeProjection { base: UserType(1), projs: [] });
        StorageDead(_4);
        StorageLive(_6);
        StorageLive(_7);
        StorageLive(_8);
        _8 = _2;
        _7 = transmute::<&dyn Baz, *const dyn Bar>(move _8) -> [return: bb1, unwind: bb2];
    }

    bb1: {
        StorageDead(_8);
        _6 = move _7 as *const dyn Bar (PointerCoercion(Unsize));
        StorageDead(_7);
        FakeRead(ForLet(None), _6);
        StorageLive(_9);
        _9 = _6;
        _1 = move _9 as *const dyn Bar (PointerCoercion(Unsize));
        StorageDead(_9);
        StorageDead(_6);
        StorageDead(_5);
        StorageDead(_2);
        _0 = move _1 as *const dyn Bar (PointerCoercion(Unsize));
        StorageDead(_1);
        return;
    }

Notice the no less than three coercions in bb1, all of which coerce from *const dyn Bar to *const dyn Bar. I would have expected to see zero of them; the transmute returns exactly the type we want so there's no reason to insert a coercion.

This came up because Miri actually considers such coercions to be a simple form of upcast that can introduce UB, so unexpected coercions can lead to unexpected UB. We can just change the MIR opsem to make identity coercions true NOPs, but we don't do this for any other kind of coercion so it's an odd special case.

Cc @rust-lang/types @rust-lang/opsem

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlT-opsemRelevant to the opsem teamT-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions