@@ -155,42 +155,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
155
155
fn lower_pattern_range_endpoint(
156
156
&mut self,
157
157
expr: Option<&'tcx hir::PatExpr<'tcx>>,
158
- ) -> Result<
159
- (Option<PatRangeBoundary<'tcx>>, Option<Ascription<'tcx>>, Option<LocalDefId>),
160
- ErrorGuaranteed,
161
- > {
162
- match expr {
163
- None => Ok((None, None, None)),
164
- Some(expr) => {
165
- let (kind, ascr, inline_const) = match self.lower_lit(expr) {
166
- PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => {
167
- (subpattern.kind, None, def_id.as_local())
168
- }
169
- PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => {
170
- (subpattern.kind, None, None)
171
- }
172
- PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => {
173
- (kind, Some(ascription), None)
174
- }
175
- kind => (kind, None, None),
176
- };
177
- let value = match kind {
178
- PatKind::Constant { value } => value,
179
- PatKind::ExpandedConstant { subpattern, .. }
180
- if let PatKind::Constant { value } = subpattern.kind =>
181
- {
182
- value
183
- }
184
- _ => {
185
- let msg = format!(
186
- "found bad range pattern endpoint `{expr:?}` outside of error recovery"
187
- );
188
- return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
158
+ // Out-parameters collecting extra data to be reapplied by the caller
159
+ ascriptions: &mut Vec<Ascription<'tcx>>,
160
+ inline_consts: &mut Vec<LocalDefId>,
161
+ ) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
162
+ let Some(expr) = expr else { return Ok(None) };
163
+
164
+ // Lower the endpoint into a temporary `PatKind` that will then be
165
+ // deconstructed to obtain the constant value and other data.
166
+ let mut kind: PatKind<'tcx> = self.lower_lit(expr);
167
+
168
+ // Unpeel any ascription or inline-const wrapper nodes.
169
+ loop {
170
+ match kind {
171
+ PatKind::AscribeUserType { ascription, subpattern } => {
172
+ ascriptions.push(ascription);
173
+ kind = subpattern.kind;
174
+ }
175
+ PatKind::ExpandedConstant { is_inline, def_id, subpattern } => {
176
+ if is_inline {
177
+ inline_consts.extend(def_id.as_local());
189
178
}
190
- };
191
- Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const))
179
+ kind = subpattern.kind;
180
+ }
181
+ _ => break,
192
182
}
193
183
}
184
+
185
+ // The unpeeled kind should now be a constant, giving us the endpoint value.
186
+ let PatKind::Constant { value } = kind else {
187
+ let msg =
188
+ format!("found bad range pattern endpoint `{expr:?}` outside of error recovery");
189
+ return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
190
+ };
191
+
192
+ Ok(Some(PatRangeBoundary::Finite(value)))
194
193
}
195
194
196
195
/// Overflowing literals are linted against in a late pass. This is mostly fine, except when we
@@ -253,11 +252,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
253
252
self.tcx.dcx().span_bug(span, msg);
254
253
}
255
254
256
- let (lo, lo_ascr, lo_inline) = self.lower_pattern_range_endpoint(lo_expr)?;
257
- let (hi, hi_ascr, hi_inline) = self.lower_pattern_range_endpoint(hi_expr)?;
255
+ // Collect extra data while lowering the endpoints, to be reapplied later.
256
+ let mut ascriptions = vec![];
257
+ let mut inline_consts = vec![];
258
+
259
+ let mut lower_endpoint =
260
+ |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut inline_consts);
258
261
259
- let lo = lo .unwrap_or(PatRangeBoundary::NegInfinity);
260
- let hi = hi .unwrap_or(PatRangeBoundary::PosInfinity);
262
+ let lo = lower_endpoint(lo_expr)? .unwrap_or(PatRangeBoundary::NegInfinity);
263
+ let hi = lower_endpoint(hi_expr)? .unwrap_or(PatRangeBoundary::PosInfinity);
261
264
262
265
let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env);
263
266
let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
@@ -298,13 +301,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
298
301
// If we are handling a range with associated constants (e.g.
299
302
// `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
300
303
// constants somewhere. Have them on the range pattern.
301
- for ascription in [lo_ascr, hi_ascr].into_iter().flatten() {
304
+ for ascription in ascriptions {
302
305
kind = PatKind::AscribeUserType {
303
306
ascription,
304
307
subpattern: Box::new(Pat { span, ty, kind }),
305
308
};
306
309
}
307
- for def in [lo_inline, hi_inline].into_iter().flatten() {
310
+ for def in inline_consts {
308
311
kind = PatKind::ExpandedConstant {
309
312
def_id: def.to_def_id(),
310
313
is_inline: true,
0 commit comments