diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 3683c1cfb7dd..3ddb5a1523d0 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -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, + + /// User-written types that must be preserved into MIR so that they can be + /// checked. + pub ascriptions: Vec>, +} + #[derive(Clone, Debug, HashStable, TypeVisitable)] pub struct Pat<'tcx> { pub ty: Ty<'tcx>, pub span: Span, + pub extra: Option>>, 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); diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index d792bbe60c88..e0c044220b81 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -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 diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 76b742aa6e45..98faf0ab613f 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -90,7 +90,7 @@ fn mk_err(&self, mut err: Diag<'_>, ty: Ty<'tcx>) -> Box> { ); } } - 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> { } }; - Box::new(Pat { span, ty, kind }) + Box::new(Pat { span, ty, kind, extra: None }) } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 01986d946d45..9c39a934c7ee 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -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> { } 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 { @@ -468,7 +470,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box 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 diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 5a2d6cfef1cc..d735ef2134ab 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -73,6 +73,24 @@ fn into_buffer(self) -> String { self.fmt } + fn print_list( + &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);