Skip to content
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

Implement generic const items #113522

Merged
merged 9 commits into from
Jul 28, 2023
Merged
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: 2 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2947,6 +2947,7 @@ pub struct StaticItem {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct ConstItem {
pub defaultness: Defaultness,
pub generics: Generics,
pub ty: P<Ty>,
pub expr: Option<P<Expr>>,
}
Expand Down Expand Up @@ -3058,6 +3059,7 @@ impl ItemKind {
match self {
Self::Fn(box Fn { generics, .. })
| Self::TyAlias(box TyAlias { generics, .. })
| Self::Const(box ConstItem { generics, .. })
| Self::Enum(_, generics)
| Self::Struct(_, generics)
| Self::Union(_, generics)
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 @@ -1149,10 +1149,11 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
}

fn visit_const_item<T: MutVisitor>(
ConstItem { defaultness, ty, expr }: &mut ConstItem,
ConstItem { defaultness, generics, ty, expr }: &mut ConstItem,
visitor: &mut T,
) {
visit_defaultness(defaultness, visitor);
visitor.visit_generics(generics);
visitor.visit_ty(ty);
visit_opt(expr, |expr| visitor.visit_expr(expr));
}
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
match &item.kind {
ItemKind::ExternCrate(_) => {}
ItemKind::Use(use_tree) => visitor.visit_use_tree(use_tree, item.id, false),
ItemKind::Static(box StaticItem { ty, mutability: _, expr })
| ItemKind::Const(box ConstItem { ty, expr, .. }) => {
ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
visitor.visit_ty(ty);
walk_list!(visitor, visit_expr, expr);
}
ItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
visitor.visit_generics(generics);
visitor.visit_ty(ty);
walk_list!(visitor, visit_expr, expr);
}
Expand Down Expand Up @@ -677,7 +681,8 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
visitor.visit_ident(ident);
walk_list!(visitor, visit_attribute, attrs);
match kind {
AssocItemKind::Const(box ConstItem { ty, expr, .. }) => {
AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
visitor.visit_generics(generics);
visitor.visit_ty(ty);
walk_list!(visitor, visit_expr, expr);
}
Expand Down
55 changes: 39 additions & 16 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
hir::ItemKind::Static(ty, *m, body_id)
}
ItemKind::Const(box ast::ConstItem { ty, expr, .. }) => {
let (ty, body_id) = self.lower_const_item(ty, span, expr.as_deref());
hir::ItemKind::Const(ty, body_id)
ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
let (generics, (ty, body_id)) = self.lower_generics(
generics,
Const::No,
id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| this.lower_const_item(ty, span, expr.as_deref()),
);
hir::ItemKind::Const(ty, generics, body_id)
}
ItemKind::Fn(box Fn {
sig: FnSig { decl, header, span: fn_sig_span },
Expand Down Expand Up @@ -715,11 +721,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
let trait_item_def_id = hir_id.expect_owner();

let (generics, kind, has_default) = match &i.kind {
AssocItemKind::Const(box ConstItem { ty, expr, .. }) => {
let ty =
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
let body = expr.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
(hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some())
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
let (generics, kind) = self.lower_generics(
&generics,
Const::No,
fmease marked this conversation as resolved.
Show resolved Hide resolved
i.id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|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)));

hir::TraitItemKind::Const(ty, body)
},
);
(generics, kind, expr.is_some())
}
AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => {
let asyncness = sig.header.asyncness;
Expand Down Expand Up @@ -817,14 +835,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_attrs(hir_id, &i.attrs);

let (generics, kind) = match &i.kind {
AssocItemKind::Const(box ConstItem { ty, expr, .. }) => {
let ty =
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
(
hir::Generics::empty(),
hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
)
}
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
&generics,
Const::No,
i.id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
let ty = this
.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
let body = this.lower_const_body(i.span, expr.as_deref());

hir::ImplItemKind::Const(ty, body)
},
),
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
self.current_item = Some(i.span);
let asyncness = sig.header.asyncness;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(const_closures, "const closures are experimental");
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
gate_all!(explicit_tail_calls, "`become` expression is experimental");
gate_all!(generic_const_items, "generic const items are experimental");

if !visitor.features.negative_bounds {
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {
Expand Down
35 changes: 26 additions & 9 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@ impl<'a> State<'a> {
ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
}
ast::ForeignItemKind::Static(ty, mutbl, body) => {
let def = ast::Defaultness::Final;
self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
}
ast::ForeignItemKind::Static(ty, mutbl, body) => self.print_item_const(
ident,
Some(*mutbl),
&ast::Generics::default(),
ty,
body.as_deref(),
vis,
ast::Defaultness::Final,
),
ast::ForeignItemKind::TyAlias(box ast::TyAlias {
defaultness,
generics,
Expand Down Expand Up @@ -67,6 +72,7 @@ impl<'a> State<'a> {
&mut self,
ident: Ident,
mutbl: Option<ast::Mutability>,
generics: &ast::Generics,
ty: &ast::Ty,
body: Option<&ast::Expr>,
vis: &ast::Visibility,
Expand All @@ -82,6 +88,7 @@ impl<'a> State<'a> {
};
self.word_space(leading);
self.print_ident(ident);
self.print_generic_params(&generics.params);
self.word_space(":");
self.print_type(ty);
if body.is_some() {
Expand All @@ -92,6 +99,7 @@ impl<'a> State<'a> {
self.word_space("=");
self.print_expr(body);
}
self.print_where_clause(&generics.where_clause);
self.word(";");
self.end(); // end the outer cbox
}
Expand Down Expand Up @@ -158,20 +166,21 @@ impl<'a> State<'a> {
self.word(";");
}
ast::ItemKind::Static(box StaticItem { ty, mutability: mutbl, expr: body }) => {
let def = ast::Defaultness::Final;
self.print_item_const(
item.ident,
Some(*mutbl),
&ast::Generics::default(),
ty,
body.as_deref(),
&item.vis,
def,
ast::Defaultness::Final,
);
}
ast::ItemKind::Const(box ast::ConstItem { defaultness, ty, expr }) => {
ast::ItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
self.print_item_const(
item.ident,
None,
generics,
ty,
expr.as_deref(),
&item.vis,
Expand Down Expand Up @@ -515,8 +524,16 @@ impl<'a> State<'a> {
ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
}
ast::AssocItemKind::Const(box ast::ConstItem { defaultness, ty, expr }) => {
self.print_item_const(ident, None, ty, expr.as_deref(), vis, *defaultness);
ast::AssocItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
self.print_item_const(
ident,
None,
generics,
ty,
expr.as_deref(),
vis,
*defaultness,
);
}
ast::AssocItemKind::Type(box ast::TyAlias {
defaultness,
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 @@ -255,6 +255,7 @@ pub fn expand_test_or_bench(
ast::ItemKind::Const(
ast::ConstItem {
defaultness: ast::Defaultness::Final,
generics: ast::Generics::default(),
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
// test::TestDescAndFn {
expr: Some(
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_expand/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,16 @@ impl<'a> ExtCtxt<'a> {
span,
name,
AttrVec::new(),
ast::ItemKind::Const(ast::ConstItem { defaultness, ty, expr: Some(expr) }.into()),
ast::ItemKind::Const(
ast::ConstItem {
defaultness,
// FIXME(generic_const_items): Pass the generics as a parameter.
generics: ast::Generics::default(),
ty,
expr: Some(expr),
}
.into(),
),
)
}

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,8 @@ declare_features! (
(incomplete, generic_associated_types_extended, "1.61.0", Some(95451), None),
/// Allows non-trivial generic constants which have to have wfness manually propagated to callers
(incomplete, generic_const_exprs, "1.56.0", Some(76560), None),
/// Allows generic parameters and where-clauses on free & associated const items.
(incomplete, generic_const_items, "CURRENT_RUSTC_VERSION", Some(113521), None),
/// Allows using `..=X` as a patterns in slices.
(active, half_open_range_patterns_in_slices, "1.66.0", Some(67264), None),
/// Allows `if let` guard in match arms.
Expand Down
23 changes: 14 additions & 9 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3130,9 +3130,9 @@ impl<'hir> Item<'hir> {
}
/// Expect an [`ItemKind::Const`] or panic.
#[track_caller]
pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) {
let ItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") };
(ty, body)
pub fn expect_const(&self) -> (&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId) {
let ItemKind::Const(ty, gen, body) = self.kind else { self.expect_failed("a constant") };
(ty, gen, body)
}
/// Expect an [`ItemKind::Fn`] or panic.
#[track_caller]
Expand Down Expand Up @@ -3319,7 +3319,7 @@ pub enum ItemKind<'hir> {
/// A `static` item.
Static(&'hir Ty<'hir>, Mutability, BodyId),
/// A `const` item.
Const(&'hir Ty<'hir>, BodyId),
Const(&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
/// A function declaration.
Fn(FnSig<'hir>, &'hir Generics<'hir>, BodyId),
/// A MBE macro definition (`macro_rules!` or `macro`).
Expand Down Expand Up @@ -3372,6 +3372,7 @@ impl ItemKind<'_> {
Some(match *self {
ItemKind::Fn(_, ref generics, _)
| ItemKind::TyAlias(_, ref generics)
| ItemKind::Const(_, ref generics, _)
| ItemKind::OpaqueTy(OpaqueTy { ref generics, .. })
| ItemKind::Enum(_, ref generics)
| ItemKind::Struct(_, ref generics)
Expand Down Expand Up @@ -3567,7 +3568,9 @@ impl<'hir> OwnerNode<'hir> {
match self {
OwnerNode::Item(Item {
kind:
ItemKind::Static(_, _, body) | ItemKind::Const(_, body) | ItemKind::Fn(_, _, body),
ItemKind::Static(_, _, body)
| ItemKind::Const(_, _, body)
| ItemKind::Fn(_, _, body),
..
})
| OwnerNode::TraitItem(TraitItem {
Expand Down Expand Up @@ -3770,9 +3773,9 @@ impl<'hir> Node<'hir> {
pub fn ty(self) -> Option<&'hir Ty<'hir>> {
match self {
Node::Item(it) => match it.kind {
ItemKind::TyAlias(ty, _) | ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => {
Some(ty)
}
ItemKind::TyAlias(ty, _)
| ItemKind::Static(ty, _, _)
| ItemKind::Const(ty, _, _) => Some(ty),
_ => None,
},
Node::TraitItem(it) => match it.kind {
Expand Down Expand Up @@ -3800,7 +3803,9 @@ impl<'hir> Node<'hir> {
match self {
Node::Item(Item {
kind:
ItemKind::Static(_, _, body) | ItemKind::Const(_, body) | ItemKind::Fn(_, _, body),
ItemKind::Static(_, _, body)
| ItemKind::Const(_, _, body)
| ItemKind::Fn(_, _, body),
..
})
| Node::TraitItem(TraitItem {
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,11 +467,17 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
ItemKind::Use(ref path, _) => {
visitor.visit_use(path, item.hir_id());
}
ItemKind::Static(ref typ, _, body) | ItemKind::Const(ref typ, body) => {
ItemKind::Static(ref typ, _, body) => {
visitor.visit_id(item.hir_id());
visitor.visit_ty(typ);
visitor.visit_nested_body(body);
}
ItemKind::Const(ref typ, ref generics, body) => {
visitor.visit_id(item.hir_id());
visitor.visit_ty(typ);
visitor.visit_generics(generics);
visitor.visit_nested_body(body);
}
ItemKind::Fn(ref sig, ref generics, body_id) => {
visitor.visit_id(item.hir_id());
visitor.visit_fn(
Expand Down
Loading