Rollup merge of #138635 - Zalathar:immediate-subpat, r=compiler-errors

Extract `for_each_immediate_subpat` from THIR pattern visitors

This is extracted from some larger changes I've been working on, trying to introduce a “THIR pattern id” to refer to THIR pattern nodes without a direct reference.

The future of those changes is somewhat uncertain, due to some [proposed changes involving upvar inference](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/upvar.20inference.20on.20THIR.3F). So I'm taking my preparatory changes that make sense on their own, and extracting them into one or more independent PRs.

---

This particular patch takes two different functions that were both matching on `PatKind` to traverse subpatterns, and extracts the core match into a single helper function.
This commit is contained in:
Matthias Krüger 2025-03-18 10:09:30 +01:00 committed by GitHub
commit 6e48c984bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 53 deletions

View File

@ -28,6 +28,7 @@ use tracing::instrument;
use crate::middle::region;
use crate::mir::interpret::AllocId;
use crate::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp};
use crate::thir::visit::for_each_immediate_subpat;
use crate::ty::adjustment::PointerCoercion;
use crate::ty::layout::IntegerExt;
use crate::ty::{
@ -672,27 +673,7 @@ impl<'tcx> Pat<'tcx> {
return;
}
use PatKind::*;
match &self.kind {
Wild
| Never
| Range(..)
| Binding { subpattern: None, .. }
| Constant { .. }
| Error(_) => {}
AscribeUserType { subpattern, .. }
| Binding { subpattern: Some(subpattern), .. }
| Deref { subpattern }
| DerefPattern { subpattern, .. }
| ExpandedConstant { subpattern, .. } => subpattern.walk_(it),
Leaf { subpatterns } | Variant { subpatterns, .. } => {
subpatterns.iter().for_each(|field| field.pattern.walk_(it))
}
Or { pats } => pats.iter().for_each(|p| p.walk_(it)),
Array { box prefix, slice, box suffix } | Slice { box prefix, slice, box suffix } => {
prefix.iter().chain(slice.as_deref()).chain(suffix.iter()).for_each(|p| p.walk_(it))
}
}
for_each_immediate_subpat(self, |p| p.walk_(it));
}
/// Whether the pattern has a `PatKind::Error` nested within.

View File

@ -240,36 +240,45 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
visitor: &mut V,
pat: &'thir Pat<'tcx>,
) {
use PatKind::*;
match &pat.kind {
AscribeUserType { subpattern, ascription: _ }
| Deref { subpattern }
| DerefPattern { subpattern, .. }
| Binding { subpattern: Some(subpattern), .. } => visitor.visit_pat(subpattern),
Binding { .. } | Wild | Never | Error(_) => {}
Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => {
for subpattern in subpatterns {
visitor.visit_pat(&subpattern.pattern);
}
}
Constant { value: _ } => {}
ExpandedConstant { def_id: _, is_inline: _, subpattern } => visitor.visit_pat(subpattern),
Range(_) => {}
Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
for subpattern in prefix.iter() {
visitor.visit_pat(subpattern);
}
if let Some(pat) = slice {
visitor.visit_pat(pat);
}
for subpattern in suffix.iter() {
visitor.visit_pat(subpattern);
}
}
Or { pats } => {
for pat in pats.iter() {
visitor.visit_pat(pat);
}
}
};
for_each_immediate_subpat(pat, |p| visitor.visit_pat(p));
}
/// Invokes `callback` on each immediate subpattern of `pat`, if any.
/// A building block for assembling THIR pattern visitors.
pub(crate) fn for_each_immediate_subpat<'a, 'tcx>(
pat: &'a Pat<'tcx>,
mut callback: impl FnMut(&'a Pat<'tcx>),
) {
match &pat.kind {
PatKind::Wild
| PatKind::Binding { subpattern: None, .. }
| PatKind::Constant { value: _ }
| PatKind::Range(_)
| PatKind::Never
| PatKind::Error(_) => {}
PatKind::AscribeUserType { subpattern, .. }
| PatKind::Binding { subpattern: Some(subpattern), .. }
| PatKind::Deref { subpattern }
| PatKind::DerefPattern { subpattern, .. }
| PatKind::ExpandedConstant { subpattern, .. } => callback(subpattern),
PatKind::Variant { subpatterns, .. } | PatKind::Leaf { subpatterns } => {
for field_pat in subpatterns {
callback(&field_pat.pattern);
}
}
PatKind::Slice { prefix, slice, suffix } | PatKind::Array { prefix, slice, suffix } => {
for pat in prefix.iter().chain(slice.as_deref()).chain(suffix) {
callback(pat);
}
}
PatKind::Or { pats } => {
for pat in pats {
callback(pat);
}
}
}
}