diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 1a166956075c7..7e59b44929930 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1393,7 +1393,7 @@ pub enum ExprKind {
/// An array (e.g, `[a, b, c, d]`).
Array(ThinVec
>),
/// Allow anonymous constants from an inline `const` block
- ConstBlock(AnonConst),
+ ConstBlock(P),
/// A function call
///
/// The first field resolves to the function itself,
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 566b20c490efb..ede0dd70b305c 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1411,7 +1411,7 @@ pub fn noop_visit_expr(
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);
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 93de42b55cc39..182aa6ed085c2 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -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));
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index a553109092842..eb206a09be313 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -75,12 +75,8 @@ 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)
+ self.has_inline_consts = true;
+ hir::ExprKind::ConstBlock(self.lower_expr(c))
}
ExprKind::Repeat(expr, count) => {
let expr = self.lower_expr(expr);
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index 7254be2b2f42a..ed3046400f603 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -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));
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index a9af5ad74592d..278049d1347b0 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -96,6 +96,8 @@ struct LoweringContext<'a, 'hir> {
/// Bodies inside the owner being lowered.
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
+ /// Whether there were inline consts that typeck will split out into bodies
+ has_inline_consts: bool,
/// Attributes inside the owner being lowered.
attrs: SortedMap,
/// Collect items that were created by lowering the current owner.
@@ -158,6 +160,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
item_local_id_counter: hir::ItemLocalId::ZERO,
node_id_to_local_id: Default::default(),
trait_map: Default::default(),
+ has_inline_consts: false,
// Lowering state.
catch_scope: None,
@@ -567,6 +570,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let current_attrs = std::mem::take(&mut self.attrs);
let current_bodies = std::mem::take(&mut self.bodies);
+ let current_has_inline_consts = std::mem::take(&mut self.has_inline_consts);
let current_node_ids = std::mem::take(&mut self.node_id_to_local_id);
let current_trait_map = std::mem::take(&mut self.trait_map);
let current_owner =
@@ -593,6 +597,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.attrs = current_attrs;
self.bodies = current_bodies;
+ self.has_inline_consts = current_has_inline_consts;
self.node_id_to_local_id = current_node_ids;
self.trait_map = current_trait_map;
self.current_hir_id_owner = current_owner;
@@ -629,6 +634,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let attrs = std::mem::take(&mut self.attrs);
let mut bodies = std::mem::take(&mut self.bodies);
let trait_map = std::mem::take(&mut self.trait_map);
+ let has_inline_consts = std::mem::take(&mut self.has_inline_consts);
#[cfg(debug_assertions)]
for (id, attrs) in attrs.iter() {
@@ -646,7 +652,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.tcx.hash_owner_nodes(node, &bodies, &attrs);
let num_nodes = self.item_local_id_counter.as_usize();
let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);
- let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
+ let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies, has_inline_consts };
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash };
self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 1e117c46b6e29..993ccc5b95609 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -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);
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index 8c66888d1007e..3c11d67e74890 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -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 {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 950e7c12da2e9..d13ba4a2b95bf 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -6,7 +6,6 @@ use std::ops::ControlFlow;
use rustc_ast::Mutability;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::fx::IndexEntry;
-use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::LangItem;
@@ -392,18 +391,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> {
instance: ty::InstanceDef<'tcx>,
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
match instance {
- ty::InstanceDef::Item(def) => {
- if ecx.tcx.is_ctfe_mir_available(def) {
- Ok(ecx.tcx.mir_for_ctfe(def))
- } else if ecx.tcx.def_kind(def) == DefKind::AssocConst {
- ecx.tcx.dcx().bug("This is likely a const item that is missing from its impl");
- } else {
- // `find_mir_or_eval_fn` checks that this is a const fn before even calling us,
- // so this should be unreachable.
- let path = ecx.tcx.def_path_str(def);
- bug!("trying to call extern function `{path}` at compile-time");
- }
- }
+ ty::InstanceDef::Item(def) => Ok(ecx.tcx.mir_for_ctfe(def)),
_ => Ok(ecx.tcx.instance_mir(instance)),
}
}
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 2f4dcdbdf2b17..e64f7aeb11b3e 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -876,6 +876,9 @@ pub struct OwnerNodes<'tcx> {
pub nodes: IndexVec>,
/// Content of local bodies.
pub bodies: SortedMap>,
+ /// Whether the body contains inline constants that are created for the query system during typeck
+ /// of the body.
+ pub has_inline_consts: bool,
}
impl<'tcx> OwnerNodes<'tcx> {
@@ -1592,14 +1595,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 +1881,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 +3604,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 +3664,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 +3761,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 +3829,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;
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index b202ea8dca37c..aba0532f0d1ee 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -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));
diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs
index baa1635f7313f..1ebd4b80e1835 100644
--- a/compiler/rustc_hir/src/stable_hash_impls.rs
+++ b/compiler/rustc_hir/src/stable_hash_impls.rs
@@ -93,7 +93,8 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable for OwnerNodes<'
// `local_id_to_def_id` is also ignored because is dependent on the body, then just hashing
// the body satisfies the condition of two nodes being different have different
// `hash_stable` results.
- let OwnerNodes { opt_hash_including_bodies, nodes: _, bodies: _ } = *self;
+ let OwnerNodes { opt_hash_including_bodies, nodes: _, bodies: _, has_inline_consts: _ } =
+ *self;
opt_hash_including_bodies.unwrap().hash_stable(hcx, hasher);
}
}
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index e51f95eed021b..8b0adebfaf467 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -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 {}",
@@ -782,25 +785,8 @@ impl<'tcx> RegionResolutionVisitor<'tcx> {
}
self.enter_scope(Scope { id, data: ScopeData::Node });
}
-}
-
-impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
- fn visit_block(&mut self, b: &'tcx Block<'tcx>) {
- resolve_block(self, b);
- }
-
- fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
- let body_id = body.id();
- let owner_id = self.tcx.hir().body_owner_def_id(body_id);
-
- debug!(
- "visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})",
- owner_id,
- self.tcx.sess.source_map().span_to_diagnostic_string(body.value.span),
- body_id,
- self.cx.parent
- );
+ fn enter_body(&mut self, hir_id: hir::HirId, f: impl FnOnce(&mut Self)) {
// Save all state that is specific to the outer function
// body. These will be restored once down below, once we've
// visited the body.
@@ -812,43 +798,12 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
// control flow assumptions. This doesn't apply to nested
// bodies within the `+=` statements. See #69307.
let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false);
- self.terminating_scopes.insert(body.value.hir_id.local_id);
-
- self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::CallSite });
- self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::Arguments });
+ self.terminating_scopes.insert(hir_id.local_id);
- // The arguments and `self` are parented to the fn.
- self.cx.var_parent = self.cx.parent.take();
- for param in body.params {
- self.visit_pat(param.pat);
- }
+ self.enter_scope(Scope { id: hir_id.local_id, data: ScopeData::CallSite });
+ self.enter_scope(Scope { id: hir_id.local_id, data: ScopeData::Arguments });
- // The body of the every fn is a root scope.
- self.cx.parent = self.cx.var_parent;
- if self.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() {
- self.visit_expr(body.value)
- } else {
- // Only functions have an outer terminating (drop) scope, while
- // temporaries in constant initializers may be 'static, but only
- // according to rvalue lifetime semantics, using the same
- // syntactical rules used for let initializers.
- //
- // e.g., in `let x = &f();`, the temporary holding the result from
- // the `f()` call lives for the entirety of the surrounding block.
- //
- // Similarly, `const X: ... = &f();` would have the result of `f()`
- // live for `'static`, implying (if Drop restrictions on constants
- // ever get lifted) that the value *could* have a destructor, but
- // it'd get leaked instead of the destructor running during the
- // evaluation of `X` (if at all allowed by CTFE).
- //
- // However, `const Y: ... = g(&f());`, like `let y = g(&f());`,
- // would *not* let the `f()` temporary escape into an outer scope
- // (i.e., `'static`), which means that after `g` returns, it drops,
- // and all the associated destruction scope rules apply.
- self.cx.var_parent = None;
- resolve_local(self, None, Some(body.value));
- }
+ f(self);
// Restore context we had at the start.
self.expr_and_pat_count = outer_ec;
@@ -856,6 +811,60 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
self.terminating_scopes = outer_ts;
self.pessimistic_yield = outer_pessimistic_yield;
}
+}
+
+impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
+ fn visit_block(&mut self, b: &'tcx Block<'tcx>) {
+ resolve_block(self, b);
+ }
+
+ fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
+ let body_id = body.id();
+ let owner_id = self.tcx.hir().body_owner_def_id(body_id);
+
+ debug!(
+ "visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})",
+ owner_id,
+ self.tcx.sess.source_map().span_to_diagnostic_string(body.value.span),
+ body_id,
+ self.cx.parent
+ );
+
+ self.enter_body(body.value.hir_id, |this| {
+ if this.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() {
+ // The arguments and `self` are parented to the fn.
+ this.cx.var_parent = this.cx.parent.take();
+ for param in body.params {
+ this.visit_pat(param.pat);
+ }
+
+ // The body of the every fn is a root scope.
+ this.cx.parent = this.cx.var_parent;
+ this.visit_expr(body.value)
+ } else {
+ // Only functions have an outer terminating (drop) scope, while
+ // temporaries in constant initializers may be 'static, but only
+ // according to rvalue lifetime semantics, using the same
+ // syntactical rules used for let initializers.
+ //
+ // e.g., in `let x = &f();`, the temporary holding the result from
+ // the `f()` call lives for the entirety of the surrounding block.
+ //
+ // Similarly, `const X: ... = &f();` would have the result of `f()`
+ // live for `'static`, implying (if Drop restrictions on constants
+ // ever get lifted) that the value *could* have a destructor, but
+ // it'd get leaked instead of the destructor running during the
+ // evaluation of `X` (if at all allowed by CTFE).
+ //
+ // However, `const Y: ... = g(&f());`, like `let y = g(&f());`,
+ // would *not* let the `f()` temporary escape into an outer scope
+ // (i.e., `'static`), which means that after `g` returns, it drops,
+ // and all the associated destruction scope rules apply.
+ this.cx.var_parent = None;
+ resolve_local(this, None, Some(body.value));
+ }
+ })
+ }
fn visit_arm(&mut self, a: &'tcx Arm<'tcx>) {
resolve_arm(self, a);
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index abdf85ad707bc..9af959681fbfa 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -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(""),
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index ed942cc50bb42..d497617f6449e 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -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()
}
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 8fe81851f9327..65b02a2ec5653 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -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(());
}
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 488537e81becf..62abdf0afabfe 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -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()
}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index fade943c5ae3d..364f0fec202ab 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -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>,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index cfd4dd4d1dd0d..0d7f59c48715d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -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));
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 466397817dae1..4386e68ce8674 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -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);
- }
_ => {}
}
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index f798deea207a4..31caa52d26710 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -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());
}
_ => {}
}
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index b17af47fbcd4f..ff8d291970556 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -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- + '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);
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index c09cb95de8837..51bbe35121878 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -737,6 +737,7 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
1,
),
bodies,
+ has_inline_consts: false,
})));
self.feed_owner_id().hir_attrs(attrs);
}
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 24e3e623ff274..69ea9c9843a08 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -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,
}
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(),
}
}
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 92cd7f75d6283..13112f2b12c8a 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -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();
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 28f9300b97a88..bd66257e6b687 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -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));
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 3c0e2521d88fe..bd72ef28cb37d 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -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>, 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
- > + 'a {
let fn_sig = self.typeck_results.liberated_fn_sigs()[owner_id];
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 7408c679f00b1..33401cad631a1 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -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
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index e4670633914e4..93ae105150cc2 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -211,7 +211,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
}
fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
- tcx.mir_keys(()).contains(&def_id)
+ tcx.hir().maybe_body_owned_by(def_id).is_some()
}
/// Finds the full set of `DefId`s within the current crate that have
@@ -222,6 +222,15 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet {
// 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() {
+ // Incremental performance optimization: only load typeck results for things that actually have inline consts
+ if tcx.hir_owner_nodes(tcx.hir().body_owned_by(def_id).hir_id.owner).has_inline_consts {
+ 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> {
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index c2183258eef14..bab8b6c06ebee 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -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).
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index eb29a65cb293d..fa2c8f69c71d5 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -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;
+ }
_ => {}
}
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index ddc50e2b811a2..0049afff528ca 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -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(
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index b0a753604e2e3..1f966be26ff45 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -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),
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index 2587a18b8c897..737310e5c04a3 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -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),
}
}
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index bd0622428569c..cad10571afe62 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -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,
};
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 63d0d6c260dbe..08326d1ef57ec 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -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);
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 253ae3aca6894..f5d3967d130db 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -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> {
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 {
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
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 9f285621e0c96..cc5ccd4053a2f 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -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);
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
index 8039c0bfa2484..df14ff396f6cf 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
@@ -1,12 +1,36 @@
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:304:5
+ --> tests/ui/arithmetic_side_effects.rs:188:36
|
-LL | _n += 1;
- | ^^^^^^^
+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;
+ | ^^^^^^^
+
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
diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs
index 6c3d991af9f14..4e5ad8ad4a932 100644
--- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs
+++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs
@@ -4,7 +4,7 @@
//@ needs-sanitizer-cfi
//@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static
-#![crate_type="lib"]
+#![crate_type = "lib"]
#![feature(type_alias_impl_trait)]
extern crate core;
@@ -14,14 +14,15 @@ pub type Type2 = impl Send;
pub type Type3 = impl Send;
pub type Type4 = impl Send;
-pub fn foo() where
+pub fn foo()
+where
Type1: 'static,
Type2: 'static,
Type3: 'static,
Type4: 'static,
{
// Type in extern path
- extern {
+ extern "C" {
fn bar();
}
let _: Type1 = bar;
@@ -35,43 +36,44 @@ pub fn foo() where
// Type in const path
const {
pub struct Foo;
- fn bar() -> Type3 { Foo }
+ fn bar() -> Type3 {
+ Foo
+ }
};
-
// Type in impl path
struct Foo;
impl Foo {
- fn bar(&self) { }
+ fn bar(&self) {}
}
let _: Type4 = ::bar;
}
// Force arguments to be passed by using a reference. Otherwise, they may end up PassMode::Ignore
-pub fn foo1(_: &Type1) { }
+pub fn foo1(_: &Type1) {}
// CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
-pub fn foo2(_: &Type1, _: &Type1) { }
+pub fn foo2(_: &Type1, _: &Type1) {}
// CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
-pub fn foo3(_: &Type1, _: &Type1, _: &Type1) { }
+pub fn foo3(_: &Type1, _: &Type1, _: &Type1) {}
// CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
-pub fn foo4(_: &Type2) { }
+pub fn foo4(_: &Type2) {}
// CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
-pub fn foo5(_: &Type2, _: &Type2) { }
+pub fn foo5(_: &Type2, _: &Type2) {}
// CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
-pub fn foo6(_: &Type2, _: &Type2, _: &Type2) { }
+pub fn foo6(_: &Type2, _: &Type2, _: &Type2) {}
// CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
-pub fn foo7(_: &Type3) { }
+pub fn foo7(_: &Type3) {}
// CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
-pub fn foo8(_: &Type3, _: &Type3) { }
+pub fn foo8(_: &Type3, _: &Type3) {}
// CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
-pub fn foo9(_: &Type3, _: &Type3, _: &Type3) { }
+pub fn foo9(_: &Type3, _: &Type3, _: &Type3) {}
// CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
-pub fn foo10(_: &Type4) { }
+pub fn foo10(_: &Type4) {}
// CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
-pub fn foo11(_: &Type4, _: &Type4) { }
+pub fn foo11(_: &Type4, _: &Type4) {}
// CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
-pub fn foo12(_: &Type4, _: &Type4, _: &Type4) { }
+pub fn foo12(_: &Type4, _: &Type4, _: &Type4) {}
// CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barEE"}
@@ -80,9 +82,9 @@ pub fn foo12(_: &Type4, _: &Type4, _: &Type4) { }
// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooEE"}
// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_E"}
// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_S0_E"}
-// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooEE"}
-// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_E"}
-// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_S0_E"}
+// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooEE"}
+// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooES0_E"}
+// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooES0_S0_E"}
// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barEE"}
// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_E"}
// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_S0_E"}
diff --git a/tests/mir-opt/building/custom/consts.consts.built.after.mir b/tests/mir-opt/building/custom/consts.consts.built.after.mir
index a011fadcef116..7b6964849d4b3 100644
--- a/tests/mir-opt/building/custom/consts.consts.built.after.mir
+++ b/tests/mir-opt/building/custom/consts.consts.built.after.mir
@@ -10,7 +10,7 @@ fn consts() -> () {
bb0: {
_1 = const 5_u8;
- _2 = const consts::::{constant#0};
+ _2 = const consts::::{constant#1};
_3 = const C;
_4 = const D;
_5 = consts::<10>;
diff --git a/tests/pretty/stmt_expr_attributes.rs b/tests/pretty/stmt_expr_attributes.rs
index 5eb7d2fcae36a..f904126821103 100644
--- a/tests/pretty/stmt_expr_attributes.rs
+++ b/tests/pretty/stmt_expr_attributes.rs
@@ -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;
diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr
index 2756ea4013877..48bdaa60823f8 100644
--- a/tests/ui/lint/non-local-defs/consts.stderr
+++ b/tests/ui/lint/non-local-defs/consts.stderr
@@ -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 `` 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
diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout
index 325bace7b5624..8737063bf3cc7 100644
--- a/tests/ui/unpretty/expanded-exhaustive.stdout
+++ b/tests/ui/unpretty/expanded-exhaustive.stdout
@@ -82,7 +82,8 @@ mod expressions {
fn expr_const_block() {
const {};
const { 1 };
- const {
+ const
+ {
struct S;
};
}