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 with let_chains #122871

Closed
Naserume opened this issue Mar 22, 2024 · 8 comments
Closed

ice: broken mir with let_chains #122871

Naserume opened this issue Mar 22, 2024 · 8 comments
Labels
C-bug Category: This is a bug. F-let_chains `#![feature(let_chains)]` 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

@Naserume
Copy link

Code

#![feature(let_chains)]

fn owned2<T, U>() -> U
where
    T: Default,
    U: Default,
{
    let foo: Result<T, ()> = Ok(T::default());
    let baz: U = U::default();

    if let Ok(foo) = foo && let Ok(bar) = transform(foo) {
        bar
    } else {
        baz
    }
}

fn transform<T, U>(input: T) -> Result<U, ()> {
    todo!()
}

fn main() {}

Meta

rustc --version --verbose:

rustc 1.79.0-nightly (0ad927c0c 2024-03-21)
binary: rustc
commit-hash: 0ad927c0c07b65fc0dae37105e09c877c87c296a
commit-date: 2024-03-21
host: x86_64-apple-darwin
release: 1.79.0-nightly
LLVM version: 18.1.2

Error output

warning: unused variable: `input`
  --> EDF91430837E67F42912F85F184235C09E30358C3D226F98C2B0098353056538.rs:20:20
   |
20 | fn transform<T, U>(input: T) -> Result<U, ()> {
   |                    ^^^^^ help: if this is intentional, prefix it with an underscore: `_input`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: function `owned2` is never used
 --> EDF91430837E67F42912F85F184235C09E30358C3D226F98C2B0098353056538.rs:5:4
  |
5 | fn owned2<T, U>() -> U
  |    ^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: function `transform` is never used
  --> EDF91430837E67F42912F85F184235C09E30358C3D226F98C2B0098353056538.rs:20:4
   |
20 | fn transform<T, U>(input: T) -> Result<U, ()> {
   |    ^^^^^^^^^

warning: 3 warnings emitted

note: no errors encountered even though delayed bugs were created

note: those delayed bugs will now be shown as internal compiler errors

command

rustc EDF91430837E67F42912F85F184235C09E30358C3D226F98C2B0098353056538.rs '-Zlint-mir'

full backtrace is very long (about 3000 lines)
you can see it in here

Backtrace

error: internal compiler error: broken MIR in Item(DefId(0:3 ~ EDF91430837E67F42912F85F184235C09E30358C3D226F98C2B0098353056538[ff8a]::owned2)) (after pass CheckPackedRef) at bb29[0]:
                                use of local _6, which has no storage here
  --> EDF91430837E67F42912F85F184235C09E30358C3D226F98C2B0098353056538.rs:18:1
   |
18 | }
   | ^
   |
note: delayed at compiler/rustc_mir_transform/src/lint.rs:75:22
         0: std::backtrace::Backtrace::create
         1: std::backtrace::Backtrace::capture
         2: <rustc_errors::DiagCtxtInner>::emit_diagnostic
         3: <rustc_errors::DiagCtxt>::emit_diagnostic
         4: <rustc_span::ErrorGuaranteed as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee
         5: <rustc_errors::DiagCtxt>::span_delayed_bug::<rustc_span::span_encoding::Span, alloc::string::String>
         6: <rustc_mir_transform::lint::Lint>::fail::<alloc::string::String>
         7: <rustc_mir_transform::lint::Lint as rustc_middle::mir::visit::Visitor>::visit_local
         8: <rustc_mir_transform::lint::Lint as rustc_middle::mir::visit::Visitor>::visit_terminator
         9: rustc_mir_transform::lint::lint_body
        10: rustc_mir_transform::pass_manager::run_passes_inner
        11: rustc_mir_transform::mir_const
        12: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::mir_const::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 8]>>
        13: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::VecCache<rustc_hir::hir_id::OwnerId, rustc_middle::query::erase::Erased<[u8; 8]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, false>
        14: rustc_query_impl::query_impl::mir_const::get_query_non_incr::__rust_end_short_backtrace
        15: rustc_middle::query::plumbing::query_get_at::<rustc_query_system::query::caches::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::Erased<[u8; 8]>>>
        16: rustc_mir_transform::mir_promoted
        17: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::mir_promoted::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 16]>>
        18: <rustc_query_impl::query_impl::mir_promoted::dynamic_query::{closure#2} as core::ops::function::FnOnce<(rustc_middle::ty::context::TyCtxt, rustc_span::def_id::LocalDefId)>>::call_once
        19: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::Erased<[u8; 16]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, false>
        20: rustc_query_impl::query_impl::mir_promoted::get_query_non_incr::__rust_end_short_backtrace
        21: rustc_middle::query::plumbing::query_get_at::<rustc_query_system::query::caches::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::Erased<[u8; 16]>>>
        22: rustc_borrowck::mir_borrowck
        23: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::mir_borrowck::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 8]>>
        24: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::VecCache<rustc_hir::hir_id::OwnerId, rustc_middle::query::erase::Erased<[u8; 8]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, false>
        25: rustc_query_impl::query_impl::mir_borrowck::get_query_non_incr::__rust_end_short_backtrace
        26: <rustc_middle::hir::map::Map>::par_body_owners::<rustc_interface::passes::analysis::{closure#1}::{closure#0}>::{closure#0}
        27: rustc_interface::passes::analysis
        28: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::analysis::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 1]>>
        29: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::SingleCache<rustc_middle::query::erase::Erased<[u8; 1]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, false>
        30: rustc_query_impl::query_impl::analysis::get_query_non_incr::__rust_end_short_backtrace
        31: <rustc_interface::queries::QueryResult<&rustc_middle::ty::context::GlobalCtxt>>::enter::<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}::{closure#1}::{closure#3}>
        32: rustc_interface::interface::run_compiler::<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}>::{closure#0}
        33: std::sys_common::backtrace::__rust_begin_short_backtrace::<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}>::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>::{closure#0}::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>
        34: <<std::thread::Builder>::spawn_unchecked_<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}>::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>::{closure#0}::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>::{closure#1} as core::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
        35: std::sys::pal::unix::thread::Thread::new::thread_start
        36: __pthread_start
  --> EDF91430837E67F42912F85F184235C09E30358C3D226F98C2B0098353056538.rs:18:1
   |
18 | }
   | ^

error: internal compiler error: broken MIR in Item(DefId(0:3 ~ EDF91430837E67F42912F85F184235C09E30358C3D226F98C2B0098353056538[ff8a]::owned2)) (after pass CheckPackedRef) at bb24[1]:
                                use of local _6, which has no storage here
  --> EDF91430837E67F42912F85F184235C09E30358C3D226F98C2B0098353056538.rs:18:1
   |
18 | }
   | ^
   |
note: delayed at compiler/rustc_mir_transform/src/lint.rs:75:22
         0: std::backtrace::Backtrace::create
         1: std::backtrace::Backtrace::capture
         2: <rustc_errors::DiagCtxtInner>::emit_diagnostic
         3: <rustc_errors::DiagCtxt>::emit_diagnostic
         4: <rustc_span::ErrorGuaranteed as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee
         5: <rustc_errors::DiagCtxt>::span_delayed_bug::<rustc_span::span_encoding::Span, alloc::string::String>
         6: <rustc_mir_transform::lint::Lint>::fail::<alloc::string::String>
         7: <rustc_mir_transform::lint::Lint as rustc_middle::mir::visit::Visitor>::visit_local
         8: <rustc_mir_transform::lint::Lint as rustc_middle::mir::visit::Visitor>::visit_terminator
         9: rustc_mir_transform::lint::lint_body
        10: rustc_mir_transform::pass_manager::run_passes_inner
        11: rustc_mir_transform::mir_const
        12: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::mir_const::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 8]>>
        13: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::VecCache<rustc_hir::hir_id::OwnerId, rustc_middle::query::erase::Erased<[u8; 8]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, false>
        14: rustc_query_impl::query_impl::mir_const::get_query_non_incr::__rust_end_short_backtrace
        15: rustc_middle::query::plumbing::query_get_at::<rustc_query_system::query::caches::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::Erased<[u8; 8]>>>
        16: rustc_mir_transform::mir_promoted
        17: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::mir_promoted::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 16]>>
        18: <rustc_query_impl::query_impl::mir_promoted::dynamic_query::{closure#2} as core::ops::function::FnOnce<(rustc_middle::ty::context::TyCtxt, rustc_span::def_id::LocalDefId)>>::call_once
        19: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::Erased<[u8; 16]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, false>
        20: rustc_query_impl::query_impl::mir_promoted::get_query_non_incr::__rust_end_short_backtrace
        21: rustc_middle::query::plumbing::query_get_at::<rustc_query_system::query::caches::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::Erased<[u8; 16]>>>
        22: rustc_borrowck::mir_borrowck
        23: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::mir_borrowck::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 8]>>
        24: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::VecCache<rustc_hir::hir_id::OwnerId, rustc_middle::query::erase::Erased<[u8; 8]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, false>
        25: rustc_query_impl::query_impl::mir_borrowck::get_query_non_incr::__rust_end_short_backtrace
        26: <rustc_middle::hir::map::Map>::par_body_owners::<rustc_interface::passes::analysis::{closure#1}::{closure#0}>::{closure#0}
        27: rustc_interface::passes::analysis
        28: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::analysis::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 1]>>
        29: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::SingleCache<rustc_middle::query::erase::Erased<[u8; 1]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, false>
        30: rustc_query_impl::query_impl::analysis::get_query_non_incr::__rust_end_short_backtrace
        31: <rustc_interface::queries::QueryResult<&rustc_middle::ty::context::GlobalCtxt>>::enter::<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}::{closure#1}::{closure#3}>
        32: rustc_interface::interface::run_compiler::<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}>::{closure#0}
        33: std::sys_common::backtrace::__rust_begin_short_backtrace::<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}>::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>::{closure#0}::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>
        34: <<std::thread::Builder>::spawn_unchecked_<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}>::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>::{closure#0}::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>::{closure#1} as core::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
        35: std::sys::pal::unix::thread::Thread::new::thread_start
        36: __pthread_start
  --> EDF91430837E67F42912F85F184235C09E30358C3D226F98C2B0098353056538.rs:18:1
   |
18 | }
   | ^

seems like bug occured at visit_local and it's different one from #120421 visit_statement and visit_terminator

@Naserume Naserume 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 Mar 22, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Mar 22, 2024
@matthiaskrgr
Copy link
Member

known issue https://github.com/rust-lang/rust/issues?q=is%3Aissue+let_chains+broken+mir+is%3Aclosed

@jieyouxu jieyouxu added F-let_chains `#![feature(let_chains)]` S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Mar 22, 2024
@Nadrieril
Copy link
Member

Nadrieril commented Apr 1, 2024

Indeed looks very similar to #99852 which was fixed in #102394.

Minimized:

#![feature(let_chains)]
struct Struct;

impl Drop for Struct {
    fn drop(&mut self) {}
}

fn main() {
    if true
        && let _ = Struct
    {}
}

This is the first pass that errors:

error: internal compiler error: broken MIR in Item(DefId(0:7 ~ foo[b740]::main)) (after pass CheckPackedRef) at bb8[1]:
                                use of local _2, which has no storage here

Here's a MIR that errors, taken in a later phase for convenience:

error: internal compiler error: broken MIR in Item(DefId(0:7 ~ foo[b740]::main)) (after pass SimplifyCfg-pre-optimizations) at bb6[0]:
                                use of local _2, which has no storage here
// MIR for `main` after SimplifyCfg-pre-optimizations

fn main() -> () {
    let mut _0: ();
    let mut _1: bool;
    let mut _2: Struct;
    let mut _3: bool;

    bb0: {
        _3 = const false;
        StorageLive(_1);
        _1 = const true;
        switchInt(move _1) -> [0: bb2, otherwise: bb1];
    }

    bb1: {
        StorageLive(_2);
        _3 = const true;
        _2 = Struct;
        _0 = const ();
        goto -> bb3;
    }

    bb2: {
        _0 = const ();
        goto -> bb3;
    }

    bb3: {
        StorageDead(_1);
        switchInt(_3) -> [0: bb4, otherwise: bb6];
    }

    bb4: {
        _3 = const false;
        StorageDead(_2);
        return;
    }

    bb5 (cleanup): {
        resume;
    }

    bb6: {
        drop(_2) -> [return: bb4, unwind: bb5];
    }
}

version: 1.79.0-nightly (805813650 2024-03-31)

@Nadrieril
Copy link
Member

Nadrieril commented Apr 1, 2024

The error is pretty clear: when testing the boolean, if found false we shortcut to bb2 which doesn't initialize the Struct, but the Struct is unconditionally dropped at the end of the if block (in bb6).

Indeed this no longer errors:

#![feature(let_chains)]
struct Struct;

impl Drop for Struct {
    fn drop(&mut self) {}
}

fn main() {
    let s = Struct;
    if true
        && let _ = s
    {}
}

@Nadrieril
Copy link
Member

Ah, this is actually an issue with -Zlint-mir more than anything, since variations on this store a drop flag to ensure we only drop the value if it was initialized. There's no unsoundness here, just a validation phase that doesn't take into account drop flags.

@lolbinarycat
Copy link

triage: neither the original repro or the minimized version cause any form of error in the latest nightly

@Nadrieril
Copy link
Member

@lolbinarycat did you try with -Zlint-mir?

@lolbinarycat
Copy link

just tried it with -Zlint-mir, still produces nothing (other than the irrefutable_let_patterns warning).

@Nadrieril
Copy link
Member

Nice, thanks for checking 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. F-let_chains `#![feature(let_chains)]` 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

No branches or pull requests

6 participants