about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_resolve/diagnostics.rs13
-rw-r--r--src/librustc_resolve/late.rs14
-rw-r--r--src/librustc_resolve/lib.rs67
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs11
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.stderr31
-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, 135 insertions, 13 deletions
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index a7a005bdeb9..81e29047dc5 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -442,7 +442,7 @@ impl<'a> Resolver<'a> {
                 );
                 err
             }
-            ResolutionError::ParamInTyOfConstArg(name) => {
+            ResolutionError::ParamInTyOfConstParam(name) => {
                 let mut err = struct_span_err!(
                     self.session,
                     span,
@@ -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 dfc50a30c12..234fcd789ee 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -215,7 +215,9 @@ enum ResolutionError<'a> {
     /// Error E0128: type parameters with a default cannot use forward-declared identifiers.
     ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
     /// ERROR E0770: the type of const parameters must not depend on other generic parameters.
-    ParamInTyOfConstArg(Symbol),
+    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
@@ -2514,7 +2516,7 @@ impl<'a> Resolver<'a> {
                         }
                         ConstParamTyRibKind => {
                             if record_used {
-                                self.report_error(span, ParamInTyOfConstArg(rib_ident.name));
+                                self.report_error(span, ParamInTyOfConstParam(rib_ident.name));
                             }
                             return Res::Err;
                         }
@@ -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,
@@ -2545,7 +2569,7 @@ impl<'a> Resolver<'a> {
                             if record_used {
                                 self.report_error(
                                     span,
-                                    ResolutionError::ParamInTyOfConstArg(rib_ident.name),
+                                    ResolutionError::ParamInTyOfConstParam(rib_ident.name),
                                 );
                             }
                             return Res::Err;
@@ -2572,22 +2596,45 @@ 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 => {
                             if record_used {
                                 self.report_error(
                                     span,
-                                    ResolutionError::ParamInTyOfConstArg(rib_ident.name),
+                                    ResolutionError::ParamInTyOfConstParam(rib_ident.name),
                                 );
                             }
                             return Res::Err;
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..84bbea5b880
--- /dev/null
+++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
@@ -0,0 +1,11 @@
+#![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
+//~| ERROR type parameters with a default
+
+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..571be91683b
--- /dev/null
+++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.stderr
@@ -0,0 +1,31 @@
+error: type parameters with a default must be trailing
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:12
+   |
+LL | struct Bar<T = [u8; N], const N: usize>(T);
+   |            ^
+   |
+   = note: using type defaults and const parameters in the same parameter list is currently not permitted
+
+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 3 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
+