Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for core::mem::forget_unsized #2872

Closed
Jules-Bertholet opened this issue May 4, 2023 · 4 comments
Closed

Support for core::mem::forget_unsized #2872

Jules-Bertholet opened this issue May 4, 2023 · 4 comments

Comments

@Jules-Bertholet
Copy link
Contributor

#![feature(forget_unsized, unsized_fn_params)]

fn main() {
    let b: Box<[u32]> = Box::new([1, 2, 3]);
    std::mem::forget_unsized(*b);
}

Miri fails to run the above program with the following error:

error: unsupported operation: unsized locals are not supported
   --> /home/julesbertholet/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/mod.rs:159:24
    |
159 |     intrinsics::forget(t)
    |                        ^ unsized locals are not supported
    |
    = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
    = note: BACKTRACE:
    = note: inside `std::mem::forget_unsized::<[u32]>`

There are no unsized locals in this program, so at the very least, the error message is incorrect.

@RalfJung
Copy link
Member

RalfJung commented May 4, 2023

We only emit that error here

https://github.com/rust-lang/rust/blob/8a9e696f43aee4b184be2e1e01fa1f6048d7aba1/compiler/rustc_const_eval/src/interpret/place.rs#L727-L729

so it very much looks like there is an unsized local in the generated MIR. Strange.

@RalfJung
Copy link
Member

RalfJung commented May 4, 2023

Yeah, this is the generated MIR (at opt-level 0):

fn forget_unsized(_1: T) -> () {
    debug t => _1;                       // in scope 0 at test.rs:4:34: 4:35
    let mut _0: ();                      // return place in scope 0 at test.rs:4:40: 4:40
    let mut _2: T;                       // in scope 0 at test.rs:5:24: 5:25

    bb0: {
        StorageLive(_2);                 // scope 0 at test.rs:5:24: 5:25
        _2 = move _1;                    // scope 0 at test.rs:5:24: 5:25
        _0 = const ();                   // scope 0 at test.rs:5:5: 5:26
        StorageDead(_2);                 // scope 0 at test.rs:5:25: 5:26
        return;                          // scope 0 at test.rs:6:2: 6:2
    }
}

So Miri is right, MIR building is introducing unsized locals here.

@RalfJung
Copy link
Member

RalfJung commented May 4, 2023

The fact that this code is accepted without the unsized_local feature gate is concerning, since this means we are hitting the broken alloca code path in codegen that is used for unsized locals:

define void @_ZN4test14forget_unsized17h6fbb3409c8556ed4E(ptr %0, i64 %1) unnamed_addr #0 {
start:
  %_2 = alloca { ptr, i64 }, align 8
  %t = alloca { ptr, i64 }, align 8
  %2 = getelementptr inbounds { ptr, i64 }, ptr %t, i32 0, i32 0
  store ptr %0, ptr %2, align 8
  %3 = getelementptr inbounds { ptr, i64 }, ptr %t, i32 0, i32 1
  store i64 %1, ptr %3, align 8
  %4 = getelementptr inbounds { ptr, i64 }, ptr %t, i32 0, i32 0
  %5 = load ptr, ptr %4, align 8, !noundef !2
  %6 = getelementptr inbounds { ptr, i64 }, ptr %t, i32 0, i32 1
  %7 = load i64, ptr %6, align 8, !noundef !2
  %8 = mul nsw i64 %7, 4
  %9 = alloca i8, i64 %8, align 16
  call void @llvm.memcpy.p0.p0.i64(ptr align 16 %9, ptr align 1 %5, i64 %8, i1 false)
  %10 = getelementptr inbounds { ptr, i64 }, ptr %_2, i32 0, i32 0
  store ptr %9, ptr %10, align 8
  %11 = getelementptr inbounds { ptr, i64 }, ptr %_2, i32 0, i32 1
  store i64 %7, ptr %11, align 8
  ret void
}

@RalfJung
Copy link
Member

RalfJung commented May 4, 2023

This is a rustc bug: rust-lang/rust#111175. Thanks for reporting!

@RalfJung RalfJung closed this as completed May 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants