about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBastian Kauschke <bastian_kauschke@hotmail.de>2020-07-18 23:42:10 +0200
committerBastian Kauschke <bastian_kauschke@hotmail.de>2020-07-27 16:33:23 +0200
commit33a05b40f7bb077221e567243ada983deabd2261 (patch)
treef59214f3e0c33782a5958d6375a51b4b3f196890
parentcb19cdb711120123a2f5803b6c0a57012206765d (diff)
downloadrust-33a05b40f7bb077221e567243ada983deabd2261.tar.gz
rust-33a05b40f7bb077221e567243ada983deabd2261.zip
forbid generic params inside of anon consts in ty defaults
-rw-r--r--src/librustc_resolve/diagnostics.rs11
-rw-r--r--src/librustc_resolve/late.rs14
-rw-r--r--src/librustc_resolve/lib.rs59
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs10
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.stderr23
-rw-r--r--src/test/ui/generic/param-in-ct-in-ty-param-default.rs4
-rw-r--r--src/test/ui/generic/param-in-ct-in-ty-param-default.stderr8
7 files changed, 121 insertions, 8 deletions
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 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
 
                     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 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
     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 @@ impl<'a> Resolver<'a> {
                 }
             }
             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<T, U = [u8; std::mem::size_of::<T>()]>`
+                        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 @@ impl<'a> Resolver<'a> {
                     // (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<T, U = [u8; std::mem::size_of::<T>()]>`
+                        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 = [u8; std::mem::size_of::<T>()]>(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 = [u8; N], const N: usize>(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 = [u8; std::mem::size_of::<T>()]>(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 = [u8; N], const N: usize>(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 <https://github.com/rust-lang/rust/issues/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 = [u8; std::mem::size_of::<T>()]>(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 = [u8; std::mem::size_of::<T>()]>(T, U);
+   |                                            ^ the anonymous constant must not depend on the parameter `T`
+
+error: aborting due to previous error
+