Skip to content

[WIP] mgca: Add ConstArg representation for const items #139558

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
Draft
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3617,7 +3617,7 @@ pub struct ConstItem {
pub ident: Ident,
pub generics: Generics,
pub ty: P<Ty>,
pub expr: Option<P<Expr>>,
pub body: Option<P<AnonConst>>,
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1331,12 +1331,12 @@ impl WalkItemKind for AssocItemKind {
}

fn walk_const_item<T: MutVisitor>(vis: &mut T, item: &mut ConstItem) {
let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item;
let ConstItem { defaultness, ident, generics, ty, body, define_opaque } = item;
visit_defaultness(vis, defaultness);
vis.visit_ident(ident);
vis.visit_generics(generics);
vis.visit_ty(ty);
visit_opt(expr, |expr| vis.visit_expr(expr));
visit_opt(body, |body| vis.visit_anon_const(body));
walk_define_opaques(vis, define_opaque);
}

Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,13 +388,13 @@ impl WalkItemKind for ItemKind {
ident,
generics,
ty,
expr,
body,
define_opaque,
}) => {
try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_ty(ty));
visit_opt!(visitor, visit_expr, expr);
visit_opt!(visitor, visit_anon_const, body);
try_visit!(walk_define_opaques(visitor, define_opaque));
}
ItemKind::Fn(func) => {
Expand Down Expand Up @@ -990,13 +990,13 @@ impl WalkItemKind for AssocItemKind {
ident,
generics,
ty,
expr,
body,
define_opaque,
}) => {
try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_ty(ty));
visit_opt!(visitor, visit_expr, expr);
visit_opt!(visitor, visit_anon_const, body);
try_visit!(walk_define_opaques(visitor, define_opaque));
}
AssocItemKind::Fn(func) => {
Expand Down
48 changes: 25 additions & 23 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,37 +182,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(ident, ty, *m, 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(body.as_deref().unwrap());
(ty, body)
},
);
self.lower_define_opaque(hir_id, &define_opaque);
hir::ItemKind::Const(ident, ty, generics, body_id)
hir::ItemKind::Const(ident, ty, generics, body)
}
ItemKind::Fn(box Fn {
sig: FnSig { decl, header, span: fn_sig_span },
Expand Down Expand Up @@ -492,15 +496,14 @@ 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))
fn lower_const_item(&mut self, body: &AnonConst) -> &'hir hir::ConstArg<'hir> {
let mgca = self.tcx.features().min_generic_const_args();
if mgca && let Some(ct_arg) = self.try_lower_as_const_path(body) {
return ct_arg;
}
let anon = self.lower_anon_const_to_anon_const(body);
self.arena
.alloc(hir::ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(anon) })
}

#[instrument(level = "debug", skip(self))]
Expand Down Expand Up @@ -798,7 +801,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ident,
generics,
ty,
expr,
body,
define_opaque,
..
}) => {
Expand All @@ -809,14 +812,13 @@ 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_const_item(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 @@ -826,7 +828,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 @@ -990,7 +992,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ident,
generics,
ty,
expr,
body,
define_opaque,
..
}) => (
Expand All @@ -1002,8 +1004,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(body.as_deref().unwrap());
hir::ImplItemKind::Const(ty, body)
},
),
Expand Down
16 changes: 16 additions & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2084,6 +2084,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}

/// Assumes mgca feature is enabled.
fn try_lower_as_const_path(&mut self, body: &AnonConst) -> Option<&'hir hir::ConstArg<'hir>> {
let ExprKind::Path(qself, path) = &body.value.kind else { return None };
let qpath = self.lower_qpath(
body.value.id,
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
let ct_kind = hir::ConstArgKind::Path(qpath);
Some(self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: ct_kind }))
}

/// Used when lowering a type argument that turned out to actually be a const argument.
///
/// Only use for that purpose since otherwise it will create a duplicate def.
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 @@ -1084,9 +1084,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
_ => visit::walk_item(self, item),
}
}
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 @@ -1436,7 +1436,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 @@ -214,15 +214,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 @@ -563,15 +563,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 @@ -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 = 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(P(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 @@ -48,7 +48,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(P(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 @@ -379,7 +379,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
i
});

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 @@ -294,8 +294,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(P(ast::AnonConst {
id: ast::DUMMY_NODE_ID,
value: cx.expr_struct(
sp,
test_path("TestDescAndFn"),
thin_vec![
Expand Down Expand Up @@ -376,7 +377,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 @@ -368,8 +369,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_item(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
23 changes: 23 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 @@ -294,6 +294,29 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
)
},
);
} else 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_val(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:?}")
}
}
}

tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
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 @@ -105,6 +105,10 @@ impl<'a> ExtCtxt<'a> {
}
}

pub fn anon_const_block(&self, b: P<ast::Block>) -> P<ast::AnonConst> {
P(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 @@ -711,7 +715,7 @@ impl<'a> ExtCtxt<'a> {
span: Span,
ident: Ident,
ty: P<ast::Ty>,
expr: P<ast::Expr>,
body: P<ast::AnonConst>,
) -> P<ast::Item> {
let defaultness = ast::Defaultness::Final;
self.item(
Expand All @@ -724,7 +728,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