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`.

0 commit comments

Comments
 (0)