Skip to content

Commit 409d124

Browse files
authored
Rollup merge of rust-lang#60284 - varkor:const-param-of-type-param, r=cramertj
Do not allow const generics to depend on type parameters Fixes rust-lang#60264. In https://github.com/rust-lang/rust/pull/58191/files/b534cf992d0189032207f395c27ed092c89b40c7#diff-aeb0880081a991f34aef2ab889e1fb7a, it was suggested that there might be a better place for this error, but as this bug already affects stable, it's probably worth merging this now, and refactoring afterwards (I can open an issue for this).
2 parents ae36d8b + 908a639 commit 409d124

6 files changed

+108
-2
lines changed

src/librustc_resolve/error_codes.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1642,6 +1642,16 @@ fn main() {
16421642
```
16431643
"##,
16441644

1645+
E0671: r##"
1646+
Const parameters cannot depend on type parameters.
1647+
The following is therefore invalid:
1648+
```
1649+
fn const_id<T, const N: T>() -> T {
1650+
N
1651+
}
1652+
```
1653+
"##,
1654+
16451655
}
16461656

16471657
register_diagnostics! {

src/librustc_resolve/lib.rs

+42-2
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ enum ResolutionError<'a> {
185185
BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
186186
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
187187
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
188+
/// Error E0671: const parameter cannot depend on type parameter.
189+
ConstParamDependentOnTypeParam,
188190
}
189191

190192
/// Combines an error with provided span and emits it.
@@ -440,6 +442,16 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
440442
span, "defaulted type parameters cannot be forward declared".to_string());
441443
err
442444
}
445+
ResolutionError::ConstParamDependentOnTypeParam => {
446+
let mut err = struct_span_err!(
447+
resolver.session,
448+
span,
449+
E0671,
450+
"const parameters cannot depend on type parameters"
451+
);
452+
err.span_label(span, format!("const parameter depends on type parameter"));
453+
err
454+
}
443455
}
444456
}
445457

@@ -915,6 +927,18 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
915927
}
916928
}));
917929

930+
// We also ban access to type parameters for use as the types of const parameters.
931+
let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy);
932+
const_ty_param_ban_rib.bindings.extend(generics.params.iter()
933+
.filter(|param| {
934+
if let GenericParamKind::Type { .. } = param.kind {
935+
true
936+
} else {
937+
false
938+
}
939+
})
940+
.map(|param| (Ident::with_empty_ctxt(param.ident.name), Def::Err)));
941+
918942
for param in &generics.params {
919943
match param.kind {
920944
GenericParamKind::Lifetime { .. } => self.visit_generic_param(param),
@@ -933,11 +957,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
933957
default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
934958
}
935959
GenericParamKind::Const { ref ty } => {
960+
self.ribs[TypeNS].push(const_ty_param_ban_rib);
961+
936962
for bound in &param.bounds {
937963
self.visit_param_bound(bound);
938964
}
939965

940966
self.visit_ty(ty);
967+
968+
const_ty_param_ban_rib = self.ribs[TypeNS].pop().unwrap();
941969
}
942970
}
943971
}
@@ -994,6 +1022,9 @@ enum RibKind<'a> {
9941022
/// from the default of a type parameter because they're not declared
9951023
/// before said type parameter. Also see the `visit_generics` override.
9961024
ForwardTyParamBanRibKind,
1025+
1026+
/// We forbid the use of type parameters as the types of const parameters.
1027+
TyParamAsConstParamTy,
9971028
}
9981029

9991030
/// A single local scope.
@@ -3944,6 +3975,15 @@ impl<'a> Resolver<'a> {
39443975
return Def::Err;
39453976
}
39463977

3978+
// An invalid use of a type parameter as the type of a const parameter.
3979+
if let TyParamAsConstParamTy = self.ribs[ns][rib_index].kind {
3980+
if record_used {
3981+
resolve_error(self, span, ResolutionError::ConstParamDependentOnTypeParam);
3982+
}
3983+
assert_eq!(def, Def::Err);
3984+
return Def::Err;
3985+
}
3986+
39473987
match def {
39483988
Def::Upvar(..) => {
39493989
span_bug!(span, "unexpected {:?} in bindings", def)
@@ -3955,7 +3995,7 @@ impl<'a> Resolver<'a> {
39553995
for rib in ribs {
39563996
match rib.kind {
39573997
NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) |
3958-
ForwardTyParamBanRibKind => {
3998+
ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
39593999
// Nothing to do. Continue.
39604000
}
39614001
ClosureRibKind(function_id) => {
@@ -4013,7 +4053,7 @@ impl<'a> Resolver<'a> {
40134053
match rib.kind {
40144054
NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) |
40154055
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
4016-
ConstantItemRibKind => {
4056+
ConstantItemRibKind | TyParamAsConstParamTy => {
40174057
// Nothing to do. Continue.
40184058
}
40194059
ItemRibKind | FnItemRibKind => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
use std::marker::PhantomData;
2+
3+
struct B<T, const N: T>(PhantomData<[T; N]>); //~ ERROR const generics are unstable
4+
//~^ ERROR const parameters cannot depend on type parameters
5+
6+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0671]: const parameters cannot depend on type 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 parameter depends on type parameter
6+
7+
error[E0658]: const generics are unstable
8+
--> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19
9+
|
10+
LL | struct B<T, const N: T>(PhantomData<[T; N]>);
11+
| ^
12+
|
13+
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
14+
= help: add #![feature(const_generics)] to the crate attributes to enable
15+
16+
error: aborting due to 2 previous errors
17+
18+
Some errors have detailed explanations: E0658, E0671.
19+
For more information about an error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![feature(const_generics)]
2+
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
3+
4+
pub struct Dependent<T, const X: T>([(); X]); //~ ERROR const parameters
5+
//~^ ERROR parameter `T` is never used
6+
7+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2+
--> $DIR/const-param-type-depends-on-type-param.rs:1:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+
7+
error[E0671]: const parameters cannot depend on type parameters
8+
--> $DIR/const-param-type-depends-on-type-param.rs:4:34
9+
|
10+
LL | pub struct Dependent<T, const X: T>([(); X]);
11+
| ^ const parameter depends on type parameter
12+
13+
error[E0392]: parameter `T` is never used
14+
--> $DIR/const-param-type-depends-on-type-param.rs:4:22
15+
|
16+
LL | pub struct Dependent<T, const X: T>([(); X]);
17+
| ^ unused parameter
18+
|
19+
= help: consider removing `T` or using a marker such as `std::marker::PhantomData`
20+
21+
error: aborting due to 2 previous errors
22+
23+
Some errors have detailed explanations: E0392, E0671.
24+
For more information about an error, try `rustc --explain E0392`.

0 commit comments

Comments
 (0)