1
Fork 0

Exhaustively handle expressions in patterns

This commit is contained in:
Oli Scherer 2024-12-11 16:50:45 +00:00
parent 5df69191cb
commit c9365dd09f
36 changed files with 447 additions and 197 deletions

View file

@ -154,7 +154,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
fn lower_pattern_range_endpoint(
&mut self,
expr: Option<&'tcx hir::Expr<'tcx>>,
expr: Option<&'tcx hir::PatExpr<'tcx>>,
) -> Result<
(Option<PatRangeBoundary<'tcx>>, Option<Ascription<'tcx>>, Option<LocalDefId>),
ErrorGuaranteed,
@ -200,13 +200,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
/// This is only called when the range is already known to be malformed.
fn error_on_literal_overflow(
&self,
expr: Option<&'tcx hir::Expr<'tcx>>,
expr: Option<&'tcx hir::PatExpr<'tcx>>,
ty: Ty<'tcx>,
) -> Result<(), ErrorGuaranteed> {
use hir::{ExprKind, UnOp};
use rustc_ast::ast::LitKind;
let Some(mut expr) = expr else {
let Some(expr) = expr else {
return Ok(());
};
let span = expr.span;
@ -214,12 +213,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
// We need to inspect the original expression, because if we only inspect the output of
// `eval_bits`, an overflowed value has already been wrapped around.
// We mostly copy the logic from the `rustc_lint::OVERFLOWING_LITERALS` lint.
let mut negated = false;
if let ExprKind::Unary(UnOp::Neg, sub_expr) = expr.kind {
negated = true;
expr = sub_expr;
}
let ExprKind::Lit(lit) = expr.kind else {
let hir::PatExprKind::Lit { lit, negated } = expr.kind else {
return Ok(());
};
let LitKind::Int(lit_val, _) = lit.node else {
@ -248,8 +242,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
fn lower_pattern_range(
&mut self,
lo_expr: Option<&'tcx hir::Expr<'tcx>>,
hi_expr: Option<&'tcx hir::Expr<'tcx>>,
lo_expr: Option<&'tcx hir::PatExpr<'tcx>>,
hi_expr: Option<&'tcx hir::PatExpr<'tcx>>,
end: RangeEnd,
ty: Ty<'tcx>,
span: Span,
@ -662,25 +656,18 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
/// The special case for negation exists to allow things like `-128_i8`
/// which would overflow if we tried to evaluate `128_i8` and then negate
/// afterwards.
fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
let (lit, neg) = match expr.kind {
hir::ExprKind::Path(ref qpath) => {
fn lower_lit(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> {
let (lit, neg) = match &expr.kind {
hir::PatExprKind::Path(qpath) => {
return self.lower_path(qpath, expr.hir_id, expr.span).kind;
}
hir::ExprKind::ConstBlock(ref anon_const) => {
hir::PatExprKind::ConstBlock(anon_const) => {
return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
}
hir::ExprKind::Lit(ref lit) => (lit, false),
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => {
let hir::ExprKind::Lit(ref lit) = expr.kind else {
span_bug!(expr.span, "not a literal: {:?}", expr);
};
(lit, true)
}
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
hir::PatExprKind::Lit { lit, negated } => (lit, *negated),
};
let ct_ty = self.typeck_results.expr_ty(expr);
let ct_ty = self.typeck_results.node_type(expr.hir_id);
let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
match self.tcx.at(expr.span).lit_to_const(lit_input) {
Ok(constant) => self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind,