Skip to content
Draft
21 changes: 20 additions & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3753,10 +3753,29 @@ pub struct ConstItem {
pub ident: Ident,
pub generics: Generics,
pub ty: Box<Ty>,
pub expr: Option<Box<Expr>>,
pub body: Option<ConstItemRhs>,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
pub body: Option<ConstItemRhs>,
pub rhs: Option<ConstItemRhs>,

body terminology doesn't make too much sense since it's only sometimes a body

pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
}

#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum ConstItemRhs {
TypeConst(AnonConst),
Body(Box<Expr>),
}

impl ConstItemRhs {
pub fn span(&self) -> Span {
self.expr().span
}

pub fn expr(&self) -> &Expr {
match self {
ConstItemRhs::TypeConst(anon_const) => &anon_const.value,
ConstItemRhs::Body(expr) => expr,
}
}
}

// Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ItemKind {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ macro_rules! common_visitor_and_walkers {
Closure,
Const,
ConstItem,
ConstItemRhs,
Defaultness,
Delegation,
DelegationMac,
Expand Down
44 changes: 19 additions & 25 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,37 +172,41 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
ItemKind::Static(box ast::StaticItem {
ident,
ty: t,
ty,
safety: _,
mutability: m,
expr: e,
define_opaque,
}) => {
let ident = self.lower_ident(*ident);
let (ty, body_id) =
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
let ty =
self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
let body_id = self.lower_const_body(span, e.as_deref());
self.lower_define_opaque(hir_id, define_opaque);
hir::ItemKind::Static(*m, ident, ty, body_id)
}
ItemKind::Const(box ast::ConstItem {
ident,
generics,
ty,
expr,
body,
define_opaque,
..
}) => {
let ident = self.lower_ident(*ident);
let (generics, (ty, body_id)) = self.lower_generics(
let (generics, (ty, body)) = self.lower_generics(
generics,
id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
let ty = this
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
let body = this.lower_const_item_rhs(attrs, body.as_ref(), span);
(ty, body)
},
);
self.lower_define_opaque(hir_id, &define_opaque);
hir::ItemKind::Const(ident, generics, ty, body_id)
hir::ItemKind::Const(ident, generics, ty, body)
}
ItemKind::Fn(box Fn {
sig: FnSig { decl, header, span: fn_sig_span },
Expand Down Expand Up @@ -463,17 +467,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

fn lower_const_item(
&mut self,
ty: &Ty,
span: Span,
body: Option<&Expr>,
impl_trait_position: ImplTraitPosition,
) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(impl_trait_position));
(ty, self.lower_const_body(span, body))
}

#[instrument(level = "debug", skip(self))]
fn lower_use_tree(
&mut self,
Expand Down Expand Up @@ -808,7 +801,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ident,
generics,
ty,
expr,
body,
define_opaque,
..
}) => {
Expand All @@ -819,14 +812,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
|this| {
let ty = this
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
let body = expr.as_ref().map(|x| this.lower_const_body(i.span, Some(x)));

let body = body
.as_ref()
.map(|body| this.lower_const_item_rhs(attrs, Some(body), i.span));
hir::TraitItemKind::Const(ty, body)
},
);

if define_opaque.is_some() {
if expr.is_some() {
if body.is_some() {
self.lower_define_opaque(hir_id, &define_opaque);
} else {
self.dcx().span_err(
Expand All @@ -836,7 +830,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

(*ident, generics, kind, expr.is_some())
(*ident, generics, kind, body.is_some())
}
AssocItemKind::Fn(box Fn {
sig, ident, generics, body: None, define_opaque, ..
Expand Down Expand Up @@ -1021,7 +1015,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ident,
generics,
ty,
expr,
body,
define_opaque,
..
}) => (
Expand All @@ -1033,8 +1027,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|this| {
let ty = this
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
let body = this.lower_const_body(i.span, expr.as_deref());
this.lower_define_opaque(hir_id, &define_opaque);
let body = this.lower_const_item_rhs(attrs, body.as_ref(), i.span);
hir::ImplItemKind::Const(ty, body)
},
),
Expand Down
27 changes: 27 additions & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2303,6 +2303,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: ct_kind })
}

fn lower_const_item_rhs(
&mut self,
attrs: &[hir::Attribute],
rhs: Option<&ConstItemRhs>,
span: Span,
) -> hir::ConstItemRhs<'hir> {
match rhs {
Some(ConstItemRhs::TypeConst(anon)) => {
hir::ConstItemRhs::TypeConst(self.lower_anon_const_to_const_arg(anon))
}
None if attr::contains_name(attrs, sym::type_const) => {
let const_arg = ConstArg {
hir_id: self.next_id(),
kind: hir::ConstArgKind::Error(
DUMMY_SP,
self.dcx().span_delayed_bug(DUMMY_SP, "no block"),
),
};
hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg))
}
Some(ConstItemRhs::Body(body)) => {
hir::ConstItemRhs::Body(self.lower_const_body(span, Some(body)))
}
None => hir::ConstItemRhs::Body(self.lower_const_body(span, None)),
}
}

/// See [`hir::ConstArg`] for when to use this function vs
/// [`Self::lower_anon_const_to_anon_const`].
fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> &'hir hir::ConstArg<'hir> {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1236,9 +1236,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
});
}
ItemKind::Const(box ConstItem { defaultness, expr, .. }) => {
ItemKind::Const(box ConstItem { defaultness, body, .. }) => {
self.check_defaultness(item.span, *defaultness);
if expr.is_none() {
if body.is_none() {
self.dcx().emit_err(errors::ConstWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
Expand Down Expand Up @@ -1578,7 +1578,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {

if let AssocCtxt::Impl { .. } = ctxt {
match &item.kind {
AssocItemKind::Const(box ConstItem { expr: None, .. }) => {
AssocItemKind::Const(box ConstItem { body: None, .. }) => {
self.dcx().emit_err(errors::AssocConstWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,15 +213,15 @@ impl<'a> State<'a> {
ident,
generics,
ty,
expr,
body,
define_opaque,
}) => {
self.print_item_const(
*ident,
None,
generics,
ty,
expr.as_deref(),
body.as_ref().map(|ct| ct.expr()),
&item.vis,
ast::Safety::Default,
*defaultness,
Expand Down Expand Up @@ -566,15 +566,15 @@ impl<'a> State<'a> {
ident,
generics,
ty,
expr,
body,
define_opaque,
}) => {
self.print_item_const(
*ident,
None,
generics,
ty,
expr.as_deref(),
body.as_ref().map(|ct| ct.expr()),
vis,
ast::Safety::Default,
*defaultness,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/alloc_error_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub(crate) fn expand(

// Generate anonymous constant serving as container for the allocator methods.
let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new()));
let const_body = ecx.expr_block(ecx.block(span, stmts));
let const_body = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts)));
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
let const_item = if is_stmt {
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/global_allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub(crate) fn expand(

// Generate anonymous constant serving as container for the allocator methods.
let const_ty = ecx.ty(ty_span, TyKind::Tup(ThinVec::new()));
let const_body = ecx.expr_block(ecx.block(span, stmts));
let const_body = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts)));
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
let const_item = if is_stmt {
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_builtin_macros/src/proc_macro_harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,9 +385,9 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> Box<ast::Item> {
cx.attr_nested_word(sym::allow, sym::deprecated, span),
]);

let block = cx.expr_block(
let block = ast::ConstItemRhs::Body(cx.expr_block(
cx.block(span, thin_vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)]),
);
));

let anon_constant = cx.item_const(
span,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_builtin_macros/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ pub(crate) fn expand_test_or_bench(
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
define_opaque: None,
// test::TestDescAndFn {
expr: Some(
body: Some(ast::ConstItemRhs::Body(
cx.expr_struct(
sp,
test_path("TestDescAndFn"),
Expand Down Expand Up @@ -371,7 +371,7 @@ pub(crate) fn expand_test_or_bench(
field("testfn", test_fn), // }
],
), // }
),
)),
}
.into(),
),
Expand Down
14 changes: 11 additions & 3 deletions compiler/rustc_const_eval/src/check_consts/qualifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
// having basically only two use-cases that act in different ways.

use rustc_errors::ErrorGuaranteed;
use rustc_hir::LangItem;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::DefKind;
use rustc_hir::{LangItem, find_attr};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, AdtDef, Ty};
Expand Down Expand Up @@ -365,8 +367,14 @@ where
// check performed after the promotion. Verify that with an assertion.
assert!(promoted.is_none() || Q::ALLOW_PROMOTED);

// Don't peek inside trait associated constants.
if promoted.is_none() && cx.tcx.trait_of_assoc(def).is_none() {
// Avoid looking at attrs of anon consts as that will ICE
let is_type_const_item =
matches!(cx.tcx.def_kind(def), DefKind::Const | DefKind::AssocConst)
&& find_attr!(cx.tcx.get_all_attrs(def), AttributeKind::TypeConst(_));

// Don't peak inside trait associated consatnts, also `#[type_const] const` items
// don't have bodies so there's nothing to look at
if promoted.is_none() && cx.tcx.trait_of_assoc(def).is_none() && !is_type_const_item {
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def);

if !Q::in_qualifs(&qualifs) {
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_expand/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ impl<'a> ExtCtxt<'a> {
}
}

pub fn anon_const_block(&self, b: Box<ast::Block>) -> Box<ast::AnonConst> {
Box::new(self.anon_const(b.span, ast::ExprKind::Block(b, None)))
}

pub fn const_ident(&self, span: Span, ident: Ident) -> ast::AnonConst {
self.anon_const(span, ast::ExprKind::Path(None, self.path_ident(span, ident)))
}
Expand Down Expand Up @@ -722,7 +726,7 @@ impl<'a> ExtCtxt<'a> {
span: Span,
ident: Ident,
ty: Box<ast::Ty>,
expr: Box<ast::Expr>,
body: ast::ConstItemRhs,
) -> Box<ast::Item> {
let defaultness = ast::Defaultness::Final;
self.item(
Expand All @@ -735,7 +739,7 @@ impl<'a> ExtCtxt<'a> {
// FIXME(generic_const_items): Pass the generics as a parameter.
generics: ast::Generics::default(),
ty,
expr: Some(expr),
body: Some(body),
define_opaque: None,
}
.into(),
Expand Down
Loading
Loading