From 33a05b40f7bb077221e567243ada983deabd2261 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 18 Jul 2020 23:42:10 +0200 Subject: [PATCH] forbid generic params inside of anon consts in ty defaults --- src/librustc_resolve/diagnostics.rs | 11 ++++ src/librustc_resolve/late.rs | 14 ++++- src/librustc_resolve/lib.rs | 59 +++++++++++++++++-- .../params-in-ct-in-ty-param-lazy-norm.rs | 10 ++++ .../params-in-ct-in-ty-param-lazy-norm.stderr | 23 ++++++++ .../param-in-ct-in-ty-param-default.rs | 4 ++ .../param-in-ct-in-ty-param-default.stderr | 8 +++ 7 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs create mode 100644 src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.stderr create mode 100644 src/test/ui/generic/param-in-ct-in-ty-param-default.rs create mode 100644 src/test/ui/generic/param-in-ct-in-ty-param-default.stderr diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index c512703b3c6..81e29047dc5 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -455,6 +455,17 @@ impl<'a> Resolver<'a> { ); err } + ResolutionError::ParamInAnonConstInTyDefault(name) => { + let mut err = self.session.struct_span_err( + span, + "constant values inside of type parameter defaults must not depend on generic parameters", + ); + err.span_label( + span, + format!("the anonymous constant must not depend on the parameter `{}`", name), + ); + err + } ResolutionError::SelfInTyParamDefault => { let mut err = struct_span_err!( self.session, diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 4b5ab03df43..bcd2c6c1f1c 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -570,7 +570,15 @@ fn visit_generics(&mut self, generics: &'ast Generics) { if let Some(ref ty) = default { self.ribs[TypeNS].push(default_ban_rib); - self.visit_ty(ty); + self.with_rib(ValueNS, ForwardTyParamBanRibKind, |this| { + // HACK: We use an empty `ForwardTyParamBanRibKind` here which + // is only used to forbid the use of const parameters inside of + // type defaults. + // + // While the rib name doesn't really fit here, it does allow us to use the same + // code for both const and type parameters. + this.visit_ty(ty); + }); default_ban_rib = self.ribs[TypeNS].pop().unwrap(); } @@ -1081,7 +1089,9 @@ fn with_item_rib(&mut self, has_generic_params: HasGenericParams, f: impl FnOnce fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) { debug!("with_constant_rib"); self.with_rib(ValueNS, ConstantItemRibKind, |this| { - this.with_label_rib(ConstantItemRibKind, f); + this.with_rib(TypeNS, ConstantItemRibKind, |this| { + this.with_label_rib(ConstantItemRibKind, f); + }) }); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 3b049c6bb4a..234fcd789ee 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -216,6 +216,8 @@ enum ResolutionError<'a> { ForwardDeclaredTyParam, // FIXME(const_generics:defaults) /// ERROR E0770: the type of const parameters must not depend on other generic parameters. ParamInTyOfConstParam(Symbol), + /// constant values inside of type parameter defaults must not depend on generic parameters. + ParamInAnonConstInTyDefault(Symbol), /// Error E0735: type parameters with a default cannot use `Self` SelfInTyParamDefault, /// Error E0767: use of unreachable label @@ -2526,18 +2528,40 @@ fn validate_res_from_ribs( } } Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => { + let mut in_ty_param_default = false; for rib in ribs { let has_generic_params = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) - | ForwardTyParamBanRibKind - | ConstantItemRibKind => { + | MacroDefinition(..) => { // Nothing to do. Continue. continue; } + + // We only forbid constant items if we are inside of type defaults, + // for example `struct Foo()]>` + ForwardTyParamBanRibKind => { + in_ty_param_default = true; + continue; + } + ConstantItemRibKind => { + if in_ty_param_default { + if record_used { + self.report_error( + span, + ResolutionError::ParamInAnonConstInTyDefault( + rib_ident.name, + ), + ); + } + return Res::Err; + } else { + continue; + } + } + // This was an attempt to use a type parameter outside its scope. ItemRibKind(has_generic_params) => has_generic_params, FnItemRibKind => HasGenericParams::Yes, @@ -2572,15 +2596,38 @@ fn validate_res_from_ribs( // (spuriously) conflicting with the const param. ribs.next(); } + + let mut in_ty_param_default = false; for rib in ribs { let has_generic_params = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) - | ForwardTyParamBanRibKind - | ConstantItemRibKind => continue, + | MacroDefinition(..) => continue, + + // We only forbid constant items if we are inside of type defaults, + // for example `struct Foo()]>` + ForwardTyParamBanRibKind => { + in_ty_param_default = true; + continue; + } + ConstantItemRibKind => { + if in_ty_param_default { + if record_used { + self.report_error( + span, + ResolutionError::ParamInAnonConstInTyDefault( + rib_ident.name, + ), + ); + } + return Res::Err; + } else { + continue; + } + } + ItemRibKind(has_generic_params) => has_generic_params, FnItemRibKind => HasGenericParams::Yes, ConstParamTyRibKind => { diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs new file mode 100644 index 00000000000..c118fa7acc4 --- /dev/null +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -0,0 +1,10 @@ +#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete + +struct Foo()]>(T, U); +//~^ ERROR constant values inside of type parameter defaults + +// FIXME(const_generics:defaults): We still don't know how to we deal with type defaults. +struct Bar(T); +//~^ ERROR constant values inside of type parameter defaults + +fn main() {} diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.stderr new file mode 100644 index 00000000000..8e6676b01f1 --- /dev/null +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.stderr @@ -0,0 +1,23 @@ +error: constant values inside of type parameter defaults must not depend on generic parameters + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:3:44 + | +LL | struct Foo()]>(T, U); + | ^ the anonymous constant must not depend on the parameter `T` + +error: constant values inside of type parameter defaults must not depend on generic parameters + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:21 + | +LL | struct Bar(T); + | ^ the anonymous constant must not depend on the parameter `N` + +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/src/test/ui/generic/param-in-ct-in-ty-param-default.rs b/src/test/ui/generic/param-in-ct-in-ty-param-default.rs new file mode 100644 index 00000000000..dd89bc0f7a0 --- /dev/null +++ b/src/test/ui/generic/param-in-ct-in-ty-param-default.rs @@ -0,0 +1,4 @@ +struct Foo()]>(T, U); +//~^ ERROR constant values inside of type parameter defaults + +fn main() {} diff --git a/src/test/ui/generic/param-in-ct-in-ty-param-default.stderr b/src/test/ui/generic/param-in-ct-in-ty-param-default.stderr new file mode 100644 index 00000000000..ea867240269 --- /dev/null +++ b/src/test/ui/generic/param-in-ct-in-ty-param-default.stderr @@ -0,0 +1,8 @@ +error: constant values inside of type parameter defaults must not depend on generic parameters + --> $DIR/param-in-ct-in-ty-param-default.rs:1:44 + | +LL | struct Foo()]>(T, U); + | ^ the anonymous constant must not depend on the parameter `T` + +error: aborting due to previous error + -- 2.44.0