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 8 commits into
base: master
Choose a base branch
from
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
5 changes: 5 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3617,6 +3617,11 @@ pub struct ConstItem {
pub ident: Ident,
pub generics: Generics,
pub ty: P<Ty>,
/// A [`NodeId`] that can be used for the body of the const, independently of the ID
/// of the body's root expression.
// HACK(mgca): this is potentially temporary, tbd, in order to create defs for const bodies.
// FIXME(mgca): maybe merge this with expr since their Options should be in sync
pub body_id: Option<NodeId>,
pub expr: Option<P<Expr>>,
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1331,11 +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_id, expr, define_opaque } = item;
visit_defaultness(vis, defaultness);
vis.visit_ident(ident);
vis.visit_generics(generics);
vis.visit_ty(ty);
visit_opt(body_id, |body_id| vis.visit_id(body_id));
visit_opt(expr, |expr| vis.visit_expr(expr));
walk_define_opaques(vis, define_opaque);
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ impl WalkItemKind for ItemKind {
ident,
generics,
ty,
body_id: _,
expr,
define_opaque,
}) => {
Expand Down Expand Up @@ -990,6 +991,7 @@ impl WalkItemKind for AssocItemKind {
ident,
generics,
ty,
body_id: _,
expr,
define_opaque,
}) => {
Expand Down
55 changes: 40 additions & 15 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,37 +182,43 @@ 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,
body_id,
expr,
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(span, body_id.unwrap(), expr.as_deref().unwrap());
Copy link
Member Author

Choose a reason for hiding this comment

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

These new unwraps should be correct in theory since an error should've already been emitted, but they might ICE if the compiler didn't stop earlier. It might be a good idea to add ConstArgKind::Err and use delayed_span_bug.

(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 @@ -494,13 +500,25 @@ 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))
body_id: NodeId,
body_expr: &Expr,
) -> &'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_expr) {
return ct_arg;
}
let anon = self.arena.alloc(self.with_new_scopes(span, |this| {
let body = this.lower_const_body(span, Some(body_expr));
hir::AnonConst {
hir_id: this.lower_node_id(body_id),
def_id: this.local_def_id(body_id),
body,
span,
}
}));
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,6 +816,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ident,
generics,
ty,
body_id,
expr,
define_opaque,
..
Expand All @@ -809,8 +828,9 @@ 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_id
.zip(expr.as_deref())
.map(|(b_id, b_ex)| this.lower_const_item(i.span, b_id, b_ex));
hir::TraitItemKind::Const(ty, body)
},
);
Expand Down Expand Up @@ -990,6 +1010,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ident,
generics,
ty,
body_id,
expr,
define_opaque,
..
Expand All @@ -1002,8 +1023,12 @@ 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(
i.span,
body_id.unwrap(),
expr.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, expr: &Expr) -> Option<&'hir hir::ConstArg<'hir>> {
let ExprKind::Path(qself, path) = &expr.kind else { return None };
let qpath = self.lower_qpath(
expr.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
2 changes: 2 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ impl<'a> State<'a> {
ident,
generics,
ty,
body_id: _,
expr,
define_opaque,
}) => {
Expand Down Expand Up @@ -563,6 +564,7 @@ impl<'a> State<'a> {
ident,
generics,
ty,
body_id: _,
expr,
define_opaque,
}) => {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_builtin_macros/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ pub(crate) fn expand_test_or_bench(
generics: ast::Generics::default(),
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
define_opaque: None,
body_id: Some(ast::DUMMY_NODE_ID),
// test::TestDescAndFn {
expr: Some(
cx.expr_struct(
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
1 change: 1 addition & 0 deletions compiler/rustc_expand/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,7 @@ impl<'a> ExtCtxt<'a> {
// FIXME(generic_const_items): Pass the generics as a parameter.
generics: ast::Generics::default(),
ty,
body_id: Some(ast::DUMMY_NODE_ID),
expr: Some(expr),
define_opaque: None,
}
Expand Down
52 changes: 29 additions & 23 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3094,7 +3094,7 @@ impl<'hir> TraitItem<'hir> {
}

expect_methods_self_kind! {
expect_const, (&'hir Ty<'hir>, Option<BodyId>),
expect_const, (&'hir Ty<'hir>, Option<&'hir ConstArg<'hir>>),
TraitItemKind::Const(ty, body), (ty, *body);

expect_fn, (&FnSig<'hir>, &TraitFn<'hir>),
Expand All @@ -3119,7 +3119,7 @@ pub enum TraitFn<'hir> {
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum TraitItemKind<'hir> {
/// An associated constant with an optional value (otherwise `impl`s must contain a value).
Const(&'hir Ty<'hir>, Option<BodyId>),
Const(&'hir Ty<'hir>, Option<&'hir ConstArg<'hir>>),
/// An associated function with an optional body.
Fn(FnSig<'hir>, TraitFn<'hir>),
/// An associated type with (possibly empty) bounds and optional concrete
Expand Down Expand Up @@ -3169,9 +3169,9 @@ impl<'hir> ImplItem<'hir> {
}

expect_methods_self_kind! {
expect_const, (&'hir Ty<'hir>, BodyId), ImplItemKind::Const(ty, body), (ty, *body);
expect_fn, (&FnSig<'hir>, BodyId), ImplItemKind::Fn(ty, body), (ty, *body);
expect_type, &'hir Ty<'hir>, ImplItemKind::Type(ty), ty;
expect_const, (&'hir Ty<'hir>, &'hir ConstArg<'hir>), ImplItemKind::Const(ty, body), (ty, body);
expect_fn, (&FnSig<'hir>, BodyId), ImplItemKind::Fn(ty, body), (ty, *body);
expect_type, &'hir Ty<'hir>, ImplItemKind::Type(ty), ty;
}
}

Expand All @@ -3180,7 +3180,7 @@ impl<'hir> ImplItem<'hir> {
pub enum ImplItemKind<'hir> {
/// An associated constant of the given type, set to the constant result
/// of the expression.
Const(&'hir Ty<'hir>, BodyId),
Const(&'hir Ty<'hir>, &'hir ConstArg<'hir>),
/// An associated function implementation with the given signature and body.
Fn(FnSig<'hir>, BodyId),
/// An associated type.
Expand Down Expand Up @@ -4107,8 +4107,8 @@ impl<'hir> Item<'hir> {
expect_static, (Ident, &'hir Ty<'hir>, Mutability, BodyId),
ItemKind::Static(ident, ty, mutbl, body), (*ident, ty, *mutbl, *body);

expect_const, (Ident, &'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
ItemKind::Const(ident, ty, generics, body), (*ident, ty, generics, *body);
expect_const, (Ident, &'hir Ty<'hir>, &'hir Generics<'hir>, &'hir ConstArg<'hir>),
ItemKind::Const(ident, ty, generics, ct_arg), (*ident, ty, generics, ct_arg);

expect_fn, (Ident, &FnSig<'hir>, &'hir Generics<'hir>, BodyId),
ItemKind::Fn { ident, sig, generics, body, .. }, (*ident, sig, generics, *body);
Expand Down Expand Up @@ -4278,7 +4278,7 @@ pub enum ItemKind<'hir> {
/// A `static` item.
Static(Ident, &'hir Ty<'hir>, Mutability, BodyId),
/// A `const` item.
Const(Ident, &'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
Const(Ident, &'hir Ty<'hir>, &'hir Generics<'hir>, &'hir ConstArg<'hir>),
/// A function declaration.
Fn {
ident: Ident,
Expand Down Expand Up @@ -4576,17 +4576,29 @@ impl<'hir> OwnerNode<'hir> {
OwnerNode::Item(Item {
kind:
ItemKind::Static(_, _, _, body)
| ItemKind::Const(_, _, _, body)
| ItemKind::Const(
..,
ConstArg { kind: ConstArgKind::Anon(AnonConst { body, .. }), .. },
)
| ItemKind::Fn { body, .. },
..
})
| OwnerNode::TraitItem(TraitItem {
kind:
TraitItemKind::Fn(_, TraitFn::Provided(body)) | TraitItemKind::Const(_, Some(body)),
TraitItemKind::Fn(_, TraitFn::Provided(body))
| TraitItemKind::Const(
_,
Some(ConstArg { kind: ConstArgKind::Anon(AnonConst { body, .. }), .. }),
),
..
})
| OwnerNode::ImplItem(ImplItem {
kind: ImplItemKind::Fn(_, body) | ImplItemKind::Const(_, body),
kind:
ImplItemKind::Fn(_, body)
| ImplItemKind::Const(
_,
ConstArg { kind: ConstArgKind::Anon(AnonConst { body, .. }), .. },
),
..
}) => Some(*body),
_ => None,
Expand Down Expand Up @@ -4832,23 +4844,17 @@ impl<'hir> Node<'hir> {
match self {
Node::Item(Item {
owner_id,
kind:
ItemKind::Const(_, _, _, body)
| ItemKind::Static(.., body)
| ItemKind::Fn { body, .. },
kind: ItemKind::Static(.., body) | ItemKind::Fn { body, .. },
..
})
| Node::TraitItem(TraitItem {
owner_id,
kind:
TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)),
kind: TraitItemKind::Fn(_, TraitFn::Provided(body)),
..
})
| Node::ImplItem(ImplItem {
owner_id,
kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body),
..
}) => Some((owner_id.def_id, *body)),
| Node::ImplItem(ImplItem { owner_id, kind: ImplItemKind::Fn(_, body), .. }) => {
Some((owner_id.def_id, *body))
}

Node::Item(Item {
owner_id, kind: ItemKind::GlobalAsm { asm: _, fake_body }, ..
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_ty_unambig(typ));
try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_nested_body(body));
try_visit!(visitor.visit_const_arg_unambig(body));
}
ItemKind::Fn { ident, sig, generics, body: body_id, .. } => {
try_visit!(visitor.visit_ident(ident));
Expand Down Expand Up @@ -1168,7 +1168,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(
match *kind {
TraitItemKind::Const(ref ty, default) => {
try_visit!(visitor.visit_ty_unambig(ty));
visit_opt!(visitor, visit_nested_body, default);
visit_opt!(visitor, visit_const_arg_unambig, default);
}
TraitItemKind::Fn(ref sig, TraitFn::Required(param_idents)) => {
try_visit!(visitor.visit_fn_decl(sig.decl));
Expand Down Expand Up @@ -1226,7 +1226,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(
match *kind {
ImplItemKind::Const(ref ty, body) => {
try_visit!(visitor.visit_ty_unambig(ty));
visitor.visit_nested_body(body)
visitor.visit_const_arg_unambig(body)
}
ImplItemKind::Fn(ref sig, body_id) => visitor.visit_fn(
FnKind::Method(impl_item.ident, sig),
Expand Down
Loading
Loading