close
Skip to content

Guard patterns: MIR lowering#154545

Open
Human9000-bit wants to merge 31 commits intorust-lang:mainfrom
Human9000-bit:guard-patterns-mir
Open

Guard patterns: MIR lowering#154545
Human9000-bit wants to merge 31 commits intorust-lang:mainfrom
Human9000-bit:guard-patterns-mir

Conversation

@Human9000-bit
Copy link
Copy Markdown
Contributor

@Human9000-bit Human9000-bit commented Mar 29, 2026

View all comments

This pr implements THIR -> MIR lowering of guard patterns:

  • When PatKind::Guard is encountered, we lower the subpattern and push ExprId of a condition to extra_data.guard_patterns in order-preserving manner
  • Then we pass that field to MatchTreeSubBranch
  • In bind_ang_guard_matched_candidate we merge arm and guard patterns into a single Vec<Exprid>
  • Then we iterate over that vec of guards and merge them in a chain at MIR level

r? @dianne
cc @Nadrieril, @max-niederman

Tracking issue: #129967

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 29, 2026

Some changes occurred in match lowering

cc @Nadrieril

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 29, 2026
@rust-log-analyzer

This comment has been minimized.

@Zalathar
Copy link
Copy Markdown
Member

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Mar 29, 2026
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Mar 29, 2026
Comment thread compiler/rustc_mir_build/src/builder/matches/mod.rs Outdated
@Human9000-bit
Copy link
Copy Markdown
Contributor Author

@Zalathar could you schedule perf run once again?

@Zalathar
Copy link
Copy Markdown
Member

It’ll be faster to just let the old try job keep running. The new changes shouldn’t affect perf, so I think benchmarking the current job will be fine.

Copy link
Copy Markdown
Contributor

@dianne dianne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need some //@ run-pass tests to make sure the runtime semantics are correct, possibly also with //@ compile-flags: -Zvalidate-mir -Zlint-mir to help catch drop scheduling bugs. Getting scoping right and scheduling drops properly for guard patterns in all cases is a little subtle and will end up being the trickiest part of this; I know my first stab at that produced broken MIR ^^

You'll also want to look into how fake borrows work; patterns with guards on them will need fake borrows to make sure the guards can't modify any places being tested. For match and irrefutable let, this is needed for soundness (and in other cases, we should probably be consistent with that). At a glance, it doesn't look like this is setting has_guard for candidates, so certain things like fake borrows won't work. Likewise, this will need tests. I think some other things might use has_guard too, like or-pattern simplification.

As a meta note, I do have some opinions about how guard patterns should be implemented from my own attempt at lowering them to MIR last year. I'll try not just to compare this to what I'd do, since I'd effectively be reviewing my own code, but it might help to have more eyes on it just in case.

View changes since this review

Comment thread compiler/rustc_mir_build/src/builder/matches/mod.rs Outdated
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Mar 29, 2026

☀️ Try build successful (CI)
Build commit: 94df5ce (94df5ce4eb9a637adba2da13b3f79cf010e61aeb, parent: 584d32e3ee7a2051c9ec1338d259ed8ef16380ca)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (94df5ce): comparison URL.

Overall result: ❌ regressions - no action needed

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

@bors rollup=never
@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.1% [0.1%, 0.1%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (secondary 2.0%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.0% [0.8%, 3.5%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Cycles

Results (primary 2.6%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.6% [2.6%, 2.6%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 2.6% [2.6%, 2.6%] 1

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 484.385s -> 484.355s (-0.01%)
Artifact size: 394.81 MiB -> 394.86 MiB (0.01%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Mar 29, 2026
@Human9000-bit
Copy link
Copy Markdown
Contributor Author

@dianne, just asking: in your local implementation, what were the signs of incorrect scoping and drop scheduling?

@theemathas
Copy link
Copy Markdown
Contributor

theemathas commented Mar 30, 2026

(Note: I had to merge this PR with the main branch locally before compiling, to work around #154408. So, line numbers might not be accurate.)

This code causes an ICE with this PR:

#![feature(guard_patterns)]

fn main() {
    let x = String::from("abc");
    match x {
        (y if false) | y => {}
        _ => {}
    }
}
Error output
warning: the feature `guard_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
 --> src/main.rs:1:12
  |
1 | #![feature(guard_patterns)]
  |            ^^^^^^^^^^^^^^
  |
  = note: see issue #129967 <https://github.com/rust-lang/rust/issues/129967> for more information
  = note: `#[warn(incomplete_features)]` on by default

warning: unreachable pattern
 --> src/main.rs:6:24
  |
6 |         (y if false) | y => {}
  |          -             ^ no value can reach this
  |          |
  |          matches any value
  |
  = note: `#[warn(unreachable_patterns)]` (part of `#[warn(unused)]`) on by default

warning: unreachable pattern
 --> src/main.rs:7:9
  |
6 |         (y if false) | y => {}
  |         ---------------- matches all the relevant values
7 |         _ => {}
  |         ^ no value can reach this

error: internal compiler error: compiler/rustc_mir_build/src/builder/mod.rs:386:17: anything with one local should never be within a guard.


thread 'rustc' (205910) panicked at compiler/rustc_mir_build/src/builder/mod.rs:386:17:
Box<dyn Any>
stack backtrace:
   0: begin_panic<rustc_errors::ExplicitBug>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/std/src/panicking.rs:761:5
   1: panic_any<rustc_errors::ExplicitBug>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/std/src/panic.rs:260:5
   2: emit_producing_guarantee
             at /Users/timch/rust/compiler/rustc_errors/src/diagnostic.rs:58:9
   3: emit<rustc_errors::diagnostic::BugAbort>
             at /Users/timch/rust/compiler/rustc_errors/src/diagnostic.rs:1285:9
   4: bug<alloc::string::String>
             at /Users/timch/rust/compiler/rustc_errors/src/lib.rs:927:30
   5: {closure#0}<rustc_span::span_encoding::Span>
             at /Users/timch/rust/compiler/rustc_middle/src/util/bug.rs:39:48
   6: {closure#0}<rustc_middle::util::bug::opt_span_bug_fmt::{closure_env#0}<rustc_span::span_encoding::Span>, !>
             at /Users/timch/rust/compiler/rustc_middle/src/ty/context/tls.rs:109:23
   7: with_context_opt<rustc_middle::ty::context::tls::with_opt::{closure_env#0}<rustc_middle::util::bug::opt_span_bug_fmt::{closure_env#0}<rustc_span::span_encoding::Span>, !>, !>
             at /Users/timch/rust/compiler/rustc_middle/src/ty/context/tls.rs:75:18
   8: with_opt<rustc_middle::util::bug::opt_span_bug_fmt::{closure_env#0}<rustc_span::span_encoding::Span>, !>
             at /Users/timch/rust/compiler/rustc_middle/src/ty/context/tls.rs:107:5
   9: opt_span_bug_fmt<rustc_span::span_encoding::Span>
             at /Users/timch/rust/compiler/rustc_middle/src/util/bug.rs:33:5
  10: bug_fmt
             at /Users/timch/rust/compiler/rustc_middle/src/util/bug.rs:16:5
  11: local_id
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/mod.rs:386:17
  12: var_local_id
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/mod.rs:257:31
  13: storage_live_binding
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/matches/mod.rs:786:29
  14: bind_matched_candidate_for_guard<core::slice::iter::Iter<rustc_mir_build::builder::matches::Binding>>
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/matches/mod.rs:2687:38
  15: bind_and_guard_matched_candidate
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/matches/mod.rs:2451:18
  16: bind_pattern
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/matches/mod.rs:557:40
  17: {closure#1}
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/matches/mod.rs:464:46
  18: opt_in_scope<(), rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure#1}::{closure#1}::{closure_env#1}>
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/scope.rs:717:13
  19: {closure#1}
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/matches/mod.rs:437:26
  20: in_scope<rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure#1}::{closure_env#1}, ()>
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/scope.rs:700:34
  21: {closure#1}
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/matches/mod.rs:436:22
  22: {closure#0}<(&rustc_middle::thir::Arm, rustc_mir_build::builder::matches::MatchTreeBranch), rustc_middle::mir::BasicBlock, (), rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}, core::iter::traits::iterator::Iterator::for_each::call::{closure_env#0}<rustc_middle::mir::BasicBlock, alloc::vec::{impl#21}::extend_trusted::{closure_env#0}<rustc_middle::mir::BasicBlock, alloc::alloc::Global, core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>>>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/core/src/iter/adapters/map.rs:88:28
  23: spec_fold<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>, (), core::iter::adapters::map::map_fold::{closure_env#0}<(&rustc_middle::thir::Arm, rustc_mir_build::builder::matches::MatchTreeBranch), rustc_middle::mir::BasicBlock, (), rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}, core::iter::traits::iterator::Iterator::for_each::call::{closure_env#0}<rustc_middle::mir::BasicBlock, alloc::vec::{impl#21}::extend_trusted::{closure_env#0}<rustc_middle::mir::BasicBlock, alloc::alloc::Global, core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>>>>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/core/src/iter/adapters/zip.rs:678:25
  24: fold<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>, (), core::iter::adapters::map::map_fold::{closure_env#0}<(&rustc_middle::thir::Arm, rustc_mir_build::builder::matches::MatchTreeBranch), rustc_middle::mir::BasicBlock, (), rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}, core::iter::traits::iterator::Iterator::for_each::call::{closure_env#0}<rustc_middle::mir::BasicBlock, alloc::vec::{impl#21}::extend_trusted::{closure_env#0}<rustc_middle::mir::BasicBlock, alloc::alloc::Global, core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>>>>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/core/src/iter/adapters/zip.rs:248:9
  25: fold<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>, (), core::iter::adapters::map::map_fold::{closure_env#0}<(&rustc_middle::thir::Arm, rustc_mir_build::builder::matches::MatchTreeBranch), rustc_middle::mir::BasicBlock, (), rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}, core::iter::traits::iterator::Iterator::for_each::call::{closure_env#0}<rustc_middle::mir::BasicBlock, alloc::vec::{impl#21}::extend_trusted::{closure_env#0}<rustc_middle::mir::BasicBlock, alloc::alloc::Global, core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>>>>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/core/src/iter/adapters/zip.rs:103:9
  26: fold<rustc_middle::mir::BasicBlock, core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}, (), core::iter::traits::iterator::Iterator::for_each::call::{closure_env#0}<rustc_middle::mir::BasicBlock, alloc::vec::{impl#21}::extend_trusted::{closure_env#0}<rustc_middle::mir::BasicBlock, alloc::alloc::Global, core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>>>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/core/src/iter/adapters/map.rs:128:19
  27: for_each<core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>, alloc::vec::{impl#21}::extend_trusted::{closure_env#0}<rustc_middle::mir::BasicBlock, alloc::alloc::Global, core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/core/src/iter/traits/iterator.rs:845:14
  28: extend_trusted<rustc_middle::mir::BasicBlock, alloc::alloc::Global, core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/alloc/src/vec/mod.rs:4001:26
  29: spec_extend<rustc_middle::mir::BasicBlock, core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>, alloc::alloc::Global>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/alloc/src/vec/spec_extend.rs:27:14
  30: from_iter<rustc_middle::mir::BasicBlock, core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/alloc/src/vec/spec_from_iter_nested.rs:60:16
  31: from_iter<rustc_middle::mir::BasicBlock, core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/alloc/src/vec/spec_from_iter.rs:33:9
  32: from_iter<rustc_middle::mir::BasicBlock, core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/alloc/src/vec/mod.rs:3865:9
  33: collect<core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::thir::ArmId>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#0}>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::MatchTreeBranch, alloc::alloc::Global>>, rustc_mir_build::builder::matches::{impl#0}::lower_match_arms::{closure_env#1}>, alloc::vec::Vec<rustc_middle::mir::BasicBlock, alloc::alloc::Global>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/core/src/iter/traits/iterator.rs:2064:9
  34: lower_match_arms
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/matches/mod.rs:483:14
  35: match_expr
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/matches/mod.rs:382:14
  36: expr_into_dest
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/expr/into.rs:60:65
  37: {closure#0}
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/expr/into.rs:53:30
  38: in_scope<rustc_mir_build::builder::expr::into::{impl#0}::expr_into_dest::{closure#0}::{closure_env#0}, ()>
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/scope.rs:700:34
  39: {closure#0}
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/expr/into.rs:52:26
  40: maybe_grow<rustc_mir_build::builder::BlockAnd<()>, rustc_mir_build::builder::expr::into::{impl#0}::expr_into_dest::{closure_env#0}>
             at /Users/timch/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/stacker-0.1.21/src/lib.rs:57:9
  41: ensure_sufficient_stack<rustc_mir_build::builder::BlockAnd<()>, rustc_mir_build::builder::expr::into::{impl#0}::expr_into_dest::{closure_env#0}>
             at /Users/timch/rust/compiler/rustc_data_structures/src/stack.rs:21:5
  42: expr_into_dest
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/expr/into.rs:51:17
  43: ast_block_stmts
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/block.rs:324:26
  44: {closure#0}
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/block.rs:29:22
  45: in_scope<rustc_mir_build::builder::block::{impl#0}::ast_block::{closure_env#0}, ()>
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/scope.rs:700:34
  46: ast_block
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/block.rs:23:14
  47: expr_into_dest
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/expr/into.rs:58:22
  48: {closure#0}
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/expr/into.rs:53:30
  49: in_scope<rustc_mir_build::builder::expr::into::{impl#0}::expr_into_dest::{closure#0}::{closure_env#0}, ()>
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/scope.rs:700:34
  50: {closure#0}
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/expr/into.rs:52:26
  51: maybe_grow<rustc_mir_build::builder::BlockAnd<()>, rustc_mir_build::builder::expr::into::{impl#0}::expr_into_dest::{closure_env#0}>
             at /Users/timch/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/stacker-0.1.21/src/lib.rs:57:9
  52: ensure_sufficient_stack<rustc_mir_build::builder::BlockAnd<()>, rustc_mir_build::builder::expr::into::{impl#0}::expr_into_dest::{closure_env#0}>
             at /Users/timch/rust/compiler/rustc_data_structures/src/stack.rs:21:5
  53: expr_into_dest
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/expr/into.rs:51:17
  54: args_and_body
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/mod.rs:1158:18
  55: {closure#0}
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/mod.rs:539:29
  56: in_scope<rustc_mir_build::builder::construct_fn::{closure#3}::{closure#0}::{closure_env#0}, ()>
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/scope.rs:700:34
  57: {closure#0}
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/mod.rs:538:30
  58: in_breakable_scope<rustc_mir_build::builder::construct_fn::{closure#3}::{closure_env#0}>
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/scope.rs:556:33
  59: {closure#3}
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/mod.rs:537:14
  60: in_scope<rustc_mir_build::builder::construct_fn::{closure_env#3}, ()>
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/scope.rs:700:34
  61: construct_fn
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/mod.rs:532:35
  62: {closure#0}
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/mod.rs:83:45
  63: build_mir_inner_impl
             at /Users/timch/rust/compiler/rustc_mir_build/src/builder/mod.rs:92:13
  64: build_mir_inner_impl
             at /Users/timch/rust/compiler/rustc_middle/src/hooks/mod.rs:24:17
  65: mir_built
             at /Users/timch/rust/compiler/rustc_mir_transform/src/lib.rs:390:24
      [... omitted 28 frames ...]
  66: query_ensure_ok_or_done<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 8]>, rustc_middle::dep_graph::graph::DepNodeIndex>>
             at /Users/timch/rust/compiler/rustc_middle/src/query/inner.rs:63:13
  67: mir_built<rustc_span::def_id::LocalDefId>
             at /Users/timch/rust/compiler/rustc_middle/src/query/plumbing.rs:635:21
  68: check_unsafety
             at /Users/timch/rust/compiler/rustc_mir_build/src/check_unsafety.rs:1153:23
      [... omitted 28 frames ...]
  69: check_unsafety<rustc_span::def_id::LocalDefId>
             at /Users/timch/rust/compiler/rustc_middle/src/query/plumbing.rs:601:21
  70: {closure#0}
             at /Users/timch/rust/compiler/rustc_interface/src/passes.rs:1142:33
  71: {closure#0}<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>
             at /Users/timch/rust/compiler/rustc_middle/src/hir/map.rs:340:79
  72: {closure#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_hir_body_owners::{closure_env#0}<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>>
             at /Users/timch/rust/compiler/rustc_data_structures/src/sync/parallel.rs:175:30
  73: call_once<(), rustc_data_structures::sync::parallel::par_for_each_in::{closure#0}::{closure#1}::{closure_env#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_hir_body_owners::{closure_env#0}<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/core/src/panic/unwind_safe.rs:274:9
  74: do_call<core::panic::unwind_safe::AssertUnwindSafe<rustc_data_structures::sync::parallel::par_for_each_in::{closure#0}::{closure#1}::{closure_env#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_hir_body_owners::{closure_env#0}<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>>>, ()>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/std/src/panicking.rs:581:40
  75: catch_unwind<(), core::panic::unwind_safe::AssertUnwindSafe<rustc_data_structures::sync::parallel::par_for_each_in::{closure#0}::{closure#1}::{closure_env#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_hir_body_owners::{closure_env#0}<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>>>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/std/src/panicking.rs:544:19
  76: catch_unwind<core::panic::unwind_safe::AssertUnwindSafe<rustc_data_structures::sync::parallel::par_for_each_in::{closure#0}::{closure#1}::{closure_env#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_hir_body_owners::{closure_env#0}<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>>>, ()>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/std/src/panic.rs:359:14
  77: run<(), rustc_data_structures::sync::parallel::par_for_each_in::{closure#0}::{closure#1}::{closure_env#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_hir_body_owners::{closure_env#0}<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>>>
             at /Users/timch/rust/compiler/rustc_data_structures/src/sync/parallel.rs:23:9
  78: {closure#1}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_hir_body_owners::{closure_env#0}<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>>
             at /Users/timch/rust/compiler/rustc_data_structures/src/sync/parallel.rs:175:23
  79: for_each<rustc_span::def_id::LocalDefId, rustc_data_structures::sync::parallel::par_for_each_in::{closure#0}::{closure_env#1}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_hir_body_owners::{closure_env#0}<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/core/src/slice/iter/macros.rs:301:21
  80: {closure#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_hir_body_owners::{closure_env#0}<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>>
             at /Users/timch/rust/compiler/rustc_data_structures/src/sync/parallel.rs:174:27
  81: parallel_guard<(), rustc_data_structures::sync::parallel::par_for_each_in::{closure_env#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_hir_body_owners::{closure_env#0}<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>>>
             at /Users/timch/rust/compiler/rustc_data_structures/src/sync/parallel.rs:39:15
  82: par_for_each_in<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_hir_body_owners::{closure_env#0}<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>>
             at /Users/timch/rust/compiler/rustc_data_structures/src/sync/parallel.rs:169:5
  83: par_hir_body_owners<rustc_interface::passes::run_required_analyses::{closure#2}::{closure_env#0}>
             at /Users/timch/rust/compiler/rustc_middle/src/hir/map.rs:340:9
  84: {closure#2}
             at /Users/timch/rust/compiler/rustc_interface/src/passes.rs:1138:13
  85: run<(), rustc_interface::passes::run_required_analyses::{closure_env#2}>
             at /Users/timch/rust/compiler/rustc_data_structures/src/profiling.rs:845:9
  86: time<(), rustc_interface::passes::run_required_analyses::{closure_env#2}>
             at /Users/timch/rust/compiler/rustc_session/src/utils.rs:17:50
  87: run_required_analyses
             at /Users/timch/rust/compiler/rustc_interface/src/passes.rs:1137:10
  88: analysis
             at /Users/timch/rust/compiler/rustc_interface/src/passes.rs:1181:5
      [... omitted 28 frames ...]
  89: query_ensure_ok_or_done<rustc_middle::query::caches::SingleCache<rustc_middle::query::erase::ErasedData<[u8; 0]>>>
             at /Users/timch/rust/compiler/rustc_middle/src/query/inner.rs:63:13
  90: analysis
             at /Users/timch/rust/compiler/rustc_middle/src/query/plumbing.rs:601:21
  91: {closure#2}
             at /Users/timch/rust/compiler/rustc_driver_impl/src/lib.rs:325:29
  92: {closure#2}<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>
             at /Users/timch/rust/compiler/rustc_interface/src/passes.rs:1022:23
  93: {closure#1}<rustc_interface::passes::create_and_enter_global_ctxt::{closure_env#2}<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option<rustc_interface::queries::Linker>>
             at /Users/timch/rust/compiler/rustc_middle/src/ty/context.rs:863:37
  94: {closure#0}<rustc_middle::ty::context::{impl#19}::enter::{closure_env#1}<rustc_interface::passes::create_and_enter_global_ctxt::{closure_env#2}<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option<rustc_interface::queries::Linker>>, core::option::Option<rustc_interface::queries::Linker>>
             at /Users/timch/rust/compiler/rustc_middle/src/ty/context/tls.rs:56:9
  95: try_with<core::cell::Cell<*const ()>, rustc_middle::ty::context::tls::enter_context::{closure_env#0}<rustc_middle::ty::context::{impl#19}::enter::{closure_env#1}<rustc_interface::passes::create_and_enter_global_ctxt::{closure_env#2}<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option<rustc_interface::queries::Linker>>, core::option::Option<rustc_interface::queries::Linker>>, core::option::Option<rustc_interface::queries::Linker>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/std/src/thread/local.rs:513:12
  96: with<core::cell::Cell<*const ()>, rustc_middle::ty::context::tls::enter_context::{closure_env#0}<rustc_middle::ty::context::{impl#19}::enter::{closure_env#1}<rustc_interface::passes::create_and_enter_global_ctxt::{closure_env#2}<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option<rustc_interface::queries::Linker>>, core::option::Option<rustc_interface::queries::Linker>>, core::option::Option<rustc_interface::queries::Linker>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/std/src/thread/local.rs:477:20
  97: enter_context<rustc_middle::ty::context::{impl#19}::enter::{closure_env#1}<rustc_interface::passes::create_and_enter_global_ctxt::{closure_env#2}<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option<rustc_interface::queries::Linker>>, core::option::Option<rustc_interface::queries::Linker>>
             at /Users/timch/rust/compiler/rustc_middle/src/ty/context/tls.rs:53:9
  98: enter<rustc_interface::passes::create_and_enter_global_ctxt::{closure_env#2}<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option<rustc_interface::queries::Linker>>
             at /Users/timch/rust/compiler/rustc_middle/src/ty/context.rs:863:9
  99: create_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_interface::passes::create_and_enter_global_ctxt::{closure_env#2}<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>>
             at /Users/timch/rust/compiler/rustc_middle/src/ty/context.rs:1068:13
 100: create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>
             at /Users/timch/rust/compiler/rustc_interface/src/passes.rs:989:5
 101: {closure#0}
             at /Users/timch/rust/compiler/rustc_driver_impl/src/lib.rs:298:22
 102: {closure#0}<(), rustc_driver_impl::run_compiler::{closure_env#0}>
             at /Users/timch/rust/compiler/rustc_interface/src/interface.rs:500:80
 103: call_once<(), rustc_interface::interface::run_compiler::{closure#1}::{closure_env#0}<(), rustc_driver_impl::run_compiler::{closure_env#0}>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/core/src/panic/unwind_safe.rs:274:9
 104: do_call<core::panic::unwind_safe::AssertUnwindSafe<rustc_interface::interface::run_compiler::{closure#1}::{closure_env#0}<(), rustc_driver_impl::run_compiler::{closure_env#0}>>, ()>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/std/src/panicking.rs:581:40
 105: catch_unwind<(), core::panic::unwind_safe::AssertUnwindSafe<rustc_interface::interface::run_compiler::{closure#1}::{closure_env#0}<(), rustc_driver_impl::run_compiler::{closure_env#0}>>>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/std/src/panicking.rs:544:19
 106: catch_unwind<core::panic::unwind_safe::AssertUnwindSafe<rustc_interface::interface::run_compiler::{closure#1}::{closure_env#0}<(), rustc_driver_impl::run_compiler::{closure_env#0}>>, ()>
             at /rustc/ad726b5063362ec9897ef3d67452fc5606ee70fa/library/std/src/panic.rs:359:14
 107: {closure#1}<(), rustc_driver_impl::run_compiler::{closure_env#0}>
             at /Users/timch/rust/compiler/rustc_interface/src/interface.rs:500:23
 108: {closure#0}<rustc_interface::interface::run_compiler::{closure_env#1}<(), rustc_driver_impl::run_compiler::{closure_env#0}>, ()>
             at /Users/timch/rust/compiler/rustc_interface/src/util.rs:203:17
 109: {closure#0}<rustc_interface::util::run_in_thread_pool_with_globals::{closure_env#0}<rustc_interface::interface::run_compiler::{closure_env#1}<(), rustc_driver_impl::run_compiler::{closure_env#0}>, ()>, ()>
             at /Users/timch/rust/compiler/rustc_interface/src/util.rs:159:24
 110: set<rustc_span::SessionGlobals, rustc_interface::util::run_in_thread_with_globals::{closure#0}::{closure#0}::{closure_env#0}<rustc_interface::util::run_in_thread_pool_with_globals::{closure_env#0}<rustc_interface::interface::run_compiler::{closure_env#1}<(), rustc_driver_impl::run_compiler::{closure_env#0}>, ()>, ()>, ()>
             at /Users/timch/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scoped-tls-1.0.1/src/lib.rs:137:9
 111: create_session_globals_then<(), rustc_interface::util::run_in_thread_with_globals::{closure#0}::{closure#0}::{closure_env#0}<rustc_interface::util::run_in_thread_pool_with_globals::{closure_env#0}<rustc_interface::interface::run_compiler::{closure_env#1}<(), rustc_driver_impl::run_compiler::{closure_env#0}>, ()>, ()>>
             at /Users/timch/rust/compiler/rustc_span/src/lib.rs:153:21
 112: {closure#0}<rustc_interface::util::run_in_thread_pool_with_globals::{closure_env#0}<rustc_interface::interface::run_compiler::{closure_env#1}<(), rustc_driver_impl::run_compiler::{closure_env#0}>, ()>, ()>
             at /Users/timch/rust/compiler/rustc_interface/src/util.rs:155:17
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

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 `/Users/timch/foo/rustc-ice-2026-03-30T08_00_41-14079.txt` to your bug report

note: rustc 1.96.0-dev running on aarch64-apple-darwin

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

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

query stack during panic:
#0 [mir_built] building MIR for `main`
#1 [check_unsafety] unsafety-checking `main`
#2 [analysis] running analysis passes on crate `foo`
end of query stack
warning: `foo` (bin "foo") generated 3 warnings
error: could not compile `foo` (bin "foo"); 3 warnings emitted

Caused by:
  process didn't exit successfully: `/Users/timch/.rustup/toolchains/stage1/bin/rustc --crate-name foo --edition=2024 src/main.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=70 --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 -C split-debuginfo=unpacked --check-cfg 'cfg(docsrs,test)' --check-cfg 'cfg(feature, values())' -C metadata=74fbbc1e3db03153 -C extra-filename=-45ca759c633b2da6 --out-dir /Users/timch/foo/target/debug/deps -C incremental=/Users/timch/foo/target/debug/incremental -L dependency=/Users/timch/foo/target/debug/deps` (exit status: 101)

The following code compiles without errors with this PR, and causes a SIGTRAP at run time.

#![feature(guard_patterns)]

fn main() -> ! {
    let (_ if panic!()) = 1;
}

The following code compiles without error with this PR and prints "abc" at run time.

#![feature(guard_patterns)]

fn main() {
    let x = String::from("abc");
    let (y if false) = x;
    println!("{y}");
}

@dianne
Copy link
Copy Markdown
Contributor

dianne commented Mar 30, 2026

in your local implementation, what were the signs of incorrect scoping and drop scheduling?

iirc StorageDeads weren't being emitted properly for RefForGuard bindings for guard patterns in if let, let, and/or function parameters. Putting -Zlint-mir on all my tests was what caught that. Some of those tests were for for runtime drop order, so it's possible that those failing for if let, let, or function parameters was also a sign.

I can also give more direction on how these things work, where to look, etc., if you'd like ^^ I'm new to mentoring, so I'm not sure what balance would be best there; please let me know!

The following code compiles without errors with this PR, and causes a SIGTRAP at run time.

The following code compiles without error with this PR and prints "abc" at run time.

Oh, that's kind of worrying. Is exhaustiveness not checked at all for guard patterns currently? Having at least a stopgap for that could be good. Neither of those should compile, of course, but it should be exhaustiveness checking's responsibility, not MIR lowering.

Edit: yeah, it looks like exhaustiveness wasn't part of #153828. That's fine; guard patterns are a work in progress. But it probably should be tackled in its own PR, not here.

@theemathas
Copy link
Copy Markdown
Contributor

This code compiles and prints 1, and generates a strange warning.

#![feature(guard_patterns)]
#![expect(unused_parens)]

fn main() {
    let x = (true, 1);
    match x {
        (true, ((y @ 1) | (y @ 1)) if false) => {
            println!("{y}");
        }
        _ => {}
    }
}
warning: unreachable pattern
 --> src/main.rs:7:32
  |
7 |         (true, ((y @ 1) | (y @ 1)) if false) => {
  |                      -         ^ no value can reach this
  |                      |
  |                      matches all the relevant values
  |
  = note: `#[warn(unreachable_patterns)]` (part of `#[warn(unused)]`) on by default

@Human9000-bit
Copy link
Copy Markdown
Contributor Author

Human9000-bit commented Mar 30, 2026

Thanks, @theemathas, for feedback
FYI this one causes SIGILL:

#![feature(guard_patterns)]
#![allow(incomplete_features)]

fn main() {
    generic_usage(true, false, true);
}

fn generic_usage(x: bool, y: bool, z: bool) -> bool {
    match (x, y) {
        (true if z, false if !z) => true,
        (false if z, true if z) => false,
        (true, true) => true,
        (false, false) => false
    }
}

@Human9000-bit

This comment was marked as off-topic.

@Human9000-bit Human9000-bit marked this pull request as draft March 30, 2026 09:26
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 30, 2026
@rust-log-analyzer

This comment has been minimized.

@Human9000-bit Human9000-bit force-pushed the guard-patterns-mir branch 2 times, most recently from 2a23009 to dbe705d Compare April 12, 2026 15:01
@Human9000-bit Human9000-bit requested a review from dianne April 12, 2026 15:16
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 12, 2026
@Human9000-bit Human9000-bit marked this pull request as ready for review April 12, 2026 15:16
@Human9000-bit Human9000-bit requested a review from Nadrieril April 13, 2026 13:15
}

let success = self.bind_pattern(self.source_info(pat.span), branch, &[], expr_span, None);
let match_scope = self.local_scope();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Un-resolving this. Could you add fixmes on each of these or revert to just passing None as the arm_match_scope? I'd like to be as clear as possible in marking code that's intentionally incorrect/incomplete.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is nit-picking, but could you reframe the test so it's about something more precise than "MIR correctness"? I'm not sure what exactly that would mean here, but it's not something UI tests test.

Copy link
Copy Markdown
Contributor

@dianne dianne Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you flesh this out and/or add more tests? Most details aren't covered by this, such as guard failure, evaluation order, or-patterns, and temporary scopes (and the ways those intersect). This may warrant multiple, more targeted files. Given how many things need to be tested about guard patterns' runtime semantics, it might get pretty crowded having it all in one file.

I wouldn't expect tests for things we're intentionally leaving for future work (like closures and non-match matches), but for anything that needed to be handled in this PR or otherwise has some special/unique behavior, we should have a test.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, test(s) should definitely be reworked

Comment on lines +785 to +786
fn pat_has_guard(&self, pat: &Pat<'tcx>) -> bool {
match &pat.kind {
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably this would more maintainable as a Pat::walk?

View changes since the review

Comment thread compiler/rustc_middle/src/thir.rs Outdated
Comment on lines -2427 to -2428
// Lower an instance of the arm guard (if present) for this candidate,
// and then perform bindings for the arm body.
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it may be nice to still have an updated version of this comment

View changes since the review

Comment on lines +2608 to +2625
fn extract_arm_span_scope(
&mut self,
sub_branch: &mut MatchTreeSubBranch<'tcx>,
arm: Option<&Arm<'tcx>>,
) -> (Span, Scope) {
if let Some(arm) = arm {
let mut span = arm.span;
if let Some(arm_guard) = arm.guard {
span = self.thir[arm_guard].span;
sub_branch.guard_patterns.push(arm_guard);
};
return (span, arm.scope);
} else {
let span = sub_branch.span;
let arm_scope = self.local_scope();
return (span, arm_scope);
};
}
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few thoughts:

  • if we need to tell where a match comes from, it'd be nice to have something more informative than just an Option<&Arm<'_>>
  • it might be cleaner to decouple the span and scope? the scope is important for correctness, so we should try to make whatever we're doing there as clean and maintainable as possible. for the span, I'm fine doing something hackier, but in that case it shouldn't be tied up with anything important
  • since the scope in else branch is a placeholder for something unimplemented, we shouldn't be returning a real incorrect result from it. we should either ICE or not try to get a scope in the first place until we're supporting non-match matches. or at the very least we should have a fixme
  • please don't mutate the list of guards here. it took me a while to figure out what was going on. can't we add the arm's guard to the list of guards sometime much earlier? Candidate::new currently takes a HasMatchGuard; could it take an optional arm guard or something? or maybe there's somewhere even earlier it could go?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

decouple the span and scope

Like, splitting it into 2 functions: one for scope and another for span?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, that's maybe getting too far ahead regardless. as long as we're only handling match for now, we don't need to handle the general case for scopes or spans. I don't think there's much use in adding general machinery for that when we don't have anything in place yet that it'd need to work with; the design constraints aren't there yet

Copy link
Copy Markdown
Contributor Author

@Human9000-bit Human9000-bit Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't we add the arm's guard to the list of guards sometime much earlier?
or maybe there's somewhere even earlier it could go?

I don't understand, why should we merge guards as early as possible?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personally, I find it cleaner and less error-prone to handle things uniformly. if we have the choice between representing guards in one way or in two different ways, we should try to just do it one way, at least if there's a natural way to do so. ideally, once guard patterns are more complete, I think it'd be nice to get rid of guards being present on match arms in the THIR entirely (representing them as guard patterns). until then, having as much code as possible only need to care about one way of representing guards feels like an okay compromise. it's just a stylistic preference, but I think Builder::bind_and_guard_matched_candidate is complex and we should try and keep it simple, minimizing how many cases we have to handle in it. treating match arm guards the same as a guard at the top level of a pattern (to the extent that we currently can) is a natural way to do that, I think.

Comment on lines +151 to +152
if !pats[0].extra_data.guard_patterns.is_empty() {
extra_data.guard_patterns.push(super::OrderedPatternData::FromOrPattern);
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this check works for guards. For bindings, it relies on the set of bound variables in each alternative being the same. Checking that there's bindings in the first alternative is the same as checking whether any and all alternatives have bindings (assuming the pattern is well-formed). And by checking that there's bindings, we ensure we won't add a FromOrPattern collection of bindings to represent an or-pattern that's being simplified into a single sub-branch; trying to inline bindings from an or-pattern that's no longer there would break the inliner. Conversely, omitting the FromOrPattern when there's no bindings is fine; nothing is inlined, but there's nothing to inline. It will always be nonempty when there's bindings, even if they're nested within further or-patterns, since in that case there'll be a FromOrPattern item in the list.

I think the simplest thing to do would be have a single check that at least one of the alternatives' extra_data is nonempty, then add FromOrPattern placeholders for both bindings and guard conditions if so.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if I implemented that as you intended, that turns out to be over generalized or smth

if let Some((arm, match_scope)) = arm_match_scope
&& let Some(guard) = arm.guard
{
if !sub_branch.guard_patterns.is_empty() || arm.is_some_and(|arm| arm.guard.is_some()) {
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it'd be nice to have all guards in the sub-branch at this point, so we don't have to check both that and an optional arm

View changes since the review

Human9000-bit and others added 5 commits April 18, 2026 22:16
Also tweak wording around arm/guard patterns in docs and comments

Co-authored-by: dianne <diannes.gm@gmail.com>
@rust-log-analyzer

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@Human9000-bit Human9000-bit force-pushed the guard-patterns-mir branch 2 times, most recently from 144ba98 to 296d6fe Compare April 21, 2026 15:20
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer
Copy link
Copy Markdown
Collaborator

The job aarch64-gnu-llvm-21-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
Executing "/scripts/stage_2_test_set1.sh"
+ /scripts/stage_2_test_set1.sh
PR_CI_JOB set; skipping tidy
+ '[' 1 == 1 ']'
+ echo 'PR_CI_JOB set; skipping tidy'
+ SKIP_TIDY='--skip tidy'
+ ../x.py --stage 2 test --skip tidy --skip compiler --skip src
##[group]Building bootstrap
    Finished `dev` profile [unoptimized] target(s) in 0.04s
##[endgroup]
downloading https://static.rust-lang.org/dist/2026-04-14/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz
---
---- [ui] tests/ui/pattern/rfc-3637-guard-patterns/runtime-behavior/or-pats.rs stdout ----

error: test compilation failed although it shouldn't!
status: exit status: 101
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/pattern/rfc-3637-guard-patterns/runtime-behavior/or-pats.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2" "--target=aarch64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "-O" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/ui/pattern/rfc-3637-guard-patterns/runtime-behavior/or-pats/a" "-A" "internal_features" "-A" "incomplete_features" "-A" "unused_parens" "-A" "unused_braces" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/aarch64-unknown-linux-gnu/native/rust-test-helpers" "-Zvalidate-mir" "-Zlint-mir"
stdout: none
--- stderr -------------------------------
warning: unused variable: `b`
##[warning]  --> /checkout/tests/ui/pattern/rfc-3637-guard-patterns/runtime-behavior/or-pats.rs:14:44
   |
LL | fn arr_with_or_pats(arr: [u8; 3], a: bool, b: bool, c: bool, d: bool, e: bool) -> bool {
   |                                            ^ help: if this is intentional, prefix it with an underscore: `_b`
   |
   = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default

warning: unused variable: `c`
##[warning]  --> /checkout/tests/ui/pattern/rfc-3637-guard-patterns/runtime-behavior/or-pats.rs:14:53
   |
LL | fn arr_with_or_pats(arr: [u8; 3], a: bool, b: bool, c: bool, d: bool, e: bool) -> bool {
   |                                                     ^ help: if this is intentional, prefix it with an underscore: `_c`

warning: 2 warnings emitted

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: mismatched or-pattern bindings/guard patterns but no error emitted
   |
   = note: delayed at compiler/rustc_mir_build/src/builder/matches/mod.rs:1600:35
              0: <std::backtrace::Backtrace>::create
              1: <rustc_errors::DiagCtxtInner>::emit_diagnostic
              2: <rustc_errors::DiagCtxtHandle>::emit_diagnostic
              3: <rustc_errors::diagnostic::Diag>::emit_producing_error_guaranteed
              4: <rustc_errors::DiagCtxtHandle>::delayed_bug::<&str>
              5: rustc_mir_build::builder::matches::push_sub_branch_ordered_pat_data::<rustc_middle::thir::ExprId, core::iter::adapters::filter::Filter<core::iter::adapters::chain::Chain<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_mir_build::builder::matches::PatternExtraData>, <rustc_mir_build::builder::matches::MatchTreeSubBranch>::from_sub_candidate::{closure#2}>, core::array::iter::IntoIter<&[rustc_mir_build::builder::matches::OrderedPatternData<rustc_middle::thir::ExprId>], 1>>, rustc_mir_build::builder::matches::sub_branch_ordered_pat_data<rustc_middle::thir::ExprId, core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_mir_build::builder::matches::PatternExtraData>, <rustc_mir_build::builder::matches::MatchTreeSubBranch>::from_sub_candidate::{closure#2}>>::{closure#0}>>
              6: rustc_mir_build::builder::matches::push_sub_branch_ordered_pat_data::<rustc_middle::thir::ExprId, core::iter::adapters::filter::Filter<core::iter::adapters::chain::Chain<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_mir_build::builder::matches::PatternExtraData>, <rustc_mir_build::builder::matches::MatchTreeSubBranch>::from_sub_candidate::{closure#2}>, core::array::iter::IntoIter<&[rustc_mir_build::builder::matches::OrderedPatternData<rustc_middle::thir::ExprId>], 1>>, rustc_mir_build::builder::matches::sub_branch_ordered_pat_data<rustc_middle::thir::ExprId, core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_mir_build::builder::matches::PatternExtraData>, <rustc_mir_build::builder::matches::MatchTreeSubBranch>::from_sub_candidate::{closure#2}>>::{closure#0}>>
              7: rustc_mir_build::builder::matches::traverse_candidate::<rustc_mir_build::builder::matches::Candidate, alloc::vec::Vec<rustc_mir_build::builder::matches::PatternExtraData>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::Candidate>, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate::{closure#0}, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate::{closure#1}, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate::{closure#2}>
              8: rustc_mir_build::builder::matches::traverse_candidate::<rustc_mir_build::builder::matches::Candidate, alloc::vec::Vec<rustc_mir_build::builder::matches::PatternExtraData>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::Candidate>, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate::{closure#0}, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate::{closure#1}, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate::{closure#2}>
              9: <alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::Candidate> as core::iter::traits::iterator::Iterator>::try_fold::<alloc::vec::in_place_drop::InPlaceDrop<rustc_mir_build::builder::matches::MatchTreeBranch>, core::iter::adapters::map::map_try_fold<rustc_mir_build::builder::matches::Candidate, rustc_mir_build::builder::matches::MatchTreeBranch, alloc::vec::in_place_drop::InPlaceDrop<rustc_mir_build::builder::matches::MatchTreeBranch>, core::result::Result<alloc::vec::in_place_drop::InPlaceDrop<rustc_mir_build::builder::matches::MatchTreeBranch>, !>, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate, alloc::vec::in_place_collect::write_in_place_with_drop<rustc_mir_build::builder::matches::MatchTreeBranch>::{closure#0}>::{closure#0}, core::result::Result<alloc::vec::in_place_drop::InPlaceDrop<rustc_mir_build::builder::matches::MatchTreeBranch>, !>>
             10: alloc::vec::in_place_collect::from_iter_in_place::<core::iter::adapters::map::Map<alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::Candidate>, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate>, rustc_mir_build::builder::matches::MatchTreeBranch>
             11: <rustc_mir_build::builder::Builder>::lower_match_tree
             12: <rustc_mir_build::builder::Builder>::expr_into_dest
             13: <rustc_mir_build::builder::Builder>::in_scope::<<rustc_mir_build::builder::Builder>::expr_into_dest::{closure#0}::{closure#0}, ()>
             14: <rustc_mir_build::builder::Builder>::expr_into_dest::{closure#0}
             15: <rustc_mir_build::builder::Builder>::expr_into_dest
---
             21: <rustc_mir_build::builder::Builder>::expr_into_dest
             22: rustc_mir_build::builder::build_mir_inner_impl::{closure#0}
             23: rustc_mir_build::builder::build_mir_inner_impl
             24: rustc_mir_transform::mir_built
             25: rustc_query_impl::query_impl::mir_built::invoke_provider_fn::__rust_begin_short_backtrace
             26: <std::thread::local::LocalKey<core::cell::Cell<*const ()>>>::with::<rustc_middle::ty::context::tls::enter_context<rustc_query_impl::execution::execute_job_non_incr<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::CrateNum, rustc_middle::query::erase::ErasedData<[u8; 8]>, rustc_middle::dep_graph::graph::DepNodeIndex>>::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 8]>>::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 8]>>
             27: rustc_query_impl::execution::try_execute_query::<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 8]>, rustc_middle::dep_graph::graph::DepNodeIndex>, false>
             28: rustc_query_impl::query_impl::mir_built::execute_query_non_incr::__rust_end_short_backtrace
             29: rustc_mir_build::check_unsafety::check_unsafety
             30: rustc_query_impl::query_impl::check_unsafety::invoke_provider_fn::__rust_begin_short_backtrace
             31: <std::thread::local::LocalKey<core::cell::Cell<*const ()>>>::with::<rustc_middle::ty::context::tls::enter_context<rustc_query_impl::execution::execute_job_non_incr<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 0]>, rustc_middle::dep_graph::graph::DepNodeIndex>>::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 0]>>::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 0]>>
             32: rustc_query_impl::execution::try_execute_query::<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 0]>, rustc_middle::dep_graph::graph::DepNodeIndex>, false>
             33: rustc_query_impl::query_impl::check_unsafety::execute_query_non_incr::__rust_end_short_backtrace
             34: <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners::<rustc_interface::passes::run_required_analyses::{closure#2}::{closure#0}>::{closure#0}
             35: std::panicking::catch_unwind::<(), core::panic::unwind_safe::AssertUnwindSafe<rustc_data_structures::sync::parallel::par_for_each_in<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners<rustc_interface::passes::run_required_analyses::{closure#2}::{closure#0}>::{closure#0}>::{closure#0}::{closure#1}::{closure#0}>>
             36: rustc_data_structures::sync::parallel::par_for_each_in::<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners<rustc_interface::passes::run_required_analyses::{closure#2}::{closure#0}>::{closure#0}>
             37: <rustc_session::session::Session>::time::<(), rustc_interface::passes::run_required_analyses::{closure#2}>
             38: rustc_interface::passes::analysis
             39: rustc_query_impl::query_impl::analysis::invoke_provider_fn::__rust_begin_short_backtrace
             40: <std::thread::local::LocalKey<core::cell::Cell<*const ()>>>::with::<rustc_middle::ty::context::tls::enter_context<rustc_query_impl::execution::execute_job_non_incr<rustc_middle::query::caches::SingleCache<rustc_middle::query::erase::ErasedData<[u8; 0]>>>::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 0]>>::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 0]>>
             41: rustc_query_impl::execution::try_execute_query::<rustc_middle::query::caches::SingleCache<rustc_middle::query::erase::ErasedData<[u8; 0]>>, false>
             42: rustc_query_impl::query_impl::analysis::execute_query_non_incr::__rust_end_short_backtrace
             43: <std::thread::local::LocalKey<core::cell::Cell<*const ()>>>::with::<rustc_middle::ty::context::tls::enter_context<<rustc_middle::ty::context::GlobalCtxt>::enter<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}, core::option::Option<rustc_interface::queries::Linker>>::{closure#1}, core::option::Option<rustc_interface::queries::Linker>>::{closure#0}, core::option::Option<rustc_interface::queries::Linker>>
             44: <rustc_middle::ty::context::TyCtxt>::create_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, 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}>
             45: rustc_interface::passes::create_and_enter_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>
             46: std::panicking::catch_unwind::<(), core::panic::unwind_safe::AssertUnwindSafe<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}::{closure#0}>>
             47: <scoped_tls::ScopedKey<rustc_span::SessionGlobals>>::set::<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#0}, ()>
             48: rustc_span::create_session_globals_then::<(), 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#0}>
             49: 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}, ()>
             50: std::panicking::catch_unwind::<(), core::panic::unwind_safe::AssertUnwindSafe<std::thread::lifecycle::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}::{closure#0}>>
             51: <std::thread::lifecycle::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}
             52: <std::sys::thread::unix::Thread>::new::thread_start
             53: <unknown>
             54: <unknown>
           

error: internal compiler error: mismatched or-pattern bindings/guard patterns but no error emitted
   |
   = note: delayed at compiler/rustc_mir_build/src/builder/matches/mod.rs:1600:35
              0: <std::backtrace::Backtrace>::create
              1: <rustc_errors::DiagCtxtInner>::emit_diagnostic
              2: <rustc_errors::DiagCtxtHandle>::emit_diagnostic
              3: <rustc_errors::diagnostic::Diag>::emit_producing_error_guaranteed
              4: <rustc_errors::DiagCtxtHandle>::delayed_bug::<&str>
              5: rustc_mir_build::builder::matches::push_sub_branch_ordered_pat_data::<rustc_middle::thir::ExprId, core::iter::adapters::filter::Filter<core::iter::adapters::chain::Chain<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_mir_build::builder::matches::PatternExtraData>, <rustc_mir_build::builder::matches::MatchTreeSubBranch>::from_sub_candidate::{closure#2}>, core::array::iter::IntoIter<&[rustc_mir_build::builder::matches::OrderedPatternData<rustc_middle::thir::ExprId>], 1>>, rustc_mir_build::builder::matches::sub_branch_ordered_pat_data<rustc_middle::thir::ExprId, core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_mir_build::builder::matches::PatternExtraData>, <rustc_mir_build::builder::matches::MatchTreeSubBranch>::from_sub_candidate::{closure#2}>>::{closure#0}>>
              6: rustc_mir_build::builder::matches::push_sub_branch_ordered_pat_data::<rustc_middle::thir::ExprId, core::iter::adapters::filter::Filter<core::iter::adapters::chain::Chain<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_mir_build::builder::matches::PatternExtraData>, <rustc_mir_build::builder::matches::MatchTreeSubBranch>::from_sub_candidate::{closure#2}>, core::array::iter::IntoIter<&[rustc_mir_build::builder::matches::OrderedPatternData<rustc_middle::thir::ExprId>], 1>>, rustc_mir_build::builder::matches::sub_branch_ordered_pat_data<rustc_middle::thir::ExprId, core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_mir_build::builder::matches::PatternExtraData>, <rustc_mir_build::builder::matches::MatchTreeSubBranch>::from_sub_candidate::{closure#2}>>::{closure#0}>>
              7: rustc_mir_build::builder::matches::traverse_candidate::<rustc_mir_build::builder::matches::Candidate, alloc::vec::Vec<rustc_mir_build::builder::matches::PatternExtraData>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::Candidate>, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate::{closure#0}, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate::{closure#1}, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate::{closure#2}>
              8: rustc_mir_build::builder::matches::traverse_candidate::<rustc_mir_build::builder::matches::Candidate, alloc::vec::Vec<rustc_mir_build::builder::matches::PatternExtraData>, alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::Candidate>, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate::{closure#0}, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate::{closure#1}, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate::{closure#2}>
              9: <alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::Candidate> as core::iter::traits::iterator::Iterator>::try_fold::<alloc::vec::in_place_drop::InPlaceDrop<rustc_mir_build::builder::matches::MatchTreeBranch>, core::iter::adapters::map::map_try_fold<rustc_mir_build::builder::matches::Candidate, rustc_mir_build::builder::matches::MatchTreeBranch, alloc::vec::in_place_drop::InPlaceDrop<rustc_mir_build::builder::matches::MatchTreeBranch>, core::result::Result<alloc::vec::in_place_drop::InPlaceDrop<rustc_mir_build::builder::matches::MatchTreeBranch>, !>, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate, alloc::vec::in_place_collect::write_in_place_with_drop<rustc_mir_build::builder::matches::MatchTreeBranch>::{closure#0}>::{closure#0}, core::result::Result<alloc::vec::in_place_drop::InPlaceDrop<rustc_mir_build::builder::matches::MatchTreeBranch>, !>>
             10: alloc::vec::in_place_collect::from_iter_in_place::<core::iter::adapters::map::Map<alloc::vec::into_iter::IntoIter<rustc_mir_build::builder::matches::Candidate>, <rustc_mir_build::builder::matches::MatchTreeBranch>::from_candidate>, rustc_mir_build::builder::matches::MatchTreeBranch>
             11: <rustc_mir_build::builder::Builder>::lower_match_tree
             12: <rustc_mir_build::builder::Builder>::expr_into_dest
             13: <rustc_mir_build::builder::Builder>::in_scope::<<rustc_mir_build::builder::Builder>::expr_into_dest::{closure#0}::{closure#0}, ()>
             14: <rustc_mir_build::builder::Builder>::expr_into_dest::{closure#0}
             15: <rustc_mir_build::builder::Builder>::expr_into_dest
---
             21: <rustc_mir_build::builder::Builder>::expr_into_dest
             22: rustc_mir_build::builder::build_mir_inner_impl::{closure#0}
             23: rustc_mir_build::builder::build_mir_inner_impl
             24: rustc_mir_transform::mir_built
             25: rustc_query_impl::query_impl::mir_built::invoke_provider_fn::__rust_begin_short_backtrace
             26: <std::thread::local::LocalKey<core::cell::Cell<*const ()>>>::with::<rustc_middle::ty::context::tls::enter_context<rustc_query_impl::execution::execute_job_non_incr<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::CrateNum, rustc_middle::query::erase::ErasedData<[u8; 8]>, rustc_middle::dep_graph::graph::DepNodeIndex>>::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 8]>>::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 8]>>
             27: rustc_query_impl::execution::try_execute_query::<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 8]>, rustc_middle::dep_graph::graph::DepNodeIndex>, false>
             28: rustc_query_impl::query_impl::mir_built::execute_query_non_incr::__rust_end_short_backtrace
             29: rustc_mir_build::check_unsafety::check_unsafety
             30: rustc_query_impl::query_impl::check_unsafety::invoke_provider_fn::__rust_begin_short_backtrace
             31: <std::thread::local::LocalKey<core::cell::Cell<*const ()>>>::with::<rustc_middle::ty::context::tls::enter_context<rustc_query_impl::execution::execute_job_non_incr<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 0]>, rustc_middle::dep_graph::graph::DepNodeIndex>>::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 0]>>::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 0]>>
             32: rustc_query_impl::execution::try_execute_query::<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 0]>, rustc_middle::dep_graph::graph::DepNodeIndex>, false>
             33: rustc_query_impl::query_impl::check_unsafety::execute_query_non_incr::__rust_end_short_backtrace
             34: <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners::<rustc_interface::passes::run_required_analyses::{closure#2}::{closure#0}>::{closure#0}
             35: std::panicking::catch_unwind::<(), core::panic::unwind_safe::AssertUnwindSafe<rustc_data_structures::sync::parallel::par_for_each_in<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners<rustc_interface::passes::run_required_analyses::{closure#2}::{closure#0}>::{closure#0}>::{closure#0}::{closure#1}::{closure#0}>>
             36: rustc_data_structures::sync::parallel::par_for_each_in::<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners<rustc_interface::passes::run_required_analyses::{closure#2}::{closure#0}>::{closure#0}>
             37: <rustc_session::session::Session>::time::<(), rustc_interface::passes::run_required_analyses::{closure#2}>
             38: rustc_interface::passes::analysis
             39: rustc_query_impl::query_impl::analysis::invoke_provider_fn::__rust_begin_short_backtrace
             40: <std::thread::local::LocalKey<core::cell::Cell<*const ()>>>::with::<rustc_middle::ty::context::tls::enter_context<rustc_query_impl::execution::execute_job_non_incr<rustc_middle::query::caches::SingleCache<rustc_middle::query::erase::ErasedData<[u8; 0]>>>::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 0]>>::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 0]>>
             41: rustc_query_impl::execution::try_execute_query::<rustc_middle::query::caches::SingleCache<rustc_middle::query::erase::ErasedData<[u8; 0]>>, false>
             42: rustc_query_impl::query_impl::analysis::execute_query_non_incr::__rust_end_short_backtrace
             43: <std::thread::local::LocalKey<core::cell::Cell<*const ()>>>::with::<rustc_middle::ty::context::tls::enter_context<<rustc_middle::ty::context::GlobalCtxt>::enter<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}, core::option::Option<rustc_interface::queries::Linker>>::{closure#1}, core::option::Option<rustc_interface::queries::Linker>>::{closure#0}, core::option::Option<rustc_interface::queries::Linker>>
             44: <rustc_middle::ty::context::TyCtxt>::create_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, 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}>
             45: rustc_interface::passes::create_and_enter_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>
             46: std::panicking::catch_unwind::<(), core::panic::unwind_safe::AssertUnwindSafe<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}::{closure#0}>>
             47: <scoped_tls::ScopedKey<rustc_span::SessionGlobals>>::set::<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#0}, ()>
             48: rustc_span::create_session_globals_then::<(), 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#0}>
             49: 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}, ()>
             50: std::panicking::catch_unwind::<(), core::panic::unwind_safe::AssertUnwindSafe<std::thread::lifecycle::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}::{closure#0}>>
             51: <std::thread::lifecycle::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}
             52: <std::sys::thread::unix::Thread>::new::thread_start
             53: <unknown>
             54: <unknown>
           
   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

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.97.0-nightly (9da5e8eb8 2026-04-21) running on aarch64-unknown-linux-gnu

note: compiler flags: -Z threads=1 -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ignore-directory-in-diagnostics-source-blocks=/cargo -Z ignore-directory-in-diagnostics-source-blocks=/checkout/vendor -C codegen-units=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z write-long-types-to-disk=no -C strip=debuginfo -C prefer-dynamic -C rpath -C debuginfo=0 -Z validate-mir -Z lint-mir

query stack during panic:
end of query stack
------------------------------------------

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants