about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-03-19 02:17:44 +0000
committerMichael Goulet <michael@errs.io>2023-03-19 03:45:47 +0000
commit322c7b6269f0a2147b85f4cc38006afca22a0d31 (patch)
tree01d060e004b85930177f80177bfaf5d542821fb2
parentab9bb3ea368b2412531a3e8c07ba73d1dd690134 (diff)
downloadrust-322c7b6269f0a2147b85f4cc38006afca22a0d31.tar.gz
rust-322c7b6269f0a2147b85f4cc38006afca22a0d31.zip
Constrain const vars to error if const types are mismatched
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs17
-rw-r--r--tests/ui/const-generics/bad-subst-const-kind.rs13
-rw-r--r--tests/ui/const-generics/bad-subst-const-kind.stderr9
-rw-r--r--tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs4
-rw-r--r--tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr4
5 files changed, 39 insertions, 8 deletions
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index bb6fdd2ffc2..4503af03ca3 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -189,10 +189,19 @@ impl<'tcx> InferCtxt<'tcx> {
         // the expected const's type. Specifically, we don't want const infer vars
         // to do any type shapeshifting before and after resolution.
         if let Err(guar) = compatible_types {
-            return Ok(self.tcx.const_error_with_guaranteed(
-                if relation.a_is_expected() { a.ty() } else { b.ty() },
-                guar,
-            ));
+            // HACK: equating both sides with `[const error]` eagerly prevents us
+            // from leaving unconstrained inference vars during things like impl
+            // matching in the solver.
+            let a_error = self.tcx.const_error_with_guaranteed(a.ty(), guar);
+            if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
+                return self.unify_const_variable(vid, a_error);
+            }
+            let b_error = self.tcx.const_error_with_guaranteed(b.ty(), guar);
+            if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
+                return self.unify_const_variable(vid, b_error);
+            }
+
+            return Ok(if relation.a_is_expected() { a_error } else { b_error });
         }
 
         match (a.kind(), b.kind()) {
diff --git a/tests/ui/const-generics/bad-subst-const-kind.rs b/tests/ui/const-generics/bad-subst-const-kind.rs
new file mode 100644
index 00000000000..e13dfbacd24
--- /dev/null
+++ b/tests/ui/const-generics/bad-subst-const-kind.rs
@@ -0,0 +1,13 @@
+// incremental
+#![crate_type = "lib"]
+
+trait Q {
+    const ASSOC: usize;
+}
+
+impl<const N: u64> Q for [u8; N] {
+    //~^ ERROR mismatched types
+    const ASSOC: usize = 1;
+}
+
+pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
diff --git a/tests/ui/const-generics/bad-subst-const-kind.stderr b/tests/ui/const-generics/bad-subst-const-kind.stderr
new file mode 100644
index 00000000000..bd24f9140e4
--- /dev/null
+++ b/tests/ui/const-generics/bad-subst-const-kind.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/bad-subst-const-kind.rs:8:31
+   |
+LL | impl<const N: u64> Q for [u8; N] {
+   |                               ^ expected `usize`, found `u64`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs
index 582b480aa25..6bad87d3d37 100644
--- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs
+++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs
@@ -2,11 +2,11 @@
 
 // An impl that has an erroneous const substitution should not specialize one
 // that is well-formed.
-
+#[derive(Clone)]
 struct S<const L: usize>;
 
 impl<const N: i32> Copy for S<N> {}
 impl<const M: usize> Copy for S<M> {}
-//~^ ERROR conflicting implementations of trait `Copy` for type `S<_>`
+//~^ ERROR conflicting implementations of trait `Copy` for type `S<[const error]>`
 
 fn main() {}
diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr
index a3906a9a22f..35848db9b56 100644
--- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr
+++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr
@@ -1,10 +1,10 @@
-error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
+error[E0119]: conflicting implementations of trait `Copy` for type `S<[const error]>`
   --> $DIR/bad-const-wf-doesnt-specialize.rs:9:1
    |
 LL | impl<const N: i32> Copy for S<N> {}
    | -------------------------------- first implementation here
 LL | impl<const M: usize> Copy for S<M> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<[const error]>`
 
 error: aborting due to previous error