about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs33
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs1
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr12
3 files changed, 38 insertions, 8 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index f449d360c16..4f0b5f59402 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -168,7 +168,9 @@ fn satisfied_from_param_env<'tcx>(
         param_env: ty::ParamEnv<'tcx>,
 
         infcx: &'a InferCtxt<'tcx>,
+        single_match: Option<Result<ty::Const<'tcx>, ()>>,
     }
+
     impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> {
         type BreakTy = ();
         fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -179,7 +181,9 @@ fn satisfied_from_param_env<'tcx>(
                     && ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
                     && ocx.select_all_or_error().is_empty()
             }) {
-                ControlFlow::BREAK
+                self.single_match =
+                    if self.single_match.is_none() { Some(Ok(c)) } else { Some(Err(())) };
+                ControlFlow::CONTINUE
             } else if let ty::ConstKind::Expr(e) = c.kind() {
                 e.visit_with(self)
             } else {
@@ -195,22 +199,37 @@ fn satisfied_from_param_env<'tcx>(
         }
     }
 
+    let mut single_match: Option<Result<ty::Const<'tcx>, ()>> = None;
+
     for pred in param_env.caller_bounds() {
         match pred.kind().skip_binder() {
             ty::PredicateKind::ConstEvaluatable(ce) => {
                 let b_ct = tcx.expand_abstract_consts(ce);
-                let mut v = Visitor { ct, infcx, param_env };
-                let result = b_ct.visit_with(&mut v);
-
-                if let ControlFlow::Break(()) = result {
-                    debug!("is_const_evaluatable: yes");
-                    return true;
+                let mut v = Visitor { ct, infcx, param_env, single_match: None };
+                let _ = b_ct.visit_with(&mut v);
+                if let Some(inner) = v.single_match {
+                    single_match = if single_match.is_none() { Some(inner) } else { Some(Err(())) };
                 }
             }
             _ => {} // don't care
         }
     }
 
+    if let Some(c) = single_match {
+        if let Ok(c) = c {
+            let is_ok = infcx
+                .commit_if_ok(|_| {
+                    let ocx = ObligationCtxt::new_in_snapshot(infcx);
+                    assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok());
+                    assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
+                    if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(()) }
+                })
+                .is_ok();
+            assert!(is_ok);
+        }
+        return true;
+    }
+
     debug!("is_const_evaluatable: no");
     false
 }
diff --git a/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs
index b96e210808b..d64468767eb 100644
--- a/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs
+++ b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs
@@ -16,6 +16,7 @@ where
 {
     foo::<_, L>([(); L + 1 + L]);
     //~^ ERROR: unconstrained generic constant
+    //~| ERROR: mismatched types
 }
 
 fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr
index 09e5e3f862a..da5194696e6 100644
--- a/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr
@@ -1,3 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/wf_obligation.rs:17:17
+   |
+LL |     foo::<_, L>([(); L + 1 + L]);
+   |                 ^^^^^^^^^^^^^^^ expected `N + 1 + M`, found `L + 1 + L`
+   |
+   = note: expected constant `N + 1 + M`
+              found constant `L + 1 + L`
+
 error: unconstrained generic constant
   --> $DIR/wf_obligation.rs:17:22
    |
@@ -6,5 +15,6 @@ LL |     foo::<_, L>([(); L + 1 + L]);
    |
    = help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0308`.