Skip to content

Commit 081c607

Browse files
authored
Rollup merge of #109336 - compiler-errors:constrain-to-ct-err, r=BoxyUwU
Constrain const vars to error if const types are mismatched When equating two consts of different types, if either are const variables, constrain them to the correct const error kind. This helps us avoid "successfully" matching a const against an impl signature but leaving unconstrained const vars, which will lead to incremental ICEs when we call const-eval queries during const projection. Fixes #109296 The second commit in the stack fixes a regression in the first commit where we end up mentioning `[const error]` in an impl overlap error message. I think the error message changes for the better, but I could implement alternative strategies to avoid this without delaying the overlap error message... r? `@BoxyUwU`
2 parents ee330a3 + 9174edb commit 081c607

File tree

6 files changed

+51
-13
lines changed

6 files changed

+51
-13
lines changed

compiler/rustc_infer/src/infer/combine.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,19 @@ impl<'tcx> InferCtxt<'tcx> {
189189
// the expected const's type. Specifically, we don't want const infer vars
190190
// to do any type shapeshifting before and after resolution.
191191
if let Err(guar) = compatible_types {
192-
return Ok(self.tcx.const_error_with_guaranteed(
193-
if relation.a_is_expected() { a.ty() } else { b.ty() },
194-
guar,
195-
));
192+
// HACK: equating both sides with `[const error]` eagerly prevents us
193+
// from leaving unconstrained inference vars during things like impl
194+
// matching in the solver.
195+
let a_error = self.tcx.const_error_with_guaranteed(a.ty(), guar);
196+
if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
197+
return self.unify_const_variable(vid, a_error);
198+
}
199+
let b_error = self.tcx.const_error_with_guaranteed(b.ty(), guar);
200+
if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
201+
return self.unify_const_variable(vid, b_error);
202+
}
203+
204+
return Ok(if relation.a_is_expected() { a_error } else { b_error });
196205
}
197206

198207
match (a.kind(), b.kind()) {

compiler/rustc_trait_selection/src/traits/specialize/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::traits::{
2222
use rustc_data_structures::fx::FxIndexSet;
2323
use rustc_errors::{error_code, DelayDm, Diagnostic};
2424
use rustc_hir::def_id::{DefId, LocalDefId};
25-
use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt};
25+
use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
2626
use rustc_middle::ty::{InternalSubsts, SubstsRef};
2727
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
2828
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
@@ -350,6 +350,10 @@ fn report_conflicting_impls<'tcx>(
350350
impl_span: Span,
351351
err: &mut Diagnostic,
352352
) {
353+
if (overlap.trait_ref, overlap.self_ty).references_error() {
354+
err.downgrade_to_delayed_bug();
355+
}
356+
353357
match tcx.span_of_impl(overlap.with_impl) {
354358
Ok(span) => {
355359
err.span_label(span, "first implementation here");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// incremental
2+
#![crate_type = "lib"]
3+
4+
trait Q {
5+
const ASSOC: usize;
6+
}
7+
8+
impl<const N: u64> Q for [u8; N] {
9+
//~^ ERROR mismatched types
10+
const ASSOC: usize = 1;
11+
}
12+
13+
pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/bad-subst-const-kind.rs:8:31
3+
|
4+
LL | impl<const N: u64> Q for [u8; N] {
5+
| ^ expected `usize`, found `u64`
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0308`.

tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
// An impl that has an erroneous const substitution should not specialize one
44
// that is well-formed.
5-
5+
#[derive(Clone)]
66
struct S<const L: usize>;
77

88
impl<const N: i32> Copy for S<N> {}
9+
//~^ ERROR the constant `N` is not of type `usize`
910
impl<const M: usize> Copy for S<M> {}
10-
//~^ ERROR conflicting implementations of trait `Copy` for type `S<_>`
1111

1212
fn main() {}

tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
2-
--> $DIR/bad-const-wf-doesnt-specialize.rs:9:1
1+
error: the constant `N` is not of type `usize`
2+
--> $DIR/bad-const-wf-doesnt-specialize.rs:8:29
33
|
44
LL | impl<const N: i32> Copy for S<N> {}
5-
| -------------------------------- first implementation here
6-
LL | impl<const M: usize> Copy for S<M> {}
7-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`
5+
| ^^^^
6+
|
7+
note: required by a bound in `S`
8+
--> $DIR/bad-const-wf-doesnt-specialize.rs:6:10
9+
|
10+
LL | struct S<const L: usize>;
11+
| ^^^^^^^^^^^^^^ required by this bound in `S`
812

913
error: aborting due to previous error
1014

11-
For more information about this error, try `rustc --explain E0119`.

0 commit comments

Comments
 (0)