Skip to content
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
9744d19
propagate guard patterns into `MatchPairTree`
Human9000-bit Mar 29, 2026
eaed728
Lower guard patterns to MIR
Human9000-bit Mar 29, 2026
3b5b2eb
bless guard pattern testing + fmt
Human9000-bit Mar 29, 2026
22563b8
add mir correctness test
Human9000-bit Mar 30, 2026
6fd9b82
set `has_guard` to `true` if guard patterns are present
Human9000-bit Mar 30, 2026
3617392
update MIR correctness test
Human9000-bit Apr 2, 2026
d6f6226
propagate `Scope` needed for guard patterns down to MIR
Human9000-bit Apr 3, 2026
7683944
guard matched candidate in case guard patterns are present, but
Human9000-bit Apr 3, 2026
b094f0d
Don't mutate `guard_span` during MIR construction
Human9000-bit Apr 3, 2026
b2c991e
Don't read disrciminant for guard patterns (for now)
Human9000-bit Apr 4, 2026
6e62fe1
Properly span guard patterns
Human9000-bit Apr 5, 2026
9dfaa88
Abstract away match arms and guard patterns handling
Human9000-bit Apr 7, 2026
9e5af3e
Generalize `sub_branch_bindings` for also guard patterns
Human9000-bit Apr 7, 2026
1bfb34c
Revert "propagate `Scope` needed for guard patterns down to MIR"
Human9000-bit Apr 8, 2026
49b3d50
more guard pattern handling
Human9000-bit Apr 10, 2026
4675c33
decouple `arm_match_scope` + rustfmt
Human9000-bit Apr 10, 2026
2235647
Propagate the fact of guard pattern's presense when visiting it's sub…
Human9000-bit Apr 10, 2026
ff38c3a
Proper spanning for arms and guards
Human9000-bit Apr 11, 2026
a37a3f9
Update docs related to `sub_branch_ordered_pat_data`
Human9000-bit Apr 11, 2026
b4cc11a
Leave `if let` guard patterns handling alone (for now)
Human9000-bit Apr 11, 2026
e756562
Check if guards are present in a pattern in separate pass
Human9000-bit Apr 11, 2026
a3b7815
Don't enter the same scope twice
Human9000-bit Apr 11, 2026
dbe705d
Properly handle guard patterns in `ScopeResolutionVisitor`
Human9000-bit Apr 11, 2026
af46f95
Properly account guard patterns when entering guard scope
Human9000-bit Apr 12, 2026
9db9f15
remove `is_guard` method
Human9000-bit Apr 18, 2026
00f0ffe
Simplify `pat_has_guard`
Human9000-bit Apr 18, 2026
0282eeb
fixmes
Human9000-bit Apr 18, 2026
d036e0b
refactor `extract_span_scope`
Human9000-bit Apr 19, 2026
a32bc5b
Merge arm/pat guards in `Candidate` creation.
Human9000-bit Apr 19, 2026
4d88621
Update match_pair.rs
Human9000-bit Apr 20, 2026
4188f21
add runtime behavior testing for guard patterns (1)
Human9000-bit Apr 20, 2026
cef0cf1
Update arm + guard pat combination and guard pat handling overall
Human9000-bit May 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions compiler/rustc_hir_analysis/src/check/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,13 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir:

#[tracing::instrument(level = "debug", skip(visitor))]
fn resolve_pat<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, pat: &'tcx hir::Pat<'tcx>) {
// We walk the whole pattern here to avoid walking `cond` expr another time on `walk_pat`
if let PatKind::Guard(pat, cond) = pat.kind {
resolve_cond(visitor, cond);
resolve_pat(visitor, pat);
return;
}

// If this is a binding then record the lifetime of that binding.
if let PatKind::Binding(..) = pat.kind {
record_var_lifetime(visitor, pat.hir_id.local_id);
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -947,13 +947,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
read_discriminant();
}
}

PatKind::Or(_)
| PatKind::Box(_)
| PatKind::Ref(..)
| PatKind::Guard(..)
| PatKind::Tuple(..)
| PatKind::Wild
| PatKind::Missing
| PatKind::Guard(..)
| PatKind::Err(_) => {
// If the PatKind is Or, Box, Ref, Guard, or Tuple, the relevant accesses
// are made later as these patterns contains subpatterns.
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,12 @@ pub enum PatKind<'tcx> {
Error(ErrorGuaranteed),
}

impl<'tcx> PatKind<'tcx> {
pub fn is_guard(&self) -> bool {
if let Self::Guard { .. } = self { true } else { false }
}
}
Comment thread
Human9000-bit marked this conversation as resolved.
Outdated

#[derive(Copy, Clone, Debug, HashStable)]
pub enum DerefPatBorrowMode {
Borrow(Mutability),
Expand Down
14 changes: 9 additions & 5 deletions compiler/rustc_mir_build/src/builder/matches/match_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,10 @@ impl<'tcx> MatchPairTree<'tcx> {
// or-patterns that will be simplified by `merge_trivial_subcandidates`. In
// other words, we can assume this expands into subcandidates.
// FIXME(@dianne): this needs updating/removing if we always merge or-patterns
extra_data.bindings.push(super::SubpatternBindings::FromOrPattern);
extra_data.bindings.push(super::OrderedPatternData::FromOrPattern);
}
if !pats[0].extra_data.guard_patterns.is_empty() {
extra_data.guard_patterns.push(super::OrderedPatternData::FromOrPattern);
Copy link
Copy Markdown
Contributor

@dianne dianne Apr 17, 2026

Choose a reason for hiding this comment

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

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

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

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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

}
Some(TestableCase::Or { pats })
}
Expand Down Expand Up @@ -217,7 +220,7 @@ impl<'tcx> MatchPairTree<'tcx> {

// Then push this binding, after any bindings in the subpattern.
if let Some(source) = place {
extra_data.bindings.push(super::SubpatternBindings::One(super::Binding {
extra_data.bindings.push(super::OrderedPatternData::One(super::Binding {
span: pattern.span,
source,
var_id: var,
Expand Down Expand Up @@ -361,9 +364,10 @@ impl<'tcx> MatchPairTree<'tcx> {
Some(TestableCase::Deref { temp, mutability })
}

PatKind::Guard { .. } => {
// FIXME(guard_patterns)
None
PatKind::Guard { ref subpattern, condition } => {
MatchPairTree::for_pattern(place_builder, subpattern, cx, match_pairs, extra_data);
extra_data.guard_patterns.push(super::OrderedPatternData::One(condition));
return;
}

PatKind::Never => Some(TestableCase::Never),
Expand Down
Loading
Loading