Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not allow const generics to depend on type parameters #60284

Merged
merged 5 commits into from
Apr 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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`.