Skip to content

Commit 58ed2d9

Browse files
authored
Unrolled build for #149667
Rollup merge of #149667 - Shinonn23:fix-ice-constblock-148138, r=dianne Fix ICE by rejecting const blocks in patterns during AST lowering (closes #148138) This PR fixes the ICE reported in #148138. The root cause is that `const` blocks aren’t allowed in pattern position, but the AST lowering logic still attempted to create `PatExprKind::ConstBlock`, allowing invalid HIR to reach type checking and trigger a `span_bug!`. Following the discussion in the issue, this patch removes the `ConstBlock` lowering path from `lower_expr_within_pat`. Any `ExprKind::ConstBlock` inside a pattern is now handled consistently with other invalid pattern expressions. A new UI test is included to ensure the compiler reports a proper error and to prevent regressions. Closes #148138.
2 parents 21cf7fb + a9442b4 commit 58ed2d9

18 files changed

Lines changed: 206 additions & 85 deletions

File tree

compiler/rustc_ast_lowering/messages.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ ast_lowering_abi_specified_multiple_times =
66
ast_lowering_arbitrary_expression_in_pattern =
77
arbitrary expressions aren't allowed in patterns
88
.pattern_from_macro_note = the `expr` fragment specifier forces the metavariable's content to be an expression
9+
.const_block_in_pattern_help = use a named `const`-item or an `if`-guard (`x if x == const {"{ ... }"}`) instead
910
1011
ast_lowering_argument = argument
1112

compiler/rustc_ast_lowering/src/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,8 @@ pub(crate) struct ArbitraryExpressionInPattern {
357357
pub span: Span,
358358
#[note(ast_lowering_pattern_from_macro_note)]
359359
pub pattern_from_macro_note: bool,
360+
#[help(ast_lowering_const_block_in_pattern_help)]
361+
pub const_block_in_pattern_help: bool,
360362
}
361363

362364
#[derive(Diagnostic)]

compiler/rustc_ast_lowering/src/pat.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
399399
ExprKind::Lit(lit) => {
400400
hir::PatExprKind::Lit { lit: self.lower_lit(lit, span), negated: false }
401401
}
402-
ExprKind::ConstBlock(c) => hir::PatExprKind::ConstBlock(self.lower_const_block(c)),
403402
ExprKind::IncludedBytes(byte_sym) => hir::PatExprKind::Lit {
404403
lit: respan(span, LitKind::ByteStr(*byte_sym, StrStyle::Cooked)),
405404
negated: false,
@@ -419,10 +418,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
419418
hir::PatExprKind::Lit { lit: self.lower_lit(lit, span), negated: true }
420419
}
421420
_ => {
421+
let is_const_block = matches!(expr.kind, ExprKind::ConstBlock(_));
422422
let pattern_from_macro = expr.is_approximately_pattern();
423423
let guar = self.dcx().emit_err(ArbitraryExpressionInPattern {
424424
span,
425425
pattern_from_macro_note: pattern_from_macro,
426+
const_block_in_pattern_help: is_const_block,
426427
});
427428
err(guar)
428429
}

compiler/rustc_hir/src/hir.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1944,7 +1944,6 @@ pub enum PatExprKind<'hir> {
19441944
// once instead of matching on unop neg expressions everywhere.
19451945
negated: bool,
19461946
},
1947-
ConstBlock(ConstBlock),
19481947
/// A path pattern for a unit struct/variant or a (maybe-associated) constant.
19491948
Path(QPath<'hir>),
19501949
}

compiler/rustc_hir/src/intravisit.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,6 @@ pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>)
792792
try_visit!(visitor.visit_id(*hir_id));
793793
match kind {
794794
PatExprKind::Lit { lit, negated } => visitor.visit_lit(*hir_id, *lit, *negated),
795-
PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
796795
PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, *span),
797796
}
798797
}

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1880,7 +1880,6 @@ impl<'a> State<'a> {
18801880
}
18811881
self.print_literal(lit);
18821882
}
1883-
hir::PatExprKind::ConstBlock(c) => self.print_inline_const(c),
18841883
hir::PatExprKind::Path(qpath) => self.print_qpath(qpath, true),
18851884
}
18861885
}

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -925,9 +925,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
925925
}
926926
ty
927927
}
928-
rustc_hir::PatExprKind::ConstBlock(c) => {
929-
self.check_expr_const_block(c, Expectation::NoExpectation)
930-
}
931928
rustc_hir::PatExprKind::Path(qpath) => {
932929
let (res, opt_ty, segments) =
933930
self.resolve_ty_and_res_fully_qualified_call(qpath, lt.hir_id, lt.span);

compiler/rustc_mir_build/src/thir/pattern/mod.rs

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,13 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
1313
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
1414
use rustc_hir::{self as hir, LangItem, RangeEnd};
1515
use rustc_index::Idx;
16-
use rustc_infer::infer::TyCtxtInferExt;
1716
use rustc_middle::mir::interpret::LitToConstInput;
1817
use rustc_middle::thir::{
1918
Ascription, DerefPatBorrowMode, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
2019
};
2120
use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
2221
use rustc_middle::ty::layout::IntegerExt;
23-
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypingMode};
22+
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
2423
use rustc_middle::{bug, span_bug};
2524
use rustc_span::def_id::DefId;
2625
use rustc_span::{ErrorGuaranteed, Span};
@@ -613,54 +612,8 @@ impl<'tcx> PatCtxt<'tcx> {
613612
pattern
614613
}
615614

616-
/// Lowers an inline const block (e.g. `const { 1 + 1 }`) to a pattern.
617-
fn lower_inline_const(
618-
&mut self,
619-
block: &'tcx hir::ConstBlock,
620-
id: hir::HirId,
621-
span: Span,
622-
) -> PatKind<'tcx> {
623-
let tcx = self.tcx;
624-
let def_id = block.def_id;
625-
let ty = tcx.typeck(def_id).node_type(block.hir_id);
626-
627-
let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
628-
let parent_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
629-
let args = ty::InlineConstArgs::new(tcx, ty::InlineConstArgsParts { parent_args, ty }).args;
630-
631-
let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
632-
let c = ty::Const::new_unevaluated(self.tcx, ct);
633-
let pattern = self.const_to_pat(c, ty, id, span);
634-
635-
// Apply a type ascription for the inline constant.
636-
let annotation = {
637-
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
638-
let args = ty::InlineConstArgs::new(
639-
tcx,
640-
ty::InlineConstArgsParts { parent_args, ty: infcx.next_ty_var(span) },
641-
)
642-
.args;
643-
infcx.canonicalize_user_type_annotation(ty::UserType::new(ty::UserTypeKind::TypeOf(
644-
def_id.to_def_id(),
645-
ty::UserArgs { args, user_self_ty: None },
646-
)))
647-
};
648-
let annotation =
649-
CanonicalUserTypeAnnotation { user_ty: Box::new(annotation), span, inferred_ty: ty };
650-
PatKind::AscribeUserType {
651-
subpattern: pattern,
652-
ascription: Ascription {
653-
annotation,
654-
// Note that we use `Contravariant` here. See the `variance` field documentation
655-
// for details.
656-
variance: ty::Contravariant,
657-
},
658-
}
659-
}
660-
661615
/// Lowers the kinds of "expression" that can appear in a HIR pattern:
662616
/// - Paths (e.g. `FOO`, `foo::BAR`, `Option::None`)
663-
/// - Inline const blocks (e.g. `const { 1 + 1 }`)
664617
/// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
665618
fn lower_pat_expr(
666619
&mut self,
@@ -669,9 +622,6 @@ impl<'tcx> PatCtxt<'tcx> {
669622
) -> PatKind<'tcx> {
670623
match &expr.kind {
671624
hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
672-
hir::PatExprKind::ConstBlock(anon_const) => {
673-
self.lower_inline_const(anon_const, expr.hir_id, expr.span)
674-
}
675625
hir::PatExprKind::Lit { lit, negated } => {
676626
// We handle byte string literal patterns by using the pattern's type instead of the
677627
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,

compiler/rustc_parse/src/parser/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1521,7 +1521,7 @@ impl<'a> Parser<'a> {
15211521
},
15221522
)
15231523
} else if this.check_inline_const(0) {
1524-
this.parse_const_block(lo, false)
1524+
this.parse_const_block(lo)
15251525
} else if this.may_recover() && this.is_do_catch_block() {
15261526
this.recover_do_catch()
15271527
} else if this.is_try_block() {

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,7 +1317,7 @@ impl<'a> Parser<'a> {
13171317
}
13181318

13191319
/// Parses inline const expressions.
1320-
fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, Box<Expr>> {
1320+
fn parse_const_block(&mut self, span: Span) -> PResult<'a, Box<Expr>> {
13211321
self.expect_keyword(exp!(Const))?;
13221322
let (attrs, blk) = self.parse_inner_attrs_and_block(None)?;
13231323
let anon_const = AnonConst {
@@ -1326,18 +1326,7 @@ impl<'a> Parser<'a> {
13261326
mgca_disambiguation: MgcaDisambiguation::AnonConst,
13271327
};
13281328
let blk_span = anon_const.value.span;
1329-
let kind = if pat {
1330-
let guar = self
1331-
.dcx()
1332-
.struct_span_err(blk_span, "const blocks cannot be used as patterns")
1333-
.with_help(
1334-
"use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead",
1335-
)
1336-
.emit();
1337-
ExprKind::Err(guar)
1338-
} else {
1339-
ExprKind::ConstBlock(anon_const)
1340-
};
1329+
let kind = ExprKind::ConstBlock(anon_const);
13411330
Ok(self.mk_expr_with_attrs(span.to(blk_span), kind, attrs))
13421331
}
13431332

0 commit comments

Comments
 (0)