Skip to content

Commit

Permalink
Auto merge of #124650 - oli-obk:pattern_types_syntax, r=<try>
Browse files Browse the repository at this point in the history
Create const block DefIds in typeck instead of ast lowering

r? `@ghost`

this is a prerequisite for cleaning up pattern types and the range pattern HIR nodes in general. Right now they contain expressions, but they are supposed to only contain constants. In order to generate the anonymous constants lazily during typeck, we need to support generating new items with bodies during typeck in general. Transforming const blocks was the simplest change I could find to allow us to do that (everything else is much more invasive if we haven't already done it for const blocks).
  • Loading branch information
bors committed May 3, 2024
2 parents 79734f1 + edb59c9 commit eeec347
Show file tree
Hide file tree
Showing 38 changed files with 184 additions and 240 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1393,7 +1393,7 @@ pub enum ExprKind {
/// An array (`[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,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1383,7 +1383,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);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,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));
Expand Down
9 changes: 1 addition & 8 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_ast_lowering/src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_ast_pretty/src/pprust/state/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_const_eval/src/const_eval/fn_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
14 changes: 1 addition & 13 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -390,18 +389,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
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)),
}
}
Expand Down
14 changes: 1 addition & 13 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1592,14 +1592,6 @@ pub struct AnonConst {
pub body: BodyId,
}

/// 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> {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -3606,7 +3598,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>),
Expand Down Expand Up @@ -3669,7 +3660,6 @@ impl<'hir> Node<'hir> {
Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident),
Node::Param(..)
| Node::AnonConst(..)
| Node::ConstBlock(..)
| Node::Expr(..)
| Node::Stmt(..)
| Node::Block(..)
Expand Down Expand Up @@ -3767,7 +3757,6 @@ impl<'hir> Node<'hir> {
}

Node::AnonConst(constant) => Some((constant.def_id, constant.body)),
Node::ConstBlock(constant) => Some((constant.def_id, constant.body)),

_ => None,
}
Expand Down Expand Up @@ -3836,7 +3825,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;
Expand Down
13 changes: 1 addition & 12 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -716,22 +713,14 @@ 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 {
ExprKind::Array(subexpressions) => {
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));
Expand Down
119 changes: 64 additions & 55 deletions compiler/rustc_hir_analysis/src/check/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,11 +406,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 {}",
Expand Down Expand Up @@ -781,25 +784,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.
Expand All @@ -811,50 +797,73 @@ 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;
self.cx = outer_cx;
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);
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_hir_analysis/src/collect/generics_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -414,7 +414,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 {
params.push(ty::GenericParamDef {
index: next_index(),
name: Symbol::intern("<const_ty>"),
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_hir_analysis/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,8 +487,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
}

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()
}
Expand Down

0 comments on commit eeec347

Please sign in to comment.