Skip to content

mir_build: Simplify lower_pattern_range_endpoint #136462

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 4, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 42 additions & 39 deletions compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,42 +155,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
fn lower_pattern_range_endpoint(
&mut self,
expr: Option<&'tcx hir::PatExpr<'tcx>>,
) -> Result<
(Option<PatRangeBoundary<'tcx>>, Option<Ascription<'tcx>>, Option<LocalDefId>),
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));
// Out-parameters collecting extra data to be reapplied by the caller
ascriptions: &mut Vec<Ascription<'tcx>>,
inline_consts: &mut Vec<LocalDefId>,
) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
let Some(expr) = expr else { return Ok(None) };

// 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());
}
};
Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const))
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));
};

Ok(Some(PatRangeBoundary::Finite(value)))
}

/// Overflowing literals are linted against in a late pass. This is mostly fine, except when we
Expand Down Expand Up @@ -253,11 +252,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 }));
Expand Down Expand Up @@ -298,13 +301,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,
Expand Down
Loading