1
Fork 0

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
This commit is contained in:
Matthias Krüger 2023-03-10 19:59:20 +01:00 committed by GitHub
commit 145e6204bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 74 additions and 34 deletions

View file

@ -34,7 +34,6 @@ use rustc_hir::def_id::DefId;
use rustc_middle::infer::canonical::OriginalQueryValues;
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
@ -171,9 +170,9 @@ impl<'tcx> InferCtxt<'tcx> {
//
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
self.probe(|_| {
let compatible_types = self.probe(|_| {
if a.ty() == b.ty() {
return;
return Ok(());
}
// 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> {
(relation.param_env(), a.ty(), b.ty()),
&mut OriginalQueryValues::default(),
);
if let Err(NoSolution) = self.tcx.check_tys_might_be_eq(canonical) {
self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
self.tcx.sess.delay_span_bug(
DUMMY_SP,
&format!("cannot relate consts of different types (a={:?}, b={:?})", a, b,),
);
}
)
})
});
// If the consts have differing types, just bail with a const error with
// 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,
));
}
match (a.kind(), b.kind()) {
(
ty::ConstKind::Infer(InferConst::Var(a_vid)),