about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-07-10 06:01:04 +0000
committerbors <bors@rust-lang.org>2021-07-10 06:01:04 +0000
commita84d1b21aea9863f0fc5f436b4982d145dade646 (patch)
treea85f0777ccf4782a6054403bcb6304f8513963a4
parent8eae2eb1d31da4b0bbdb80dcf2625535c3f147ae (diff)
parent4a53b115181a16d681dc05b312bbc913b7f836ac (diff)
downloadrust-a84d1b21aea9863f0fc5f436b4982d145dade646.tar.gz
rust-a84d1b21aea9863f0fc5f436b4982d145dade646.zip
Auto merge of #86987 - lcnr:const-default-eval-bound, r=oli-obk
only check cg defaults wf once instantiated

the previous fixmes here didn't make too much sense as I didn't yet fully understand the code further below.
That code only runs if the predicates using our generic param default are fully concrete after substituting our default, which never happens if our default is generic.

r? `@oli-obk` `@BoxyUwU`
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs26
-rw-r--r--compiler/rustc_typeck/src/collect.rs10
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs6
-rw-r--r--src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr18
-rw-r--r--src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr2
-rw-r--r--src/test/ui/const-generics/defaults/complex-generic-default-expr.rs7
6 files changed, 31 insertions, 38 deletions
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 0e063c86f2f..4838d70a831 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -738,15 +738,19 @@ fn check_where_clauses<'tcx, 'fcx>(
                 }
             }
             GenericParamDefKind::Const { .. } => {
-                // FIXME(const_generics_defaults): Figure out if this
-                // is the behavior we want, see the comment further below.
                 if is_our_default(&param) {
+                    // FIXME(const_generics_defaults): This
+                    // is incorrect when dealing with unused substs, for example
+                    // for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
+                    // we should eagerly error.
                     let default_ct = tcx.const_param_default(param.def_id);
-                    fcx.register_wf_obligation(
-                        default_ct.into(),
-                        tcx.def_span(param.def_id),
-                        ObligationCauseCode::MiscObligation,
-                    );
+                    if !default_ct.needs_subst() {
+                        fcx.register_wf_obligation(
+                            default_ct.into(),
+                            tcx.def_span(param.def_id),
+                            ObligationCauseCode::MiscObligation,
+                        );
+                    }
                 }
             }
             // Doesn't have defaults.
@@ -783,14 +787,6 @@ fn check_where_clauses<'tcx, 'fcx>(
                 tcx.mk_param_from_def(param)
             }
             GenericParamDefKind::Const { .. } => {
-                // FIXME(const_generics_defaults): I(@lcnr) feel like always
-                // using the const parameter is the right choice here, even
-                // if it needs substs.
-                //
-                // Before stabilizing this we probably want to get some tests
-                // where this makes a difference and figure out what's the exact
-                // behavior we want here.
-
                 // If the param has a default, ...
                 if is_our_default(param) {
                     let default_ct = tcx.const_param_default(param.def_id);
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index b0e5453b7db..583ba9392f0 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -2308,6 +2308,16 @@ fn const_evaluatable_predicates_of<'tcx>(
                 ));
             }
         }
+
+        fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) {
+            // Do not look into const param defaults,
+            // these get checked when they are actually instantiated.
+            //
+            // We do not want the following to error:
+            //
+            //     struct Foo<const N: usize, const M: usize = { N + 1 }>;
+            //     struct Bar<const N: usize>(Foo<N, 3>);
+        }
     }
 
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs b/src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs
new file mode 100644
index 00000000000..21f14f58ab5
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs
@@ -0,0 +1,6 @@
+// check-pass
+#![feature(const_generics, const_evaluatable_checked, const_generics_defaults)]
+#![allow(incomplete_features)]
+struct Foo<const N: usize, const M: usize = { N + 1 }>;
+struct Bar<const N: usize>(Foo<N, 3>);
+fn main() {}
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
deleted file mode 100644
index e0e2b6c69f2..00000000000
--- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-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);
-   |                     ^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
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 58abd8db9f0..44df2ac9f40 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:6:47
+  --> $DIR/complex-generic-default-expr.rs:7:47
    |
 LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
    |                                               ^ cannot perform const operation using `N`
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 a7b712f7b4b..d3558007977 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,14 +1,13 @@
 // revisions: full min
+//[full] check-pass
 #![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
 struct Foo<const N: usize, const M: usize = { N + 1 }>;
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[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, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used in const operations
+//[min]~^ ERROR generic parameters may not be used in const operations
 
 fn main() {}