about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs30
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr8
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr2
-rw-r--r--src/test/ui/const_evaluatable/needs_where_clause.rs14
-rw-r--r--src/test/ui/const_evaluatable/needs_where_clause.stderr14
-rw-r--r--src/test/ui/const_evaluatable/no_where_clause.rs29
-rw-r--r--src/test/ui/const_evaluatable/no_where_clause.stderr14
7 files changed, 93 insertions, 18 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index b587ed6487e..5240df6cf1e 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -16,8 +16,7 @@ use rustc_infer::infer::InferCtxt;
 use rustc_middle::mir::abstract_const::{Node, NodeId};
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::mir::{self, Rvalue, StatementKind, TerminatorKind};
-use rustc_middle::ty::subst::Subst;
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 use rustc_session::lint;
 use rustc_span::def_id::{DefId, LocalDefId};
@@ -43,10 +42,6 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
                 for pred in param_env.caller_bounds() {
                     match pred.kind().skip_binder() {
                         ty::PredicateKind::ConstEvaluatable(b_def, b_substs) => {
-                            debug!(
-                                "is_const_evaluatable: caller_bound={:?}, {:?}",
-                                b_def, b_substs
-                            );
                             if b_def == def && b_substs == substs {
                                 debug!("is_const_evaluatable: caller_bound ~~> ok");
                                 return Ok(());
@@ -100,15 +95,24 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
                     }
                     FailureKind::MentionsParam => {
                         // FIXME(const_evaluatable_checked): Better error message.
-                        infcx
-                            .tcx
-                            .sess
-                            .struct_span_err(span, "unconstrained generic constant")
-                            .span_help(
+                        let mut err =
+                            infcx.tcx.sess.struct_span_err(span, "unconstrained generic constant");
+                        let const_span = tcx.def_span(def.did);
+                        // FIXME(const_evaluatable_checked): Update this suggestion once
+                        // explicit const evaluatable bounds are implemented.
+                        if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(const_span)
+                        {
+                            err.span_help(
                                 tcx.def_span(def.did),
+                                &format!("try adding a `where` bound using this expression: where [u8; {}]: Sized", snippet),
+                            );
+                        } else {
+                            err.span_help(
+                                const_span,
                                 "consider adding a `where` bound for this expression",
-                            )
-                            .emit();
+                            );
+                        }
+                        err.emit();
                         return Err(ErrorHandled::Reported(ErrorReported));
                     }
                     FailureKind::Concrete => {
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr
index 8a298b47fff..92547ca4796 100644
--- a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr
+++ b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr
@@ -4,7 +4,7 @@ error: unconstrained generic constant
 LL |     let _ = const_evaluatable_lib::test1::<T>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: consider adding a `where` bound for this expression
+help: try adding a `where` bound using this expression: where [u8; std::mem::size_of::<T>() - 1]: Sized
   --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10
    |
 LL |     [u8; std::mem::size_of::<T>() - 1]: Sized,
@@ -16,7 +16,7 @@ error: unconstrained generic constant
 LL |     let _ = const_evaluatable_lib::test1::<T>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: consider adding a `where` bound for this expression
+help: try adding a `where` bound using this expression: where [u8; std::mem::size_of::<T>() - 1]: Sized
   --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27
    |
 LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
@@ -28,7 +28,7 @@ error: unconstrained generic constant
 LL |     let _ = const_evaluatable_lib::test1::<T>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: consider adding a `where` bound for this expression
+help: try adding a `where` bound using this expression: where [u8; std::mem::size_of::<T>() - 1]: Sized
   --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10
    |
 LL |     [u8; std::mem::size_of::<T>() - 1]: Sized,
@@ -40,7 +40,7 @@ error: unconstrained generic constant
 LL |     let _ = const_evaluatable_lib::test1::<T>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: consider adding a `where` bound for this expression
+help: try adding a `where` bound using this expression: where [u8; std::mem::size_of::<T>() - 1]: Sized
   --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27
    |
 LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr
index 1f6dddb04e5..00efb610004 100644
--- a/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr
+++ b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr
@@ -4,7 +4,7 @@ error: unconstrained generic constant
 LL |     [0; size_of::<Foo<T>>()]
    |         ^^^^^^^^^^^^^^^^^^^
    |
-help: consider adding a `where` bound for this expression
+help: try adding a `where` bound using this expression: where [u8; size_of::<Foo<T>>()]: Sized
   --> $DIR/different-fn.rs:10:9
    |
 LL |     [0; size_of::<Foo<T>>()]
diff --git a/src/test/ui/const_evaluatable/needs_where_clause.rs b/src/test/ui/const_evaluatable/needs_where_clause.rs
new file mode 100644
index 00000000000..498a2ae7533
--- /dev/null
+++ b/src/test/ui/const_evaluatable/needs_where_clause.rs
@@ -0,0 +1,14 @@
+#![crate_type = "lib"]
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+const fn complex_maths<T>(n : usize) -> usize {
+  2 * n + 1
+}
+
+struct Example<T, const N: usize> {
+  a: [f32; N],
+  b: [f32; complex_maths::<T>(N)],
+  //~^ ERROR unconstrained
+  c: T,
+}
diff --git a/src/test/ui/const_evaluatable/needs_where_clause.stderr b/src/test/ui/const_evaluatable/needs_where_clause.stderr
new file mode 100644
index 00000000000..e991c508c03
--- /dev/null
+++ b/src/test/ui/const_evaluatable/needs_where_clause.stderr
@@ -0,0 +1,14 @@
+error: unconstrained generic constant
+  --> $DIR/needs_where_clause.rs:11:6
+   |
+LL |   b: [f32; complex_maths::<T>(N)],
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try adding a `where` bound using this expression: where [u8; complex_maths::<T>(N)]: Sized
+  --> $DIR/needs_where_clause.rs:11:12
+   |
+LL |   b: [f32; complex_maths::<T>(N)],
+   |            ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const_evaluatable/no_where_clause.rs b/src/test/ui/const_evaluatable/no_where_clause.rs
new file mode 100644
index 00000000000..12f4a22038e
--- /dev/null
+++ b/src/test/ui/const_evaluatable/no_where_clause.rs
@@ -0,0 +1,29 @@
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features, unused)]
+
+const fn complex_maths(n : usize) -> usize {
+  2 * n + 1
+}
+
+pub struct Example<const N: usize> {
+  a: [f32; N],
+  b: [f32; complex_maths(N)],
+  //~^ ERROR unconstrained generic
+}
+
+impl<const N: usize> Example<N> {
+  pub fn new() -> Self {
+    Self {
+      a: [0.; N],
+      b: [0.; complex_maths(N)],
+    }
+  }
+}
+
+impl Example<2> {
+  pub fn sum(&self) -> f32 {
+    self.a.iter().sum::<f32>() + self.b.iter().sum::<f32>()
+  }
+}
+
+fn main() {}
diff --git a/src/test/ui/const_evaluatable/no_where_clause.stderr b/src/test/ui/const_evaluatable/no_where_clause.stderr
new file mode 100644
index 00000000000..65100909e53
--- /dev/null
+++ b/src/test/ui/const_evaluatable/no_where_clause.stderr
@@ -0,0 +1,14 @@
+error: unconstrained generic constant
+  --> $DIR/no_where_clause.rs:10:6
+   |
+LL |   b: [f32; complex_maths(N)],
+   |      ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try adding a `where` bound using this expression: where [u8; complex_maths(N)]: Sized
+  --> $DIR/no_where_clause.rs:10:12
+   |
+LL |   b: [f32; complex_maths(N)],
+   |            ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+