Rollup merge of #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.
This commit is contained in:
commit
e7c09a8e12
1 changed files with 42 additions and 39 deletions
|
@ -155,42 +155,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||||
fn lower_pattern_range_endpoint(
|
fn lower_pattern_range_endpoint(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Option<&'tcx hir::PatExpr<'tcx>>,
|
expr: Option<&'tcx hir::PatExpr<'tcx>>,
|
||||||
) -> Result<
|
// Out-parameters collecting extra data to be reapplied by the caller
|
||||||
(Option<PatRangeBoundary<'tcx>>, Option<Ascription<'tcx>>, Option<LocalDefId>),
|
ascriptions: &mut Vec<Ascription<'tcx>>,
|
||||||
ErrorGuaranteed,
|
inline_consts: &mut Vec<LocalDefId>,
|
||||||
> {
|
) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
|
||||||
match expr {
|
let Some(expr) = expr else { return Ok(None) };
|
||||||
None => Ok((None, None, None)),
|
|
||||||
Some(expr) => {
|
// Lower the endpoint into a temporary `PatKind` that will then be
|
||||||
let (kind, ascr, inline_const) = match self.lower_lit(expr) {
|
// deconstructed to obtain the constant value and other data.
|
||||||
PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => {
|
let mut kind: PatKind<'tcx> = self.lower_lit(expr);
|
||||||
(subpattern.kind, None, def_id.as_local())
|
|
||||||
|
// 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());
|
||||||
}
|
}
|
||||||
PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => {
|
kind = subpattern.kind;
|
||||||
(subpattern.kind, None, None)
|
}
|
||||||
}
|
_ => break,
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
/// 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> {
|
||||||
self.tcx.dcx().span_bug(span, msg);
|
self.tcx.dcx().span_bug(span, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (lo, lo_ascr, lo_inline) = self.lower_pattern_range_endpoint(lo_expr)?;
|
// Collect extra data while lowering the endpoints, to be reapplied later.
|
||||||
let (hi, hi_ascr, hi_inline) = self.lower_pattern_range_endpoint(hi_expr)?;
|
let mut ascriptions = vec![];
|
||||||
|
let mut inline_consts = vec![];
|
||||||
|
|
||||||
let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity);
|
let mut lower_endpoint =
|
||||||
let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity);
|
|expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut inline_consts);
|
||||||
|
|
||||||
|
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 cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env);
|
||||||
let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
|
let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
|
||||||
|
@ -298,13 +301,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||||
// If we are handling a range with associated constants (e.g.
|
// 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
|
// `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
|
||||||
// constants somewhere. Have them on the range pattern.
|
// 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 {
|
kind = PatKind::AscribeUserType {
|
||||||
ascription,
|
ascription,
|
||||||
subpattern: Box::new(Pat { span, ty, kind }),
|
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 {
|
kind = PatKind::ExpandedConstant {
|
||||||
def_id: def.to_def_id(),
|
def_id: def.to_def_id(),
|
||||||
is_inline: true,
|
is_inline: true,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue