Skip to content

Commit 263637d

Browse files
committed
Start implementing #[type_const]
1 parent 96c158b commit 263637d

File tree

12 files changed

+157
-5
lines changed

12 files changed

+157
-5
lines changed

Diff for: compiler/rustc_feature/src/builtin_attrs.rs

+7
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
581581
EncodeCrossCrate::Yes, experimental!(patchable_function_entry)
582582
),
583583

584+
// Probably temporary component of min_generic_const_args.
585+
// `#[type_const] const ASSOC: usize;`
586+
gated!(
587+
type_const, Normal, template!(Word), ErrorFollowing,
588+
EncodeCrossCrate::Yes, min_generic_const_args, experimental!(type_const),
589+
),
590+
584591
// ==========================================================================
585592
// Internal attributes: Stability, deprecation, and unsafe:
586593
// ==========================================================================

Diff for: compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -2337,7 +2337,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23372337
let assoc_const = self
23382338
.probe_assoc_item(assoc_ident, ty::AssocKind::Const, hir_ref_id, span, trait_did)
23392339
.expect("failed to find associated const");
2340-
self.lower_assoc_const(span, assoc_const.def_id, assoc_segment, bound)
2340+
if assoc_const.has_type_const_attr(tcx) {
2341+
self.lower_assoc_const(span, assoc_const.def_id, assoc_segment, bound)
2342+
} else {
2343+
let mut err = tcx
2344+
.dcx()
2345+
.struct_span_err(span, "use of trait associated const without `#[type_const]`");
2346+
err.note("the declaration in the trait must be marked with `#[type_const]`");
2347+
Const::new_error(tcx, err.emit())
2348+
}
23412349
}
23422350

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

Diff for: compiler/rustc_middle/src/ty/assoc.rs

+18-1
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)]

Diff for: compiler/rustc_passes/src/check_attr.rs

+21
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, as
1111
use rustc_data_structures::fx::FxHashMap;
1212
use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
1313
use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
14+
use rustc_hir::def::DefKind;
1415
use rustc_hir::def_id::LocalModDefId;
1516
use rustc_hir::intravisit::{self, Visitor};
1617
use rustc_hir::{
@@ -246,6 +247,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
246247
[sym::coroutine, ..] => {
247248
self.check_coroutine(attr, target);
248249
}
250+
[sym::type_const, ..] => {
251+
self.check_type_const(hir_id,attr, target);
252+
}
249253
[sym::linkage, ..] => self.check_linkage(attr, span, target),
250254
[sym::rustc_pub_transparent, ..] => self.check_rustc_pub_transparent( attr.span, span, attrs),
251255
[
@@ -2455,6 +2459,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
24552459
}
24562460
}
24572461

2462+
fn check_type_const(&self, hir_id: HirId, attr: &Attribute, target: Target) {
2463+
let tcx = self.tcx;
2464+
if target == Target::AssocConst
2465+
&& let parent = tcx.parent(hir_id.expect_owner().to_def_id())
2466+
&& self.tcx.def_kind(parent) == DefKind::Trait
2467+
{
2468+
return;
2469+
} else {
2470+
self.dcx()
2471+
.struct_span_err(
2472+
attr.span,
2473+
"`#[type_const]` must only be applied to trait associated constants",
2474+
)
2475+
.emit();
2476+
}
2477+
}
2478+
24582479
fn check_linkage(&self, attr: &Attribute, span: Span, target: Target) {
24592480
match target {
24602481
Target::Fn

Diff for: compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2052,6 +2052,7 @@ symbols! {
20522052
type_ascribe,
20532053
type_ascription,
20542054
type_changing_struct_update,
2055+
type_const,
20552056
type_id,
20562057
type_ir_inherent,
20572058
type_length_limit,
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() {}
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+

Diff for: tests/ui/const-generics/mgca/assoc-const.rs

+1
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

+17
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() {}
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: malformed `type_const` attribute input
2+
--> $DIR/bad-type_const-syntax.rs:2:5
3+
|
4+
LL | #[type_const()]
5+
| ^^^^^^^^^^^^^^^ help: must be of the form: `#[type_const]`
6+
7+
error[E0658]: the `#[type_const]` attribute is an experimental feature
8+
--> $DIR/bad-type_const-syntax.rs:2:5
9+
|
10+
LL | #[type_const()]
11+
| ^^^^^^^^^^^^^^^
12+
|
13+
= note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
14+
= help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
15+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
16+
17+
error[E0658]: the `#[type_const]` attribute is an experimental feature
18+
--> $DIR/bad-type_const-syntax.rs:11:5
19+
|
20+
LL | #[type_const]
21+
| ^^^^^^^^^^^^^
22+
|
23+
= note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
24+
= help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
25+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
26+
27+
error: `#[type_const]` must only be applied to trait associated constants
28+
--> $DIR/bad-type_const-syntax.rs:11:5
29+
|
30+
LL | #[type_const]
31+
| ^^^^^^^^^^^^^
32+
33+
error: aborting due to 4 previous errors
34+
35+
For more information about this error, try `rustc --explain E0658`.

Diff for: tests/ui/feature-gates/feature-gate-min-generic-const-args.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
trait Trait {
2+
#[type_const]
3+
//~^ ERROR experimental
24
const ASSOC: usize;
35
}
46

5-
// FIXME(min_generic_const_args): implement support for this, behind the feature gate
7+
// FIXME(min_generic_const_args): add suggestion for mgca to this error
68
fn foo<T: Trait>() -> [u8; <T as Trait>::ASSOC] {
79
//~^ ERROR generic parameters may not be used in const operations
810
loop {}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
error: generic parameters may not be used in const operations
2-
--> $DIR/feature-gate-min-generic-const-args.rs:6:29
2+
--> $DIR/feature-gate-min-generic-const-args.rs:8:29
33
|
44
LL | fn foo<T: Trait>() -> [u8; <T as Trait>::ASSOC] {
55
| ^ cannot perform const operation using `T`
66
|
77
= note: type parameters may not be used in const expressions
88
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
99

10-
error: aborting due to 1 previous error
10+
error[E0658]: the `#[type_const]` attribute is an experimental feature
11+
--> $DIR/feature-gate-min-generic-const-args.rs:2:5
12+
|
13+
LL | #[type_const]
14+
| ^^^^^^^^^^^^^
15+
|
16+
= note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
17+
= help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
18+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
19+
20+
error: aborting due to 2 previous errors
1121

22+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)