Skip to content

Commit 72b21e1

Browse files
committed
Auto merge of #139558 - camelid:mgca-const-items, r=oli-obk,BoxyUwU
mgca: Add ConstArg representation for const items tracking issue: #132980 fixes #131046 fixes #134641 As part of implementing `min_generic_const_args`, we need to distinguish const items that can be used in the type system, such as in associated const equality projections, from const items containing arbitrary const code, which must be kept out of the type system. Specifically, all "type consts" must be either concrete (no generics) or generic with a trivial expression like `N` or a path to another type const item. To syntactically distinguish these cases, we require, for now at least, that users annotate all type consts with the `#[type_const]` attribute. Then, we validate that the const's right-hand side is indeed eligible to be a type const and represent it differently in the HIR. We accomplish this representation using a new `ConstItemRhs` enum in the HIR, and a similar but simpler enum in the AST. When `#[type_const]` is **not** applied to a const (e.g. on stable), we represent const item right-hand sides (rhs's) as HIR bodies, like before. However, when the attribute is applied, we instead lower to a `hir::ConstArg`. This syntactically distinguishes between trivial const args (paths) and arbitrary expressions, which are represented using `AnonConst`s. Then in `generics_of`, we can take advantage of the existing machinery to bar the `AnonConst` rhs's from using parent generics.
2 parents fb23dd3 + 45391bd commit 72b21e1

File tree

117 files changed

+1180
-758
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+1180
-758
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3759,10 +3759,29 @@ pub struct ConstItem {
37593759
pub ident: Ident,
37603760
pub generics: Generics,
37613761
pub ty: Box<Ty>,
3762-
pub expr: Option<Box<Expr>>,
3762+
pub rhs: Option<ConstItemRhs>,
37633763
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
37643764
}
37653765

3766+
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
3767+
pub enum ConstItemRhs {
3768+
TypeConst(AnonConst),
3769+
Body(Box<Expr>),
3770+
}
3771+
3772+
impl ConstItemRhs {
3773+
pub fn span(&self) -> Span {
3774+
self.expr().span
3775+
}
3776+
3777+
pub fn expr(&self) -> &Expr {
3778+
match self {
3779+
ConstItemRhs::TypeConst(anon_const) => &anon_const.value,
3780+
ConstItemRhs::Body(expr) => expr,
3781+
}
3782+
}
3783+
}
3784+
37663785
// Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
37673786
#[derive(Clone, Encodable, Decodable, Debug)]
37683787
pub enum ItemKind {

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ macro_rules! common_visitor_and_walkers {
423423
Closure,
424424
Const,
425425
ConstItem,
426+
ConstItemRhs,
426427
Defaultness,
427428
Delegation,
428429
DelegationMac,

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -170,37 +170,36 @@ impl<'hir> LoweringContext<'_, 'hir> {
170170
}
171171
ItemKind::Static(box ast::StaticItem {
172172
ident,
173-
ty: t,
173+
ty,
174174
safety: _,
175175
mutability: m,
176176
expr: e,
177177
define_opaque,
178178
}) => {
179179
let ident = self.lower_ident(*ident);
180-
let (ty, body_id) =
181-
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
180+
let ty =
181+
self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
182+
let body_id = self.lower_const_body(span, e.as_deref());
182183
self.lower_define_opaque(hir_id, define_opaque);
183184
hir::ItemKind::Static(*m, ident, ty, body_id)
184185
}
185186
ItemKind::Const(box ast::ConstItem {
186-
ident,
187-
generics,
188-
ty,
189-
expr,
190-
define_opaque,
191-
..
187+
ident, generics, ty, rhs, define_opaque, ..
192188
}) => {
193189
let ident = self.lower_ident(*ident);
194-
let (generics, (ty, body_id)) = self.lower_generics(
190+
let (generics, (ty, rhs)) = self.lower_generics(
195191
generics,
196192
id,
197193
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
198194
|this| {
199-
this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
195+
let ty = this
196+
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
197+
let rhs = this.lower_const_item_rhs(attrs, rhs.as_ref(), span);
198+
(ty, rhs)
200199
},
201200
);
202201
self.lower_define_opaque(hir_id, &define_opaque);
203-
hir::ItemKind::Const(ident, generics, ty, body_id)
202+
hir::ItemKind::Const(ident, generics, ty, rhs)
204203
}
205204
ItemKind::Fn(box Fn {
206205
sig: FnSig { decl, header, span: fn_sig_span },
@@ -462,17 +461,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
462461
}
463462
}
464463

465-
fn lower_const_item(
466-
&mut self,
467-
ty: &Ty,
468-
span: Span,
469-
body: Option<&Expr>,
470-
impl_trait_position: ImplTraitPosition,
471-
) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
472-
let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(impl_trait_position));
473-
(ty, self.lower_const_body(span, body))
474-
}
475-
476464
#[instrument(level = "debug", skip(self))]
477465
fn lower_use_tree(
478466
&mut self,
@@ -804,12 +792,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
804792

805793
let (ident, generics, kind, has_default) = match &i.kind {
806794
AssocItemKind::Const(box ConstItem {
807-
ident,
808-
generics,
809-
ty,
810-
expr,
811-
define_opaque,
812-
..
795+
ident, generics, ty, rhs, define_opaque, ..
813796
}) => {
814797
let (generics, kind) = self.lower_generics(
815798
generics,
@@ -818,14 +801,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
818801
|this| {
819802
let ty = this
820803
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
821-
let body = expr.as_ref().map(|x| this.lower_const_body(i.span, Some(x)));
822-
823-
hir::TraitItemKind::Const(ty, body)
804+
let rhs = rhs
805+
.as_ref()
806+
.map(|rhs| this.lower_const_item_rhs(attrs, Some(rhs), i.span));
807+
hir::TraitItemKind::Const(ty, rhs)
824808
},
825809
);
826810

827811
if define_opaque.is_some() {
828-
if expr.is_some() {
812+
if rhs.is_some() {
829813
self.lower_define_opaque(hir_id, &define_opaque);
830814
} else {
831815
self.dcx().span_err(
@@ -835,7 +819,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
835819
}
836820
}
837821

838-
(*ident, generics, kind, expr.is_some())
822+
(*ident, generics, kind, rhs.is_some())
839823
}
840824
AssocItemKind::Fn(box Fn {
841825
sig, ident, generics, body: None, define_opaque, ..
@@ -1022,12 +1006,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
10221006

10231007
let (ident, (generics, kind)) = match &i.kind {
10241008
AssocItemKind::Const(box ConstItem {
1025-
ident,
1026-
generics,
1027-
ty,
1028-
expr,
1029-
define_opaque,
1030-
..
1009+
ident, generics, ty, rhs, define_opaque, ..
10311010
}) => (
10321011
*ident,
10331012
self.lower_generics(
@@ -1037,9 +1016,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
10371016
|this| {
10381017
let ty = this
10391018
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
1040-
let body = this.lower_const_body(i.span, expr.as_deref());
10411019
this.lower_define_opaque(hir_id, &define_opaque);
1042-
hir::ImplItemKind::Const(ty, body)
1020+
let rhs = this.lower_const_item_rhs(attrs, rhs.as_ref(), i.span);
1021+
hir::ImplItemKind::Const(ty, rhs)
10431022
},
10441023
),
10451024
),

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2327,6 +2327,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23272327
self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: ct_kind })
23282328
}
23292329

2330+
fn lower_const_item_rhs(
2331+
&mut self,
2332+
attrs: &[hir::Attribute],
2333+
rhs: Option<&ConstItemRhs>,
2334+
span: Span,
2335+
) -> hir::ConstItemRhs<'hir> {
2336+
match rhs {
2337+
Some(ConstItemRhs::TypeConst(anon)) => {
2338+
hir::ConstItemRhs::TypeConst(self.lower_anon_const_to_const_arg(anon))
2339+
}
2340+
None if attr::contains_name(attrs, sym::type_const) => {
2341+
let const_arg = ConstArg {
2342+
hir_id: self.next_id(),
2343+
kind: hir::ConstArgKind::Error(
2344+
DUMMY_SP,
2345+
self.dcx().span_delayed_bug(DUMMY_SP, "no block"),
2346+
),
2347+
};
2348+
hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg))
2349+
}
2350+
Some(ConstItemRhs::Body(body)) => {
2351+
hir::ConstItemRhs::Body(self.lower_const_body(span, Some(body)))
2352+
}
2353+
None => hir::ConstItemRhs::Body(self.lower_const_body(span, None)),
2354+
}
2355+
}
2356+
23302357
/// See [`hir::ConstArg`] for when to use this function vs
23312358
/// [`Self::lower_anon_const_to_anon_const`].
23322359
fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> &'hir hir::ConstArg<'hir> {

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,9 +1239,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12391239
}
12401240
});
12411241
}
1242-
ItemKind::Const(box ConstItem { defaultness, expr, .. }) => {
1242+
ItemKind::Const(box ConstItem { defaultness, rhs, .. }) => {
12431243
self.check_defaultness(item.span, *defaultness);
1244-
if expr.is_none() {
1244+
if rhs.is_none() {
12451245
self.dcx().emit_err(errors::ConstWithoutBody {
12461246
span: item.span,
12471247
replace_span: self.ending_semi_or_hi(item.span),
@@ -1581,7 +1581,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
15811581

15821582
if let AssocCtxt::Impl { .. } = ctxt {
15831583
match &item.kind {
1584-
AssocItemKind::Const(box ConstItem { expr: None, .. }) => {
1584+
AssocItemKind::Const(box ConstItem { rhs: None, .. }) => {
15851585
self.dcx().emit_err(errors::AssocConstWithoutBody {
15861586
span: item.span,
15871587
replace_span: self.ending_semi_or_hi(item.span),

compiler/rustc_ast_pretty/src/pprust/state/item.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,15 +210,15 @@ impl<'a> State<'a> {
210210
ident,
211211
generics,
212212
ty,
213-
expr,
213+
rhs,
214214
define_opaque,
215215
}) => {
216216
self.print_item_const(
217217
*ident,
218218
None,
219219
generics,
220220
ty,
221-
expr.as_deref(),
221+
rhs.as_ref().map(|ct| ct.expr()),
222222
&item.vis,
223223
ast::Safety::Default,
224224
*defaultness,
@@ -566,15 +566,15 @@ impl<'a> State<'a> {
566566
ident,
567567
generics,
568568
ty,
569-
expr,
569+
rhs,
570570
define_opaque,
571571
}) => {
572572
self.print_item_const(
573573
*ident,
574574
None,
575575
generics,
576576
ty,
577-
expr.as_deref(),
577+
rhs.as_ref().map(|ct| ct.expr()),
578578
vis,
579579
ast::Safety::Default,
580580
*defaultness,

compiler/rustc_builtin_macros/src/alloc_error_handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub(crate) fn expand(
4343

4444
// Generate anonymous constant serving as container for the allocator methods.
4545
let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new()));
46-
let const_body = ecx.expr_block(ecx.block(span, stmts));
46+
let const_body = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts)));
4747
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
4848
let const_item = if is_stmt {
4949
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))

compiler/rustc_builtin_macros/src/global_allocator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub(crate) fn expand(
4747

4848
// Generate anonymous constant serving as container for the allocator methods.
4949
let const_ty = ecx.ty(ty_span, TyKind::Tup(ThinVec::new()));
50-
let const_body = ecx.expr_block(ecx.block(span, stmts));
50+
let const_body = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts)));
5151
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
5252
let const_item = if is_stmt {
5353
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))

compiler/rustc_builtin_macros/src/proc_macro_harness.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,9 +385,9 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> Box<ast::Item> {
385385
cx.attr_nested_word(sym::allow, sym::deprecated, span),
386386
]);
387387

388-
let block = cx.expr_block(
388+
let block = ast::ConstItemRhs::Body(cx.expr_block(
389389
cx.block(span, thin_vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)]),
390-
);
390+
));
391391

392392
let anon_constant = cx.item_const(
393393
span,

compiler/rustc_builtin_macros/src/test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ pub(crate) fn expand_test_or_bench(
289289
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
290290
define_opaque: None,
291291
// test::TestDescAndFn {
292-
expr: Some(
292+
rhs: Some(ast::ConstItemRhs::Body(
293293
cx.expr_struct(
294294
sp,
295295
test_path("TestDescAndFn"),
@@ -371,7 +371,7 @@ pub(crate) fn expand_test_or_bench(
371371
field("testfn", test_fn), // }
372372
],
373373
), // }
374-
),
374+
)),
375375
}
376376
.into(),
377377
),

0 commit comments

Comments
 (0)