about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs25
-rw-r--r--src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.rs22
-rw-r--r--src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr12
4 files changed, 49 insertions, 23 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index b1ac02d9fed..8a1be7ea172 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -72,17 +72,16 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
                 // We were unable to unify the abstract constant with
                 // a constant found in the caller bounds, there are
                 // now three possible cases here.
-                //
-                // - The substs are concrete enough that we can simply
-                //   try and evaluate the given constant.
-                // - The abstract const still references an inference
-                //   variable, in this case we return `TooGeneric`.
-                // - The abstract const references a generic parameter,
-                //   this means that we emit an error here.
                 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
                 enum FailureKind {
+                    /// The abstract const still references an inference
+                    /// variable, in this case we return `TooGeneric`.
                     MentionsInfer,
+                    /// The abstract const references a generic parameter,
+                    /// this means that we emit an error here.
                     MentionsParam,
+                    /// The substs are concrete enough that we can simply
+                    /// try and evaluate the given constant.
                     Concrete,
                 }
                 let mut failure_kind = FailureKind::Concrete;
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 69f66f6e6b1..e6a1cf58fe3 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -200,22 +200,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             if let Some(def) = aty.ty_adt_def() {
                 // We also want to be able to select the array's type's original
                 // signature with no type arguments resolved
-                flags.push((
-                    sym::_Self,
-                    Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
-                ));
-                let tcx = self.tcx;
-                if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
-                    ));
-                } else {
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
-                    ));
-                }
+                let type_string = self.tcx.type_of(def.did).to_string();
+                flags.push((sym::_Self, Some(format!("[{}]", type_string))));
+
+                let len = len.val.try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx));
+                let string = match len {
+                    Some(n) => format!("[{}; {}]", type_string, n),
+                    None => format!("[{}; _]", type_string),
+                };
+                flags.push((sym::_Self, Some(string)));
             }
         }
         if let ty::Dynamic(traits, _) = self_ty.kind() {
diff --git a/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.rs b/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.rs
new file mode 100644
index 00000000000..afef748ff46
--- /dev/null
+++ b/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.rs
@@ -0,0 +1,22 @@
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+// This tests that during error handling for the "trait not implemented" error
+// we dont try to evaluate std::mem::size_of::<Self::Assoc> causing an ICE
+
+struct Adt;
+
+trait Foo {
+    type Assoc;
+    fn foo()
+    where
+        [Adt; std::mem::size_of::<Self::Assoc>()]: ,
+    {
+        <[Adt; std::mem::size_of::<Self::Assoc>()] as Foo>::bar()
+        //~^ Error: the trait bound
+    }
+
+    fn bar() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr b/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr
new file mode 100644
index 00000000000..d894fa90ba9
--- /dev/null
+++ b/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `[Adt; _]: Foo` is not satisfied
+  --> $DIR/dont-evaluate-array-len-on-err-1.rs:15:9
+   |
+LL |         <[Adt; std::mem::size_of::<Self::Assoc>()] as Foo>::bar()
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; _]`
+...
+LL |     fn bar() {}
+   |     -------- required by `Foo::bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.