Skip to content

Guard patterns: MIR lowering#154545

Open
Human9000-bit wants to merge 33 commits into
rust-lang:mainfrom
Human9000-bit:guard-patterns-mir
Open

Guard patterns: MIR lowering#154545
Human9000-bit wants to merge 33 commits into
rust-lang:mainfrom
Human9000-bit:guard-patterns-mir

Conversation

@Human9000-bit

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

Copy link
Copy Markdown
Member

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

rustbot commented Mar 29, 2026

Copy link
Copy Markdown
Collaborator

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
Member 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.

@dianne dianne left a comment

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.

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

rust-bors Bot commented Mar 29, 2026

Copy link
Copy Markdown
Contributor

☀️ 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
Member Author

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

@theemathas

theemathas commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

(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

dianne commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

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

Human9000-bit commented Mar 30, 2026

Copy link
Copy Markdown
Member Author

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.

@rust-cloud-vms rust-cloud-vms Bot force-pushed the guard-patterns-mir branch from cef0cf1 to 9ff6ae5 Compare June 8, 2026 13:52
@Human9000-bit

Copy link
Copy Markdown
Member Author

gotta clean git history

@rust-log-analyzer

This comment has been minimized.

@Human9000-bit

Copy link
Copy Markdown
Member Author

uh well it actually fails with explicit bugging

@rust-cloud-vms rust-cloud-vms Bot force-pushed the guard-patterns-mir branch from 0c6b9a7 to 8a3fbab Compare June 10, 2026 07:14
@Nadrieril

Copy link
Copy Markdown
Member

uh well it actually fails with explicit bugging

sounds like the invariants weren't as we expected then, good thing we caught it. I'd suggest reverting the signature of bind_pattern to what it was, and erroring if we end up with a guard pattern not inside a match.

@rust-log-analyzer

This comment has been minimized.

@rust-cloud-vms rust-cloud-vms Bot force-pushed the guard-patterns-mir branch from 8c90218 to 94465eb Compare June 14, 2026 14:04
@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job x86_64-gnu-pre-stabilization failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
failures:

---- [ui] tests/ui/or-patterns/search-via-bindings.rs stdout ----

error: test did not exit with success! code=Some(101) so test would pass with `run-fail`
status: exit status: 101
command: cd "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/or-patterns/search-via-bindings" && RUSTC="/checkout/obj/build/x86_64-unknown-linux-gnu/stage1/bin/rustc" RUST_TEST_THREADS="4" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/or-patterns/search-via-bindings/a"
stdout: none
--- stderr -------------------------------

thread 'main' (128923) panicked at /checkout/tests/ui/or-patterns/search-via-bindings.rs:17:14:
internal error: entered unreachable code
stack backtrace:
   0: __rustc::rust_begin_unwind
   1: core::panicking::panic_fmt
   2: core::panicking::panic
   3: search_via_bindings::search
   4: search_via_bindings::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
------------------------------------------

---- [ui] tests/ui/or-patterns/search-via-bindings.rs stdout end ----

For more information how to resolve CI failures of this job, visit this link.

Comment on lines +91 to +93
if let Some(guard_pat) = inter_pat.guard {
guard_patterns.push(super::OrderedPatternData::One(guard_pat));
}

@Nadrieril Nadrieril Jun 15, 2026

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.

Uh, seems you're adding this guard twice? Once here and once in squash_inter_pat

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks for noticing! I'll fix it now.

Comment on lines +151 to 153
if or_subpats.iter().any(|pat| !pat.extra_data.guards.is_empty()) {
extra_data.guards.push(super::OrderedPatternData::FromOrPattern);
}

@Nadrieril Nadrieril Jun 15, 2026

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.

What if the or-pattern had a nested guard, e.g. (X | (Y if guard())) | Z? I think this would miss it? Not exactly sure why this works for bindings, can you write a comment that explains the invariant you have in mind? And please add a test like that one

View changes since the review

Comment on lines 1090 to 1091
/// For subcandidates, this is copied from the parent candidate, so it indicates
/// whether the enclosing match arm has a guard.

@Nadrieril Nadrieril Jun 15, 2026

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.

Suggested change
/// For subcandidates, this is copied from the parent candidate, so it indicates
/// whether the enclosing match arm has a guard.
/// For subcandidates, this indicates that the pattern is inside
/// a guard pattern or a match arm guard.

View changes since the review

Comment on lines +1143 to +1146
// if there're 2 or more guards, one of them is definitely guard pattern
let contains_guards = flat_pat.extra_data.guards.len() >= 2
// or there is only one guard and we know there aren't any arm guards in there, it is guard pat as well.
|| flat_pat.extra_data.guards.len() == 1 && !under_guard;

@Nadrieril Nadrieril Jun 15, 2026

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.

I'm confused by this logic. What's the meaning of contains_guards you're trying to capture here?

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I though contains_guards is supposed to indicate whether the candidate contains guard patterns, isn't it?

@Nadrieril Nadrieril Jun 15, 2026

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.

your logic doesn't capture that properly: a pattern like (X | (Y if guard())) will have flat_pat.extra_data.guards.len() == 0 but it contains a guard. and under_guard is (or should be!) recursive anyway so I see what you're trying to do (cancel out the arm guard) but that's not what you're doing (e.g. the middle pattern of (X if guard()) if other_guard()) should have both under_guard and contains_guard)

ty,
user_tys,
ArmHasGuard(guard.is_some()),
ArmHasGuard(has_guard),

@Nadrieril Nadrieril Jun 15, 2026

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.

Could you rename that variant to ArmContainsGuard, since ArmHasGuard could be understood to mean "the arm itself has a guard", i.e. looks like pat if guard(), but the logic also includes guard patterns not of that form

View changes since the review

match_pairs: flat_pat.match_pairs,
extra_data: flat_pat.extra_data,
has_guard,
under_guard,

@Nadrieril Nadrieril Jun 15, 2026

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.

Also you must update under_guards to be correct here:

Suggested change
under_guard,
under_guard: under_guard || !flat_pat.extra_data.guards.is_empty(),

View changes since the review

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