Skip to content
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
37 changes: 27 additions & 10 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3869,27 +3869,44 @@ pub struct ConstItem {
pub ident: Ident,
pub generics: Generics,
pub ty: Box<Ty>,
pub rhs: Option<ConstItemRhs>,
pub rhs_kind: ConstItemRhsKind,
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
}

#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum ConstItemRhs {
TypeConst(AnonConst),
Body(Box<Expr>),
pub enum ConstItemRhsKind {
Body { rhs: Option<Box<Expr>> },
TypeConst { rhs: Option<AnonConst> },
}

impl ConstItemRhs {
pub fn span(&self) -> Span {
self.expr().span
impl ConstItemRhsKind {
pub fn new_body(rhs: Box<Expr>) -> Self {
Self::Body { rhs: Some(rhs) }
}

pub fn span(&self) -> Option<Span> {
Some(self.expr()?.span)
}

pub fn expr(&self) -> Option<&Expr> {
match self {
Self::Body { rhs: Some(body) } => Some(&body),
Self::TypeConst { rhs: Some(anon) } => Some(&anon.value),
_ => None,
}
}

pub fn expr(&self) -> &Expr {
pub fn has_expr(&self) -> bool {
match self {
ConstItemRhs::TypeConst(anon_const) => &anon_const.value,
ConstItemRhs::Body(expr) => expr,
Self::Body { rhs: Some(_) } => true,
Self::TypeConst { rhs: Some(_) } => true,
_ => false,
}
}

pub fn is_type_const(&self) -> bool {
matches!(self, &Self::TypeConst { .. })
}
}

#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ macro_rules! common_visitor_and_walkers {
Const,
ConstBlockItem,
ConstItem,
ConstItemRhs,
ConstItemRhsKind,
Defaultness,
Delegation,
DelegationMac,
Expand Down
35 changes: 24 additions & 11 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ident,
generics,
ty,
rhs,
rhs_kind,
define_opaque,
}) => {
let ident = self.lower_ident(*ident);
Expand All @@ -301,7 +301,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ty,
ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
);
let rhs = this.lower_const_item_rhs(attrs, rhs.as_ref(), span);
let rhs = this.lower_const_item_rhs(rhs_kind, span);
(ty, rhs)
},
);
Expand Down Expand Up @@ -941,7 +941,12 @@ impl<'hir> LoweringContext<'_, 'hir> {

let (ident, generics, kind, has_default) = match &i.kind {
AssocItemKind::Const(box ConstItem {
ident, generics, ty, rhs, define_opaque, ..
ident,
generics,
ty,
rhs_kind,
define_opaque,
..
}) => {
let (generics, kind) = self.lower_generics(
generics,
Expand All @@ -952,15 +957,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
ty,
ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
);
let rhs = rhs
.as_ref()
.map(|rhs| this.lower_const_item_rhs(attrs, Some(rhs), i.span));
hir::TraitItemKind::Const(ty, rhs)
// Trait associated consts don't need an expression/body.
let rhs = if rhs_kind.has_expr() {
Some(this.lower_const_item_rhs(rhs_kind, i.span))
} else {
None
};
hir::TraitItemKind::Const(ty, rhs, rhs_kind.is_type_const().into())
},
);

if define_opaque.is_some() {
if rhs.is_some() {
if rhs_kind.has_expr() {
self.lower_define_opaque(hir_id, &define_opaque);
} else {
self.dcx().span_err(
Expand All @@ -970,7 +978,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

(*ident, generics, kind, rhs.is_some())
(*ident, generics, kind, rhs_kind.has_expr())
}
AssocItemKind::Fn(box Fn {
sig, ident, generics, body: None, define_opaque, ..
Expand Down Expand Up @@ -1154,7 +1162,12 @@ impl<'hir> LoweringContext<'_, 'hir> {

let (ident, (generics, kind)) = match &i.kind {
AssocItemKind::Const(box ConstItem {
ident, generics, ty, rhs, define_opaque, ..
ident,
generics,
ty,
rhs_kind,
define_opaque,
..
}) => (
*ident,
self.lower_generics(
Expand All @@ -1167,7 +1180,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
);
this.lower_define_opaque(hir_id, &define_opaque);
let rhs = this.lower_const_item_rhs(attrs, rhs.as_ref(), i.span);
let rhs = this.lower_const_item_rhs(rhs_kind, i.span);
hir::ImplItemKind::Const(ty, rhs)
},
),
Expand Down
19 changes: 10 additions & 9 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2374,15 +2374,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {

fn lower_const_item_rhs(
&mut self,
attrs: &[hir::Attribute],
rhs: Option<&ConstItemRhs>,
rhs_kind: &ConstItemRhsKind,
span: Span,
) -> hir::ConstItemRhs<'hir> {
match rhs {
Some(ConstItemRhs::TypeConst(anon)) => {
match rhs_kind {
ConstItemRhsKind::Body { rhs: Some(body) } => {
hir::ConstItemRhs::Body(self.lower_const_body(span, Some(body)))
}
ConstItemRhsKind::Body { rhs: None } => {
hir::ConstItemRhs::Body(self.lower_const_body(span, None))
}
ConstItemRhsKind::TypeConst { rhs: Some(anon) } => {
hir::ConstItemRhs::TypeConst(self.lower_anon_const_to_const_arg_and_alloc(anon))
}
None if find_attr!(attrs, AttributeKind::TypeConst(_)) => {
ConstItemRhsKind::TypeConst { rhs: None } => {
let const_arg = ConstArg {
hir_id: self.next_id(),
kind: hir::ConstArgKind::Error(
Expand All @@ -2392,10 +2397,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
};
hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg))
}
Some(ConstItemRhs::Body(body)) => {
hir::ConstItemRhs::Body(self.lower_const_body(span, Some(body)))
}
None => hir::ConstItemRhs::Body(self.lower_const_body(span, None)),
}
}

Expand Down
16 changes: 9 additions & 7 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1361,9 +1361,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
});
}
ItemKind::Const(box ConstItem { defaultness, ident, rhs, .. }) => {
ItemKind::Const(box ConstItem { defaultness, ident, rhs_kind, .. }) => {
self.check_defaultness(item.span, *defaultness);
if rhs.is_none() {
if !rhs_kind.has_expr() {
self.dcx().emit_err(errors::ConstWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
Expand Down Expand Up @@ -1715,11 +1715,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {

if let AssocCtxt::Impl { .. } = ctxt {
match &item.kind {
AssocItemKind::Const(box ConstItem { rhs: None, .. }) => {
self.dcx().emit_err(errors::AssocConstWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
});
AssocItemKind::Const(box ConstItem { rhs_kind, .. }) => {
if !rhs_kind.has_expr() {
self.dcx().emit_err(errors::AssocConstWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
});
}
}
AssocItemKind::Fn(box Fn { body, .. }) => {
if body.is_none() && !self.is_sdylib_interface {
Expand Down
43 changes: 43 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
self.check_impl_trait(ty, false)
}
ast::ItemKind::Const(box ast::ConstItem {
rhs_kind: ast::ConstItemRhsKind::TypeConst { .. },
..
}) => {
// Make sure this is only allowed if the feature gate is enabled.
// #![feature(min_generic_const_args)]
gate!(&self, min_generic_const_args, i.span, "top-level `type const` are unstable");
}

_ => {}
}
Expand Down Expand Up @@ -422,6 +430,20 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
false
}
ast::AssocItemKind::Const(box ast::ConstItem {
rhs_kind: ast::ConstItemRhsKind::TypeConst { .. },
..
}) => {
// Make sure this is only allowed if the feature gate is enabled.
// #![feature(min_generic_const_args)]
gate!(
&self,
min_generic_const_args,
i.span,
"associated `type const` are unstable"
);
false
}
_ => false,
};
if let ast::Defaultness::Default(_) = i.kind.defaultness() {
Expand Down Expand Up @@ -528,6 +550,27 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
}
}
}
// `mgca_type_const_syntax` is part of `min_generic_const_args` so either
// or both are enabled we don't need to emit a feature error.
if let Some(spans) = spans.get(&sym::mgca_type_const_syntax) {
for span in spans {
if visitor.features.min_generic_const_args()
|| visitor.features.mgca_type_const_syntax()
|| span.allows_unstable(sym::min_generic_const_args)
|| span.allows_unstable(sym::mgca_type_const_syntax)
{
continue;
}
feature_err(
&visitor.sess,
sym::min_generic_const_args,
*span,
"`type const` syntax is experimental",
)
.emit();
}
}

gate_all!(global_registration, "global registration is experimental");
gate_all!(return_type_notation, "return type notation is experimental");
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
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 @@ -221,15 +221,15 @@ impl<'a> State<'a> {
ident,
generics,
ty,
rhs,
rhs_kind,
define_opaque,
}) => {
self.print_item_const(
*ident,
None,
generics,
ty,
rhs.as_ref().map(|ct| ct.expr()),
rhs_kind.expr(),
&item.vis,
ast::Safety::Default,
*defaultness,
Expand Down Expand Up @@ -573,15 +573,15 @@ impl<'a> State<'a> {
ident,
generics,
ty,
rhs,
rhs_kind,
define_opaque,
}) => {
self.print_item_const(
*ident,
None,
generics,
ty,
rhs.as_ref().map(|ct| ct.expr()),
rhs_kind.expr(),
vis,
ast::Safety::Default,
*defaultness,
Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_attr_parsing/src/attributes/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for ParenSugarParser {
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcParenSugar;
}

pub(crate) struct TypeConstParser;
impl<S: Stage> NoArgsAttributeParser<S> for TypeConstParser {
const PATH: &[Symbol] = &[sym::type_const];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[Allow(Target::Const), Allow(Target::AssocConst)]);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst;
}

// Markers

pub(crate) struct MarkerParser;
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,6 @@ attribute_parsers!(
Single<WithoutArgs<StdInternalSymbolParser>>,
Single<WithoutArgs<ThreadLocalParser>>,
Single<WithoutArgs<TrackCallerParser>>,
Single<WithoutArgs<TypeConstParser>>,
Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
// tidy-alphabetical-end
];
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 = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts)));
let const_body = ast::ConstItemRhsKind::new_body(ecx.expr_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/eii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ fn generate_default_impl(
span,
underscore,
unit,
ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts))),
ast::ConstItemRhsKind::new_body(ecx.expr_block(ecx.block(span, stmts))),
)
};

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 = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts)));
let const_body = ast::ConstItemRhsKind::new_body(ecx.expr_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 = ast::ConstItemRhs::Body(cx.expr_block(
let block = ast::ConstItemRhsKind::new_body(cx.expr_block(
cx.block(span, thin_vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)]),
));

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_builtin_macros/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ pub(crate) fn expand_test_or_bench(
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
define_opaque: None,
// test::TestDescAndFn {
rhs: Some(ast::ConstItemRhs::Body(
rhs_kind: ast::ConstItemRhsKind::new_body(
cx.expr_struct(
sp,
test_path("TestDescAndFn"),
Expand Down Expand Up @@ -371,7 +371,7 @@ pub(crate) fn expand_test_or_bench(
field("testfn", test_fn), // }
],
), // }
)),
),
}
.into(),
),
Expand Down
Loading
Loading