Skip to content
/ rust Public
forked from rust-lang/rust

Commit e7c09a8

Browse files
authored
Rollup merge of rust-lang#136462 - Zalathar:endpoint, r=oli-obk
mir_build: Simplify `lower_pattern_range_endpoint` By accumulating ascriptions and inline-consts in separate vectors, we can streamline some previously-tricky code for dealing with range patterns.
2 parents a24d859 + 2fb1261 commit e7c09a8

File tree

1 file changed

+42
-39
lines changed
  • compiler/rustc_mir_build/src/thir/pattern

1 file changed

+42
-39
lines changed

Diff for: compiler/rustc_mir_build/src/thir/pattern/mod.rs

+42-39
Original file line numberDiff line numberDiff line change
@@ -155,42 +155,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
155155
fn lower_pattern_range_endpoint(
156156
&mut self,
157157
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());
189178
}
190-
};
191-
Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const))
179+
kind = subpattern.kind;
180+
}
181+
_ => break,
192182
}
193183
}
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)))
194193
}
195194

196195
/// 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> {
253252
self.tcx.dcx().span_bug(span, msg);
254253
}
255254

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);
258261

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);
261264

262265
let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env);
263266
let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
@@ -298,13 +301,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
298301
// If we are handling a range with associated constants (e.g.
299302
// `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
300303
// constants somewhere. Have them on the range pattern.
301-
for ascription in [lo_ascr, hi_ascr].into_iter().flatten() {
304+
for ascription in ascriptions {
302305
kind = PatKind::AscribeUserType {
303306
ascription,
304307
subpattern: Box::new(Pat { span, ty, kind }),
305308
};
306309
}
307-
for def in [lo_inline, hi_inline].into_iter().flatten() {
310+
for def in inline_consts {
308311
kind = PatKind::ExpandedConstant {
309312
def_id: def.to_def_id(),
310313
is_inline: true,

0 commit comments

Comments
 (0)