Skip to content

ICE error performing operation: fully_perform #140123

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

Open
RedRam567 opened this issue Apr 21, 2025 · 4 comments
Open

ICE error performing operation: fully_perform #140123

RedRam567 opened this issue Apr 21, 2025 · 4 comments
Labels
C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@RedRam567
Copy link

RedRam567 commented Apr 21, 2025

ICE when const {} initializing mutable references in [expr; N] array initializers where N is >= 2. Does not happen when setting every element explicitly [expr, expr]. Interestingly you cannot use const { &mut[] } directly and must use a function call to get around it. I will make another issue for that.

Related issue: "Compile error when using &mut in explicity const context directly" #140126

Code

// error[E0764]: mutable references are not allowed in the final value of constants
// pub const NO_COMPILE: [&mut [f32]; 2] = [const { &mut[] }; 2];
const OK: [&mut [()]; 2] = [empty_mut(), empty_mut()];
const ICE: [&mut [()]; 2] = [const { empty_mut() }; 2];

// Any kind of fn call gets around E0764.
const fn empty_mut() -> &'static mut [()] {
    &mut []
}

Meta

Occurs in version >= 1.83.0. Older versions fail to compile normally due to mutable references in const.

rustc --version --verbose:

rustc 1.88.0-nightly (b8c54d635 2025-04-20)
binary: rustc
commit-hash: b8c54d6358926028ac2fab1ec2b8665c70edb1c0
commit-date: 2025-04-20
host: x86_64-unknown-linux-gnu
release: 1.88.0-nightly
LLVM version: 20.1.2

Error output

   Compiling rust_playground2 v0.1.0 (/tmp/rust_playground2)
note: no errors encountered even though delayed bugs were created

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

error: internal compiler error: error performing operation: fully_perform
 --> src/lib.rs:1:34
  |
1 | pub const ICE: [&mut [f32]; 2] = [const { empty_mut() }; 2];
  |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
note: delayed at /rustc/b8c54d6358926028ac2fab1ec2b8665c70edb1c0/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs:87:25 - disabled backtrace
 --> src/lib.rs:1:34
  |
1 | pub const ICE: [&mut [f32]; 2] = [const { empty_mut() }; 2];
  |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^

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: please attach the file at `/tmp/rust_playground2/rustc-ice-2025-04-21T16_27_11-21059.txt` to your bug report

note: compiler flags: --crate-type lib -C embed-bitcode=no -C debuginfo=2 -C incremental=[REDACTED]

note: some of the compiler flags provided by cargo are hidden

query stack during panic:
end of query stack
error: could not compile `rust_playground2` (lib)

Caused by:
  process didn't exit successfully: `/home/redram/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/rustc --crate-name rust_playground2 --edition=2024 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 --check-cfg 'cfg(docsrs,test)' --check-cfg 'cfg(feature, values())' -C metadata=1f5395c8c0077482 -C extra-filename=-be321adee2c2c0a3 --out-dir /mnt/extra/cargo_target/debug/deps -C incremental=/mnt/extra/cargo_target/debug/incremental -L dependency=/mnt/extra/cargo_target/debug/deps` (exit status: 101)
Backtrace

delayed bug: error performing operation: fully_perform
   0: <rustc_errors::DiagCtxtInner>::emit_diagnostic
   1: <rustc_errors::DiagCtxtHandle>::emit_diagnostic
   2: <rustc_span::ErrorGuaranteed as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee
   3: <rustc_errors::DiagCtxtHandle>::span_delayed_bug::<rustc_span::span_encoding::Span, alloc::string::String>
   4: <rustc_borrowck::type_check::TypeChecker>::prove_trait_ref
   5: <rustc_borrowck::type_check::TypeChecker as rustc_middle::mir::visit::Visitor>::visit_rvalue
   6: <rustc_borrowck::type_check::TypeChecker as rustc_middle::mir::visit::Visitor>::visit_body
   7: rustc_borrowck::do_mir_borrowck
   8: rustc_borrowck::mir_borrowck
   9: 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]>>
  10: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::Erased<[u8; 8]>, rustc_query_system::dep_graph::graph::DepNodeIndex>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, true>
  11: rustc_query_impl::query_impl::mir_borrowck::get_query_incr::__rust_end_short_backtrace
  12: rustc_mir_transform::mir_drops_elaborated_and_const_checked
  13: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::mir_drops_elaborated_and_const_checked::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 8]>>
  14: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::Erased<[u8; 8]>, rustc_query_system::dep_graph::graph::DepNodeIndex>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, true>
  15: rustc_query_impl::query_impl::mir_drops_elaborated_and_const_checked::get_query_incr::__rust_end_short_backtrace
  16: rustc_mir_transform::mir_for_ctfe
  17: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::mir_for_ctfe::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 8]>>
  18: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::DefIdCache<rustc_middle::query::erase::Erased<[u8; 8]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, true>
  19: rustc_query_impl::query_impl::mir_for_ctfe::get_query_incr::__rust_end_short_backtrace
  20: <rustc_const_eval::interpret::eval_context::InterpCx<rustc_const_eval::const_eval::machine::CompileTimeMachine>>::load_mir
  21: rustc_const_eval::const_eval::eval_queries::eval_to_allocation_raw_provider
  22: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::eval_to_allocation_raw::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 24]>>
  23: <rustc_query_impl::query_impl::eval_to_allocation_raw::dynamic_query::{closure#2} as core::ops::function::FnOnce<(rustc_middle::ty::context::TyCtxt, rustc_middle::ty::PseudoCanonicalInput<rustc_middle::mir::interpret::GlobalId>)>>::call_once
  24: <rustc_query_system::query::plumbing::execute_job_incr<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::DefaultCache<rustc_middle::ty::PseudoCanonicalInput<rustc_middle::mir::interpret::GlobalId>, rustc_middle::query::erase::Erased<[u8; 24]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt>::{closure#2}::{closure#2} as core::ops::function::FnOnce<((rustc_query_impl::plumbing::QueryCtxt, rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::DefaultCache<rustc_middle::ty::PseudoCanonicalInput<rustc_middle::mir::interpret::GlobalId>, rustc_middle::query::erase::Erased<[u8; 24]>>, false, false, false>), rustc_middle::ty::PseudoCanonicalInput<rustc_middle::mir::interpret::GlobalId>)>>::call_once
  25: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::DefaultCache<rustc_middle::ty::PseudoCanonicalInput<rustc_middle::mir::interpret::GlobalId>, rustc_middle::query::erase::Erased<[u8; 24]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, true>
  26: rustc_query_impl::query_impl::eval_to_allocation_raw::get_query_incr::__rust_end_short_backtrace
  27: rustc_const_eval::const_eval::eval_queries::eval_to_const_value_raw_provider
  28: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::eval_to_const_value_raw::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 24]>>
  29: <rustc_query_impl::query_impl::eval_to_const_value_raw::dynamic_query::{closure#2} as core::ops::function::FnOnce<(rustc_middle::ty::context::TyCtxt, rustc_middle::ty::PseudoCanonicalInput<rustc_middle::mir::interpret::GlobalId>)>>::call_once
  30: <rustc_query_system::query::plumbing::execute_job_incr<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::DefaultCache<rustc_middle::ty::PseudoCanonicalInput<rustc_middle::mir::interpret::GlobalId>, rustc_middle::query::erase::Erased<[u8; 24]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt>::{closure#2}::{closure#2} as core::ops::function::FnOnce<((rustc_query_impl::plumbing::QueryCtxt, rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::DefaultCache<rustc_middle::ty::PseudoCanonicalInput<rustc_middle::mir::interpret::GlobalId>, rustc_middle::query::erase::Erased<[u8; 24]>>, false, false, false>), rustc_middle::ty::PseudoCanonicalInput<rustc_middle::mir::interpret::GlobalId>)>>::call_once
  31: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::DefaultCache<rustc_middle::ty::PseudoCanonicalInput<rustc_middle::mir::interpret::GlobalId>, rustc_middle::query::erase::Erased<[u8; 24]>>, false, true, false>, rustc_query_impl::plumbing::QueryCtxt, true>
  32: rustc_query_impl::query_impl::eval_to_const_value_raw::get_query_incr::__rust_end_short_backtrace
  33: rustc_hir_analysis::check_crate
  34: rustc_interface::passes::run_required_analyses
  35: rustc_interface::passes::analysis
  36: 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; 0]>>
  37: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::SingleCache<rustc_middle::query::erase::Erased<[u8; 0]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, true>
  38: rustc_query_impl::query_impl::analysis::get_query_incr::__rust_end_short_backtrace
  39: rustc_interface::passes::create_and_enter_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2}::{closure#0}
  40: rustc_interface::interface::run_compiler::<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}
  41: std::sys::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<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>
  42: <<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<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
  43: std::sys::pal::unix::thread::Thread::new::thread_start
  44: <unknown>
  45: <unknown>



rustc version: 1.88.0-nightly (b8c54d635 2025-04-20)
platform: x86_64-unknown-linux-gnu

@RedRam567 RedRam567 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 Apr 21, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Apr 21, 2025
@compiler-errors
Copy link
Member

// MIR for `ICE` after built

const ICE: [&mut [()]; 2] = {
    let mut _0: [&mut [()]; 2];
    let mut _1: &mut [()];
    let mut _2: &mut [()];

    bb0: {
        StorageLive(_1);
        StorageLive(_2);
        _2 = const ICE::{constant#1};
        _1 = &mut (*_2);
        _0 = [move _1; 2];
        StorageDead(_2);
        StorageDead(_1);
        return;
    }
}

We're reborrowing the &mut [()] argument at _1 = &mut (*_2), b/c we always reborrow unsized mut refs in coercion I think.

This could be fixed, but we still have other operations that still cause ICEs like real unsize coercions:

trait Trait {}

impl Trait for [(); 0] {}

const ICE: [&mut dyn Trait; 2] = [const { empty_mut() }; 2];

const fn empty_mut() -> &'static mut [(); 0] {
    &mut []
}

Which also leads to an ICE:

// MIR for `ICE` after built

const ICE: [&mut dyn Trait; 2] = {
    let mut _0: [&mut dyn Trait; 2];
    let mut _1: &mut dyn Trait;
    let mut _2: &mut dyn Trait;
    let mut _3: &mut dyn Trait;

    bb0: {
        StorageLive(_1);
        StorageLive(_2);
        StorageLive(_3);
        _3 = const ICE::{constant#1};
        _2 = &mut (*_3);
        _1 = move _2 as &mut dyn Trait (PointerCoercion(Unsize, Implicit));
        StorageDead(_2);
        _0 = [move _1; 2];
        StorageDead(_3);
        StorageDead(_1);
        return;
    }
}

@RedRam567
Copy link
Author

This also ICEs when using std::slice::from_raw_parts_mut instead.

const ICE: [&mut [()]; 2] = [const { empty_mut() }; 2];

const fn empty_mut() -> &'static mut [()] {
    unsafe {
        std::slice::from_raw_parts_mut(std::ptr::dangling_mut(), 0)
    }
}

@theemathas
Copy link
Contributor

A variant that doesn't involve unsized coercions:

const ICE: [&mut [(); 0]; 2] = [const { empty_mut() }; 2];

const fn empty_mut() -> &'static mut [(); 0] {
    &mut []
}

@theemathas
Copy link
Contributor

A variant without a function call:

const ICE: [&mut [(); 0]; 2] = [const {
    let x = &mut [];
    x
}; 2];

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. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. 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

4 participants