Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3754,7 +3754,7 @@ pub struct ConstItem {
pub ident: Ident,
pub generics: Generics,
pub ty: Box<Ty>,
pub expr: Option<Box<Expr>>,
pub body: Option<Box<AnonConst>>,
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
}

Expand Down
43 changes: 18 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_anon_const_to_const_arg(body.as_deref().unwrap());
(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,14 @@ 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_deref().map(|body| this.lower_anon_const_to_const_arg(body));
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 +829,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 +1014,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ident,
generics,
ty,
expr,
body,
define_opaque,
..
}) => (
Expand All @@ -1033,8 +1026,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_anon_const_to_const_arg(body.as_deref().unwrap());
hir::ImplItemKind::Const(ty, body)
},
),
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_deref().map(|ct| &*ct.value),
&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_deref().map(|ct| &*ct.value),
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 @@ -42,7 +42,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 = ecx.anon_const_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 = ecx.anon_const_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/proc_macro_harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ 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 = cx.anon_const_block(
cx.block(span, thin_vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)]),
);

Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_builtin_macros/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,9 @@ 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(
cx.expr_struct(
body: Some(Box::new(ast::AnonConst {
id: ast::DUMMY_NODE_ID,
value: cx.expr_struct(
sp,
test_path("TestDescAndFn"),
thin_vec![
Expand Down Expand Up @@ -371,7 +372,7 @@ pub(crate) fn expand_test_or_bench(
field("testfn", test_fn), // }
],
), // }
),
})),
}
.into(),
),
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_const_eval/src/check_consts/qualifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

use rustc_errors::ErrorGuaranteed;
use rustc_hir::LangItem;
use rustc_hir::def::DefKind;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, AdtDef, Ty};
Expand Down Expand Up @@ -366,8 +367,12 @@ 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() {
// Const items don't themselves have bodies -- they will have either a path or an anon const instead.
// FIXME(mgca): is this really the right behavior? should we return the qualifs of the anon const body instead?
// (note also that original code ignored trait assoc items)
if promoted.is_none()
&& !matches!(cx.tcx.def_kind(def), DefKind::Const | DefKind::AssocConst)
{
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def);

if !Q::in_qualifs(&qualifs) {
Expand Down
25 changes: 25 additions & 0 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,31 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
trace!("const eval: {:?} ({})", key, instance);
}

if let ty::InstanceKind::Item(def_id) = key.value.instance.def
&& matches!(tcx.def_kind(def_id), DefKind::Const | DefKind::AssocConst)
{
let ct = tcx.const_of_item(def_id).instantiate(tcx, key.value.instance.args);
match ct.kind() {
ty::ConstKind::Unevaluated(_) => {
return Err(ErrorHandled::TooGeneric(DUMMY_SP));
}
ty::ConstKind::Value(cv) => return Ok(tcx.valtree_to_const_alloc(cv)),
ty::ConstKind::Error(guar) => {
return Err(ErrorHandled::Reported(
ReportedErrorInfo::const_eval_error(guar),
DUMMY_SP,
));
}
ty::ConstKind::Expr(_) => return Err(ErrorHandled::TooGeneric(DUMMY_SP)),
ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) => {
return Err(ErrorHandled::TooGeneric(DUMMY_SP));
}
ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) => {
bug!("unexpected constant {ct:?}")
}
}
}

eval_in_interpreter(tcx, key.value, key.typing_env)
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/const_eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub use self::error::*;
pub use self::eval_queries::*;
pub use self::fn_queries::*;
pub use self::machine::*;
pub(crate) use self::valtrees::{eval_to_valtree, valtree_to_const_value};
pub(crate) use self::valtrees::{eval_to_valtree, valtree_to_const_alloc, valtree_to_const_value};

// We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.
const VALTREE_MAX_NODES: usize = 100000;
Expand Down
16 changes: 15 additions & 1 deletion compiler/rustc_const_eval/src/const_eval/valtrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use rustc_middle::{bug, mir};
use rustc_span::DUMMY_SP;
use tracing::{debug, instrument, trace};

use super::VALTREE_MAX_NODES;
use super::eval_queries::{mk_eval_cx_to_read_const_val, op_to_const};
use super::machine::CompileTimeInterpCx;
use super::{InterpretationResult as _, VALTREE_MAX_NODES};
use crate::const_eval::CanAccessMutGlobal;
use crate::interpret::{
ImmTy, Immediate, InternKind, MPlaceTy, MemPlaceMeta, MemoryKind, PlaceTy, Projectable, Scalar,
Expand Down Expand Up @@ -349,6 +349,20 @@ pub fn valtree_to_const_value<'tcx>(
}
}

#[instrument(skip(tcx), level = "debug", ret)]
pub(crate) fn valtree_to_const_alloc<'tcx>(
tcx: TyCtxt<'tcx>,
env: ty::TypingEnv<'tcx>,
val: ty::Value<'tcx>,
) -> mir::ConstAlloc<'tcx> {
let mut ecx = mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, env, CanAccessMutGlobal::No);
let layout = ecx.layout_of(val.ty).unwrap();
let mplace = create_valtree_place(&mut ecx, layout, val.valtree);
valtree_into_mplace(&mut ecx, &mplace, val.valtree);
intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &mplace).unwrap();
mir::ConstAlloc::make_result(mplace, &mut ecx)
}

/// Put a valtree into memory and return a reference to that.
fn valtree_to_ref<'tcx>(
ecx: &mut CompileTimeInterpCx<'tcx>,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_const_eval/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub fn provide(providers: &mut Providers) {
const_eval::try_destructure_mir_constant_for_user_output;
providers.valtree_to_const_val =
|tcx, cv| const_eval::valtree_to_const_value(tcx, ty::TypingEnv::fully_monomorphized(), cv);
providers.valtree_to_const_alloc =
|tcx, cv| const_eval::valtree_to_const_alloc(tcx, ty::TypingEnv::fully_monomorphized(), cv);
providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
};
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: Box<ast::AnonConst>,
) -> 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