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

ICE: broken MIR in DropGlue Transmute is not supported in non-runtime phase Analysis(PostCleanup) #137243

Open
matthiaskrgr opened this issue Feb 18, 2025 · 3 comments · May be fixed by #137264
Open
Assignees
Labels
-Zvalidate-mir Unstable option: MIR validation C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@matthiaskrgr
Copy link
Member

auto-reduced (treereduce-rust):

//@compile-flags: --edition=2024 -Zvalidate-mir
use std::{
    cell::{Cell, RefCell},
    future::Future,
    marker::Unpin,
    panic,
    pin::Pin,
    ptr,
    rc::Rc,
    task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
};

struct Defer<T> {
    ready: bool,
    value: Option<T>,
}

impl<T: Unpin> Future for Defer<T> {
    type Output = T;
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
        if self.ready {
            Poll::Ready(self.value.take().unwrap())
        } else {
            Poll::Pending
        }
    }
}

struct Allocator {
    data: RefCell<Vec<bool>>,
    failing_op: usize,
    cur_ops: Cell<usize>,
}

impl Allocator {
    fn new(failing_op: usize) -> Self {
        Allocator {
            failing_op,
            cur_ops: Cell::new(0),
            data: RefCell::new(vec![]),
        }
    }
    fn alloc(&self) -> impl Future + '_ {
        let mut data = self.data.borrow_mut();

        let addr = data.len();

        Defer {
            ready: false,
            value: Some(Ptr(addr, self)),
        }
    }
}

struct Ptr<'a>(usize, &'a Allocator);
impl<'a> Drop for Ptr<'a> {
    fn drop(&mut self) {}
}

async fn vec_unreachable(a: Rc<Allocator>) {
    let _x = vec![a.alloc().await, a.alloc().await, a.alloc().await, return];
}

fn run_test<F, G>(cx: &mut Context<'_>, ref f: F)
where
    F: Fn(Rc<Allocator>) -> G,
    G:,
{
    for polls in 0.. {
        let first_alloc = Rc::new(Allocator::new(usize::MAX));
        let mut fut = Box::pin(f(first_alloc.clone()));

        drop(fut);
    }
}

fn clone_waker(data: *const ()) -> RawWaker {
    RawWaker::new(data, &RawWakerVTable::new(clone_waker, drop, drop, drop))
}

fn main() {
    let waker = unsafe { Waker::from_raw(clone_waker(ptr::null())) };
    let context = &mut Context::from_waker(&waker);

    run_test(context, |a| vec_unreachable(a));
}
original code

original:

// Test that values are not leaked in async functions, even in the cases where:
// * Dropping one of the values panics while running the future.
// * The future is dropped at one of its suspend points.
// * Dropping one of the values panics while dropping the future.

//@ run-pass
//@ needs-unwind
//@ edition:2018

#![allow(unused)]

use std::{
    cell::{Cell, RefCell},
    future::Future,
    marker::Unpin,
    panic,
    pin::Pin,
    ptr,
    rc::Rc,
    task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
};

struct InjectedFailure;

struct Defer<T> {
    ready: bool,
    value: Option<T>,
}

impl<T: Unpin> Future for Defer<T> {
    type Output = T;
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
        if self.ready {
            Poll::Ready(self.value.take().unwrap())
        } else {
            self.ready = true;
            Poll::Pending
        }
    }
}

/// Allocator tracks the creation and destruction of `Ptr`s.
/// The `failing_op`-th operation will panic.
struct Allocator {
    data: RefCell<Vec<bool>>,
    failing_op: usize,
    cur_ops: Cell<usize>,
}

impl panic::UnwindSafe for Allocator {}
impl panic::RefUnwindSafe for Allocator {}

impl Drop for Allocator {
    fn drop(&mut self) {
        let data = self.data.borrow();
        if data.iter().any(|d| *d) {
            panic!("missing free: {:?}", data);
        }
    }
}

impl Allocator {
    fn new(failing_op: usize) -> Self {
        Allocator { failing_op, cur_ops: Cell::new(0), data: RefCell::new(vec![]) }
    }
    fn alloc(&self) -> impl Future<Output = Ptr<'_>> + '_ {
        self.fallible_operation();

        let mut data = self.data.borrow_mut();

        let addr = data.len();
        data.push(true);
        Defer { ready: false, value: Some(Ptr(addr, self)) }
    }
    fn fallible_operation(&self) {
        self.cur_ops.set(self.cur_ops.get() + 1);

        if self.cur_ops.get() == self.failing_op {
            panic::panic_any(InjectedFailure);
        }
    }
}

// Type that tracks whether it was dropped and can panic when it's created or
// destroyed.
struct Ptr<'a>(usize, &'a Allocator);
impl<'a> Drop for Ptr<'a> {
    fn drop(&mut self) {
        match self.1.data.borrow_mut()[self.0] {
            false => panic!("double free at index {:?}", self.0),
            ref mut d => *d = false,
        }

        self.1.fallible_operation();
    }
}

async fn dynamic_init(a: Rc<Allocator>, c: bool) {
    let _x;
    if c {
        _x = Some(a.alloc().await);
    }
}

async fn dynamic_drop(a: Rc<Allocator>, c: bool) {
    let x = a.alloc().await;
    if c {
        Some(x)
    } else {
        None
    };
}

struct TwoPtrs<'a>(Ptr<'a>, Ptr<'a>);
async fn struct_dynamic_drop(a: Rc<Allocator>, c0: bool, c1: bool, c: bool) {
    for i in 0..2 {
        let x;
        let y;
        if (c0 && i == 0) || (c1 && i == 1) {
            x = (a.alloc().await, a.alloc().await, a.alloc().await);
            y = TwoPtrs(a.alloc().await, a.alloc().await);
            if c {
                drop(x.1);
                a.alloc().await;
                drop(y.0);
                a.alloc().await;
            }
        }
    }
}

async fn field_assignment(a: Rc<Allocator>, c0: bool) {
    let mut x = (TwoPtrs(a.alloc().await, a.alloc().await), a.alloc().await);

    x.1 = a.alloc().await;
    x.1 = a.alloc().await;

    let f = (x.0).0;
    a.alloc().await;
    if c0 {
        (x.0).0 = f;
    }
    a.alloc().await;
}

async fn assignment(a: Rc<Allocator>, c0: bool, c1: bool) {
    let mut _v = a.alloc().await;
    let mut _w = a.alloc().await;
    if c0 {
        drop(_v);
    }
    _v = _w;
    if c1 {
        _w = a.alloc().await;
    }
}

async fn array_simple(a: Rc<Allocator>) {
    let _x = [a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await];
}

async fn vec_simple(a: Rc<Allocator>) {
    let _x = vec![a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await];
}

async fn mixed_drop_and_nondrop(a: Rc<Allocator>) {
    // check that destructor panics handle drop
    // and non-drop blocks in the same scope correctly.
    //
    // Surprisingly enough, this used to not work.
    let (x, y, z);
    x = a.alloc().await;
    y = 5;
    z = a.alloc().await;
}

#[allow(unreachable_code)]
async fn vec_unreachable(a: Rc<Allocator>) {
    let _x = vec![a.alloc().await, a.alloc().await, a.alloc().await, return];
}

async fn slice_pattern_one_of(a: Rc<Allocator>, i: usize) {
    let array = [a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await];
    let _x = match i {
        0 => {
            let [a, ..] = array;
            a
        }
        1 => {
            let [_, a, ..] = array;
            a
        }
        2 => {
            let [_, _, a, _] = array;
            a
        }
        3 => {
            let [_, _, _, a] = array;
            a
        }
        _ => panic!("unmatched"),
    };
    a.alloc().await;
}

async fn subslice_pattern_from_end_with_drop(a: Rc<Allocator>, arg: bool, arg2: bool) {
    let arr = [a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await];
    if arg2 {
        drop(arr);
        return;
    }

    if arg {
        let [.., _x, _] = arr;
    } else {
        let [_, _y @ ..] = arr;
    }
    a.alloc().await;
}

async fn subslice_pattern_reassign(a: Rc<Allocator>) {
    let mut ar = [a.alloc().await, a.alloc().await, a.alloc().await];
    let [_, _, _x] = ar;
    ar = [a.alloc().await, a.alloc().await, a.alloc().await];
    let [_, _y @ ..] = ar;
    a.alloc().await;
}

async fn move_ref_pattern(a: Rc<Allocator>) {
    let mut tup = (a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await);
    let (ref _a, ref mut _b, _c, mut _d) = tup;
    a.alloc().await;
}

fn run_test<F, G>(cx: &mut Context<'_>, ref f: F)
where
    F: Fn(Rc<Allocator>) -> G,
    G: Future<Output = ()>,
{
    for polls in 0.. {
        // Run without any panics to find which operations happen after the
        // penultimate `poll`.
        let first_alloc = Rc::new(Allocator::new(usize::MAX));
        let mut fut = Box::pin(f(first_alloc.clone()));
        let mut ops_before_last_poll = 0;
        let mut completed = false;
        for _ in 0..polls {
            ops_before_last_poll = first_alloc.cur_ops.get();
            if let Poll::Ready(()) = fut.as_mut().poll(cx) {
                completed = true;
            }
        }
        drop(fut);

        // Start at `ops_before_last_poll` so that we will always be able to
        // `poll` the expected number of times.
        for failing_op in ops_before_last_poll..first_alloc.cur_ops.get() {
            let alloc = Rc::new(Allocator::new(failing_op + 1));
            let f = &f;
            let cx = &mut *cx;
            let result = panic::catch_unwind(panic::AssertUnwindSafe(move || {
                let mut fut = Box::pin(f(alloc));
                for _ in 0..polls {
                    let _ = fut.as_mut().poll(cx);
                }
                drop(fut);
            }));
            match result {
                Ok(..) => panic!("test executed more ops on first call"),
                Err(e) => {
                    if e.downcast_ref::<InjectedFailure>().is_none() {
                        panic::resume_unwind(e);
                    }
                }
            }
        }

        if completed {
            break;
        }
    }
}

fn clone_waker(data: *const ()) -> RawWaker {
    RawWaker::new(data, &RawWakerVTable::new(clone_waker, drop, drop, drop))
}

fn main() {
    let waker = unsafe { Waker::from_raw(clone_waker(ptr::null())) };
    let context = &mut Context::from_waker(&waker);

    run_test(context, |a| dynamic_init(a, false));
    run_test(context, |a| dynamic_init(a, true));
    run_test(context, |a| dynamic_drop(a, false));
    run_test(context, |a| dynamic_drop(a, true));

    run_test(context, |a| assignment(a, false, false));
    run_test(context, |a| assignment(a, false, true));
    run_test(context, |a| assignment(a, true, false));
    run_test(context, |a| assignment(a, true, true));

    run_test(context, |a| array_simple(a));
    run_test(context, |a| vec_simple(a));
    run_test(context, |a| vec_unreachable(a));

    run_test(context, |a| struct_dynamic_drop(a, false, false, false));
    run_test(context, |a| struct_dynamic_drop(a, false, false, true));
    run_test(context, |a| struct_dynamic_drop(a, false, true, false));
    run_test(context, |a| struct_dynamic_drop(a, false, true, true));
    run_test(context, |a| struct_dynamic_drop(a, true, false, false));
    run_test(context, |a| struct_dynamic_drop(a, true, false, true));
    run_test(context, |a| struct_dynamic_drop(a, true, true, false));
    run_test(context, |a| struct_dynamic_drop(a, true, true, true));

    run_test(context, |a| field_assignment(a, false));
    run_test(context, |a| field_assignment(a, true));

    run_test(context, |a| mixed_drop_and_nondrop(a));

    run_test(context, |a| slice_pattern_one_of(a, 0));
    run_test(context, |a| slice_pattern_one_of(a, 1));
    run_test(context, |a| slice_pattern_one_of(a, 2));
    run_test(context, |a| slice_pattern_one_of(a, 3));

    run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, true));
    run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, false));
    run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, true));
    run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, false));
    run_test(context, |a| subslice_pattern_reassign(a));

    run_test(context, |a| move_ref_pattern(a));
}

Version information

rustc 1.87.0-nightly (3b022d8ce 2025-02-18)
binary: rustc
commit-hash: 3b022d8ceea570db9730be34d964f0cc663a567f
commit-date: 2025-02-18
host: x86_64-unknown-linux-gnu
release: 1.87.0-nightly
LLVM version: 20.1.0

Possibly related line of code:

};
cfg_checker.visit_body(body);
cfg_checker.check_cleanup_control_flow();
// Also run the TypeChecker.
for (location, msg) in validate_types(tcx, typing_env, body, body) {
cfg_checker.fail(location, msg);
}
if let MirPhase::Runtime(_) = body.phase {
if let ty::InstanceKind::Item(_) = body.source.instance {
if body.has_free_regions() {
cfg_checker.fail(

Command:
/home/matthias/.rustup/toolchains/master/bin/rustc --edition=2024 -Zvalidate-mir

Program output

warning: unused import: `panic`
 --> /tmp/icemaker_global_tempdir.RCp5KYktJql7/rustc_testrunner_tmpdir_reporting.UlnYvRre65To/mvce.rs:5:5
  |
5 |     panic,
  |     ^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: variable does not need to be mutable
  --> /tmp/icemaker_global_tempdir.RCp5KYktJql7/rustc_testrunner_tmpdir_reporting.UlnYvRre65To/mvce.rs:43:13
   |
43 |         let mut data = self.data.borrow_mut();
   |             ----^^^^
   |             |
   |             help: remove this `mut`
   |
   = note: `#[warn(unused_mut)]` on by default

warning: unreachable expression
  --> /tmp/icemaker_global_tempdir.RCp5KYktJql7/rustc_testrunner_tmpdir_reporting.UlnYvRre65To/mvce.rs:60:14
   |
60 |     let _x = vec![a.alloc().await, a.alloc().await, a.alloc().await, return];
   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^
   |              |                                                       |
   |              |                                                       any code following this expression is unreachable
   |              unreachable expression
   |
   = note: `#[warn(unreachable_code)]` on by default
   = note: this warning originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: unused variable: `cx`
  --> /tmp/icemaker_global_tempdir.RCp5KYktJql7/rustc_testrunner_tmpdir_reporting.UlnYvRre65To/mvce.rs:19:39
   |
19 |     fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
   |                                       ^^ help: if this is intentional, prefix it with an underscore: `_cx`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `polls`
  --> /tmp/icemaker_global_tempdir.RCp5KYktJql7/rustc_testrunner_tmpdir_reporting.UlnYvRre65To/mvce.rs:68:9
   |
68 |     for polls in 0.. {
   |         ^^^^^ help: if this is intentional, prefix it with an underscore: `_polls`

warning: unused variable: `cx`
  --> /tmp/icemaker_global_tempdir.RCp5KYktJql7/rustc_testrunner_tmpdir_reporting.UlnYvRre65To/mvce.rs:63:19
   |
63 | fn run_test<F, G>(cx: &mut Context<'_>, ref f: F)
   |                   ^^ help: if this is intentional, prefix it with an underscore: `_cx`

warning: variable does not need to be mutable
  --> /tmp/icemaker_global_tempdir.RCp5KYktJql7/rustc_testrunner_tmpdir_reporting.UlnYvRre65To/mvce.rs:70:13
   |
70 |         let mut fut = Box::pin(f(first_alloc.clone()));
   |             ----^^^
   |             |
   |             help: remove this `mut`

warning: fields `failing_op` and `cur_ops` are never read
  --> /tmp/icemaker_global_tempdir.RCp5KYktJql7/rustc_testrunner_tmpdir_reporting.UlnYvRre65To/mvce.rs:30:5
   |
28 | struct Allocator {
   |        --------- fields in this struct
29 |     data: RefCell<Vec<bool>>,
30 |     failing_op: usize,
   |     ^^^^^^^^^^
31 |     cur_ops: Cell<usize>,
   |     ^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: fields `0` and `1` are never read
  --> /tmp/icemaker_global_tempdir.RCp5KYktJql7/rustc_testrunner_tmpdir_reporting.UlnYvRre65To/mvce.rs:54:16
   |
54 | struct Ptr<'a>(usize, &'a Allocator);
   |        ---     ^^^^^  ^^^^^^^^^^^^^
   |        |
   |        fields in this struct
   |
   = help: consider removing these fields


thread 'rustc' panicked at compiler/rustc_mir_transform/src/validate.rs:80:25:
broken MIR in DropGlue(DefId(2:2857 ~ core[b00e]::ptr::drop_in_place), Some(Coroutine(DefId(0:45 ~ mvce[7c74]::vec_unreachable::{closure#0}), [(), std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:45 ~ mvce[7c74]::vec_unreachable::{closure#0}), []), (std::rc::Rc<Allocator, std::alloc::Global>,)]))) (after pass MentionedItems) at bb39[0]:
Transmute is not supported in non-runtime phase Analysis(PostCleanup).
stack backtrace:
   0:     0x7a5dde3878b4 - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::hb1dbb105bd2d1c24
   1:     0x7a5ddea1a26c - core::fmt::write::h7da158f89ab4458f
   2:     0x7a5ddfb9c251 - std::io::Write::write_fmt::h39957863a56e5cac
   3:     0x7a5dde387712 - std::sys::backtrace::BacktraceLock::print::h3be96afe5576ef80
   4:     0x7a5dde389f1e - std::panicking::default_hook::{{closure}}::h272c7564c84a1176
   5:     0x7a5dde389af4 - std::panicking::default_hook::he5fe1aaab2f25425
   6:     0x7a5ddd4d9237 - std[e3e91186ef571fb2]::panicking::update_hook::<alloc[534667ecbc51a4ea]::boxed::Box<rustc_driver_impl[8214a48106e737a0]::install_ice_hook::{closure#1}>>::{closure#0}
   7:     0x7a5dde38a793 - std::panicking::rust_panic_with_hook::hc0ab1a47eab84af9
   8:     0x7a5dde38a48a - std::panicking::begin_panic_handler::{{closure}}::hc3f7509381a5f194
   9:     0x7a5dde387d79 - std::sys::backtrace::__rust_end_short_backtrace::h0946700dcbd1e531
  10:     0x7a5dde38a14d - rust_begin_unwind
  11:     0x7a5ddb043850 - core::panicking::panic_fmt::hc766ac463fa3fc75
  12:     0x7a5ddc0b5112 - <rustc_mir_transform[c38770258410c05c]::validate::CfgChecker>::fail::<alloc[534667ecbc51a4ea]::string::String>
  13:     0x7a5ddf429ca0 - <rustc_mir_transform[c38770258410c05c]::validate::Validator as rustc_mir_transform[c38770258410c05c]::pass_manager::MirPass>::run_pass
  14:     0x7a5ddcdcf765 - rustc_mir_transform[c38770258410c05c]::pass_manager::validate_body
  15:     0x7a5ddea05a68 - rustc_mir_transform[c38770258410c05c]::pass_manager::run_passes_inner
  16:     0x7a5ddf40660a - rustc_mir_transform[c38770258410c05c]::shim::make_shim
  17:     0x7a5ddf4057af - rustc_query_impl[d25549a6c4185600]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[d25549a6c4185600]::query_impl::mir_shims::dynamic_query::{closure#2}::{closure#0}, rustc_middle[197a7b3770fbd787]::query::erase::Erased<[u8; 8usize]>>
  18:     0x7a5ddf405773 - <rustc_query_impl[d25549a6c4185600]::query_impl::mir_shims::dynamic_query::{closure#2} as core[b00e6010bfa5719a]::ops::function::FnOnce<(rustc_middle[197a7b3770fbd787]::ty::context::TyCtxt, rustc_middle[197a7b3770fbd787]::ty::instance::InstanceKind)>>::call_once
  19:     0x7a5ddf483780 - rustc_query_system[22c8932483092702]::query::plumbing::try_execute_query::<rustc_query_impl[d25549a6c4185600]::DynamicConfig<rustc_query_system[22c8932483092702]::query::caches::DefaultCache<rustc_middle[197a7b3770fbd787]::ty::instance::InstanceKind, rustc_middle[197a7b3770fbd787]::query::erase::Erased<[u8; 8usize]>>, false, false, false>, rustc_query_impl[d25549a6c4185600]::plumbing::QueryCtxt, false>
  20:     0x7a5ddf4834f1 - rustc_query_impl[d25549a6c4185600]::query_impl::mir_shims::get_query_non_incr::__rust_end_short_backtrace
  21:     0x7a5ddef24174 - <rustc_middle[197a7b3770fbd787]::ty::context::TyCtxt>::instance_mir
  22:     0x7a5ddb79eb29 - rustc_monomorphize[1ec9e6f51add3954]::mono_checks::check_mono_item
  23:     0x7a5ddef1eaa0 - rustc_query_impl[d25549a6c4185600]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[d25549a6c4185600]::query_impl::check_mono_item::dynamic_query::{closure#2}::{closure#0}, rustc_middle[197a7b3770fbd787]::query::erase::Erased<[u8; 0usize]>>
  24:     0x7a5ddef1e3b3 - rustc_query_system[22c8932483092702]::query::plumbing::try_execute_query::<rustc_query_impl[d25549a6c4185600]::DynamicConfig<rustc_query_system[22c8932483092702]::query::caches::DefaultCache<rustc_middle[197a7b3770fbd787]::ty::instance::Instance, rustc_middle[197a7b3770fbd787]::query::erase::Erased<[u8; 0usize]>>, false, false, false>, rustc_query_impl[d25549a6c4185600]::plumbing::QueryCtxt, false>
  25:     0x7a5ddef1e063 - rustc_query_impl[d25549a6c4185600]::query_impl::check_mono_item::get_query_non_incr::__rust_end_short_backtrace
  26:     0x7a5ddb78bae0 - rustc_monomorphize[1ec9e6f51add3954]::collector::items_of_instance
  27:     0x7a5ddf47f5b2 - rustc_query_impl[d25549a6c4185600]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[d25549a6c4185600]::query_impl::items_of_instance::dynamic_query::{closure#2}::{closure#0}, rustc_middle[197a7b3770fbd787]::query::erase::Erased<[u8; 32usize]>>
  28:     0x7a5ddf47ede9 - rustc_query_system[22c8932483092702]::query::plumbing::try_execute_query::<rustc_query_impl[d25549a6c4185600]::DynamicConfig<rustc_query_system[22c8932483092702]::query::caches::DefaultCache<(rustc_middle[197a7b3770fbd787]::ty::instance::Instance, rustc_middle[197a7b3770fbd787]::mir::mono::CollectionMode), rustc_middle[197a7b3770fbd787]::query::erase::Erased<[u8; 32usize]>>, false, false, false>, rustc_query_impl[d25549a6c4185600]::plumbing::QueryCtxt, false>
  29:     0x7a5ddf47ea2c - rustc_query_impl[d25549a6c4185600]::query_impl::items_of_instance::get_query_non_incr::__rust_end_short_backtrace
  30:     0x7a5ddf47b792 - rustc_monomorphize[1ec9e6f51add3954]::collector::collect_items_rec::{closure#0}
  31:     0x7a5ddfba14c7 - rustc_monomorphize[1ec9e6f51add3954]::collector::collect_items_rec
  32:     0x7a5ddfba1e22 - rustc_monomorphize[1ec9e6f51add3954]::collector::collect_items_rec
  33:     0x7a5ddfba1e22 - rustc_monomorphize[1ec9e6f51add3954]::collector::collect_items_rec
  34:     0x7a5ddfba1e22 - rustc_monomorphize[1ec9e6f51add3954]::collector::collect_items_rec
  35:     0x7a5ddfba1e22 - rustc_monomorphize[1ec9e6f51add3954]::collector::collect_items_rec
  36:     0x7a5ddef402de - rustc_monomorphize[1ec9e6f51add3954]::collector::collect_crate_mono_items
  37:     0x7a5ddf97e762 - rustc_monomorphize[1ec9e6f51add3954]::partitioning::collect_and_partition_mono_items
  38:     0x7a5ddf97e6d6 - rustc_query_impl[d25549a6c4185600]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[d25549a6c4185600]::query_impl::collect_and_partition_mono_items::dynamic_query::{closure#2}::{closure#0}, rustc_middle[197a7b3770fbd787]::query::erase::Erased<[u8; 40usize]>>
  39:     0x7a5ddf97e6b3 - <rustc_query_impl[d25549a6c4185600]::query_impl::collect_and_partition_mono_items::dynamic_query::{closure#2} as core[b00e6010bfa5719a]::ops::function::FnOnce<(rustc_middle[197a7b3770fbd787]::ty::context::TyCtxt, ())>>::call_once
  40:     0x7a5ddf97dde2 - rustc_query_system[22c8932483092702]::query::plumbing::try_execute_query::<rustc_query_impl[d25549a6c4185600]::DynamicConfig<rustc_query_system[22c8932483092702]::query::caches::SingleCache<rustc_middle[197a7b3770fbd787]::query::erase::Erased<[u8; 40usize]>>, false, false, false>, rustc_query_impl[d25549a6c4185600]::plumbing::QueryCtxt, false>
  41:     0x7a5ddf97db85 - rustc_query_impl[d25549a6c4185600]::query_impl::collect_and_partition_mono_items::get_query_non_incr::__rust_end_short_backtrace
  42:     0x7a5ddf985920 - <rustc_codegen_llvm[6f7f5741bbc2f41f]::LlvmCodegenBackend as rustc_codegen_ssa[72a5fc54c4d6959c]::traits::backend::CodegenBackend>::codegen_crate
  43:     0x7a5ddfa623eb - <rustc_interface[daed2421835a31ce]::queries::Linker>::codegen_and_build_linker
  44:     0x7a5ddfa57cf0 - rustc_interface[daed2421835a31ce]::passes::create_and_enter_global_ctxt::<core[b00e6010bfa5719a]::option::Option<rustc_interface[daed2421835a31ce]::queries::Linker>, rustc_driver_impl[8214a48106e737a0]::run_compiler::{closure#0}::{closure#2}>::{closure#2}::{closure#0}
  45:     0x7a5ddf9d31eb - rustc_interface[daed2421835a31ce]::interface::run_compiler::<(), rustc_driver_impl[8214a48106e737a0]::run_compiler::{closure#0}>::{closure#1}
  46:     0x7a5ddf9245c8 - std[e3e91186ef571fb2]::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface[daed2421835a31ce]::util::run_in_thread_with_globals<rustc_interface[daed2421835a31ce]::util::run_in_thread_pool_with_globals<rustc_interface[daed2421835a31ce]::interface::run_compiler<(), rustc_driver_impl[8214a48106e737a0]::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>
  47:     0x7a5ddf9249f4 - <<std[e3e91186ef571fb2]::thread::Builder>::spawn_unchecked_<rustc_interface[daed2421835a31ce]::util::run_in_thread_with_globals<rustc_interface[daed2421835a31ce]::util::run_in_thread_pool_with_globals<rustc_interface[daed2421835a31ce]::interface::run_compiler<(), rustc_driver_impl[8214a48106e737a0]::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core[b00e6010bfa5719a]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
  48:     0x7a5ddf9253af - std::sys::pal::unix::thread::Thread::new::thread_start::he442680e6614a233
  49:     0x7a5dd9ca370a - <unknown>
  50:     0x7a5dd9d27aac - <unknown>
  51:                0x0 - <unknown>

error: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: please make sure that you have updated to the latest nightly

note: rustc 1.87.0-nightly (3b022d8ce 2025-02-18) running on x86_64-unknown-linux-gnu

note: compiler flags: -Z validate-mir -Z dump-mir-dir=dir

query stack during panic:
#0 [mir_shims] generating MIR shim for `core::ptr::drop_in_place`
#1 [check_mono_item] monomorphization-time checking
#2 [items_of_instance] collecting items used by `core::ptr::drop_in_place::<{async fn body of vec_unreachable()}> - shim(Some({async fn body of vec_unreachable()}))`
#3 [collect_and_partition_mono_items] collect_and_partition_mono_items
end of query stack
warning: 9 warnings emitted


@matthiaskrgr matthiaskrgr added C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 18, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Feb 18, 2025
@matthiaskrgr matthiaskrgr added E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. -Zvalidate-mir Unstable option: MIR validation needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. C-bug Category: This is a bug. and removed I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Feb 18, 2025
@matthiaskrgr
Copy link
Member Author

bisection points to #137112 cc @scottmcm

@scottmcm
Copy link
Member

Oh, yeah, that sounds like me. mir_drops_elaborated_and_const_checked is before runtime.

Weird that nothing in-tree caught this. Is this super-specific to async or something?

@cyrgani
Copy link
Contributor

cyrgani commented Feb 18, 2025

a bit simpler:

//@compile-flags: --edition=2024 -Zvalidate-mir
struct HasDrop;
impl Drop for HasDrop {
    fn drop(&mut self) {}
}

fn main() {
    async {
        vec![async { HasDrop }.await];
    };
}

@rustbot label -E-needs-mcve S-has-mcve

@rustbot rustbot added S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue and removed E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example labels Feb 18, 2025
@scottmcm scottmcm self-assigned this Feb 19, 2025
@scottmcm scottmcm linked a pull request Feb 19, 2025 that will close this issue
@saethlin saethlin removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Feb 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
-Zvalidate-mir Unstable option: MIR validation C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants