Skip to content
Closed
Show file tree
Hide file tree
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
1 change: 0 additions & 1 deletion compiler/rustc_ast_lowering/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ExprKind::Lit(lit) => {
hir::PatExprKind::Lit { lit: self.lower_lit(lit, span), negated: false }
}
ExprKind::ConstBlock(c) => hir::PatExprKind::ConstBlock(self.lower_const_block(c)),
ExprKind::IncludedBytes(byte_sym) => hir::PatExprKind::Lit {
lit: respan(span, LitKind::ByteStr(*byte_sym, StrStyle::Cooked)),
negated: false,
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1926,7 +1926,6 @@ pub enum PatExprKind<'hir> {
// once instead of matching on unop neg expressions everywhere.
negated: bool,
},
ConstBlock(ConstBlock),
/// A path pattern for a unit struct/variant or a (maybe-associated) constant.
Path(QPath<'hir>),
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,6 @@ pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>)
try_visit!(visitor.visit_id(*hir_id));
match kind {
PatExprKind::Lit { lit, negated } => visitor.visit_lit(*hir_id, *lit, *negated),
PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, *span),
}
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1876,7 +1876,6 @@ impl<'a> State<'a> {
}
self.print_literal(lit);
}
hir::PatExprKind::ConstBlock(c) => self.print_inline_const(c),
hir::PatExprKind::Path(qpath) => self.print_qpath(qpath, true),
}
}
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,9 +925,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
ty
}
rustc_hir::PatExprKind::ConstBlock(c) => {
self.check_expr_const_block(c, Expectation::NoExpectation)
}
rustc_hir::PatExprKind::Path(qpath) => {
let (res, opt_ty, segments) =
self.resolve_ty_and_res_fully_qualified_call(qpath, lt.hir_id, lt.span);
Expand Down
51 changes: 1 addition & 50 deletions compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
use rustc_hir::{self as hir, ByRef, LangItem, Mutability, Pinnedness, RangeEnd};
use rustc_index::Idx;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::interpret::LitToConstInput;
use rustc_middle::thir::{
Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
};
use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypingMode};
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
use rustc_span::{ErrorGuaranteed, Span};
Expand Down Expand Up @@ -621,51 +620,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
pattern
}

/// Lowers an inline const block (e.g. `const { 1 + 1 }`) to a pattern.
fn lower_inline_const(
&mut self,
block: &'tcx hir::ConstBlock,
id: hir::HirId,
span: Span,
) -> PatKind<'tcx> {
let tcx = self.tcx;
let def_id = block.def_id;
let ty = tcx.typeck(def_id).node_type(block.hir_id);

let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
let parent_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
let args = ty::InlineConstArgs::new(tcx, ty::InlineConstArgsParts { parent_args, ty }).args;

let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
let c = ty::Const::new_unevaluated(self.tcx, ct);
let pattern = self.const_to_pat(c, ty, id, span);

// Apply a type ascription for the inline constant.
let annotation = {
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let args = ty::InlineConstArgs::new(
tcx,
ty::InlineConstArgsParts { parent_args, ty: infcx.next_ty_var(span) },
)
.args;
infcx.canonicalize_user_type_annotation(ty::UserType::new(ty::UserTypeKind::TypeOf(
def_id.to_def_id(),
ty::UserArgs { args, user_self_ty: None },
)))
};
let annotation =
CanonicalUserTypeAnnotation { user_ty: Box::new(annotation), span, inferred_ty: ty };
PatKind::AscribeUserType {
subpattern: pattern,
ascription: Ascription {
annotation,
// Note that we use `Contravariant` here. See the `variance` field documentation
// for details.
variance: ty::Contravariant,
},
}
}

/// Lowers the kinds of "expression" that can appear in a HIR pattern:
/// - Paths (e.g. `FOO`, `foo::BAR`, `Option::None`)
/// - Inline const blocks (e.g. `const { 1 + 1 }`)
Expand All @@ -677,9 +631,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
) -> PatKind<'tcx> {
match &expr.kind {
hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
hir::PatExprKind::ConstBlock(anon_const) => {
self.lower_inline_const(anon_const, expr.hir_id, expr.span)
}
hir::PatExprKind::Lit { lit, negated } => {
// We handle byte string literal patterns by using the pattern's type instead of the
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1514,7 +1514,7 @@ impl<'a> Parser<'a> {
},
)
} else if this.check_inline_const(0) {
this.parse_const_block(lo, false)
this.parse_const_block(lo)
} else if this.may_recover() && this.is_do_catch_block() {
this.recover_do_catch()
} else if this.is_try_block() {
Expand Down Expand Up @@ -3951,6 +3951,18 @@ impl<'a> Parser<'a> {
})
}

/// Parses inline const expressions.
pub(super) fn parse_const_block(&mut self, span: Span) -> PResult<'a, Box<Expr>> {
self.expect_keyword(exp!(Const))?;
let (attrs, blk) = self.parse_inner_attrs_and_block(None)?;
let anon_const = AnonConst {
id: DUMMY_NODE_ID,
value: self.mk_expr(blk.span, ExprKind::Block(blk, None)),
};
let blk_span = anon_const.value.span;
Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(anon_const), attrs))
}

/// Check for `=`. This means the source incorrectly attempts to
/// initialize a field with an eq rather than a colon.
fn error_on_eq_field_init(&self, field_name: Ident) {
Expand Down
29 changes: 2 additions & 27 deletions compiler/rustc_parse/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ use rustc_ast::tokenstream::{
};
use rustc_ast::util::case::Case;
use rustc_ast::{
self as ast, AnonConst, AttrArgs, AttrId, ByRef, Const, CoroutineKind, DUMMY_NODE_ID,
DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit,
Visibility, VisibilityKind,
self as ast, AttrArgs, AttrId, ByRef, Const, CoroutineKind, DUMMY_NODE_ID, DelimArgs, ExprKind,
Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit, Visibility, VisibilityKind,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
Expand Down Expand Up @@ -1299,30 +1298,6 @@ impl<'a> Parser<'a> {
}
}

/// Parses inline const expressions.
fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, Box<Expr>> {
self.expect_keyword(exp!(Const))?;
let (attrs, blk) = self.parse_inner_attrs_and_block(None)?;
let anon_const = AnonConst {
id: DUMMY_NODE_ID,
value: self.mk_expr(blk.span, ExprKind::Block(blk, None)),
};
let blk_span = anon_const.value.span;
let kind = if pat {
let guar = self
.dcx()
.struct_span_err(blk_span, "const blocks cannot be used as patterns")
.with_help(
"use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead",
)
.emit();
ExprKind::Err(guar)
} else {
ExprKind::ConstBlock(anon_const)
};
Ok(self.mk_expr_with_attrs(span.to(blk_span), kind, attrs))
}

/// Parses mutability (`mut` or nothing).
fn parse_mutability(&mut self) -> Mutability {
if self.eat_keyword(exp!(Mut)) { Mutability::Mut } else { Mutability::Not }
Expand Down
18 changes: 16 additions & 2 deletions compiler/rustc_parse/src/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ impl<'a> Parser<'a> {
self.parse_pat_box()?
} else if self.check_inline_const(0) {
// Parse `const pat`
let const_expr = self.parse_const_block(lo.to(self.token.span), true)?;
let const_expr = self.parse_pat_const_block(lo.to(self.token.span))?;

if let Some(re) = self.parse_range_end() {
self.parse_pat_range_begin_with(const_expr, re)?
Expand Down Expand Up @@ -1281,7 +1281,7 @@ impl<'a> Parser<'a> {
.then_some(self.prev_token.span);

let bound = if self.check_inline_const(0) {
self.parse_const_block(self.token.span, true)
self.parse_pat_const_block(self.token.span)
Comment on lines 1283 to +1284
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be untested, as discovered in #149667; we'll probably want a test for it.

} else if self.check_path() {
let lo = self.token.span;
let (qself, path) = if self.eat_lt() {
Expand Down Expand Up @@ -1767,6 +1767,20 @@ impl<'a> Parser<'a> {
})
}

/// Parse `const {}` in patterns - this syntax has been removed, but we still parse this
/// for now to provide a more useful error.
fn parse_pat_const_block(&mut self, span: Span) -> PResult<'a, Box<Expr>> {
let expr = self.parse_const_block(span)?;
let guar = self
.dcx()
.struct_span_err(expr.span, "const blocks cannot be used as patterns")
.with_help(
"use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead",
)
.emit();
Ok(self.mk_expr_err(expr.span, guar))
}
Comment on lines +1770 to +1782
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't catch every const block used in patterns; see #148138 (comment). Of course, the cases this doesn't catch will be caught in AST lowering after this change and result in an arbitrary expressions aren't allowed in patterns error so this does fix #148138, but we'd be checking for const blocks in patterns at two separate stages of compilation.


pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingMode, ident: Ident) -> Pat {
self.mk_pat(span, PatKind::Ident(ann, ident, None))
}
Expand Down
1 change: 0 additions & 1 deletion src/tools/clippy/clippy_lints/src/utils/author.rs
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,6 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
kind!("Lit {{ ref {lit}, {negated} }}");
self.lit(lit);
},
PatExprKind::ConstBlock(_) => kind!("ConstBlock(_)"),
PatExprKind::Path(_) => self.maybe_path(pat),
}
}
Expand Down
1 change: 0 additions & 1 deletion src/tools/clippy/clippy_utils/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,6 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
Some(val)
}
},
PatExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir_body(*body).value),
PatExprKind::Path(qpath) => self.qpath(qpath, pat_expr.hir_id),
}
}
Expand Down
4 changes: 1 addition & 3 deletions src/tools/clippy/clippy_utils/src/hir_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,9 +506,8 @@ impl HirEqInterExpr<'_, '_, '_> {
negated: right_neg,
},
) => left_neg == right_neg && left.node == right.node,
(PatExprKind::ConstBlock(left), PatExprKind::ConstBlock(right)) => self.eq_body(left.body, right.body),
(PatExprKind::Path(left), PatExprKind::Path(right)) => self.eq_qpath(left, right),
(PatExprKind::Lit { .. } | PatExprKind::ConstBlock(..) | PatExprKind::Path(..), _) => false,
(PatExprKind::Lit { .. } | PatExprKind::Path(..), _) => false,
}
}

Expand Down Expand Up @@ -1102,7 +1101,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
lit.node.hash(&mut self.s);
negated.hash(&mut self.s);
},
PatExprKind::ConstBlock(c) => self.hash_body(c.body),
PatExprKind::Path(qpath) => self.hash_qpath(qpath),
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/inline-const/in-pat-recovery.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: const blocks cannot be used as patterns
--> $DIR/in-pat-recovery.rs:6:15
--> $DIR/in-pat-recovery.rs:6:9
|
LL | const { 1 + 7 } => {}
| ^^^^^^^^^
| ^^^^^^^^^^^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

Expand Down
Loading