Skip to content

Commit 338a271

Browse files
committed
forbid generic params in the type of const params
1 parent e2e29de commit 338a271

16 files changed

+160
-29
lines changed

src/librustc_error_codes/error_codes.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ E0766: include_str!("./error_codes/E0766.md"),
452452
E0767: include_str!("./error_codes/E0767.md"),
453453
E0768: include_str!("./error_codes/E0768.md"),
454454
E0769: include_str!("./error_codes/E0769.md"),
455+
E0770: include_str!("./error_codes/E0770.md"),
455456
;
456457
// E0006, // merged with E0005
457458
// E0008, // cannot bind by-move into a pattern guard

src/librustc_error_codes/error_codes/E0671.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Const parameters cannot depend on type parameters.
44
The following is therefore invalid:
55

6-
```compile_fail,E0741
6+
```compile_fail,E0770
77
#![feature(const_generics)]
88
99
fn const_id<T, const N: T>() -> T { // error
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
The type of a const parameter references other generic parameters.
2+
3+
Erroneous code example:
4+
5+
```compile_fail,E0770
6+
#![feature(const_generics)]
7+
fn foo<T, const N: T>() {} // error!
8+
```
9+
10+
To fix this error, use a concrete type for the const parameter:
11+
12+
```
13+
#![feature(const_generics)]
14+
fn foo<T, const N: usize>() {}
15+
```

src/librustc_resolve/diagnostics.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,16 @@ impl<'a> Resolver<'a> {
442442
);
443443
err
444444
}
445+
ResolutionError::ParamInTyOfConstArg => {
446+
let mut err = struct_span_err!(
447+
self.session,
448+
span,
449+
E0770,
450+
"the type of const parameters must not depend on other generic parameters"
451+
);
452+
err.span_label(span, "const parameters must have a concrete type");
453+
err
454+
}
445455
ResolutionError::SelfInTyParamDefault => {
446456
let mut err = struct_span_err!(
447457
self.session,

src/librustc_resolve/late.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ crate enum RibKind<'a> {
123123
/// from the default of a type parameter because they're not declared
124124
/// before said type parameter. Also see the `visit_generics` override.
125125
ForwardTyParamBanRibKind,
126+
127+
/// We are inside of the type of a const parameter. Can't refer to any
128+
/// parameters.
129+
ConstParamTyRibKind,
126130
}
127131

128132
impl RibKind<'_> {
@@ -135,7 +139,8 @@ impl RibKind<'_> {
135139
| FnItemRibKind
136140
| ConstantItemRibKind
137141
| ModuleRibKind(_)
138-
| MacroDefinition(_) => false,
142+
| MacroDefinition(_)
143+
| ConstParamTyRibKind => false,
139144
AssocItemRibKind | ItemRibKind(_) | ForwardTyParamBanRibKind => true,
140145
}
141146
}
@@ -562,7 +567,11 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
562567
for bound in &param.bounds {
563568
self.visit_param_bound(bound);
564569
}
570+
self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
571+
self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
565572
self.visit_ty(ty);
573+
self.ribs[TypeNS].pop().unwrap();
574+
self.ribs[ValueNS].pop().unwrap();
566575
}
567576
}
568577
}
@@ -798,7 +807,8 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
798807
| ItemRibKind(..)
799808
| ConstantItemRibKind
800809
| ModuleRibKind(..)
801-
| ForwardTyParamBanRibKind => {
810+
| ForwardTyParamBanRibKind
811+
| ConstParamTyRibKind => {
802812
return false;
803813
}
804814
}

src/librustc_resolve/lib.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ enum ResolutionError<'a> {
214214
BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
215215
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
216216
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
217+
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
218+
ParamInTyOfConstArg,
217219
/// Error E0735: type parameters with a default cannot use `Self`
218220
SelfInTyParamDefault,
219221
/// Error E0767: use of unreachable label
@@ -2480,6 +2482,12 @@ impl<'a> Resolver<'a> {
24802482
}
24812483
return Res::Err;
24822484
}
2485+
ConstParamTyRibKind => {
2486+
if record_used {
2487+
self.report_error(span, ParamInTyOfConstArg);
2488+
}
2489+
return Res::Err;
2490+
}
24832491
}
24842492
}
24852493
if let Some(res_err) = res_err {
@@ -2503,6 +2511,12 @@ impl<'a> Resolver<'a> {
25032511
// This was an attempt to use a type parameter outside its scope.
25042512
ItemRibKind(has_generic_params) => has_generic_params,
25052513
FnItemRibKind => HasGenericParams::Yes,
2514+
ConstParamTyRibKind => {
2515+
if record_used {
2516+
self.report_error(span, ResolutionError::ParamInTyOfConstArg);
2517+
}
2518+
return Res::Err;
2519+
}
25062520
};
25072521

25082522
if record_used {
@@ -2527,9 +2541,21 @@ impl<'a> Resolver<'a> {
25272541
}
25282542
for rib in ribs {
25292543
let has_generic_params = match rib.kind {
2544+
NormalRibKind
2545+
| ClosureOrAsyncRibKind
2546+
| AssocItemRibKind
2547+
| ModuleRibKind(..)
2548+
| MacroDefinition(..)
2549+
| ForwardTyParamBanRibKind
2550+
| ConstantItemRibKind => continue,
25302551
ItemRibKind(has_generic_params) => has_generic_params,
25312552
FnItemRibKind => HasGenericParams::Yes,
2532-
_ => continue,
2553+
ConstParamTyRibKind => {
2554+
if record_used {
2555+
self.report_error(span, ResolutionError::ParamInTyOfConstArg);
2556+
}
2557+
return Res::Err;
2558+
}
25332559
};
25342560

25352561
// This was an attempt to use a const parameter outside its scope.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(const_generics)]
2+
//~^ WARN the feature `const_generics` is incomplete
3+
4+
// Currently, const parameters cannot depend on other generic parameters,
5+
// as our current implementation can't really support this.
6+
//
7+
// We may want to lift this restriction in the future.
8+
9+
pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
10+
//~^ ERROR: the type of const parameters must not depend on other generic parameters
11+
//~| ERROR: cycle detected when computing type of `Dependent::X`
12+
13+
fn main() {}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error[E0770]: the type of const parameters must not depend on other generic parameters
2+
--> $DIR/const-param-type-depends-on-const-param.rs:9:52
3+
|
4+
LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
5+
| ^ const parameters must have a concrete type
6+
7+
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
8+
--> $DIR/const-param-type-depends-on-const-param.rs:1:12
9+
|
10+
LL | #![feature(const_generics)]
11+
| ^^^^^^^^^^^^^^
12+
|
13+
= note: `#[warn(incomplete_features)]` on by default
14+
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
15+
16+
error[E0391]: cycle detected when computing type of `Dependent::X`
17+
--> $DIR/const-param-type-depends-on-const-param.rs:9:44
18+
|
19+
LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
20+
| ^
21+
|
22+
= note: ...which again requires computing type of `Dependent::X`, completing the cycle
23+
note: cycle used when computing type of `Dependent`
24+
--> $DIR/const-param-type-depends-on-const-param.rs:9:1
25+
|
26+
LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
28+
29+
error: aborting due to 2 previous errors; 1 warning emitted
30+
31+
For more information about this error, try `rustc --explain E0391`.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::marker::PhantomData;
22

33
struct B<T, const N: T>(PhantomData<[T; N]>); //~ ERROR const generics are unstable
4-
//~^ ERROR `T` is not guaranteed to `#[derive(PartialEq, Eq)]`
4+
//~^ ERROR the type of const parameters must not depend on other generic parameters
55

66
fn main() {}
Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
error[E0770]: the type of const parameters must not depend on other generic parameters
2+
--> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
3+
|
4+
LL | struct B<T, const N: T>(PhantomData<[T; N]>);
5+
| ^ const parameters must have a concrete type
6+
17
error[E0658]: const generics are unstable
28
--> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19
39
|
@@ -7,15 +13,6 @@ LL | struct B<T, const N: T>(PhantomData<[T; N]>);
713
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
814
= help: add `#![feature(const_generics)]` to the crate attributes to enable
915

10-
error[E0741]: `T` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be used as the type of a const parameter
11-
--> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
12-
|
13-
LL | struct B<T, const N: T>(PhantomData<[T; N]>);
14-
| ^ `T` may not derive both `PartialEq` and `Eq`
15-
|
16-
= note: it is not currently possible to use a type parameter as the type of a const parameter
17-
1816
error: aborting due to 2 previous errors
1917

20-
Some errors have detailed explanations: E0658, E0741.
21-
For more information about an error, try `rustc --explain E0658`.
18+
For more information about this error, try `rustc --explain E0658`.
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
#![feature(const_generics)]
22
//~^ WARN the feature `const_generics` is incomplete
33

4-
// Currently, const parameters cannot depend on type parameters, because there is no way to
5-
// enforce the structural-match property on an arbitrary type parameter. This restriction
6-
// may be relaxed in the future. See https://github.com/rust-lang/rfcs/pull/2000 for more
7-
// details.
4+
// Currently, const parameters cannot depend on other generic parameters,
5+
// as our current implementation can't really support this.
6+
//
7+
// We may want to lift this restriction in the future.
88

99
pub struct Dependent<T, const X: T>([(); X]);
10-
//~^ ERROR `T` is not guaranteed to `#[derive(PartialEq, Eq)]`
10+
//~^ ERROR: the type of const parameters must not depend on other generic parameters
11+
//~| ERROR: parameter `T` is never used
1112

1213
fn main() {}
Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
error[E0770]: the type of const parameters must not depend on other generic parameters
2+
--> $DIR/const-param-type-depends-on-type-param.rs:9:34
3+
|
4+
LL | pub struct Dependent<T, const X: T>([(); X]);
5+
| ^ const parameters must have a concrete type
6+
17
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
28
--> $DIR/const-param-type-depends-on-type-param.rs:1:12
39
|
@@ -7,14 +13,14 @@ LL | #![feature(const_generics)]
713
= note: `#[warn(incomplete_features)]` on by default
814
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
915

10-
error[E0741]: `T` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be used as the type of a const parameter
11-
--> $DIR/const-param-type-depends-on-type-param.rs:9:34
16+
error[E0392]: parameter `T` is never used
17+
--> $DIR/const-param-type-depends-on-type-param.rs:9:22
1218
|
1319
LL | pub struct Dependent<T, const X: T>([(); X]);
14-
| ^ `T` may not derive both `PartialEq` and `Eq`
20+
| ^ unused parameter
1521
|
16-
= note: it is not currently possible to use a type parameter as the type of a const parameter
22+
= help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
1723

18-
error: aborting due to previous error; 1 warning emitted
24+
error: aborting due to 2 previous errors; 1 warning emitted
1925

20-
For more information about this error, try `rustc --explain E0741`.
26+
For more information about this error, try `rustc --explain E0392`.

src/test/ui/const-generics/issues/issue-71381.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ unsafe extern "C" fn pass(args: PassArg) {
1212
impl Test {
1313
pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
1414
//~^ ERROR: using function pointers as const generic parameters is forbidden
15+
//~| ERROR: the type of const parameters must not depend on other generic parameters
1516
self.0 = Self::trampiline::<Args, IDX, FN> as _
1617
}
1718

@@ -20,6 +21,7 @@ impl Test {
2021
const IDX: usize,
2122
const FN: unsafe extern "C" fn(Args),
2223
//~^ ERROR: using function pointers as const generic parameters is forbidden
24+
//~| ERROR: the type of const parameters must not depend on other generic parameters
2325
>(
2426
args: Args,
2527
) {
Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
1+
error[E0770]: the type of const parameters must not depend on other generic parameters
2+
--> $DIR/issue-71381.rs:13:82
3+
|
4+
LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
5+
| ^^^^ const parameters must have a concrete type
6+
7+
error[E0770]: the type of const parameters must not depend on other generic parameters
8+
--> $DIR/issue-71381.rs:22:40
9+
|
10+
LL | const FN: unsafe extern "C" fn(Args),
11+
| ^^^^ const parameters must have a concrete type
12+
113
error: using function pointers as const generic parameters is forbidden
214
--> $DIR/issue-71381.rs:13:61
315
|
416
LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
517
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
618

719
error: using function pointers as const generic parameters is forbidden
8-
--> $DIR/issue-71381.rs:21:19
20+
--> $DIR/issue-71381.rs:22:19
921
|
1022
LL | const FN: unsafe extern "C" fn(Args),
1123
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1224

13-
error: aborting due to 2 previous errors
25+
error: aborting due to 4 previous errors
1426

src/test/ui/const-generics/issues/issue-71611.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
fn func<A, const F: fn(inner: A)>(outer: A) {
55
//~^ ERROR: using function pointers as const generic parameters is forbidden
6+
//~| ERROR: the type of const parameters must not depend on other generic parameters
67
F(outer);
78
}
89

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1+
error[E0770]: the type of const parameters must not depend on other generic parameters
2+
--> $DIR/issue-71611.rs:4:31
3+
|
4+
LL | fn func<A, const F: fn(inner: A)>(outer: A) {
5+
| ^ const parameters must have a concrete type
6+
17
error: using function pointers as const generic parameters is forbidden
28
--> $DIR/issue-71611.rs:4:21
39
|
410
LL | fn func<A, const F: fn(inner: A)>(outer: A) {
511
| ^^^^^^^^^^^^
612

7-
error: aborting due to previous error
13+
error: aborting due to 2 previous errors
814

0 commit comments

Comments
 (0)