Skip to content

Commit 93a5ef0

Browse files
committed
Start implementing #[type_const]
1 parent 6ce6194 commit 93a5ef0

File tree

13 files changed

+158
-6
lines changed

13 files changed

+158
-6
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,13 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
576576
EncodeCrossCrate::Yes, experimental!(patchable_function_entry)
577577
),
578578

579+
// Probably temporary component of min_generic_const_args.
580+
// `#[type_const] const ASSOC: usize;`
581+
gated!(
582+
type_const, Normal, template!(Word), ErrorFollowing,
583+
EncodeCrossCrate::Yes, min_generic_const_args, experimental!(type_const),
584+
),
585+
579586
// ==========================================================================
580587
// Internal attributes: Stability, deprecation, and unsafe:
581588
// ==========================================================================

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
557557
let item = self
558558
.tcx
559559
.hir()
560-
.expect_item(self.tcx.hir().get_parent_item(self.hir_id()).def_id);
560+
.expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
561561
match &item.kind {
562562
hir::ItemKind::Enum(_, generics)
563563
| hir::ItemKind::Struct(_, generics)

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2399,7 +2399,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23992399
let assoc_const = self
24002400
.probe_assoc_item(assoc_ident, ty::AssocKind::Const, hir_ref_id, span, trait_did)
24012401
.expect("failed to find associated const");
2402-
self.lower_assoc_const(span, assoc_const.def_id, assoc_segment, bound)
2402+
if assoc_const.has_type_const_attr(tcx) {
2403+
self.lower_assoc_const(span, assoc_const.def_id, assoc_segment, bound)
2404+
} else {
2405+
let mut err = tcx
2406+
.dcx()
2407+
.struct_span_err(span, "use of trait associated const without `#[type_const]`");
2408+
err.note("the declaration in the trait must be marked with `#[type_const]`");
2409+
Const::new_error(tcx, err.emit())
2410+
}
24032411
}
24042412

24052413
/// Literals are eagerly converted to a constant, everything else becomes `Unevaluated`.

compiler/rustc_middle/src/ty/assoc.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_hir as hir;
33
use rustc_hir::def::{DefKind, Namespace};
44
use rustc_hir::def_id::DefId;
55
use rustc_macros::{Decodable, Encodable, HashStable};
6-
use rustc_span::{Ident, Symbol};
6+
use rustc_span::{Ident, Symbol, sym};
77

88
use super::{TyCtxt, Visibility};
99
use crate::ty;
@@ -108,6 +108,23 @@ impl AssocItem {
108108
pub fn is_impl_trait_in_trait(&self) -> bool {
109109
self.opt_rpitit_info.is_some()
110110
}
111+
112+
/// Does this associated item have the `#[type_const]` attribute,
113+
/// or (if it is in a trait impl), does the item from the original
114+
/// trait have this attribute?
115+
pub fn has_type_const_attr(&self, tcx: TyCtxt<'_>) -> bool {
116+
if self.kind != ty::AssocKind::Const {
117+
return false;
118+
}
119+
120+
let def_id = match (self.container, self.trait_item_def_id) {
121+
(AssocItemContainer::Trait, _) => self.def_id,
122+
(AssocItemContainer::Impl, Some(trait_item_did)) => trait_item_did,
123+
// Inherent impl but this attr is only applied to trait assoc items.
124+
(AssocItemContainer::Impl, None) => return false,
125+
};
126+
tcx.has_attr(def_id, sym::type_const)
127+
}
111128
}
112129

113130
#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)]

compiler/rustc_passes/src/check_attr.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_attr_parsing::{AttributeKind, ReprAttr, find_attr};
1414
use rustc_data_structures::fx::FxHashMap;
1515
use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
1616
use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
17+
use rustc_hir::def::DefKind;
1718
use rustc_hir::def_id::LocalModDefId;
1819
use rustc_hir::intravisit::{self, Visitor};
1920
use rustc_hir::{
@@ -257,6 +258,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
257258
[sym::coroutine, ..] => {
258259
self.check_coroutine(attr, target);
259260
}
261+
[sym::type_const, ..] => {
262+
self.check_type_const(hir_id,attr, target);
263+
}
260264
[sym::linkage, ..] => self.check_linkage(attr, span, target),
261265
[sym::rustc_pub_transparent, ..] => self.check_rustc_pub_transparent(attr.span(), span, attrs),
262266
[
@@ -2519,6 +2523,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
25192523
}
25202524
}
25212525

2526+
fn check_type_const(&self, hir_id: HirId, attr: &Attribute, target: Target) {
2527+
let tcx = self.tcx;
2528+
if target == Target::AssocConst
2529+
&& let parent = tcx.parent(hir_id.expect_owner().to_def_id())
2530+
&& self.tcx.def_kind(parent) == DefKind::Trait
2531+
{
2532+
return;
2533+
} else {
2534+
self.dcx()
2535+
.struct_span_err(
2536+
attr.span(),
2537+
"`#[type_const]` must only be applied to trait associated constants",
2538+
)
2539+
.emit();
2540+
}
2541+
}
2542+
25222543
fn check_linkage(&self, attr: &Attribute, span: Span, target: Target) {
25232544
match target {
25242545
Target::Fn

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2083,6 +2083,7 @@ symbols! {
20832083
type_ascribe,
20842084
type_ascription,
20852085
type_changing_struct_update,
2086+
type_const,
20862087
type_id,
20872088
type_ir_inherent,
20882089
type_length_limit,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![feature(min_generic_const_args)]
2+
#![allow(incomplete_features)]
3+
4+
pub trait Tr {
5+
const SIZE: usize;
6+
}
7+
8+
fn mk_array<T: Tr>(_x: T) -> [(); T::SIZE] {
9+
//~^ ERROR type_const
10+
[(); T::SIZE]
11+
//~^ ERROR type_const
12+
}
13+
14+
fn main() {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: use of trait associated const without `#[type_const]`
2+
--> $DIR/assoc-const-without-type_const.rs:8:35
3+
|
4+
LL | fn mk_array<T: Tr>(_x: T) -> [(); T::SIZE] {
5+
| ^^^^^^^
6+
|
7+
= note: the declaration in the trait must be marked with `#[type_const]`
8+
9+
error: use of trait associated const without `#[type_const]`
10+
--> $DIR/assoc-const-without-type_const.rs:10:10
11+
|
12+
LL | [(); T::SIZE]
13+
| ^^^^^^^
14+
|
15+
= note: the declaration in the trait must be marked with `#[type_const]`
16+
17+
error: aborting due to 2 previous errors
18+

tests/ui/const-generics/mgca/assoc-const.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![allow(incomplete_features)]
55

66
pub trait Tr {
7+
#[type_const]
78
const SIZE: usize;
89
}
910

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
trait Tr {
2+
#[type_const()]
3+
//~^ ERROR malformed
4+
//~| ERROR experimental
5+
const N: usize;
6+
}
7+
8+
struct S;
9+
10+
impl Tr for S {
11+
#[type_const]
12+
//~^ ERROR must only be applied to trait associated constants
13+
//~| ERROR experimental
14+
const N: usize = 0;
15+
}
16+
17+
fn main() {}

0 commit comments

Comments
 (0)