From 7de67a16c57872a0529384bac04bbbe01eebc221 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Feb 2025 12:51:58 +1100 Subject: [PATCH 1/3] Flatten the option check in `lower_pattern_range_endpoint` --- .../rustc_mir_build/src/thir/pattern/mod.rs | 59 +++++++++---------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 20a728d6d5b2c..f8f00c02ad2c8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -159,38 +159,35 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { (Option>, Option>, Option), ErrorGuaranteed, > { - match expr { - None => Ok((None, None, None)), - Some(expr) => { - let (kind, ascr, inline_const) = match self.lower_lit(expr) { - PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { - (subpattern.kind, None, def_id.as_local()) - } - PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => { - (subpattern.kind, None, None) - } - PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { - (kind, Some(ascription), None) - } - kind => (kind, None, None), - }; - let value = match kind { - PatKind::Constant { value } => value, - PatKind::ExpandedConstant { subpattern, .. } - if let PatKind::Constant { value } = subpattern.kind => - { - value - } - _ => { - let msg = format!( - "found bad range pattern endpoint `{expr:?}` outside of error recovery" - ); - return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); - } - }; - Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const)) + let Some(expr) = expr else { return Ok((None, None, None)) }; + + let (kind, ascr, inline_const) = match self.lower_lit(expr) { + PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { + (subpattern.kind, None, def_id.as_local()) } - } + PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => { + (subpattern.kind, None, None) + } + PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { + (kind, Some(ascription), None) + } + kind => (kind, None, None), + }; + let value = match kind { + PatKind::Constant { value } => value, + PatKind::ExpandedConstant { subpattern, .. } + if let PatKind::Constant { value } = subpattern.kind => + { + value + } + _ => { + let msg = format!( + "found bad range pattern endpoint `{expr:?}` outside of error recovery" + ); + return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); + } + }; + Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const)) } /// Overflowing literals are linted against in a late pass. This is mostly fine, except when we From 85f4cdc62692f27e897ba0da2cd5fae30a19f740 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Feb 2025 14:18:04 +1100 Subject: [PATCH 2/3] Return range endpoint ascriptions/consts via a `&mut Vec` --- .../rustc_mir_build/src/thir/pattern/mod.rs | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index f8f00c02ad2c8..3aa2b343b557a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -155,11 +155,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { fn lower_pattern_range_endpoint( &mut self, expr: Option<&'tcx hir::PatExpr<'tcx>>, - ) -> Result< - (Option>, Option>, Option), - ErrorGuaranteed, - > { - let Some(expr) = expr else { return Ok((None, None, None)) }; + // Out-parameters collecting extra data to be reapplied by the caller + ascriptions: &mut Vec>, + inline_consts: &mut Vec, + ) -> Result>, ErrorGuaranteed> { + let Some(expr) = expr else { return Ok(None) }; let (kind, ascr, inline_const) = match self.lower_lit(expr) { PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { @@ -187,7 +187,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); } }; - Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const)) + + ascriptions.extend(ascr); + inline_consts.extend(inline_const); + Ok(Some(PatRangeBoundary::Finite(value))) } /// Overflowing literals are linted against in a late pass. This is mostly fine, except when we @@ -250,11 +253,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { self.tcx.dcx().span_bug(span, msg); } - let (lo, lo_ascr, lo_inline) = self.lower_pattern_range_endpoint(lo_expr)?; - let (hi, hi_ascr, hi_inline) = self.lower_pattern_range_endpoint(hi_expr)?; + // Collect extra data while lowering the endpoints, to be reapplied later. + let mut ascriptions = vec![]; + let mut inline_consts = vec![]; + + let mut lower_endpoint = + |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut inline_consts); - let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity); - let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity); + let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity); + let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity); let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env); let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty })); @@ -295,13 +302,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // 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 // constants somewhere. Have them on the range pattern. - for ascription in [lo_ascr, hi_ascr].into_iter().flatten() { + for ascription in ascriptions { kind = PatKind::AscribeUserType { ascription, subpattern: Box::new(Pat { span, ty, kind }), }; } - for def in [lo_inline, hi_inline].into_iter().flatten() { + for def in inline_consts { kind = PatKind::ExpandedConstant { def_id: def.to_def_id(), is_inline: true, From 2fb1261c2156087d003359db25b13b282934669c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Feb 2025 14:29:13 +1100 Subject: [PATCH 3/3] Simplify the pattern unpeeling in `lower_pattern_range_endpoint` --- .../rustc_mir_build/src/thir/pattern/mod.rs | 51 +++++++++---------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 3aa2b343b557a..0aa61152330a7 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -161,35 +161,34 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { ) -> Result>, ErrorGuaranteed> { let Some(expr) = expr else { return Ok(None) }; - let (kind, ascr, inline_const) = match self.lower_lit(expr) { - PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { - (subpattern.kind, None, def_id.as_local()) - } - PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => { - (subpattern.kind, None, None) - } - PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { - (kind, Some(ascription), None) - } - kind => (kind, None, None), - }; - let value = match kind { - PatKind::Constant { value } => value, - PatKind::ExpandedConstant { subpattern, .. } - if let PatKind::Constant { value } = subpattern.kind => - { - value - } - _ => { - let msg = format!( - "found bad range pattern endpoint `{expr:?}` outside of error recovery" - ); - return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); + // Lower the endpoint into a temporary `PatKind` that will then be + // deconstructed to obtain the constant value and other data. + let mut kind: PatKind<'tcx> = self.lower_lit(expr); + + // Unpeel any ascription or inline-const wrapper nodes. + loop { + match kind { + PatKind::AscribeUserType { ascription, subpattern } => { + ascriptions.push(ascription); + kind = subpattern.kind; + } + PatKind::ExpandedConstant { is_inline, def_id, subpattern } => { + if is_inline { + inline_consts.extend(def_id.as_local()); + } + kind = subpattern.kind; + } + _ => break, } + } + + // The unpeeled kind should now be a constant, giving us the endpoint value. + let PatKind::Constant { value } = kind else { + let msg = + format!("found bad range pattern endpoint `{expr:?}` outside of error recovery"); + return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); }; - ascriptions.extend(ascr); - inline_consts.extend(inline_const); Ok(Some(PatRangeBoundary::Finite(value))) }