Initial plumbing for thir::PatExtra

This commit is contained in:
Zalathar
2026-01-06 18:20:31 +11:00
parent f85b898c45
commit bd77048303
5 changed files with 78 additions and 13 deletions
+17 -1
View File
@@ -643,10 +643,26 @@ pub struct FieldPat<'tcx> {
pub pattern: Pat<'tcx>,
}
/// Additional per-node data that is not present on most THIR pattern nodes.
#[derive(Clone, Debug, Default, HashStable, TypeVisitable)]
pub struct PatExtra<'tcx> {
/// If present, this node represents a named constant that was lowered to
/// a pattern using `const_to_pat`.
///
/// This is used by some diagnostics for non-exhaustive matches, to map
/// the pattern node back to the `DefId` of its original constant.
pub expanded_const: Option<DefId>,
/// User-written types that must be preserved into MIR so that they can be
/// checked.
pub ascriptions: Vec<Ascription<'tcx>>,
}
#[derive(Clone, Debug, HashStable, TypeVisitable)]
pub struct Pat<'tcx> {
pub ty: Ty<'tcx>,
pub span: Span,
pub extra: Option<Box<PatExtra<'tcx>>>,
pub kind: PatKind<'tcx>,
}
@@ -1119,7 +1135,7 @@ mod size_asserts {
static_assert_size!(Block, 48);
static_assert_size!(Expr<'_>, 64);
static_assert_size!(ExprKind<'_>, 40);
static_assert_size!(Pat<'_>, 64);
static_assert_size!(Pat<'_>, 72);
static_assert_size!(PatKind<'_>, 48);
static_assert_size!(Stmt<'_>, 48);
static_assert_size!(StmtKind<'_>, 48);
+1 -1
View File
@@ -259,7 +259,7 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>(
pat: &'a Pat<'tcx>,
mut callback: impl FnMut(&'a Pat<'tcx>),
) {
let Pat { kind, ty: _, span: _ } = pat;
let Pat { kind, ty: _, span: _, extra: _ } = pat;
match kind {
PatKind::Missing
| PatKind::Wild
@@ -90,7 +90,7 @@ fn mk_err(&self, mut err: Diag<'_>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
);
}
}
Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()) })
Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()), extra: None })
}
fn unevaluated_to_pat(
@@ -192,6 +192,7 @@ fn unevaluated_to_pat(
ty: thir_pat.ty,
span: thir_pat.span,
kind: PatKind::ExpandedConstant { def_id: uv.def, subpattern: thir_pat },
extra: None,
});
thir_pat
}
@@ -355,7 +356,7 @@ fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
}
};
Box::new(Pat { span, ty, kind })
Box::new(Pat { span, ty, kind, extra: None })
}
}
@@ -78,6 +78,7 @@ pub(super) fn pat_from_hir<'tcx>(
ascription: Ascription { annotation, variance: ty::Covariant },
subpattern: thir_pat,
},
extra: None,
});
}
@@ -142,7 +143,7 @@ fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
}
PatAdjust::PinDeref => PatKind::Deref { subpattern: thir_pat },
};
Box::new(Pat { span, ty: adjust.source, kind })
Box::new(Pat { span, ty: adjust.source, kind, extra: None })
});
if let Some(s) = &mut self.rust_2024_migration
@@ -307,7 +308,7 @@ fn lower_pattern_range(
return Err(e);
}
}
let mut thir_pat = Box::new(Pat { ty, span, kind });
let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
// If we are handling a range with associated constants (e.g.
// `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
@@ -317,6 +318,7 @@ fn lower_pattern_range(
ty,
span,
kind: PatKind::AscribeUserType { ascription, subpattern: thir_pat },
extra: None,
});
}
// `PatKind::ExpandedConstant` wrappers from range endpoints used to
@@ -428,7 +430,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tc
};
// We might have modified the type or span, so use the modified
// values in the THIR pattern node.
return Box::new(Pat { ty: thir_pat_ty, span: thir_pat_span, kind });
return Box::new(Pat { ty: thir_pat_ty, span: thir_pat_span, kind, extra: None });
}
hir::PatKind::TupleStruct(ref qpath, pats, ddpos) => {
@@ -468,7 +470,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tc
// For pattern kinds that haven't already returned, create a `thir::Pat`
// with the HIR pattern node's type and span.
Box::new(Pat { span, ty, kind })
Box::new(Pat { span, ty, kind, extra: None })
}
fn lower_tuple_subpats(
@@ -520,7 +522,7 @@ fn slice_or_array_pattern(
}
_ => span_bug!(span, "bad slice pattern type {ty:?}"),
};
Box::new(Pat { ty, span, kind })
Box::new(Pat { ty, span, kind, extra: None })
}
fn lower_variant_or_leaf(
@@ -562,7 +564,12 @@ fn lower_variant_or_leaf(
ty::Adt(_, args) | ty::FnDef(_, args) => args,
ty::Error(e) => {
// Avoid ICE (#50585)
return Box::new(Pat { ty, span, kind: PatKind::Error(*e) });
return Box::new(Pat {
ty,
span,
kind: PatKind::Error(*e),
extra: None,
});
}
_ => bug!("inappropriate type for def: {:?}", ty),
};
@@ -603,7 +610,7 @@ fn lower_variant_or_leaf(
PatKind::Error(e)
}
};
let mut thir_pat = Box::new(Pat { ty, span, kind });
let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
if let Some(user_ty) = self.user_args_applied_to_ty_of_hir_id(hir_id) {
debug!(?thir_pat, ?user_ty, ?span, "lower_variant_or_leaf: applying ascription");
@@ -619,6 +626,7 @@ fn lower_variant_or_leaf(
subpattern: thir_pat,
ascription: Ascription { annotation, variance: ty::Covariant },
},
extra: None,
});
}
@@ -685,7 +693,7 @@ fn lower_path(
variance: ty::Contravariant,
},
};
pattern = Box::new(Pat { span, kind, ty });
pattern = Box::new(Pat { span, kind, ty, extra: None });
}
pattern
+41 -1
View File
@@ -73,6 +73,24 @@ fn into_buffer(self) -> String {
self.fmt
}
fn print_list<T>(
&mut self,
label: &str,
list: &[T],
depth_lvl: usize,
print_fn: impl Fn(&mut Self, &T, usize),
) {
if list.is_empty() {
print_indented!(self, format_args!("{label}: []"), depth_lvl);
} else {
print_indented!(self, format_args!("{label}: ["), depth_lvl);
for item in list {
print_fn(self, item, depth_lvl + 1)
}
print_indented!(self, "]", depth_lvl);
}
}
fn print_param(&mut self, param: &Param<'tcx>, depth_lvl: usize) {
let Param { pat, ty, ty_span, self_kind, hir_id } = param;
@@ -663,15 +681,37 @@ fn print_arm(&mut self, arm_id: ArmId, depth_lvl: usize) {
}
fn print_pat(&mut self, pat: &Pat<'tcx>, depth_lvl: usize) {
let &Pat { ty, span, ref kind } = pat;
let &Pat { ty, span, ref kind, ref extra } = pat;
print_indented!(self, "Pat: {", depth_lvl);
print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
self.print_pat_extra(extra.as_deref(), depth_lvl + 1);
self.print_pat_kind(kind, depth_lvl + 1);
print_indented!(self, "}", depth_lvl);
}
fn print_pat_extra(&mut self, extra: Option<&PatExtra<'tcx>>, depth_lvl: usize) {
let Some(extra) = extra else {
// Skip printing in the common case of a pattern node with no extra data.
return;
};
let PatExtra { expanded_const, ascriptions } = extra;
print_indented!(self, "extra: PatExtra {", depth_lvl);
print_indented!(self, format_args!("expanded_const: {expanded_const:?}"), depth_lvl + 1);
self.print_list(
"ascriptions",
ascriptions,
depth_lvl + 1,
|this, ascription, depth_lvl| {
print_indented!(this, format_args!("{ascription:?}"), depth_lvl);
},
);
print_indented!(self, "}", depth_lvl);
}
fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) {
print_indented!(self, "kind: PatKind {", depth_lvl);