rust-lang/rust

ICE `all spans must be disjoint` (attrs)

Opened this issue · 8 comments

auto-reduced (treereduce-rust):

#![core::contracts::requires(x > 0)]
#![allow{
    #
    !  
}]

fn main() {}

original:

//@ check-pass

#![core::contracts::requires(x > 0)]
#![allow{
    #[macro_export]
    macro_rules! panic {
        () => ()
    }
}]

fn main() {}

Version information

rustc 1.92.0-nightly (b00998aaa 2025-09-20)
binary: rustc
commit-hash: b00998aaa50a78b1e45fb107a6c0cfd3f1dc44dd
commit-date: 2025-09-20
host: x86_64-unknown-linux-gnu
release: 1.92.0-nightly
LLVM version: 21.1.1

Possibly related line of code:

.cloned()
.filter_map(|mut substitution| {
// Assumption: all spans are in the same file, and all spans
// are disjoint. Sort in ascending order.
substitution.parts.sort_by_key(|part| part.span.lo());
// Verify the assumption that all spans are disjoint
assert_eq!(
substitution.parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
None,
"all spans must be disjoint",
);
// Account for cases where we are suggesting the same code that's already

Command:
/home/matthias/.rustup/toolchains/master/bin/rustc

Program output

error[E0658]: use of unstable library feature `contracts`
 --> /tmp/icemaker_global_tempdir.E7hQgXd7LAKL/rustc_testrunner_tmpdir_reporting.MUBnYeHThp1W/mvce.rs:3:4
  |
3 | #![core::contracts::requires(x > 0)]
  |    ^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
  = help: add `#![feature(contracts)]` to the crate attributes to enable
  = note: this compiler was built on 2025-09-20; consider upgrading it if it is out of date

error[E0658]: inner macro attributes are unstable
 --> /tmp/icemaker_global_tempdir.E7hQgXd7LAKL/rustc_testrunner_tmpdir_reporting.MUBnYeHThp1W/mvce.rs:3:4
  |
3 | #![core::contracts::requires(x > 0)]
  |    ^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
  = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
  = note: this compiler was built on 2025-09-20; consider upgrading it if it is out of date

error: wrong meta list delimiters
 --> /tmp/icemaker_global_tempdir.E7hQgXd7LAKL/rustc_testrunner_tmpdir_reporting.MUBnYeHThp1W/mvce.rs:3:1
  |
3 | / #![core::contracts::requires(x > 0)]
4 | | #![allow{
5 | |     #
6 | |     !  
... |
9 | | fn main() {}
  | |____________^
  |

thread 'rustc' (1511766) panicked at compiler/rustc_errors/src/lib.rs:385:17:
assertion `left == right` failed: all spans must be disjoint
  left: Some([SubstitutionPart { span: /tmp/icemaker_global_tempdir.E7hQgXd7LAKL/rustc_testrunner_tmpdir_reporting.MUBnYeHThp1W/mvce.rs:3:1: 9:13 (#0), snippet: "(" }, SubstitutionPart { span: /tmp/icemaker_global_tempdir.E7hQgXd7LAKL/rustc_testrunner_tmpdir_reporting.MUBnYeHThp1W/mvce.rs:3:1: 9:13 (#0), snippet: ")" }])
 right: None
stack backtrace:
   0:     0x7f03bc2045c3 - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::h7d3016e1c941944f
   1:     0x7f03bca02004 - core::fmt::write::h921ea77fbff93f70
   2:     0x7f03bc1b8e41 - std::io::Write::write_fmt::h47e0fa70cca1f8bd
   3:     0x7f03bc1ca332 - std::sys::backtrace::BacktraceLock::print::h817fc06c9153f428
   4:     0x7f03bc1d0299 - std::panicking::default_hook::{{closure}}::ha9e124657af3b922
   5:     0x7f03bc1cfdc3 - std::panicking::default_hook::h1f433e920268743c
   6:     0x7f03bb1f40d7 - std[32ad0880f2c1b772]::panicking::update_hook::<alloc[b304ad98ec0f4a1c]::boxed::Box<rustc_driver_impl[326e7f6ae07792a4]::install_ice_hook::{closure#1}>>::{closure#0}
   7:     0x7f03bc1d06bf - std::panicking::panic_with_hook::h5626f65517dee992
   8:     0x7f03bc1d047a - std::panicking::panic_handler::{{closure}}::hbebe8c8476ee5a6e
   9:     0x7f03bc1ca479 - std::sys::backtrace::__rust_end_short_backtrace::hd1c52aa13481922b
  10:     0x7f03bc1aafad - __rustc[8e2c4287e81e192a]::rust_begin_unwind
  11:     0x7f03b950e2e0 - core::panicking::panic_fmt::h6d63006811d5ceda
  12:     0x7f03babea083 - core::panicking::assert_failed_inner::h8592d3e0338e9a50
  13:     0x7f03bb223f38 - core[5c94e0b3abe5a55e]::panicking::assert_failed::<core[5c94e0b3abe5a55e]::option::Option<&[rustc_errors[1b01786b4caf07ae]::SubstitutionPart; 2usize]>, core[5c94e0b3abe5a55e]::option::Option<&[rustc_errors[1b01786b4caf07ae]::SubstitutionPart; 2usize]>>
  14:     0x7f03bddeb1af - <core[5c94e0b3abe5a55e]::iter::adapters::filter_map::FilterMap<core[5c94e0b3abe5a55e]::iter::adapters::cloned::Cloned<core[5c94e0b3abe5a55e]::iter::adapters::filter::Filter<core[5c94e0b3abe5a55e]::slice::iter::Iter<rustc_errors[1b01786b4caf07ae]::Substitution>, <rustc_errors[1b01786b4caf07ae]::CodeSuggestion>::splice_lines::{closure#0}>>, <rustc_errors[1b01786b4caf07ae]::CodeSuggestion>::splice_lines::{closure#1}> as core[5c94e0b3abe5a55e]::iter::traits::iterator::Iterator>::next
  15:     0x7f03bddec39f - <rustc_errors[1b01786b4caf07ae]::emitter::HumanEmitter>::emit_suggestion_default
  16:     0x7f03bdeb5953 - <rustc_errors[1b01786b4caf07ae]::emitter::HumanEmitter as rustc_errors[1b01786b4caf07ae]::emitter::Emitter>::emit_diagnostic
  17:     0x7f03bdebce95 - <rustc_errors[1b01786b4caf07ae]::DiagCtxtInner>::emit_diagnostic::{closure#3}
  18:     0x7f03bdeba85a - rustc_interface[5054a517fd15f988]::callbacks::track_diagnostic::<core[5c94e0b3abe5a55e]::option::Option<rustc_span[efaea81bac4f363]::ErrorGuaranteed>>
  19:     0x7f03bdeb9876 - <rustc_errors[1b01786b4caf07ae]::DiagCtxtInner>::emit_diagnostic
  20:     0x7f03bdeb973f - <rustc_errors[1b01786b4caf07ae]::DiagCtxtHandle>::emit_diagnostic
  21:     0x7f03b90db5be - <rustc_span[efaea81bac4f363]::ErrorGuaranteed as rustc_errors[1b01786b4caf07ae]::diagnostic::EmissionGuarantee>::emit_producing_guarantee
  22:     0x7f03bcf5189b - rustc_attr_parsing[de633f658bc3b1ce]::validate_attr::parse_meta
  23:     0x7f03bcf51e62 - rustc_attr_parsing[de633f658bc3b1ce]::validate_attr::check_attr
  24:     0x7f03bcf4f82d - rustc_interface[5054a517fd15f988]::passes::configure_and_expand
  25:     0x7f03bdc9e117 - rustc_interface[5054a517fd15f988]::passes::resolver_for_lowering_raw
  26:     0x7f03bdc9de5b - rustc_query_impl[9b0a68892776d472]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[9b0a68892776d472]::query_impl::resolver_for_lowering_raw::dynamic_query::{closure#2}::{closure#0}, rustc_middle[892f50a53bd7ad3d]::query::erase::Erased<[u8; 16usize]>>
  27:     0x7f03bdc9de49 - <rustc_query_impl[9b0a68892776d472]::query_impl::resolver_for_lowering_raw::dynamic_query::{closure#2} as core[5c94e0b3abe5a55e]::ops::function::FnOnce<(rustc_middle[892f50a53bd7ad3d]::ty::context::TyCtxt, ())>>::call_once
  28:     0x7f03bda4699f - rustc_query_system[ab3a9463f805284c]::query::plumbing::try_execute_query::<rustc_query_impl[9b0a68892776d472]::DynamicConfig<rustc_query_system[ab3a9463f805284c]::query::caches::SingleCache<rustc_middle[892f50a53bd7ad3d]::query::erase::Erased<[u8; 16usize]>>, false, false, false>, rustc_query_impl[9b0a68892776d472]::plumbing::QueryCtxt, false>
  29:     0x7f03bda464fc - rustc_query_impl[9b0a68892776d472]::query_impl::resolver_for_lowering_raw::get_query_non_incr::__rust_end_short_backtrace
  30:     0x7f03bdceb8fa - rustc_interface[5054a517fd15f988]::passes::create_and_enter_global_ctxt::<core[5c94e0b3abe5a55e]::option::Option<rustc_interface[5054a517fd15f988]::queries::Linker>, rustc_driver_impl[326e7f6ae07792a4]::run_compiler::{closure#0}::{closure#2}>::{closure#2}::{closure#0}
  31:     0x7f03bdc363be - rustc_interface[5054a517fd15f988]::interface::run_compiler::<(), rustc_driver_impl[326e7f6ae07792a4]::run_compiler::{closure#0}>::{closure#1}
  32:     0x7f03bdba3b78 - std[32ad0880f2c1b772]::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface[5054a517fd15f988]::util::run_in_thread_with_globals<rustc_interface[5054a517fd15f988]::util::run_in_thread_pool_with_globals<rustc_interface[5054a517fd15f988]::interface::run_compiler<(), rustc_driver_impl[326e7f6ae07792a4]::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>
  33:     0x7f03bdba3848 - <<std[32ad0880f2c1b772]::thread::Builder>::spawn_unchecked_<rustc_interface[5054a517fd15f988]::util::run_in_thread_with_globals<rustc_interface[5054a517fd15f988]::util::run_in_thread_pool_with_globals<rustc_interface[5054a517fd15f988]::interface::run_compiler<(), rustc_driver_impl[326e7f6ae07792a4]::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core[5c94e0b3abe5a55e]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
  34:     0x7f03bdba9b0d - std::sys::thread::unix::Thread::new::thread_start::h617e06fcb73c5f56
  35:     0x7f03b72969cb - <unknown>
  36:     0x7f03b731aa0c - <unknown>
  37:                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.92.0-nightly (b00998aaa 2025-09-20) running on x86_64-unknown-linux-gnu

query stack during panic:
#0 [resolver_for_lowering_raw] getting the resolver for lowering
end of query stack
error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0658`.

#![core::contracts::requires]
#[allow{}]
fn main() {}

searched nightlies: from nightly-2025-08-10 to nightly-2025-09-15
regressed nightly: nightly-2025-09-06
searched commit range: af00ff2...6c699a3
regressed commit: 99317ef

bisected with cargo-bisect-rustc v0.6.10

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc --start 2025-08-10 --end 2025-09-15 --regress ice 

@Muscraft

@rustbot label regression-from-stable-to-beta

Assigning priority (discussion on Zulip).

@rustbot label -I-prioritize +P-medium

okay, the problem here is specific to requires. it parses and re-emits all tokens it sees with the same span. Therefore, the entire module gets the same span, and any error after that that tries to make suggestions will have every part of said suggestion apply to the same span, which then crashes in suggestion code. I think the exact same ICE would trigger on any other error with a suggestion, with a contract attribute on it.

This should be fixed, I think contract attributes should just start using syn/quote for example, and make sure to emit the original code with the correct spans (@celinval). There's already a FIXME for this.

This PR (#147778) attempted to fix the issue by making sure this specific suggestion is emitted correctly, but I think it doesn't address the root cause. The one problem I see is that another, user-made macro can also set all spans to the same value. This diff also reproduces the ICE without requires: 436c2eb. In other words: there are two problems

  • contracts set all spans to the same value
  • when a macro sets all spans to the same value, suggestions can ICE, in probably more ways than just the one demonstrated here. Basically, whenever a user uses a macro to set spans to be non-disjoint or not from the same file, suggestion code can panic. You wouldn't often do this of course, it took me a bit to make the macro correctly to achieve that. It's much easier to do in built-in macros. So I think that issue is P-low (@apiraino), but should be addressed, probably by more gracefully handling that

@chenyukang I think your PR is not inherently wrong, but it doesn't fix the root cause so I'm going to close it. I'll make another PR that adds a regression test for this (the version without contract attributes) and makes suggestion code more permissive.

this should fix the root cause, and contains a test for this issue that doesn't involve contracts: #147849

made a separate issue to track the fact that contract attributes give their output a single span: #147851

I'd expect this to be nightly-only, I don't think we've stabilized contracts? But I don't see feature gates in the reduced code above... maybe it fails before we'd fail anyway due to feature gates?

this ices on beta already so I guess it will ice on stable in a bit.