diff options
| author | Michael Goulet <michael@errs.io> | 2023-03-19 02:17:44 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2023-03-19 03:45:47 +0000 |
| commit | 322c7b6269f0a2147b85f4cc38006afca22a0d31 (patch) | |
| tree | 01d060e004b85930177f80177bfaf5d542821fb2 | |
| parent | ab9bb3ea368b2412531a3e8c07ba73d1dd690134 (diff) | |
| download | rust-322c7b6269f0a2147b85f4cc38006afca22a0d31.tar.gz rust-322c7b6269f0a2147b85f4cc38006afca22a0d31.zip | |
Constrain const vars to error if const types are mismatched
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 |
