Skip to content

Commit 145e620

Browse files
authored
Rollup merge of #108947 - compiler-errors:ct-infer-no-shapeshifting, r=BoxyUwU
Don't even try to combine consts with incompatible types ~I left a more detailed explanation for why this fixes this issue in the UI test, but in general, we should not try to unify const infer vars and rigid consts if they have incompatible types. That's because we don't want something like a `ConstArgHasType` predicate to suddenly go from passing to failing, or vice versa, due to a shallow resolve.~ 1. Use the `type_of` for a parameter in `try_eval_lit_or_param`, instead of the "expected" type from a `WithOptConstParam` def id. 2. Don't combine consts that have incompatible types. Fixes #108781
2 parents 772b1ce + f714613 commit 145e620

File tree

11 files changed

+74
-34
lines changed

11 files changed

+74
-34
lines changed

compiler/rustc_infer/src/infer/combine.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ use rustc_hir::def_id::DefId;
3434
use rustc_middle::infer::canonical::OriginalQueryValues;
3535
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
3636
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
37-
use rustc_middle::traits::query::NoSolution;
3837
use rustc_middle::traits::ObligationCause;
3938
use rustc_middle::ty::error::{ExpectedFound, TypeError};
4039
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
@@ -171,9 +170,9 @@ impl<'tcx> InferCtxt<'tcx> {
171170
//
172171
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
173172
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
174-
self.probe(|_| {
173+
let compatible_types = self.probe(|_| {
175174
if a.ty() == b.ty() {
176-
return;
175+
return Ok(());
177176
}
178177

179178
// We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
@@ -183,15 +182,24 @@ impl<'tcx> InferCtxt<'tcx> {
183182
(relation.param_env(), a.ty(), b.ty()),
184183
&mut OriginalQueryValues::default(),
185184
);
186-
187-
if let Err(NoSolution) = self.tcx.check_tys_might_be_eq(canonical) {
185+
self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
188186
self.tcx.sess.delay_span_bug(
189187
DUMMY_SP,
190188
&format!("cannot relate consts of different types (a={:?}, b={:?})", a, b,),
191-
);
192-
}
189+
)
190+
})
193191
});
194192

193+
// If the consts have differing types, just bail with a const error with
194+
// the expected const's type. Specifically, we don't want const infer vars
195+
// to do any type shapeshifting before and after resolution.
196+
if let Err(guar) = compatible_types {
197+
return Ok(self.tcx.const_error_with_guaranteed(
198+
if relation.a_is_expected() { a.ty() } else { b.ty() },
199+
guar,
200+
));
201+
}
202+
195203
match (a.kind(), b.kind()) {
196204
(
197205
ty::ConstKind::Infer(InferConst::Var(a_vid)),

compiler/rustc_middle/src/ty/consts.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ impl<'tcx> Const<'tcx> {
135135
_,
136136
&hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
137137
)) => {
138+
// Use the type from the param's definition, since we can resolve it,
139+
// not the expected parameter type from WithOptConstParam.
140+
let param_ty = tcx.type_of(def_id).subst_identity();
138141
match tcx.named_bound_var(expr.hir_id) {
139142
Some(rbv::ResolvedArg::EarlyBound(_)) => {
140143
// Find the name and index of the const parameter by indexing the generics of
@@ -143,14 +146,14 @@ impl<'tcx> Const<'tcx> {
143146
let generics = tcx.generics_of(item_def_id);
144147
let index = generics.param_def_id_to_index[&def_id];
145148
let name = tcx.item_name(def_id);
146-
Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
149+
Some(tcx.mk_const(ty::ParamConst::new(index, name), param_ty))
147150
}
148151
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
149152
ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
150-
ty,
153+
param_ty,
151154
)),
152155
Some(rbv::ResolvedArg::Error(guar)) => {
153-
Some(tcx.const_error_with_guaranteed(ty, guar))
156+
Some(tcx.const_error_with_guaranteed(param_ty, guar))
154157
}
155158
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
156159
}

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ pub fn translate_substs<'tcx>(
9999
}
100100

101101
fulfill_implication(infcx, param_env, source_trait_ref, target_impl).unwrap_or_else(
102-
|_| {
102+
|()| {
103103
bug!(
104-
"When translating substitutions for specialization, the expected \
105-
specialization failed to hold"
104+
"When translating substitutions from {source_impl:?} to {target_impl:?}, \
105+
the expected specialization failed to hold"
106106
)
107107
},
108108
)

tests/ui/const-generics/type_mismatch.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
fn foo<const N: usize>() -> [u8; N] {
22
bar::<N>() //~ ERROR mismatched types
3+
//~^ ERROR the constant `N` is not of type `u8`
34
}
45

56
fn bar<const N: u8>() -> [u8; N] {}
+15-3
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,35 @@
1+
error: the constant `N` is not of type `u8`
2+
--> $DIR/type_mismatch.rs:2:5
3+
|
4+
LL | bar::<N>()
5+
| ^^^^^^^^
6+
|
7+
note: required by a bound in `bar`
8+
--> $DIR/type_mismatch.rs:6:8
9+
|
10+
LL | fn bar<const N: u8>() -> [u8; N] {}
11+
| ^^^^^^^^^^^ required by this bound in `bar`
12+
113
error[E0308]: mismatched types
214
--> $DIR/type_mismatch.rs:2:11
315
|
416
LL | bar::<N>()
517
| ^ expected `u8`, found `usize`
618

719
error[E0308]: mismatched types
8-
--> $DIR/type_mismatch.rs:5:26
20+
--> $DIR/type_mismatch.rs:6:26
921
|
1022
LL | fn bar<const N: u8>() -> [u8; N] {}
1123
| --- ^^^^^^^ expected `[u8; N]`, found `()`
1224
| |
1325
| implicitly returns `()` as its body has no tail or `return` expression
1426

1527
error[E0308]: mismatched types
16-
--> $DIR/type_mismatch.rs:5:31
28+
--> $DIR/type_mismatch.rs:6:31
1729
|
1830
LL | fn bar<const N: u8>() -> [u8; N] {}
1931
| ^ expected `usize`, found `u8`
2032

21-
error: aborting due to 3 previous errors
33+
error: aborting due to 4 previous errors
2234

2335
For more information about this error, try `rustc --explain E0308`.

tests/ui/const-generics/type_not_in_scope.rs

-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,5 @@ impl X {
66
}
77
fn getn<const N: cfg_attr>() -> [u8; N] {}
88
//~^ ERROR expected type, found built-in attribute `cfg_attr`
9-
//~| ERROR mismatched types
109

1110
fn main() {}

tests/ui/const-generics/type_not_in_scope.stderr

+3-11
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,7 @@ error[E0573]: expected type, found built-in attribute `cfg_attr`
1010
LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
1111
| ^^^^^^^^ not a type
1212

13-
error[E0308]: mismatched types
14-
--> $DIR/type_not_in_scope.rs:7:33
15-
|
16-
LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
17-
| ---- ^^^^^^^ expected `[u8; N]`, found `()`
18-
| |
19-
| implicitly returns `()` as its body has no tail or `return` expression
20-
21-
error: aborting due to 3 previous errors
13+
error: aborting due to 2 previous errors
2214

23-
Some errors have detailed explanations: E0308, E0412, E0573.
24-
For more information about an error, try `rustc --explain E0308`.
15+
Some errors have detailed explanations: E0412, E0573.
16+
For more information about an error, try `rustc --explain E0412`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![feature(min_specialization)]
2+
3+
// An impl that has an erroneous const substitution should not specialize one
4+
// that is well-formed.
5+
6+
struct S<const L: usize>;
7+
8+
impl<const N: i32> Copy for S<N> {}
9+
impl<const M: usize> Copy for S<M> {}
10+
//~^ ERROR conflicting implementations of trait `Copy` for type `S<_>`
11+
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
2+
--> $DIR/bad-const-wf-doesnt-specialize.rs:9:1
3+
|
4+
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<_>`
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0119`.

tests/ui/transmutability/issue-101739-1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod assert {
66
pub fn is_transmutable<Src, Context, const ASSUME_ALIGNMENT: bool>()
77
where
88
Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope
9-
//~^ ERROR mismatched types
9+
//~^ the constant `ASSUME_ALIGNMENT` is not of type `Assume`
1010
{
1111
}
1212
}

tests/ui/transmutability/issue-101739-1.stderr

+7-5
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ error[E0412]: cannot find type `Dst` in this scope
44
LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
55
| ^^^ not found in this scope
66

7-
error[E0308]: mismatched types
8-
--> $DIR/issue-101739-1.rs:8:50
7+
error: the constant `ASSUME_ALIGNMENT` is not of type `Assume`
8+
--> $DIR/issue-101739-1.rs:8:14
99
|
1010
LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
11-
| ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
|
13+
note: required by a bound in `BikeshedIntrinsicFrom`
14+
--> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
1215

1316
error: aborting due to 2 previous errors
1417

15-
Some errors have detailed explanations: E0308, E0412.
16-
For more information about an error, try `rustc --explain E0308`.
18+
For more information about this error, try `rustc --explain E0412`.

0 commit comments

Comments
 (0)