Create const block DefIds in typeck instead of ast lowering

This commit is contained in:
Oli Scherer 2024-05-03 09:22:55 +00:00
parent e5cba17b84
commit ddc5f9b6c1
39 changed files with 162 additions and 189 deletions

View File

@ -1393,7 +1393,7 @@ pub enum ExprKind {
/// An array (e.g, `[a, b, c, d]`).
Array(ThinVec<P<Expr>>),
/// Allow anonymous constants from an inline `const` block
ConstBlock(AnonConst),
ConstBlock(P<Expr>),
/// A function call
///
/// The first field resolves to the function itself,

View File

@ -1411,7 +1411,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
match kind {
ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
ExprKind::ConstBlock(anon_const) => {
vis.visit_anon_const(anon_const);
vis.visit_expr(anon_const);
}
ExprKind::Repeat(expr, count) => {
vis.visit_expr(expr);

View File

@ -951,7 +951,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
ExprKind::Array(subexpressions) => {
walk_list!(visitor, visit_expr, subexpressions);
}
ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_anon_const(anon_const)),
ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_expr(anon_const)),
ExprKind::Repeat(element, count) => {
try_visit!(visitor.visit_expr(element));
try_visit!(visitor.visit_anon_const(count));

View File

@ -74,14 +74,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let kind = match &e.kind {
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
ExprKind::ConstBlock(c) => {
let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock {
def_id: this.local_def_id(c.id),
hir_id: this.lower_node_id(c.id),
body: this.lower_const_body(c.value.span, Some(&c.value)),
});
hir::ExprKind::ConstBlock(c)
}
ExprKind::ConstBlock(c) => hir::ExprKind::ConstBlock(self.lower_expr(c)),
ExprKind::Repeat(expr, count) => {
let expr = self.lower_expr(expr);
let count = self.lower_array_length(count);

View File

@ -236,14 +236,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
});
}
fn visit_inline_const(&mut self, constant: &'hir ConstBlock) {
self.insert(DUMMY_SP, constant.hir_id, Node::ConstBlock(constant));
self.with_parent(constant.hir_id, |this| {
intravisit::walk_inline_const(this, constant);
});
}
fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
self.insert(expr.span, expr.hir_id, Node::Expr(expr));

View File

@ -380,8 +380,9 @@ impl<'a> State<'a> {
ast::ExprKind::Array(exprs) => {
self.print_expr_vec(exprs);
}
ast::ExprKind::ConstBlock(anon_const) => {
self.print_expr_anon_const(anon_const, attrs);
ast::ExprKind::ConstBlock(expr) => {
self.word_space("const");
self.print_expr(expr, FixupContext::default());
}
ast::ExprKind::Repeat(element, count) => {
self.print_expr_repeat(element, count);

View File

@ -38,7 +38,6 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
match node {
hir::Node::Ctor(_)
| hir::Node::AnonConst(_)
| hir::Node::ConstBlock(_)
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => {
hir::Constness::Const
}
@ -57,6 +56,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
}
hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness,
hir::Node::Expr(e) if let hir::ExprKind::ConstBlock(_) = e.kind => hir::Constness::Const,
_ => {
if let Some(fn_kind) = node.fn_kind() {
if fn_kind.constness() == hir::Constness::Const {

View File

@ -1592,14 +1592,6 @@ pub struct AnonConst {
pub span: Span,
}
/// An inline constant expression `const { something }`.
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub struct ConstBlock {
pub hir_id: HirId,
pub def_id: LocalDefId,
pub body: BodyId,
}
/// An expression.
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct Expr<'hir> {
@ -1886,7 +1878,7 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum ExprKind<'hir> {
/// Allow anonymous constants from an inline `const` block
ConstBlock(ConstBlock),
ConstBlock(&'hir Expr<'hir>),
/// An array (e.g., `[a, b, c, d]`).
Array(&'hir [Expr<'hir>]),
/// A function call.
@ -3609,7 +3601,6 @@ pub enum Node<'hir> {
Variant(&'hir Variant<'hir>),
Field(&'hir FieldDef<'hir>),
AnonConst(&'hir AnonConst),
ConstBlock(&'hir ConstBlock),
Expr(&'hir Expr<'hir>),
ExprField(&'hir ExprField<'hir>),
Stmt(&'hir Stmt<'hir>),
@ -3670,7 +3661,6 @@ impl<'hir> Node<'hir> {
Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident),
Node::Param(..)
| Node::AnonConst(..)
| Node::ConstBlock(..)
| Node::Expr(..)
| Node::Stmt(..)
| Node::Block(..)
@ -3768,7 +3758,6 @@ impl<'hir> Node<'hir> {
}
Node::AnonConst(constant) => Some((constant.def_id, constant.body)),
Node::ConstBlock(constant) => Some((constant.def_id, constant.body)),
_ => None,
}
@ -3837,7 +3826,6 @@ impl<'hir> Node<'hir> {
expect_variant, &'hir Variant<'hir>, Node::Variant(n), n;
expect_field, &'hir FieldDef<'hir>, Node::Field(n), n;
expect_anon_const, &'hir AnonConst, Node::AnonConst(n), n;
expect_inline_const, &'hir ConstBlock, Node::ConstBlock(n), n;
expect_expr, &'hir Expr<'hir>, Node::Expr(n), n;
expect_expr_field, &'hir ExprField<'hir>, Node::ExprField(n), n;
expect_stmt, &'hir Stmt<'hir>, Node::Stmt(n), n;

View File

@ -344,9 +344,6 @@ pub trait Visitor<'v>: Sized {
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
walk_anon_const(self, c)
}
fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result {
walk_inline_const(self, c)
}
fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result {
walk_expr(self, ex)
}
@ -716,14 +713,6 @@ pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonCo
visitor.visit_nested_body(constant.body)
}
pub fn walk_inline_const<'v, V: Visitor<'v>>(
visitor: &mut V,
constant: &'v ConstBlock,
) -> V::Result {
try_visit!(visitor.visit_id(constant.hir_id));
visitor.visit_nested_body(constant.body)
}
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result {
try_visit!(visitor.visit_id(expression.hir_id));
match expression.kind {
@ -731,7 +720,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
walk_list!(visitor, visit_expr, subexpressions);
}
ExprKind::ConstBlock(ref const_block) => {
try_visit!(visitor.visit_inline_const(const_block))
try_visit!(visitor.visit_expr(const_block))
}
ExprKind::Repeat(ref element, ref count) => {
try_visit!(visitor.visit_expr(element));

View File

@ -407,11 +407,14 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
match expr.kind {
// Manually recurse over closures and inline consts, because they are the only
// case of nested bodies that share the parent environment.
hir::ExprKind::Closure(&hir::Closure { body, .. })
| hir::ExprKind::ConstBlock(hir::ConstBlock { body, .. }) => {
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
let body = visitor.tcx.hir().body(body);
visitor.visit_body(body);
}
hir::ExprKind::ConstBlock(expr) => visitor.enter_body(expr.hir_id, |this| {
this.cx.var_parent = None;
resolve_local(this, None, Some(expr));
}),
hir::ExprKind::AssignOp(_, left_expr, right_expr) => {
debug!(
"resolve_expr - enabling pessimistic_yield, was previously {}",

View File

@ -177,10 +177,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
}
}
}
Node::ConstBlock(_)
| Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
Some(tcx.typeck_root_def_id(def_id.to_def_id()))
}
Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure { .. } | hir::ExprKind::ConstBlock { .. },
..
}) => Some(tcx.typeck_root_def_id(def_id.to_def_id())),
Node::Item(item) => match item.kind {
ItemKind::OpaqueTy(&hir::OpaqueTy {
origin:
@ -415,7 +415,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
}
// provide junk type parameter defs for const blocks.
if let Node::ConstBlock(_) = node {
if let Node::Expr(Expr { kind: ExprKind::ConstBlock(..), .. }) = node {
own_params.push(ty::GenericParamDef {
index: next_index(),
name: Symbol::intern("<const_ty>"),

View File

@ -484,8 +484,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
}
Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
Node::ConstBlock(_) => {
Node::Expr(&Expr { kind: ExprKind::ConstBlock(..), .. }) => {
let args = ty::GenericArgs::identity_for_item(tcx, def_id.to_def_id());
args.as_inline_const().ty()
}

View File

@ -190,10 +190,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
}
});
// Freeze definitions as we don't add new ones at this point. This improves performance by
// allowing lock-free access to them.
tcx.untracked().definitions.freeze();
// FIXME: Remove this when we implement creating `DefId`s
// for anon constants during their parents' typeck.
// Typeck all body owners in parallel will produce queries
@ -205,6 +201,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
}
});
// Freeze definitions as we don't add new ones at this point. This improves performance by
// allowing lock-free access to them.
tcx.untracked().definitions.freeze();
tcx.ensure().check_unused_traits(());
}

View File

@ -84,7 +84,6 @@ impl<'a> State<'a> {
Node::ImplItem(a) => self.print_impl_item(a),
Node::Variant(a) => self.print_variant(a),
Node::AnonConst(a) => self.print_anon_const(a),
Node::ConstBlock(a) => self.print_inline_const(a),
Node::Expr(a) => self.print_expr(a),
Node::ExprField(a) => self.print_expr_field(a),
Node::Stmt(a) => self.print_stmt(a),
@ -1049,10 +1048,10 @@ impl<'a> State<'a> {
self.end()
}
fn print_inline_const(&mut self, constant: &hir::ConstBlock) {
fn print_inline_const(&mut self, constant: &hir::Expr<'_>) {
self.ibox(INDENT_UNIT);
self.word_space("const");
self.ann.nested(self, Nested::Body(constant.body));
self.print_expr(constant);
self.end()
}

View File

@ -32,7 +32,6 @@ use rustc_errors::{
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, HirId, QPath};
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
@ -336,7 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected),
ExprKind::Array(args) => self.check_expr_array(args, expected, expr),
ExprKind::ConstBlock(ref block) => self.check_expr_const_block(block, expected),
ExprKind::ConstBlock(ref block) => self.check_expr_with_expectation(block, expected),
ExprKind::Repeat(element, ref count) => {
self.check_expr_repeat(element, count, expected, expr)
}
@ -1460,24 +1459,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
fn check_expr_const_block(
&self,
block: &'tcx hir::ConstBlock,
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
let body = self.tcx.hir().body(block.body);
// Create a new function context.
let def_id = block.def_id;
let fcx = FnCtxt::new(self, self.param_env, def_id);
crate::GatherLocalsVisitor::new(&fcx).visit_body(body);
let ty = fcx.check_expr_with_expectation(body.value, expected);
fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::ConstSized);
fcx.write_ty(block.hir_id, ty);
ty
}
fn check_expr_repeat(
&self,
element: &'tcx hir::Expr<'tcx>,

View File

@ -1055,6 +1055,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.take_while(|(_, node)| {
// look at parents until we find the first body owner
node.body_id().is_none()
&& !matches!(
node,
Node::Expr(Expr { kind: ExprKind::ConstBlock { .. }, .. })
)
})
.any(|(parent_id, _)| self.is_loop(parent_id));

View File

@ -149,10 +149,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
self.visit_body(body);
self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause);
}
hir::ExprKind::ConstBlock(anon_const) => {
let body = self.fcx.tcx.hir().body(anon_const.body);
self.visit_body(body);
}
_ => {}
}

View File

@ -3,6 +3,7 @@
// generic parameters.
use crate::FnCtxt;
use hir::def::DefKind;
use rustc_data_structures::unord::ExtendUnord;
use rustc_errors::{ErrorGuaranteed, StashKey};
use rustc_hir as hir;
@ -16,7 +17,7 @@ use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::TypeSuperFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::symbol::{kw, sym};
use rustc_span::Span;
use rustc_trait_selection::solve;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
@ -295,11 +296,11 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
hir::ExprKind::Field(..) | hir::ExprKind::OffsetOf(..) => {
self.visit_field_id(e.hir_id);
}
hir::ExprKind::ConstBlock(anon_const) => {
self.visit_node_id(e.span, anon_const.hir_id);
let body = self.tcx().hir().body(anon_const.body);
self.visit_body(body);
hir::ExprKind::ConstBlock(_) => {
let feed = self.tcx().create_def(self.fcx.body_id, kw::Empty, DefKind::InlineConst);
feed.def_span(e.span);
feed.local_def_id_to_hir_id(e.hir_id);
self.typeck_results.inline_consts.insert(e.hir_id.local_id, feed.def_id());
}
_ => {}
}

View File

@ -321,7 +321,7 @@ impl<'hir> Map<'hir> {
/// Returns an iterator of the `DefId`s for all body-owners in this
/// crate. If you would prefer to iterate over the bodies
/// themselves, you can do `self.hir().krate().body_ids.iter()`.
/// themselves, you can do `self.hir().krate().owners.iter()`.
#[inline]
pub fn body_owners(self) -> impl Iterator<Item = LocalDefId> + 'hir {
self.tcx.hir_crate_items(()).body_owners.iter().copied()
@ -508,7 +508,17 @@ impl<'hir> Map<'hir> {
/// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
/// Used exclusively for diagnostics, to avoid suggestion function calls.
pub fn is_inside_const_context(self, hir_id: HirId) -> bool {
self.body_const_context(self.enclosing_body_owner(hir_id)).is_some()
for (_, node) in self.parent_iter(hir_id) {
if let Some((def_id, _)) = node.associated_body() {
return self.body_const_context(def_id).is_some();
}
if let Node::Expr(e) = node {
if let ExprKind::ConstBlock(_) = e.kind {
return true;
}
}
}
false
}
/// Retrieves the `HirId` for `id`'s enclosing function *if* the `id` block or return is
@ -891,7 +901,6 @@ impl<'hir> Map<'hir> {
Node::Variant(variant) => variant.span,
Node::Field(field) => field.span,
Node::AnonConst(constant) => constant.span,
Node::ConstBlock(constant) => self.body(constant.body).value.span,
Node::Expr(expr) => expr.span,
Node::ExprField(field) => field.span,
Node::Stmt(stmt) => stmt.span,
@ -1161,7 +1170,6 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
}
Node::AnonConst(_) => node_str("const"),
Node::ConstBlock(_) => node_str("const"),
Node::Expr(_) => node_str("expr"),
Node::ExprField(_) => node_str("expr field"),
Node::Stmt(_) => node_str("stmt"),
@ -1311,11 +1319,6 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
intravisit::walk_anon_const(self, c)
}
fn visit_inline_const(&mut self, c: &'hir ConstBlock) {
self.body_owners.push(c.def_id);
intravisit::walk_inline_const(self, c)
}
fn visit_expr(&mut self, ex: &'hir Expr<'hir>) {
if let ExprKind::Closure(closure) = ex.kind {
self.body_owners.push(closure.def_id);

View File

@ -217,6 +217,10 @@ pub struct TypeckResults<'tcx> {
/// Container types and field indices of `offset_of!` expressions
offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)>,
/// Maps from `HirId`s of const blocks (the `ExprKind::ConstBlock`, not the inner expression's)
/// to the `DefId` of the corresponding inline const.
pub inline_consts: FxIndexMap<ItemLocalId, LocalDefId>,
}
impl<'tcx> TypeckResults<'tcx> {
@ -249,6 +253,7 @@ impl<'tcx> TypeckResults<'tcx> {
treat_byte_string_as_slice: Default::default(),
closure_size_eval: Default::default(),
offset_of_data: Default::default(),
inline_consts: Default::default(),
}
}

View File

@ -568,11 +568,8 @@ fn construct_const<'a, 'tcx>(
..
}) => (*span, ty.span),
Node::AnonConst(ct) => (ct.span, ct.span),
Node::ConstBlock(_) => {
let span = tcx.def_span(def);
(span, span)
}
_ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
Node::Expr(&hir::Expr { span, kind: hir::ExprKind::ConstBlock(_), .. }) => (span, span),
node => span_bug!(tcx.def_span(def), "can't build MIR for {def:?}: {node:#?}"),
};
let infcx = tcx.infer_ctxt().build();

View File

@ -671,9 +671,9 @@ impl<'tcx> Cx<'tcx> {
ExprKind::OffsetOf { container, fields }
}
hir::ExprKind::ConstBlock(ref anon_const) => {
let ty = self.typeck_results().node_type(anon_const.hir_id);
let did = anon_const.def_id.to_def_id();
hir::ExprKind::ConstBlock(body) => {
let ty = self.typeck_results().node_type(body.hir_id);
let did = self.typeck_results().inline_consts[&expr.hir_id.local_id].into();
let typeck_root_def_id = tcx.typeck_root_def_id(did);
let parent_args =
tcx.erase_regions(GenericArgs::identity_for_item(tcx, typeck_root_def_id));

View File

@ -13,10 +13,10 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::HirId;
use rustc_hir::Node;
use rustc_middle::bug;
use rustc_middle::middle::region;
use rustc_middle::thir::*;
use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
use rustc_middle::{bug, span_bug};
use tracing::instrument;
pub(crate) fn thir_body(
@ -24,7 +24,22 @@ pub(crate) fn thir_body(
owner_def: LocalDefId,
) -> Result<(&Steal<Thir<'_>>, ExprId), ErrorGuaranteed> {
let hir = tcx.hir();
let body = hir.body(hir.body_owned_by(owner_def));
let body;
let body = match tcx.def_kind(owner_def) {
// Inline consts do not have bodies of their own, so create one to make the follow-up logic simpler.
DefKind::InlineConst => {
let e = hir.expect_expr(tcx.local_def_id_to_hir_id(owner_def));
body = hir::Body {
params: &[],
value: match e.kind {
hir::ExprKind::ConstBlock(body) => body,
_ => span_bug!(e.span, "InlineConst was not a ConstBlock: {e:#?}"),
},
};
&body
}
_ => hir.body(hir.body_owned_by(owner_def)),
};
let mut cx = Cx::new(tcx, owner_def);
if let Some(reported) = cx.typeck_results.tainted_by_errors {
return Err(reported);
@ -165,7 +180,7 @@ impl<'tcx> Cx<'tcx> {
&'a mut self,
owner_id: HirId,
fn_decl: &'tcx hir::FnDecl<'tcx>,
body: &'tcx hir::Body<'tcx>,
body: &hir::Body<'tcx>,
) -> impl Iterator<Item = Param<'tcx>> + 'a {
let fn_sig = self.typeck_results.liberated_fn_sigs()[owner_id];

View File

@ -637,15 +637,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
/// Converts inline const patterns.
fn lower_inline_const(
&mut self,
block: &'tcx hir::ConstBlock,
expr: &'tcx hir::Expr<'tcx>,
id: hir::HirId,
span: Span,
) -> PatKind<'tcx> {
let tcx = self.tcx;
let def_id = block.def_id;
let body_id = block.body;
let expr = &tcx.hir().body(body_id).value;
let ty = tcx.typeck(def_id).node_type(block.hir_id);
let def_id = self.typeck_results.inline_consts[&id.local_id];
let ty = tcx.typeck(def_id).node_type(expr.hir_id);
// Special case inline consts that are just literals. This is solely
// a performance optimization, as we could also just go through the regular

View File

@ -222,6 +222,12 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
// All body-owners have MIR associated with them.
set.extend(tcx.hir().body_owners());
// Inline consts' bodies are created in
// typeck instead of during ast lowering, like all other bodies so far.
for def_id in tcx.hir().body_owners() {
set.extend(tcx.typeck(def_id).inline_consts.values())
}
// Additionally, tuple struct/variant constructors have MIR, but
// they don't have a BodyId, so we need to build them separately.
struct GatherCtors<'a> {

View File

@ -25,8 +25,8 @@ use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing};
use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
use rustc_ast::util::case::Case;
use rustc_ast::{
self as ast, AnonConst, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs,
Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit, Visibility,
self as ast, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs, Expr,
ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit, Visibility,
VisibilityKind, DUMMY_NODE_ID,
};
use rustc_ast_pretty::pprust;
@ -1260,12 +1260,9 @@ impl<'a> Parser<'a> {
}
self.eat_keyword(kw::Const);
let (attrs, blk) = self.parse_inner_attrs_and_block()?;
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))
let expr = self.mk_expr(blk.span, ExprKind::Block(blk, None));
let blk_span = expr.span;
Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(expr), attrs))
}
/// Parses mutability (`mut` or nothing).

View File

@ -196,11 +196,6 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
}
fn visit_inline_const(&mut self, block: &'tcx hir::ConstBlock) {
let kind = Some(hir::ConstContext::Const { inline: true });
self.recurse_into(kind, None, |this| intravisit::walk_inline_const(this, block));
}
fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
let owner = self.tcx.hir().body_owner_def_id(body.id());
let kind = self.tcx.hir().body_const_context(owner);
@ -228,6 +223,11 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
self.const_check_violated(expr, e.span);
}
}
hir::ExprKind::ConstBlock(expr) => {
let kind = Some(hir::ConstContext::Const { inline: true });
self.recurse_into(kind, None, |this| intravisit::walk_expr(this, expr));
return;
}
_ => {}
}

View File

@ -587,6 +587,16 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
hir::ExprKind::OffsetOf(..) => {
self.handle_offset_of(expr);
}
hir::ExprKind::ConstBlock(expr) => {
// When inline const blocks are used in pattern position, paths
// referenced by it should be considered as used.
let in_pat = mem::replace(&mut self.in_pat, false);
intravisit::walk_expr(self, expr);
self.in_pat = in_pat;
return;
}
_ => (),
}
@ -648,17 +658,6 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
self.in_pat = in_pat;
}
fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) {
// When inline const blocks are used in pattern position, paths
// referenced by it should be considered as used.
let in_pat = mem::replace(&mut self.in_pat, false);
self.live_symbols.insert(c.def_id);
intravisit::walk_inline_const(self, c);
self.in_pat = in_pat;
}
}
fn has_allow_dead_code_or_lang_attr(

View File

@ -147,6 +147,11 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) {
return;
}
// Don't run for inline consts, they are collected together with their parent
if let DefKind::InlineConst = tcx.def_kind(def_id) {
return;
}
// Don't run unused pass for #[naked]
if tcx.has_attr(def_id.to_def_id(), sym::naked) {
return;
@ -1144,12 +1149,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}
hir::ExprKind::Lit(..)
| hir::ExprKind::ConstBlock(..)
| hir::ExprKind::Err(_)
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
| hir::ExprKind::Path(hir::QPath::LangItem(..))
| hir::ExprKind::OffsetOf(..) => succ,
hir::ExprKind::ConstBlock(expr) => self.propagate_through_expr(expr, succ),
// Note that labels have been resolved, so we don't need to look
// at the label ident
hir::ExprKind::Block(ref blk, _) => self.propagate_through_block(blk, succ),

View File

@ -93,10 +93,6 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
self.with_context(Constant, |v| intravisit::walk_anon_const(v, c));
}
fn visit_inline_const(&mut self, c: &'hir hir::ConstBlock) {
self.with_context(Constant, |v| intravisit::walk_inline_const(v, c));
}
fn visit_fn(
&mut self,
fk: hir::intravisit::FnKind<'hir>,
@ -289,6 +285,9 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
self.cx_stack.len() - 1,
)
}
hir::ExprKind::ConstBlock(expr) => {
self.with_context(Constant, |v| intravisit::walk_expr(v, expr));
}
_ => intravisit::walk_expr(self, e),
}
}

View File

@ -325,16 +325,6 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
ExprKind::Gen(_, _, _) => {
self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
}
ExprKind::ConstBlock(ref constant) => {
let def = self.create_def(
constant.id,
kw::Empty,
DefKind::InlineConst,
constant.value.span,
);
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
return;
}
_ => self.parent_def,
};

View File

@ -4502,9 +4502,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
self.visit_expr(elem);
self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::Yes));
}
ExprKind::ConstBlock(ref ct) => {
self.resolve_anon_const(ct, AnonConstKind::InlineConst);
}
ExprKind::Index(ref elem, ref idx, _) => {
self.resolve_expr(elem, Some(expr));
self.visit_expr(idx);

View File

@ -6,7 +6,7 @@ use crate::{clip, is_direct_expn_of, sext, unsext};
use rustc_ast::ast::{self, LitFloatType, LitKind};
use rustc_data_structures::sync::Lrc;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
use rustc_lexer::tokenize;
use rustc_lint::LateContext;
use rustc_middle::mir::interpret::{alloc_range, Scalar};
@ -412,7 +412,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
/// Simple constant folding: Insert an expression, get a constant or none.
pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
match e.kind {
ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.lcx.tcx.hir().body(body).value),
ExprKind::ConstBlock(e) |
ExprKind::DropTemps(e) => self.expr(e),
ExprKind::Path(ref qpath) => {
self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| {
@ -491,7 +491,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
/// leaves the local crate.
pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option<bool> {
match e.kind {
ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr_is_empty(self.lcx.tcx.hir().body(body).value),
ExprKind::ConstBlock(e) |
ExprKind::DropTemps(e) => self.expr_is_empty(e),
ExprKind::Path(ref qpath) => {
if !self

View File

@ -295,7 +295,7 @@ impl HirEqInterExpr<'_, '_, '_> {
self.eq_expr(lx, rx) && self.eq_ty(lt, rt)
},
(&ExprKind::Closure(_l), &ExprKind::Closure(_r)) => false,
(&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_body(lb.body, rb.body),
(&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_expr(lb, rb),
(&ExprKind::Continue(li), &ExprKind::Continue(ri)) => {
both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name)
},
@ -770,7 +770,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_expr(self.cx.tcx.hir().body(body).value);
},
ExprKind::ConstBlock(ref l_id) => {
self.hash_body(l_id.body);
self.hash_expr(l_id);
},
ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
self.hash_expr(e);

View File

@ -1,11 +1,35 @@
error: arithmetic operation that can potentially result in unexpected side-effects
--> tests/ui/arithmetic_side_effects.rs:188:36
|
LL | let _ = const { let mut n = 1; n += 1; n };
| ^^^^^^
|
= note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::arithmetic_side_effects)]`
error: arithmetic operation that can potentially result in unexpected side-effects
--> tests/ui/arithmetic_side_effects.rs:191:40
|
LL | let _ = const { let mut n = 1; n = n + 1; n };
| ^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> tests/ui/arithmetic_side_effects.rs:194:40
|
LL | let _ = const { let mut n = 1; n = 1 + n; n };
| ^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> tests/ui/arithmetic_side_effects.rs:200:59
|
LL | let _ = const { let mut n = 1; n = -1; n = -(-1); n = -n; n };
| ^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> tests/ui/arithmetic_side_effects.rs:304:5
|
LL | _n += 1;
| ^^^^^^^
|
= note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::arithmetic_side_effects)]`
error: arithmetic operation that can potentially result in unexpected side-effects
--> tests/ui/arithmetic_side_effects.rs:305:5
@ -727,5 +751,5 @@ error: arithmetic operation that can potentially result in unexpected side-effec
LL | one.sub_assign(1);
| ^^^^^^^^^^^^^^^^^
error: aborting due to 121 previous errors
error: aborting due to 125 previous errors

View File

@ -10,7 +10,7 @@ fn consts() -> () {
bb0: {
_1 = const 5_u8;
_2 = const consts::<C>::{constant#0};
_2 = const consts::<C>::{constant#1};
_3 = const C;
_4 = const D;
_5 = consts::<10>;

View File

@ -206,12 +206,7 @@ fn _11() {
let _ = ();
()
};
let const {
#![rustc_dummy]
} =
#[rustc_dummy] const {
#![rustc_dummy]
};
let const {} = #[rustc_dummy] const {};
let mut x = 0;
let _ = (#[rustc_dummy] x) = 15;
let _ = (#[rustc_dummy] x) += 15;

View File

@ -67,18 +67,13 @@ LL | impl Test {
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
--> $DIR/consts.rs:50:9
|
LL | const {
| ___________-
LL | | impl Test {
| | ^^^^^----
| | |
| | `Test` is not local
LL | |
LL | | fn hoo() {}
... |
LL | | 1
LL | | };
| |_____- move the `impl` block outside of this inline constant `<unnameable>` and up 2 bodies
LL | fn main() {
| --------- move the `impl` block outside of this function `main`
...
LL | impl Test {
| ^^^^^----
| |
| `Test` is not local
|
= note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl`
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>

View File

@ -82,7 +82,8 @@ mod expressions {
fn expr_const_block() {
const {};
const { 1 };
const {
const
{
struct S;
};
}