Skip to content

Commit 7ea507e

Browse files
authored
Rollup merge of #125451 - oli-obk:const_type_mismatch, r=compiler-errors
Fail relating constants of different types fixes #121585 fixes #121858 fixes #124151 I gave this several attempts before, but we lost too many important diagnostics until I managed to make compilation never bail out early. We have reached this point, so now we can finally fix all those ICEs by bubbling up an error instead of continueing when we encounter a bug.
2 parents f28d368 + d5eb7a7 commit 7ea507e

File tree

21 files changed

+129
-180
lines changed

21 files changed

+129
-180
lines changed

compiler/rustc_infer/src/infer/relate/combine.rs

+7-32
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ use super::glb::Glb;
2222
use super::lub::Lub;
2323
use super::type_relating::TypeRelating;
2424
use super::StructurallyRelateAliases;
25-
use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
25+
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, TypeTrace};
2626
use crate::traits::{Obligation, PredicateObligations};
2727
use rustc_middle::bug;
28-
use rustc_middle::infer::canonical::OriginalQueryValues;
2928
use rustc_middle::infer::unify_key::EffectVarValue;
29+
use rustc_middle::traits::ObligationCause;
3030
use rustc_middle::ty::error::{ExpectedFound, TypeError};
3131
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
3232
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast};
@@ -159,36 +159,11 @@ impl<'tcx> InferCtxt<'tcx> {
159159
let a = self.shallow_resolve_const(a);
160160
let b = self.shallow_resolve_const(b);
161161

162-
// We should never have to relate the `ty` field on `Const` as it is checked elsewhere that consts have the
163-
// correct type for the generic param they are an argument for. However there have been a number of cases
164-
// historically where asserting that the types are equal has found bugs in the compiler so this is valuable
165-
// to check even if it is a bit nasty impl wise :(
166-
//
167-
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
168-
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
169-
self.probe(|_| {
170-
if a.ty() == b.ty() {
171-
return;
172-
}
173-
174-
// We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
175-
// two const param's types are able to be equal has to go through a canonical query with the actual logic
176-
// in `rustc_trait_selection`.
177-
let canonical = self.canonicalize_query(
178-
relation.param_env().and((a.ty(), b.ty())),
179-
&mut OriginalQueryValues::default(),
180-
);
181-
self.tcx.check_tys_might_be_eq(canonical).unwrap_or_else(|_| {
182-
// The error will only be reported later. If we emit an ErrorGuaranteed
183-
// here, then we will never get to the code that actually emits the error.
184-
self.tcx.dcx().delayed_bug(format!(
185-
"cannot relate consts of different types (a={a:?}, b={b:?})",
186-
));
187-
// We treat these constants as if they were of the same type, so that any
188-
// such constants being used in impls make these impls match barring other mismatches.
189-
// This helps with diagnostics down the road.
190-
});
191-
});
162+
// It is always an error if the types of two constants that are related are not equal.
163+
let InferOk { value: (), obligations } = self
164+
.at(&ObligationCause::dummy_with_span(relation.span()), relation.param_env())
165+
.eq(DefineOpaqueTypes::No, a.ty(), b.ty())?;
166+
relation.register_obligations(obligations);
192167

193168
match (a.kind(), b.kind()) {
194169
(

compiler/rustc_middle/src/query/mod.rs

-9
Original file line numberDiff line numberDiff line change
@@ -2218,15 +2218,6 @@ rustc_queries! {
22182218
separate_provide_extern
22192219
}
22202220

2221-
/// Used in `super_combine_consts` to ICE if the type of the two consts are definitely not going to end up being
2222-
/// equal to eachother. This might return `Ok` even if the types are not equal, but will never return `Err` if
2223-
/// the types might be equal.
2224-
query check_tys_might_be_eq(
2225-
arg: Canonical<'tcx, ty::ParamEnvAnd<'tcx, (Ty<'tcx>, Ty<'tcx>)>>
2226-
) -> Result<(), NoSolution> {
2227-
desc { "check whether two const param are definitely not equal to eachother"}
2228-
}
2229-
22302221
/// Get all item paths that were stripped by a `#[cfg]` in a particular crate.
22312222
/// Should not be called for the local crate before the resolver outputs are created, as it
22322223
/// is only fed there.

compiler/rustc_trait_selection/src/traits/misc.rs

+1-20
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
22
33
use crate::regions::InferCtxtRegionExt;
4-
use crate::traits::{self, ObligationCause, ObligationCtxt};
4+
use crate::traits::{self, ObligationCause};
55

66
use hir::LangItem;
77
use rustc_data_structures::fx::FxIndexSet;
88
use rustc_hir as hir;
9-
use rustc_infer::infer::canonical::Canonical;
109
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
11-
use rustc_infer::traits::query::NoSolution;
1210
use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
1311
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt};
14-
use rustc_span::DUMMY_SP;
1512

1613
use super::outlives_bounds::InferCtxtExt;
1714

@@ -207,19 +204,3 @@ pub fn all_fields_implement_trait<'tcx>(
207204

208205
if infringing.is_empty() { Ok(()) } else { Err(infringing) }
209206
}
210-
211-
pub fn check_tys_might_be_eq<'tcx>(
212-
tcx: TyCtxt<'tcx>,
213-
canonical: Canonical<'tcx, ty::ParamEnvAnd<'tcx, (Ty<'tcx>, Ty<'tcx>)>>,
214-
) -> Result<(), NoSolution> {
215-
let (infcx, key, _) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical);
216-
let (param_env, (ty_a, ty_b)) = key.into_parts();
217-
let ocx = ObligationCtxt::new(&infcx);
218-
219-
let result = ocx.eq(&ObligationCause::dummy(), param_env, ty_a, ty_b);
220-
// use `select_where_possible` instead of `select_all_or_error` so that
221-
// we don't get errors from obligations being ambiguous.
222-
let errors = ocx.select_where_possible();
223-
224-
if errors.len() > 0 || result.is_err() { Err(NoSolution) } else { Ok(()) }
225-
}

compiler/rustc_trait_selection/src/traits/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,6 @@ pub fn provide(providers: &mut Providers) {
551551
specialization_graph_of: specialize::specialization_graph_provider,
552552
specializes: specialize::specializes,
553553
instantiate_and_check_impossible_predicates,
554-
check_tys_might_be_eq: misc::check_tys_might_be_eq,
555554
is_impossible_associated_item,
556555
..*providers
557556
};

tests/crashes/119381.rs

-6
This file was deleted.

tests/crashes/121585-1.rs

-13
This file was deleted.

tests/crashes/121585-2.rs

-30
This file was deleted.

tests/crashes/121858-2.rs

-20
This file was deleted.

tests/crashes/124151.rs

-14
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//! This test used to ICE (#119381), because relating the `u8` and `i8` generic
2+
//! const with the array length of the `Self` type was succeeding under the
3+
//! assumption that an error had already been reported.
4+
5+
#![feature(with_negative_coherence)]
6+
trait Trait {}
7+
impl<const N: u8> Trait for [(); N] {}
8+
//~^ ERROR: mismatched types
9+
impl<const N: i8> Trait for [(); N] {}
10+
//~^ ERROR: mismatched types
11+
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/generic_const_type_mismatch.rs:7:34
3+
|
4+
LL | impl<const N: u8> Trait for [(); N] {}
5+
| ^ expected `usize`, found `u8`
6+
7+
error[E0308]: mismatched types
8+
--> $DIR/generic_const_type_mismatch.rs:9:34
9+
|
10+
LL | impl<const N: i8> Trait for [(); N] {}
11+
| ^ expected `usize`, found `i8`
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0308`.

tests/ui/const-generics/bad-subst-const-kind.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ impl<const N: u64> Q for [u8; N] {
1111
}
1212

1313
pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
14-
//~^ ERROR: the constant `13` is not of type `u64`
14+
//~^ ERROR: `[u8; 13]: Q` is not satisfied
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
1-
error: the constant `13` is not of type `u64`
1+
error[E0277]: the trait bound `[u8; 13]: Q` is not satisfied
22
--> $DIR/bad-subst-const-kind.rs:13:24
33
|
44
LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
5-
| ^^^^^^^^ expected `u64`, found `usize`
5+
| ^^^^^^^^ the trait `Q` is not implemented for `[u8; 13]`
66
|
7-
note: required for `[u8; 13]` to implement `Q`
8-
--> $DIR/bad-subst-const-kind.rs:8:20
9-
|
10-
LL | impl<const N: u64> Q for [u8; N] {
11-
| ------------ ^ ^^^^^^^
12-
| |
13-
| unsatisfied trait bound introduced here
7+
= help: the trait `Q` is implemented for `[u8; N]`
148

159
error[E0308]: mismatched types
1610
--> $DIR/bad-subst-const-kind.rs:8:31
@@ -20,4 +14,5 @@ LL | impl<const N: u64> Q for [u8; N] {
2014

2115
error: aborting due to 2 previous errors
2216

23-
For more information about this error, try `rustc --explain E0308`.
17+
Some errors have detailed explanations: E0277, E0308.
18+
For more information about an error, try `rustc --explain E0277`.

tests/ui/const-generics/generic_const_exprs/type_mismatch.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ impl<const N: u64> Q for [u8; N] {}
1010
//~| ERROR mismatched types
1111

1212
pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
13-
//~^ ERROR the constant `13` is not of type `u64`
13+
//~^ ERROR `[u8; 13]: Q` is not satisfied
1414
//~| ERROR mismatched types
1515

1616
pub fn main() {}

tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr

+4-10
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,13 @@ LL | const ASSOC: usize;
77
LL | impl<const N: u64> Q for [u8; N] {}
88
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `ASSOC` in implementation
99

10-
error: the constant `13` is not of type `u64`
10+
error[E0277]: the trait bound `[u8; 13]: Q` is not satisfied
1111
--> $DIR/type_mismatch.rs:12:26
1212
|
1313
LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
14-
| ^^^^^^^^ expected `u64`, found `usize`
14+
| ^^^^^^^^ the trait `Q` is not implemented for `[u8; 13]`
1515
|
16-
note: required for `[u8; 13]` to implement `Q`
17-
--> $DIR/type_mismatch.rs:8:20
18-
|
19-
LL | impl<const N: u64> Q for [u8; N] {}
20-
| ------------ ^ ^^^^^^^
21-
| |
22-
| unsatisfied trait bound introduced here
16+
= help: the trait `Q` is implemented for `[u8; N]`
2317

2418
error[E0308]: mismatched types
2519
--> $DIR/type_mismatch.rs:12:20
@@ -37,5 +31,5 @@ LL | impl<const N: u64> Q for [u8; N] {}
3731

3832
error: aborting due to 4 previous errors
3933

40-
Some errors have detailed explanations: E0046, E0308.
34+
Some errors have detailed explanations: E0046, E0277, E0308.
4135
For more information about an error, try `rustc --explain E0046`.

tests/ui/const-generics/issues/issue-105821.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
//@ check-pass
1+
//@ failure-status: 101
2+
//@ known-bug: unknown
3+
//@ normalize-stderr-test "note: .*\n\n" -> ""
4+
//@ normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> ""
5+
//@ normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
6+
//@ normalize-stderr-test "delayed at .*" -> ""
7+
//@ rustc-env:RUST_BACKTRACE=0
28

39
#![allow(incomplete_features)]
410
#![feature(adt_const_params, generic_const_exprs)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: internal compiler error: compiler/rustc_borrowck/src/universal_regions.rs:LL:CC: cannot convert `'{erased}` to a region vid
2+
3+
query stack during panic:
4+
#0 [mir_borrowck] borrow-checking `<impl at $DIR/issue-105821.rs:21:1: 23:24>::R`
5+
#1 [analysis] running analysis passes on this crate
6+
end of query stack
7+
error: aborting due to 1 previous error
8+
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
//@ known-bug: #121858
21
#![feature(generic_const_exprs)]
2+
#![allow(incomplete_features)]
33

44
struct Outer<const A: i64, const B: usize>();
55
impl<const A: usize, const B: usize> Outer<A, B>
6+
//~^ ERROR: `A` is not of type `i64`
7+
//~| ERROR: mismatched types
68
where
79
[(); A + (B * 2)]:,
810
{
9-
fn o() -> Union {}
11+
fn o() {}
1012
}
1113

1214
fn main() {
1315
Outer::<1, 1>::o();
16+
//~^ ERROR: no function or associated item named `o` found
1417
}
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
error: the constant `A` is not of type `i64`
2+
--> $DIR/eval_type_mismatch.rs:5:38
3+
|
4+
LL | impl<const A: usize, const B: usize> Outer<A, B>
5+
| ^^^^^^^^^^^ expected `i64`, found `usize`
6+
|
7+
note: required by a bound in `Outer`
8+
--> $DIR/eval_type_mismatch.rs:4:14
9+
|
10+
LL | struct Outer<const A: i64, const B: usize>();
11+
| ^^^^^^^^^^^^ required by this bound in `Outer`
12+
13+
error[E0599]: no function or associated item named `o` found for struct `Outer<1, 1>` in the current scope
14+
--> $DIR/eval_type_mismatch.rs:15:20
15+
|
16+
LL | struct Outer<const A: i64, const B: usize>();
17+
| ------------------------------------------ function or associated item `o` not found for this struct
18+
...
19+
LL | Outer::<1, 1>::o();
20+
| ^ function or associated item not found in `Outer<1, 1>`
21+
|
22+
= note: the function or associated item was found for
23+
- `Outer<A, B>`
24+
25+
error[E0308]: mismatched types
26+
--> $DIR/eval_type_mismatch.rs:5:44
27+
|
28+
LL | impl<const A: usize, const B: usize> Outer<A, B>
29+
| ^ expected `i64`, found `usize`
30+
31+
error: aborting due to 3 previous errors
32+
33+
Some errors have detailed explanations: E0308, E0599.
34+
For more information about an error, try `rustc --explain E0308`.

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ struct S<const L: usize>;
77

88
impl<const N: i32> Copy for S<N> {}
99
//~^ ERROR: mismatched types
10+
//~| ERROR: the trait bound `S<N>: Clone` is not satisfied
11+
//~| ERROR: the constant `N` is not of type `usize`
1012
impl<const M: usize> Copy for S<M> {}
11-
//~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>`
1213

1314
fn main() {}

0 commit comments

Comments
 (0)