about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBastian Kauschke <bastian_kauschke@hotmail.de>2020-07-08 22:16:18 +0200
committerBastian Kauschke <bastian_kauschke@hotmail.de>2020-07-16 11:13:05 +0200
commit338a27174a0bd900e573b2ee0e7383244a8b0bf9 (patch)
treea570321149ca2c501e430852c252389972c5d4c9
parente2e29de5e8a2908260d54182638241ff086a26c2 (diff)
downloadrust-338a27174a0bd900e573b2ee0e7383244a8b0bf9.tar.gz
rust-338a27174a0bd900e573b2ee0e7383244a8b0bf9.zip
forbid generic params in the type of const params
-rw-r--r--src/librustc_error_codes/error_codes.rs1
-rw-r--r--src/librustc_error_codes/error_codes/E0671.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0770.md15
-rw-r--r--src/librustc_resolve/diagnostics.rs10
-rw-r--r--src/librustc_resolve/late.rs14
-rw-r--r--src/librustc_resolve/lib.rs28
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-const-param.rs13
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr31
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs2
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr17
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param.rs11
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr18
-rw-r--r--src/test/ui/const-generics/issues/issue-71381.rs2
-rw-r--r--src/test/ui/const-generics/issues/issue-71381.stderr16
-rw-r--r--src/test/ui/const-generics/issues/issue-71611.rs1
-rw-r--r--src/test/ui/const-generics/issues/issue-71611.stderr8
16 files changed, 160 insertions, 29 deletions
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 60aa12b0511..6160450d766 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -452,6 +452,7 @@ E0766: include_str!("./error_codes/E0766.md"),
 E0767: include_str!("./error_codes/E0767.md"),
 E0768: include_str!("./error_codes/E0768.md"),
 E0769: include_str!("./error_codes/E0769.md"),
+E0770: include_str!("./error_codes/E0770.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/src/librustc_error_codes/error_codes/E0671.md b/src/librustc_error_codes/error_codes/E0671.md
index 449fb8ffc89..a993ce826a7 100644
--- a/src/librustc_error_codes/error_codes/E0671.md
+++ b/src/librustc_error_codes/error_codes/E0671.md
@@ -3,7 +3,7 @@
 Const parameters cannot depend on type parameters.
 The following is therefore invalid:
 
-```compile_fail,E0741
+```compile_fail,E0770
 #![feature(const_generics)]
 
 fn const_id<T, const N: T>() -> T { // error
diff --git a/src/librustc_error_codes/error_codes/E0770.md b/src/librustc_error_codes/error_codes/E0770.md
new file mode 100644
index 00000000000..278bf9b907b
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0770.md
@@ -0,0 +1,15 @@
+The type of a const parameter references other generic parameters.
+
+Erroneous code example:
+
+```compile_fail,E0770
+#![feature(const_generics)]
+fn foo<T, const N: T>() {} // error!
+```
+
+To fix this error, use a concrete type for the const parameter:
+
+```
+#![feature(const_generics)]
+fn foo<T, const N: usize>() {}
+```
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 4f25b948eb6..c5ac7f7413a 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -442,6 +442,16 @@ impl<'a> Resolver<'a> {
                 );
                 err
             }
+            ResolutionError::ParamInTyOfConstArg => {
+                let mut err = struct_span_err!(
+                    self.session,
+                    span,
+                    E0770,
+                    "the type of const parameters must not depend on other generic parameters"
+                );
+                err.span_label(span, "const parameters must have a concrete type");
+                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 c165a601408..b252e5f29a3 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -123,6 +123,10 @@ crate 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 are inside of the type of a const parameter. Can't refer to any
+    /// parameters.
+    ConstParamTyRibKind,
 }
 
 impl RibKind<'_> {
@@ -135,7 +139,8 @@ impl RibKind<'_> {
             | FnItemRibKind
             | ConstantItemRibKind
             | ModuleRibKind(_)
-            | MacroDefinition(_) => false,
+            | MacroDefinition(_)
+            | ConstParamTyRibKind => false,
             AssocItemRibKind | ItemRibKind(_) | ForwardTyParamBanRibKind => true,
         }
     }
@@ -562,7 +567,11 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                     for bound in &param.bounds {
                         self.visit_param_bound(bound);
                     }
+                    self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
+                    self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
                     self.visit_ty(ty);
+                    self.ribs[TypeNS].pop().unwrap();
+                    self.ribs[ValueNS].pop().unwrap();
                 }
             }
         }
@@ -798,7 +807,8 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 | ItemRibKind(..)
                 | ConstantItemRibKind
                 | ModuleRibKind(..)
-                | ForwardTyParamBanRibKind => {
+                | ForwardTyParamBanRibKind
+                | ConstParamTyRibKind => {
                     return false;
                 }
             }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index a265c15c18b..ba365e8f841 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -214,6 +214,8 @@ enum ResolutionError<'a> {
     BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'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,
     /// Error E0735: type parameters with a default cannot use `Self`
     SelfInTyParamDefault,
     /// Error E0767: use of unreachable label
@@ -2480,6 +2482,12 @@ impl<'a> Resolver<'a> {
                             }
                             return Res::Err;
                         }
+                        ConstParamTyRibKind => {
+                            if record_used {
+                                self.report_error(span, ParamInTyOfConstArg);
+                            }
+                            return Res::Err;
+                        }
                     }
                 }
                 if let Some(res_err) = res_err {
@@ -2503,6 +2511,12 @@ impl<'a> Resolver<'a> {
                         // This was an attempt to use a type parameter outside its scope.
                         ItemRibKind(has_generic_params) => has_generic_params,
                         FnItemRibKind => HasGenericParams::Yes,
+                        ConstParamTyRibKind => {
+                            if record_used {
+                                self.report_error(span, ResolutionError::ParamInTyOfConstArg);
+                            }
+                            return Res::Err;
+                        }
                     };
 
                     if record_used {
@@ -2527,9 +2541,21 @@ impl<'a> Resolver<'a> {
                 }
                 for rib in ribs {
                     let has_generic_params = match rib.kind {
+                        NormalRibKind
+                        | ClosureOrAsyncRibKind
+                        | AssocItemRibKind
+                        | ModuleRibKind(..)
+                        | MacroDefinition(..)
+                        | ForwardTyParamBanRibKind
+                        | ConstantItemRibKind => continue,
                         ItemRibKind(has_generic_params) => has_generic_params,
                         FnItemRibKind => HasGenericParams::Yes,
-                        _ => continue,
+                        ConstParamTyRibKind => {
+                            if record_used {
+                                self.report_error(span, ResolutionError::ParamInTyOfConstArg);
+                            }
+                            return Res::Err;
+                        }
                     };
 
                     // This was an attempt to use a const parameter outside its scope.
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs
new file mode 100644
index 00000000000..6eb13c38e02
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs
@@ -0,0 +1,13 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete
+
+// Currently, const parameters cannot depend on other generic parameters,
+// as our current implementation can't really support this.
+//
+// We may want to lift this restriction in the future.
+
+pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
+//~^ ERROR: the type of const parameters must not depend on other generic parameters
+//~| ERROR: cycle detected when computing type of `Dependent::X`
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr
new file mode 100644
index 00000000000..63416732bf4
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr
@@ -0,0 +1,31 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-const-param.rs:9:52
+   |
+LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
+   |                                                    ^ const parameters must have a concrete type
+
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/const-param-type-depends-on-const-param.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[E0391]: cycle detected when computing type of `Dependent::X`
+  --> $DIR/const-param-type-depends-on-const-param.rs:9:44
+   |
+LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
+   |                                            ^
+   |
+   = note: ...which again requires computing type of `Dependent::X`, completing the cycle
+note: cycle used when computing type of `Dependent`
+  --> $DIR/const-param-type-depends-on-const-param.rs:9:1
+   |
+LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0391`.
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
index 86ab8075896..db15ececfa4 100644
--- 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
@@ -1,6 +1,6 @@
 use std::marker::PhantomData;
 
 struct B<T, const N: T>(PhantomData<[T; N]>); //~ ERROR const generics are unstable
-//~^ ERROR `T` is not guaranteed to `#[derive(PartialEq, Eq)]`
+//~^ ERROR the type of const parameters must not depend on other generic 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
index 92a7edf96bc..a2182d9edaf 100644
--- 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
@@ -1,3 +1,9 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
+   |
+LL | struct B<T, const N: T>(PhantomData<[T; N]>);
+   |                      ^ const parameters must have a concrete type
+
 error[E0658]: const generics are unstable
   --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19
    |
@@ -7,15 +13,6 @@ LL | struct B<T, const N: T>(PhantomData<[T; N]>);
    = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
 
-error[E0741]: `T` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be used as the type of a const parameter
-  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
-   |
-LL | struct B<T, const N: T>(PhantomData<[T; N]>);
-   |                      ^ `T` may not derive both `PartialEq` and `Eq`
-   |
-   = note: it is not currently possible to use a type parameter as the type of a const parameter
-
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0658, E0741.
-For more information about an error, try `rustc --explain E0658`.
+For more information about this 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
index 654e36df37e..7fe04a43412 100644
--- 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
@@ -1,12 +1,13 @@
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete
 
-// 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.
+// Currently, const parameters cannot depend on other generic parameters,
+// as our current implementation can't really support this.
+//
+// We may want to lift this restriction in the future.
 
 pub struct Dependent<T, const X: T>([(); X]);
-//~^ ERROR `T` is not guaranteed to `#[derive(PartialEq, Eq)]`
+//~^ ERROR: the type of const parameters must not depend on other generic 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
index ed05264161e..606bb4f4fe7 100644
--- 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
@@ -1,3 +1,9 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-type-param.rs:9:34
+   |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+   |                                  ^ const parameters must have a concrete type
+
 warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/const-param-type-depends-on-type-param.rs:1:12
    |
@@ -7,14 +13,14 @@ 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[E0741]: `T` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be used as the type of a const parameter
-  --> $DIR/const-param-type-depends-on-type-param.rs:9:34
+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]);
-   |                                  ^ `T` may not derive both `PartialEq` and `Eq`
+   |                      ^ unused parameter
    |
-   = note: it is not currently possible to use a type parameter as the type of a const parameter
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0741`.
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/issue-71381.rs b/src/test/ui/const-generics/issues/issue-71381.rs
index c32bd2847f8..08f94823942 100644
--- a/src/test/ui/const-generics/issues/issue-71381.rs
+++ b/src/test/ui/const-generics/issues/issue-71381.rs
@@ -12,6 +12,7 @@ unsafe extern "C" fn pass(args: PassArg) {
 impl Test {
     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
         //~^ ERROR: using function pointers as const generic parameters is forbidden
+        //~| ERROR: the type of const parameters must not depend on other generic parameters
         self.0 = Self::trampiline::<Args, IDX, FN> as _
     }
 
@@ -20,6 +21,7 @@ impl Test {
         const IDX: usize,
         const FN: unsafe extern "C" fn(Args),
         //~^ ERROR: using function pointers as const generic parameters is forbidden
+        //~| ERROR: the type of const parameters must not depend on other generic parameters
     >(
         args: Args,
     ) {
diff --git a/src/test/ui/const-generics/issues/issue-71381.stderr b/src/test/ui/const-generics/issues/issue-71381.stderr
index 6bb776fcfc0..177a2cdf14c 100644
--- a/src/test/ui/const-generics/issues/issue-71381.stderr
+++ b/src/test/ui/const-generics/issues/issue-71381.stderr
@@ -1,3 +1,15 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/issue-71381.rs:13:82
+   |
+LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
+   |                                                                                  ^^^^ const parameters must have a concrete type
+
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/issue-71381.rs:22:40
+   |
+LL |         const FN: unsafe extern "C" fn(Args),
+   |                                        ^^^^ const parameters must have a concrete type
+
 error: using function pointers as const generic parameters is forbidden
   --> $DIR/issue-71381.rs:13:61
    |
@@ -5,10 +17,10 @@ LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "
    |                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: using function pointers as const generic parameters is forbidden
-  --> $DIR/issue-71381.rs:21:19
+  --> $DIR/issue-71381.rs:22:19
    |
 LL |         const FN: unsafe extern "C" fn(Args),
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-71611.rs b/src/test/ui/const-generics/issues/issue-71611.rs
index 64a049e743f..06ff38dec66 100644
--- a/src/test/ui/const-generics/issues/issue-71611.rs
+++ b/src/test/ui/const-generics/issues/issue-71611.rs
@@ -3,6 +3,7 @@
 
 fn func<A, const F: fn(inner: A)>(outer: A) {
     //~^ ERROR: using function pointers as const generic parameters is forbidden
+    //~| ERROR: the type of const parameters must not depend on other generic parameters
     F(outer);
 }
 
diff --git a/src/test/ui/const-generics/issues/issue-71611.stderr b/src/test/ui/const-generics/issues/issue-71611.stderr
index 9a7bf1c0a88..fe8978b4298 100644
--- a/src/test/ui/const-generics/issues/issue-71611.stderr
+++ b/src/test/ui/const-generics/issues/issue-71611.stderr
@@ -1,8 +1,14 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/issue-71611.rs:4:31
+   |
+LL | fn func<A, const F: fn(inner: A)>(outer: A) {
+   |                               ^ const parameters must have a concrete type
+
 error: using function pointers as const generic parameters is forbidden
   --> $DIR/issue-71611.rs:4:21
    |
 LL | fn func<A, const F: fn(inner: A)>(outer: A) {
    |                     ^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors