about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2021-04-18 16:43:43 +0200
committerlcnr <rust@lcnr.de>2021-04-21 15:25:58 +0200
commitd3e0d2f53dd69bf10b4260760e5fbaddc77c2a3d (patch)
treeb248f895c4123eac71e18ea2ec91c9c65e42266a
parent312b4fdfd281a5ebd740acaf88cc82c47225be23 (diff)
downloadrust-d3e0d2f53dd69bf10b4260760e5fbaddc77c2a3d.tar.gz
rust-d3e0d2f53dd69bf10b4260760e5fbaddc77c2a3d.zip
supply substs to anon consts in defaults
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs4
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs4
-rw-r--r--compiler/rustc_typeck/src/collect.rs39
-rw-r--r--src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr24
-rw-r--r--src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr4
-rw-r--r--src/test/ui/const-generics/defaults/complex-generic-default-expr.rs13
-rw-r--r--src/test/ui/const-generics/defaults/const-param-as-default-value.rs9
-rw-r--r--src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs4
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr22
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr6
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs4
11 files changed, 62 insertions, 71 deletions
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index b6de491911a..62a1584d16b 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -513,7 +513,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     GenericParamDefKind::Const { has_default } => {
                         let ty = tcx.at(self.span).type_of(param.def_id);
                         if !infer_args && has_default {
-                            tcx.const_param_default(param.def_id).into()
+                            tcx.const_param_default(param.def_id)
+                                .subst_spanned(tcx, substs.unwrap(), Some(self.span))
+                                .into()
                         } else {
                             if infer_args {
                                 self.astconv.ct_infer(ty, Some(param), self.span).into()
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 9ace4550421..a50f8e1c655 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -1446,7 +1446,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     GenericParamDefKind::Const { has_default, .. } => {
                         if !infer_args && has_default {
-                            tcx.const_param_default(param.def_id).into()
+                            tcx.const_param_default(param.def_id)
+                                .subst_spanned(tcx, substs.unwrap(), Some(self.span))
+                                .into()
                         } else {
                             self.fcx.var_for_def(self.span, param)
                         }
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 1477418d5d8..927d8c57191 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1316,13 +1316,13 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
     }
 }
 
-struct AnonConstInParamListDetector {
-    in_param_list: bool,
-    found_anon_const_in_list: bool,
+struct AnonConstInParamTyDetector {
+    in_param_ty: bool,
+    found_anon_const_in_param_ty: bool,
     ct: HirId,
 }
 
-impl<'v> Visitor<'v> for AnonConstInParamListDetector {
+impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
     type Map = intravisit::ErasedMap<'v>;
 
     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
@@ -1330,15 +1330,17 @@ impl<'v> Visitor<'v> for AnonConstInParamListDetector {
     }
 
     fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
-        let prev = self.in_param_list;
-        self.in_param_list = true;
-        intravisit::walk_generic_param(self, p);
-        self.in_param_list = prev;
+        if let GenericParamKind::Const { ref ty, default: _ } = p.kind {
+            let prev = self.in_param_ty;
+            self.in_param_ty = true;
+            self.visit_ty(ty);
+            self.in_param_ty = prev;
+        }
     }
 
     fn visit_anon_const(&mut self, c: &'v hir::AnonConst) {
-        if self.in_param_list && self.ct == c.hir_id {
-            self.found_anon_const_in_list = true;
+        if self.in_param_ty && self.ct == c.hir_id {
+            self.found_anon_const_in_param_ty = true;
         } else {
             intravisit::walk_anon_const(self, c)
         }
@@ -1366,27 +1368,24 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             let parent_id = tcx.hir().get_parent_item(hir_id);
             let parent_def_id = tcx.hir().local_def_id(parent_id);
 
-            let mut in_param_list = false;
+            let mut in_param_ty = false;
             for (_parent, node) in tcx.hir().parent_iter(hir_id) {
                 if let Some(generics) = node.generics() {
-                    let mut visitor = AnonConstInParamListDetector {
-                        in_param_list: false,
-                        found_anon_const_in_list: false,
+                    let mut visitor = AnonConstInParamTyDetector {
+                        in_param_ty: false,
+                        found_anon_const_in_param_ty: false,
                         ct: hir_id,
                     };
 
                     visitor.visit_generics(generics);
-                    in_param_list = visitor.found_anon_const_in_list;
+                    in_param_ty = visitor.found_anon_const_in_param_ty;
                     break;
                 }
             }
 
-            if in_param_list {
+            if in_param_ty {
                 // We do not allow generic parameters in anon consts if we are inside
-                // of a param list.
-                //
-                // This affects both default type bindings, e.g. `struct<T, U = [u8; std::mem::size_of::<T>()]>(T, U)`,
-                // and the types of const parameters, e.g. `struct V<const N: usize, const M: [u8; N]>();`.
+                // of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
                 None
             } else if tcx.lazy_normalization() {
                 // HACK(eddyb) this provides the correct generics when
diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr
index c1444abbd3f..e0e2b6c69f2 100644
--- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr
+++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr
@@ -1,16 +1,18 @@
-error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/complex-generic-default-expr.rs:9:62
+error: constant expression depends on a generic parameter
+  --> $DIR/complex-generic-default-expr.rs:6:34
+   |
+LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
+   |                                  ^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/complex-generic-default-expr.rs:10:21
    |
 LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
-   |            -                                                 ^ doesn't have a size known at compile-time
-   |            |
-   |            this type parameter needs to be `std::marker::Sized`
-   | 
-  ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |                     ^^^^^^^^^
    |
-LL | pub const fn size_of<T>() -> usize {
-   |                      - required by this bound in `std::mem::size_of`
+   = note: this may fail depending on what value the parameter takes
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr
index 7d51e9aa0f3..58abd8db9f0 100644
--- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr
+++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr
@@ -1,5 +1,5 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/complex-generic-default-expr.rs:10:47
+  --> $DIR/complex-generic-default-expr.rs:6:47
    |
 LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
    |                                               ^ cannot perform const operation using `N`
@@ -8,7 +8,7 @@ LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
    = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/complex-generic-default-expr.rs:13:62
+  --> $DIR/complex-generic-default-expr.rs:10:62
    |
 LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
    |                                                              ^ cannot perform const operation using `T`
diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs
index a1c04b5e7c3..a7b712f7b4b 100644
--- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs
+++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs
@@ -1,17 +1,14 @@
-// revisions: min
-// FIXME(const_generics): add the `full` revision,
-// currently causes an ICE as we don't supply substs to
-// anon consts in the parameter listing, as that would
-// cause that anon const to reference itself.
+// revisions: full min
 #![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
 struct Foo<const N: usize, const M: usize = { N + 1 }>;
-//[min]~^ ERROR generic parameters may not be used in const operations
+//[full]~^ ERROR constant expression depends on a generic parameter
+//[min]~^^ ERROR generic parameters may not be used in const operations
 
 struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
-//[min]~^ ERROR generic parameters may not be used in const operations
-//[full]~^^ ERROR the size for values of type `T` cannot be known at compilation time
+//[full]~^ ERROR constant expression depends on a generic parameter
+//[min]~^^ ERROR generic parameters may not be used in const operations
 
 fn main() {}
diff --git a/src/test/ui/const-generics/defaults/const-param-as-default-value.rs b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs
index d9cab34327e..59ac261f44f 100644
--- a/src/test/ui/const-generics/defaults/const-param-as-default-value.rs
+++ b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs
@@ -8,7 +8,16 @@ fn foo<const N: usize>() -> Foo<N> {
     Foo(x, x)
 }
 
+// To check that we actually apply the correct substs for const param defaults.
+fn concrete_foo() -> Foo<13> {
+    Foo(Default::default(), Default::default())
+}
+
+
 fn main() {
     let val = foo::<13>();
     assert_eq!(val.0, val.1);
+
+    let val = concrete_foo();
+    assert_eq!(val.0, val.1);
 }
diff --git a/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs
index e3d78fe2ee0..3f534ca0308 100644
--- a/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs
+++ b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs
@@ -1,10 +1,6 @@
 // run-pass
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
-// FIXME(const_generics_defaults): while we can allow this,
-// we probably won't easily allow this with more complex const operations.
-//
-// So we have to make a conscious decision here when stabilizing a relaxed parameter ordering.
 struct Foo<const N: usize, T = [u8; N]>(T);
 
 impl<const N: usize> Foo<N> {
diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
index cf947a565c4..e8fd9e7769b 100644
--- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
+++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
@@ -1,5 +1,5 @@
 error: generic parameters with a default must be trailing
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:12
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
    |            ^
@@ -7,25 +7,11 @@ 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[E0128]: generic parameters with a default cannot use forward declared identifiers
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:21
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
    |                     ^ defaulted generic parameters cannot be forward declared
 
-error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44
-   |
-LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
-   |            -                               ^ doesn't have a size known at compile-time
-   |            |
-   |            this type parameter needs to be `std::marker::Sized`
-   | 
-  ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      - required by this bound in `std::mem::size_of`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0128, E0277.
-For more information about an error, try `rustc --explain E0128`.
+For more information about this error, try `rustc --explain E0128`.
diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
index 4c97012f361..5fa6423306c 100644
--- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
+++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
@@ -1,5 +1,5 @@
 error: generic parameters with a default must be trailing
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:12
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
    |            ^
@@ -7,7 +7,7 @@ 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: generic parameters may not be used in const operations
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:5:44
    |
 LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    |                                            ^ cannot perform const operation using `T`
@@ -16,7 +16,7 @@ LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
 error[E0128]: generic parameters with a default cannot use forward declared identifiers
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:21
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
    |                     ^ defaulted generic parameters cannot be forward declared
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
index bf4f9558adc..76c1b84aef5 100644
--- 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
@@ -1,11 +1,9 @@
 // revisions: full min
-
 #![cfg_attr(full, feature(const_generics))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
-//[full]~^ ERROR the size for values of type `T` cannot be known at compilation time
-//[min]~^^ ERROR generic parameters may not be used in const operations
+//[min]~^ ERROR generic parameters may not be used in const operations
 
 struct Bar<T = [u8; N], const N: usize>(T);
 //~^ ERROR generic parameters with a default cannot use forward declared identifiers