Skip to content

Commit

Permalink
Rollup merge of rust-lang#60284 - varkor:const-param-of-type-param, r…
Browse files Browse the repository at this point in the history
…=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).
  • Loading branch information
Centril authored Apr 26, 2019
2 parents 4387f99 + 6d7c794 commit 3a907ce
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 2 deletions.
13 changes: 13 additions & 0 deletions src/librustc_resolve/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,19 @@ fn main() {
```
"##,

E0671: r##"
Const parameters cannot depend on type parameters.
The following is therefore invalid:
```compile_fail,E0671
#![feature(const_generics)]
fn const_id<T, const N: T>() -> T { // error: const parameter
// depends on type parameter
N
}
```
"##,

}

register_diagnostics! {
Expand Down
44 changes: 42 additions & 2 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ enum ResolutionError<'a> {
BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
/// Error E0671: const parameter cannot depend on type parameter.
ConstParamDependentOnTypeParam,
}

/// Combines an error with provided span and emits it.
Expand Down Expand Up @@ -440,6 +442,16 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
span, "defaulted type parameters cannot be forward declared".to_string());
err
}
ResolutionError::ConstParamDependentOnTypeParam => {
let mut err = struct_span_err!(
resolver.session,
span,
E0671,
"const parameters cannot depend on type parameters"
);
err.span_label(span, format!("const parameter depends on type parameter"));
err
}
}
}

Expand Down Expand Up @@ -915,6 +927,18 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
}
}));

// We also ban access to type parameters for use as the types of const parameters.
let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy);
const_ty_param_ban_rib.bindings.extend(generics.params.iter()
.filter(|param| {
if let GenericParamKind::Type { .. } = param.kind {
true
} else {
false
}
})
.map(|param| (Ident::with_empty_ctxt(param.ident.name), Def::Err)));

for param in &generics.params {
match param.kind {
GenericParamKind::Lifetime { .. } => self.visit_generic_param(param),
Expand All @@ -933,11 +957,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
}
GenericParamKind::Const { ref ty } => {
self.ribs[TypeNS].push(const_ty_param_ban_rib);

for bound in &param.bounds {
self.visit_param_bound(bound);
}

self.visit_ty(ty);

const_ty_param_ban_rib = self.ribs[TypeNS].pop().unwrap();
}
}
}
Expand Down Expand Up @@ -994,6 +1022,9 @@ enum RibKind<'a> {
/// from the default of a type parameter because they're not declared
/// before said type parameter. Also see the `visit_generics` override.
ForwardTyParamBanRibKind,

/// We forbid the use of type parameters as the types of const parameters.
TyParamAsConstParamTy,
}

/// A single local scope.
Expand Down Expand Up @@ -3944,6 +3975,15 @@ impl<'a> Resolver<'a> {
return Def::Err;
}

// An invalid use of a type parameter as the type of a const parameter.
if let TyParamAsConstParamTy = self.ribs[ns][rib_index].kind {
if record_used {
resolve_error(self, span, ResolutionError::ConstParamDependentOnTypeParam);
}
assert_eq!(def, Def::Err);
return Def::Err;
}

match def {
Def::Upvar(..) => {
span_bug!(span, "unexpected {:?} in bindings", def)
Expand All @@ -3955,7 +3995,7 @@ impl<'a> Resolver<'a> {
for rib in ribs {
match rib.kind {
NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) |
ForwardTyParamBanRibKind => {
ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
// Nothing to do. Continue.
}
ClosureRibKind(function_id) => {
Expand Down Expand Up @@ -4013,7 +4053,7 @@ impl<'a> Resolver<'a> {
match rib.kind {
NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) |
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
ConstantItemRibKind => {
ConstantItemRibKind | TyParamAsConstParamTy => {
// Nothing to do. Continue.
}
ItemRibKind | FnItemRibKind => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use std::marker::PhantomData;

struct B<T, const N: T>(PhantomData<[T; N]>); //~ ERROR const generics are unstable
//~^ ERROR const parameters cannot depend on type parameters

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0671]: const parameters cannot depend on type parameters
--> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
|
LL | struct B<T, const N: T>(PhantomData<[T; N]>);
| ^ const parameter depends on type parameter

error[E0658]: const generics are unstable
--> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19
|
LL | struct B<T, const N: T>(PhantomData<[T; N]>);
| ^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
= help: add #![feature(const_generics)] to the crate attributes to enable

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0658, E0671.
For more information about an error, try `rustc --explain E0658`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash

// Currently, const parameters cannot depend on type parameters, because there is no way to
// enforce the `structural_match` property on an arbitrary type parameter. This restriction
// may be relaxed in the future. See https://github.com/rust-lang/rfcs/pull/2000 for more
// details.

pub struct Dependent<T, const X: T>([(); X]);
//~^ ERROR const parameters cannot depend on type parameters
//~^^ ERROR parameter `T` is never used

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/const-param-type-depends-on-type-param.rs:1:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^

error[E0671]: const parameters cannot depend on type parameters
--> $DIR/const-param-type-depends-on-type-param.rs:9:34
|
LL | pub struct Dependent<T, const X: T>([(); X]);
| ^ const parameter depends on type parameter

error[E0392]: parameter `T` is never used
--> $DIR/const-param-type-depends-on-type-param.rs:9:22
|
LL | pub struct Dependent<T, const X: T>([(); X]);
| ^ unused parameter
|
= help: consider removing `T` or using a marker such as `std::marker::PhantomData`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0392, E0671.
For more information about an error, try `rustc --explain E0392`.

0 comments on commit 3a907ce

Please sign in to comment.