Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
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_item_body_to_const_arg(body.as_deref());
(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_deref()
.map(|body| this.lower_item_body_to_const_arg(Some(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 +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_item_body_to_const_arg(body.as_deref());
hir::ImplItemKind::Const(ty, body)
},
),
Expand Down
32 changes: 30 additions & 2 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2303,14 +2303,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: ct_kind })
}

/// See [`hir::ConstArg`] for when to use this function vs
/// [`Self::lower_anon_const_to_anon_const`].
fn lower_item_body_to_const_arg(
&mut self,
anon: Option<&AnonConst>,
) -> &'hir hir::ConstArg<'hir> {
let Some(anon) = anon else {
let const_arg = ConstArg {
hir_id: self.next_id(),
kind: hir::ConstArgKind::Error(
DUMMY_SP,
self.dcx().span_delayed_bug(DUMMY_SP, "no block"),
),
};
return self.arena.alloc(const_arg);
};

self.arena.alloc(self.lower_anon_const_to_const_arg_direct(
anon,
!self.tcx.features().min_generic_const_args(),
))
}

/// 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> {
self.arena.alloc(self.lower_anon_const_to_const_arg_direct(anon))
self.arena.alloc(self.lower_anon_const_to_const_arg_direct(anon, false))
}

#[instrument(level = "debug", skip(self))]
fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> {
fn lower_anon_const_to_const_arg_direct(
&mut self,
anon: &AnonConst,
always_lower_to_anon_const: bool,
) -> hir::ConstArg<'hir> {
let tcx = self.tcx;
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
Expand All @@ -2329,6 +2356,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&& path.is_potential_trivial_const_arg(tcx.features().min_generic_const_args())
&& (tcx.features().min_generic_const_args()
|| matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _))))
&& !always_lower_to_anon_const
{
let qpath = self.lower_qpath(
expr.id,
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
24 changes: 20 additions & 4 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,12 +367,27 @@ 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() {
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def);
// If we want the qualifs of a const item, fudge the def to be for the
// const's body instead.
let def_kind = cx.tcx.def_kind(def);
let fudged_def = if let DefKind::Const | DefKind::AssocConst = def_kind {
let const_body = cx.tcx.const_of_item(def).instantiate_identity();
match const_body.kind() {
ty::ConstKind::Unevaluated(uv) => Some(uv.def),
ty::ConstKind::Error(_) => None,
_ => bug!("unexpected non anon const const body"),
}
} else {
Some(def)
};

if let Some(fudged_def) = fudged_def {
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(fudged_def);

if !Q::in_qualifs(&qualifs) {
return false;
if !Q::in_qualifs(&qualifs) {
return false;
}
}

// Just in case the type is more specific than
Expand Down
31 changes: 31 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,37 @@ 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(uv) => {
assert_eq!(tcx.def_kind(uv.def), DefKind::AnonConst);

let id = GlobalId {
instance: ty::Instance { def: ty::InstanceKind::Item(uv.def), args: uv.args },
promoted: None,
};
return eval_in_interpreter(tcx, id, key.typing_env);
}
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
Loading
Loading