diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index 5c095994a1bbd..d3b66ddb4a7b4 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1642,6 +1642,16 @@ fn main() { ``` "##, +E0671: r##" +Const parameters cannot depend on type parameters. +The following is therefore invalid: +``` +fn const_id() -> T { + N +} +``` +"##, + } register_diagnostics! { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 7754bb26f9055..80b82bc4dbd84 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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. @@ -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 + } } } @@ -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), @@ -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 ¶m.bounds { self.visit_param_bound(bound); } self.visit_ty(ty); + + const_ty_param_ban_rib = self.ribs[TypeNS].pop().unwrap(); } } } @@ -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. @@ -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) @@ -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) => { @@ -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 => { diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs new file mode 100644 index 0000000000000..af5e8f49754e8 --- /dev/null +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs @@ -0,0 +1,6 @@ +use std::marker::PhantomData; + +struct B(PhantomData<[T; N]>); //~ ERROR const generics are unstable +//~^ ERROR const parameters cannot depend on type parameters + +fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr new file mode 100644 index 0000000000000..e3adbcfe60204 --- /dev/null +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr @@ -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(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(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`. diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs new file mode 100644 index 0000000000000..ca924695993ca --- /dev/null +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs @@ -0,0 +1,7 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +pub struct Dependent([(); X]); //~ ERROR const parameters +//~^ ERROR parameter `T` is never used + +fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr new file mode 100644 index 0000000000000..0722c2c99fe07 --- /dev/null +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr @@ -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:4:34 + | +LL | pub struct Dependent([(); X]); + | ^ const parameter depends on type parameter + +error[E0392]: parameter `T` is never used + --> $DIR/const-param-type-depends-on-type-param.rs:4:22 + | +LL | pub struct Dependent([(); 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`.