Skip to content

Guard patterns: MIR lowering#154545

Draft
Human9000-bit wants to merge 18 commits intorust-lang:mainfrom
Human9000-bit:guard-patterns-mir
Draft

Guard patterns: MIR lowering#154545
Human9000-bit wants to merge 18 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
@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

@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 and others added 4 commits April 4, 2026 12:48
the problem was in unimplemented exhaustiveness checking, which caused SIGILL
Co-authored-by: dianne <diannes.gm@gmail.com>
`arm_match_scope` isn't provided

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

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

Comment on lines 984 to 990
enum PossiblyOr<T> {
/// A single item.
Value(T),
/// Holds the place for an or-pattern's item. This ensures their drops are scheduled in the
/// order the items appear. See rust-lang/rust#142163 for more information.
FromOrPattern,
}
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.

Is the naming ok?

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.

It's a bit hard to know what PossiblyOr could mean without looking at the docs; just glancing at it, I read the "or" as the English word, not as a shortened form of "data inlined from a sub-pattern of an or-pattern". I'm not sure I'd recommend this exact name (it's a mouthful!), but something like OrderedPatternData would capture what it's for: it's used for the bits of PatternExtraData that are order-sensitive, in order to preserve their orderings.

I'm also wary about "item" in the comments, since that term has a different technical meaning in Rust. Since this is pretty abstract, it might be worth spelling out the concrete uses and/or putting a doc comment on the enum itself to give a high-level description of it.

Similarly, "value" has a technical meaning in Rust, so I'd caution against using that as the name of the constructor for a single datum.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

MaybeOrPat?

@rust-log-analyzer

This comment has been minimized.

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

This comment has been minimized.

Co-authored-by: dianne <diannes.gm@gmail.com>
@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-03-05/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz
---
test [coverage-map] tests/coverage/uses_inline_crate.rs ... ok

failures:

---- [coverage-map] tests/coverage/branch/guard.rs stdout ----
Saved the actual cov-map to `/checkout/obj/build/aarch64-unknown-linux-gnu/test/coverage/branch/guard.coverage-map/guard.cov-map`
diff of cov-map:

1 Function name: guard::branch_match_guard
- Raw bytes (104): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 10, 01, 0c, 01, 00, 26, 01, 01, 05, 00, 0e, 02, 02, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 00, 1e, 0d, 00, 22, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 19, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 1d, 00, 1e, 11, 00, 22, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02]
+ Raw bytes (94): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 0e, 01, 0c, 01, 00, 26, 01, 01, 05, 00, 0e, 02, 02, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 1e, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 22, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 1e, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 22, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02]
3 Number of files: 1
4 - file 0 => $DIR/guard.rs
5 Number of expressions: 8

11 - expression 5 operands: lhs = Counter(0), rhs = Counter(1)
12 - expression 6 operands: lhs = Expression(7, Add), rhs = Counter(4)
13 - expression 7 operands: lhs = Counter(2), rhs = Counter(3)
- Number of file 0 mappings: 16
+ Number of file 0 mappings: 14
15 - Code(Counter(0)) at (prev + 12, 1) to (start + 0, 38)
16 - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14)
17 - Code(Expression(0, Sub)) at (prev + 2, 11) to (start + 0, 12)

19 - Code(Expression(1, Sub)) at (prev + 1, 20) to (start + 2, 10)
20     = (c2 - c1)
21 - Code(Counter(3)) at (prev + 3, 14) to (start + 0, 15)
- - Code(Counter(1)) at (prev + 0, 20) to (start + 0, 25)
+ - Code(Counter(1)) at (prev + 0, 20) to (start + 0, 30)
23 - Branch { true: Counter(3), false: Expression(0, Sub) } at (prev + 0, 20) to (start + 0, 30)
24     true  = c3
25     false = (c1 - c3)

- - Code(Counter(3)) at (prev + 0, 29) to (start + 0, 30)
27 - Code(Counter(3)) at (prev + 0, 34) to (start + 2, 10)
28 - Code(Counter(4)) at (prev + 3, 14) to (start + 0, 15)
- - Code(Expression(0, Sub)) at (prev + 0, 20) to (start + 0, 25)
+ - Code(Expression(0, Sub)) at (prev + 0, 20) to (start + 0, 30)
30     = (c1 - c3)
31 - Branch { true: Counter(4), false: Expression(2, Sub) } at (prev + 0, 20) to (start + 0, 30)
32     true  = c4

33     false = (c1 - (c3 + c4))
- - Code(Counter(4)) at (prev + 0, 29) to (start + 0, 30)
35 - Code(Counter(4)) at (prev + 0, 34) to (start + 2, 10)
36 - Code(Expression(4, Sub)) at (prev + 3, 14) to (start + 2, 10)
37     = ((c0 + c1) - ((c2 + c3) + c4))


The actual cov-map differed from the expected cov-map

error: an error occurred comparing coverage output.
status: exit status: 0
command: "/checkout/obj/build/aarch64-unknown-linux-gnu/stage1-tools-bin/coverage-dump" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/coverage/branch/guard.coverage-map/guard.ll"
--- stdout -------------------------------
Function name: guard::branch_match_guard
Raw bytes (94): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 0e, 01, 0c, 01, 00, 26, 01, 01, 05, 00, 0e, 02, 02, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 1e, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 22, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 1e, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 22, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02]
Number of files: 1
- file 0 => /checkout/tests/coverage/branch/guard.rs
Number of expressions: 8
- expression 0 operands: lhs = Counter(1), rhs = Counter(3)
- expression 1 operands: lhs = Counter(2), rhs = Counter(1)
- expression 2 operands: lhs = Counter(1), rhs = Expression(3, Add)
- expression 3 operands: lhs = Counter(3), rhs = Counter(4)
- expression 4 operands: lhs = Expression(5, Add), rhs = Expression(6, Add)
- expression 5 operands: lhs = Counter(0), rhs = Counter(1)
- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(4)
- expression 7 operands: lhs = Counter(2), rhs = Counter(3)
Number of file 0 mappings: 14
- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 38)
- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14)
- Code(Expression(0, Sub)) at (prev + 2, 11) to (start + 0, 12)
    = (c1 - c3)
- Code(Expression(1, Sub)) at (prev + 1, 20) to (start + 2, 10)
    = (c2 - c1)
- Code(Counter(3)) at (prev + 3, 14) to (start + 0, 15)
- Code(Counter(1)) at (prev + 0, 20) to (start + 0, 30)
- Branch { true: Counter(3), false: Expression(0, Sub) } at (prev + 0, 20) to (start + 0, 30)
    true  = c3
    false = (c1 - c3)
- Code(Counter(3)) at (prev + 0, 34) to (start + 2, 10)
- Code(Counter(4)) at (prev + 3, 14) to (start + 0, 15)
- Code(Expression(0, Sub)) at (prev + 0, 20) to (start + 0, 30)
    = (c1 - c3)
- Branch { true: Counter(4), false: Expression(2, Sub) } at (prev + 0, 20) to (start + 0, 30)
    true  = c4
    false = (c1 - (c3 + c4))
- Code(Counter(4)) at (prev + 0, 34) to (start + 2, 10)
- Code(Expression(4, Sub)) at (prev + 3, 14) to (start + 2, 10)
    = ((c0 + c1) - ((c2 + c3) + c4))
- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 2)
Highest counter ID seen: c4
------------------------------------------
stderr: none

---- [coverage-map] tests/coverage/branch/guard.rs stdout end ----
---- [coverage-map] tests/coverage/branch/match-arms.rs stdout ----
Saved the actual cov-map to `/checkout/obj/build/aarch64-unknown-linux-gnu/test/coverage/branch/match-arms.coverage-map/match-arms.cov-map`
diff of cov-map:

1 Function name: match_arms::guards
- Raw bytes (158): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 1a, 01, 30, 01, 00, 23, 01, 01, 05, 00, 0e, 21, 02, 0b, 00, 10, 05, 01, 11, 00, 12, 20, 05, 02, 00, 17, 00, 1b, 05, 00, 1a, 00, 1b, 05, 00, 1f, 00, 26, 05, 00, 27, 00, 28, 09, 01, 11, 00, 12, 20, 09, 06, 00, 17, 00, 1b, 09, 00, 1a, 00, 1b, 09, 00, 1f, 00, 26, 09, 00, 27, 00, 28, 0d, 01, 11, 00, 12, 20, 0d, 0a, 00, 17, 00, 1b, 0d, 00, 1a, 00, 1b, 0d, 00, 1f, 00, 26, 0d, 00, 27, 00, 28, 11, 01, 11, 00, 12, 20, 11, 0e, 00, 17, 00, 1b, 11, 00, 1a, 00, 1b, 11, 00, 1f, 00, 26, 11, 00, 27, 00, 28, 12, 01, 0e, 00, 15, 01, 03, 05, 00, 0c, 01, 01, 01, 00, 02]
+ Raw bytes (158): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 1a, 01, 30, 01, 00, 23, 01, 01, 05, 00, 0e, 21, 02, 0b, 00, 10, 05, 01, 11, 00, 12, 15, 00, 17, 00, 1b, 20, 05, 02, 00, 17, 00, 1b, 05, 00, 1f, 00, 26, 05, 00, 27, 00, 29, 09, 01, 11, 00, 12, 19, 00, 17, 00, 1b, 20, 09, 06, 00, 17, 00, 1b, 09, 00, 1f, 00, 26, 09, 00, 27, 00, 29, 0d, 01, 11, 00, 12, 1d, 00, 17, 00, 1b, 20, 0d, 0a, 00, 17, 00, 1b, 0d, 00, 1f, 00, 26, 0d, 00, 27, 00, 29, 11, 01, 11, 00, 12, 21, 00, 17, 00, 1b, 20, 11, 0e, 00, 17, 00, 1b, 11, 00, 1f, 00, 26, 11, 00, 27, 00, 29, 12, 01, 0e, 00, 15, 01, 03, 05, 00, 0c, 01, 01, 01, 00, 02]
3 Number of files: 1
4 - file 0 => $DIR/match-arms.rs
5 Number of expressions: 8

16 - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14)
17 - Code(Counter(8)) at (prev + 2, 11) to (start + 0, 16)
18 - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18)
+ - Code(Counter(5)) at (prev + 0, 23) to (start + 0, 27)
19 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 23) to (start + 0, 27)
20     true  = c1
21     false = (c5 - c1)

- - Code(Counter(1)) at (prev + 0, 26) to (start + 0, 27)
23 - Code(Counter(1)) at (prev + 0, 31) to (start + 0, 38)
- - Code(Counter(1)) at (prev + 0, 39) to (start + 0, 40)
+ - Code(Counter(1)) at (prev + 0, 39) to (start + 0, 41)
25 - Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18)
+ - Code(Counter(6)) at (prev + 0, 23) to (start + 0, 27)
26 - Branch { true: Counter(2), false: Expression(1, Sub) } at (prev + 0, 23) to (start + 0, 27)
27     true  = c2
28     false = (c6 - c2)

- - Code(Counter(2)) at (prev + 0, 26) to (start + 0, 27)
30 - Code(Counter(2)) at (prev + 0, 31) to (start + 0, 38)
- - Code(Counter(2)) at (prev + 0, 39) to (start + 0, 40)
+ - Code(Counter(2)) at (prev + 0, 39) to (start + 0, 41)
32 - Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18)
+ - Code(Counter(7)) at (prev + 0, 23) to (start + 0, 27)
33 - Branch { true: Counter(3), false: Expression(2, Sub) } at (prev + 0, 23) to (start + 0, 27)
34     true  = c3
35     false = (c7 - c3)

- - Code(Counter(3)) at (prev + 0, 26) to (start + 0, 27)
37 - Code(Counter(3)) at (prev + 0, 31) to (start + 0, 38)
- - Code(Counter(3)) at (prev + 0, 39) to (start + 0, 40)
+ - Code(Counter(3)) at (prev + 0, 39) to (start + 0, 41)
39 - Code(Counter(4)) at (prev + 1, 17) to (start + 0, 18)
+ - Code(Counter(8)) at (prev + 0, 23) to (start + 0, 27)
40 - Branch { true: Counter(4), false: Expression(3, Sub) } at (prev + 0, 23) to (start + 0, 27)
41     true  = c4
42     false = (c8 - c4)

- - Code(Counter(4)) at (prev + 0, 26) to (start + 0, 27)
44 - Code(Counter(4)) at (prev + 0, 31) to (start + 0, 38)
- - Code(Counter(4)) at (prev + 0, 39) to (start + 0, 40)
+ - Code(Counter(4)) at (prev + 0, 39) to (start + 0, 41)
46 - Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 21)
47     = (c0 - (((c1 + c2) + c3) + c4))
48 - Code(Counter(0)) at (prev + 3, 5) to (start + 0, 12)


The actual cov-map differed from the expected cov-map

error: an error occurred comparing coverage output.
status: exit status: 0
command: "/checkout/obj/build/aarch64-unknown-linux-gnu/stage1-tools-bin/coverage-dump" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/coverage/branch/match-arms.coverage-map/match-arms.ll"
--- stdout -------------------------------
Function name: match_arms::guards
Raw bytes (158): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 1a, 01, 30, 01, 00, 23, 01, 01, 05, 00, 0e, 21, 02, 0b, 00, 10, 05, 01, 11, 00, 12, 15, 00, 17, 00, 1b, 20, 05, 02, 00, 17, 00, 1b, 05, 00, 1f, 00, 26, 05, 00, 27, 00, 29, 09, 01, 11, 00, 12, 19, 00, 17, 00, 1b, 20, 09, 06, 00, 17, 00, 1b, 09, 00, 1f, 00, 26, 09, 00, 27, 00, 29, 0d, 01, 11, 00, 12, 1d, 00, 17, 00, 1b, 20, 0d, 0a, 00, 17, 00, 1b, 0d, 00, 1f, 00, 26, 0d, 00, 27, 00, 29, 11, 01, 11, 00, 12, 21, 00, 17, 00, 1b, 20, 11, 0e, 00, 17, 00, 1b, 11, 00, 1f, 00, 26, 11, 00, 27, 00, 29, 12, 01, 0e, 00, 15, 01, 03, 05, 00, 0c, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => /checkout/tests/coverage/branch/match-arms.rs
Number of expressions: 8
- expression 0 operands: lhs = Counter(5), rhs = Counter(1)
- expression 1 operands: lhs = Counter(6), rhs = Counter(2)
- expression 2 operands: lhs = Counter(7), rhs = Counter(3)
- expression 3 operands: lhs = Counter(8), rhs = Counter(4)
- expression 4 operands: lhs = Counter(0), rhs = Expression(5, Add)
- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(4)
- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(3)
- expression 7 operands: lhs = Counter(1), rhs = Counter(2)
Number of file 0 mappings: 26
- Code(Counter(0)) at (prev + 48, 1) to (start + 0, 35)
- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14)
- Code(Counter(8)) at (prev + 2, 11) to (start + 0, 16)
- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18)
- Code(Counter(5)) at (prev + 0, 23) to (start + 0, 27)
- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 23) to (start + 0, 27)
    true  = c1
    false = (c5 - c1)
- Code(Counter(1)) at (prev + 0, 31) to (start + 0, 38)
- Code(Counter(1)) at (prev + 0, 39) to (start + 0, 41)
- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18)
- Code(Counter(6)) at (prev + 0, 23) to (start + 0, 27)
- Branch { true: Counter(2), false: Expression(1, Sub) } at (prev + 0, 23) to (start + 0, 27)
    true  = c2
    false = (c6 - c2)
- Code(Counter(2)) at (prev + 0, 31) to (start + 0, 38)
- Code(Counter(2)) at (prev + 0, 39) to (start + 0, 41)
- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18)
- Code(Counter(7)) at (prev + 0, 23) to (start + 0, 27)
- Branch { true: Counter(3), false: Expression(2, Sub) } at (prev + 0, 23) to (start + 0, 27)
    true  = c3
    false = (c7 - c3)
- Code(Counter(3)) at (prev + 0, 31) to (start + 0, 38)
- Code(Counter(3)) at (prev + 0, 39) to (start + 0, 41)
- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 18)
- Code(Counter(8)) at (prev + 0, 23) to (start + 0, 27)
- Branch { true: Counter(4), false: Expression(3, Sub) } at (prev + 0, 23) to (start + 0, 27)
    true  = c4
    false = (c8 - c4)
- Code(Counter(4)) at (prev + 0, 31) to (start + 0, 38)
- Code(Counter(4)) at (prev + 0, 39) to (start + 0, 41)
- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 21)
    = (c0 - (((c1 + c2) + c3) + c4))
- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 12)
- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
Highest counter ID seen: c8

Function name: match_arms::match_arms
Raw bytes (95): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 11, 01, 18, 01, 00, 1b, 01, 01, 05, 00, 0e, 01, 02, 0b, 00, 10, 05, 01, 11, 00, 12, 05, 00, 17, 00, 1e, 05, 00, 1f, 00, 20, 09, 01, 11, 00, 12, 09, 00, 17, 00, 1e, 09, 00, 1f, 00, 20, 0d, 01, 11, 00, 12, 0d, 00, 17, 00, 1e, 0d, 00, 1f, 00, 20, 02, 01, 11, 00, 12, 02, 00, 17, 00, 1e, 02, 00, 1f, 00, 20, 01, 03, 05, 00, 0c, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => /checkout/tests/coverage/branch/match-arms.rs
Number of expressions: 3
- expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add)
- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3)
- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
Number of file 0 mappings: 17
- Code(Counter(0)) at (prev + 24, 1) to (start + 0, 27)
- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14)
- Code(Counter(0)) at (prev + 2, 11) to (start + 0, 16)
- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18)
- Code(Counter(1)) at (prev + 0, 23) to (start + 0, 30)
- Code(Counter(1)) at (prev + 0, 31) to (start + 0, 32)
- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18)
- Code(Counter(2)) at (prev + 0, 23) to (start + 0, 30)
- Code(Counter(2)) at (prev + 0, 31) to (start + 0, 32)
- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18)
- Code(Counter(3)) at (prev + 0, 23) to (start + 0, 30)
- Code(Counter(3)) at (prev + 0, 31) to (start + 0, 32)
- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 18)
    = (c0 - ((c1 + c2) + c3))
- Code(Expression(0, Sub)) at (prev + 0, 23) to (start + 0, 30)
    = (c0 - ((c1 + c2) + c3))
- Code(Expression(0, Sub)) at (prev + 0, 31) to (start + 0, 32)
    = (c0 - ((c1 + c2) + c3))
- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 12)
- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
Highest counter ID seen: c3

Function name: match_arms::or_patterns
Raw bytes (79): 0x[01, 01, 05, 05, 09, 01, 0b, 03, 0d, 01, 03, 01, 03, 0d, 01, 25, 01, 00, 1c, 01, 01, 05, 00, 0e, 01, 02, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2b, 03, 00, 2c, 00, 2d, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 12, 00, 24, 00, 2b, 12, 00, 2c, 00, 2d, 01, 03, 05, 00, 0c, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => /checkout/tests/coverage/branch/match-arms.rs
Number of expressions: 5
- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
- expression 1 operands: lhs = Counter(0), rhs = Expression(2, Add)
- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
- expression 3 operands: lhs = Counter(0), rhs = Expression(0, Add)
- expression 4 operands: lhs = Counter(0), rhs = Expression(0, Add)
Number of file 0 mappings: 13
- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 28)
- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 14)
- Code(Counter(0)) at (prev + 2, 11) to (start + 0, 16)
- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18)
- Code(Counter(2)) at (prev + 0, 30) to (start + 0, 31)
- Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 43)
    = (c1 + c2)
- Code(Expression(0, Add)) at (prev + 0, 44) to (start + 0, 45)
    = (c1 + c2)
- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18)
- Code(Expression(1, Sub)) at (prev + 0, 30) to (start + 0, 31)
    = (c0 - ((c1 + c2) + c3))
- Code(Expression(4, Sub)) at (prev + 0, 36) to (start + 0, 43)
    = (c0 - (c1 + c2))
- Code(Expression(4, Sub)) at (prev + 0, 44) to (start + 0, 45)
    = (c0 - (c1 + c2))
- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 12)
- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
Highest counter ID seen: c3
------------------------------------------
stderr: none

---- [coverage-map] tests/coverage/branch/match-arms.rs stdout end ----

Comment on lines +201 to +218
match (arm.guard, arm.pat.kind) {
(Some(arm_guard), PatKind::Guard(_, pat_guard)) => {
// We introduce a new scope to contain bindings and temporaries from `if let` guards, to
// ensure they're dropped before the arm's pattern's bindings. This extends to the end of
// the arm body and is the scope of its locals as well.
visitor
.enter_scope(Scope { local_id: arm.hir_id.local_id, data: ScopeData::MatchGuard });
visitor.cx.var_parent = visitor.cx.parent;
resolve_cond(visitor, arm_guard);
resolve_cond(visitor, pat_guard);
}
(Some(guard), _) | (_, PatKind::Guard(_, guard)) => {
visitor
.enter_scope(Scope { local_id: arm.hir_id.local_id, data: ScopeData::MatchGuard });
visitor.cx.var_parent = visitor.cx.parent;
resolve_cond(visitor, guard);
}
_ => (),
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

Isn't this only checking the top-level pattern? Also, how is this meant to interact with the pattern being visited in the resolve_pat call above? Eventually, we'll also need to visit guard conditions for patterns outside of match.

.map(|_| region::Scope { data: region::ScopeData::MatchGuard, ..arm.scope });
.map(|_| region::Scope { data: region::ScopeData::MatchGuard, ..arm.scope })
.or_else(|| {
if let PatKind::Guard { condition, .. } = arm.pattern.kind {
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

Isn't this only checking the top-level pattern?

For what it's worth, the MatchGuard scope is only strictly needed for guards that can introduce bindings that live into the, i.e. if let guards. Eventually, I'd like if let guard patterns as well, but if it's easier to deal with for now, we don't really need a MatchGuard scope for arms with guard patterns, since they don't support let conditions yet.

Comment on lines +438 to +441
Some(region::Scope {
local_id: self.thir[condition].temp_scope_id,
data: region::ScopeData::MatchGuard,
})
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

The local_id of a MatchGuard scope should be the whole arm, at least with how they work currently. There's a single one for an arm with guards on it, since that's where the if let bindings and temps live. If it would be less confusing, we could put the scope in the THIR like usual, instead of needing to construct it reusing the local_id from the arm's scope here.

Comment on lines 81 to +82
LL | } => (), // What value should `s` have in the arm?
| - borrow later used here
| - borrow later used here
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

The spans in these borrowck errors should be pointing to the end of the guard, I think, rather than the start of the arm.

Comment on lines -2469 to +2499
self.bind_matched_candidate_for_guard(block, sub_branch.bindings.iter());
let _ = self.in_scope(
(match_scope, self.source_info(arm_span)),
LintLevel::Inherited,
|this| {
this.bind_matched_candidate_for_guard(block, sub_branch.bindings.iter());
BasicBlock::ZERO.unit()
},
);
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

What's this for? We should already be in the match_scope; we enter it before calling anything related to match lowering.

bool,
),
) {
guard_pat_present |= pattern.kind.is_guard();
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

Won't this only catch if a guard pattern has been encountered thus far? If I'm understanding right, you're using this to tell whether to declare RefForGuard locals, but I think it'd be simplest if they were always present if there's a guard anywhere in the pattern/arm, since then we can always bind all of them when entering a guard; we don't need to analyze whether we need to or not.

Comment on lines +761 to +763
if let PatKind::Guard { condition, .. } = pattern.kind {
self.declare_guard_bindings(condition, scope_span, visibility_scope);
};
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

declare_guard_bindings is specifically for if let guards, I think?

}

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

@dianne dianne Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

It'd be easiest to not worry about non-match matches just yet; there's a lot more complexity in getting them to work (particularly with regards to scoping).

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

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. 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