use fulfillment in `Coerce::unify'

only checking whether nested goals hold means that we don't consider
their inference constraints. Given that we now emit `AliasRelate` when relating
aliases and infer vars, this previously resulted in an "unconstrained" inference var
in `coerce_unsized`.
This commit is contained in:
lcnr 2024-02-26 10:19:03 +01:00
parent 1b3164f5c9
commit a788be0aae

View File

@ -44,6 +44,8 @@
use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
use rustc_infer::traits::TraitEngine;
use rustc_infer::traits::TraitEngineExt as _;
use rustc_infer::traits::{Obligation, PredicateObligation};
use rustc_middle::lint::in_external_macro;
use rustc_middle::traits::BuiltinImplSource;
@ -61,6 +63,7 @@
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::TraitEngineExt as _;
use rustc_trait_selection::traits::{
self, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt,
};
@ -157,17 +160,19 @@ fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
// In the new solver, lazy norm may allow us to shallowly equate
// more types, but we emit possibly impossible-to-satisfy obligations.
// Filter these cases out to make sure our coercion is more accurate.
if self.next_trait_solver() {
if let Ok(res) = &res {
for obligation in &res.obligations {
if !self.predicate_may_hold(obligation) {
return Err(TypeError::Mismatch);
}
match res {
Ok(InferOk { value, obligations }) if self.next_trait_solver() => {
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self);
fulfill_cx.register_predicate_obligations(self, obligations);
let errs = fulfill_cx.select_where_possible(self);
if errs.is_empty() {
Ok(InferOk { value, obligations: fulfill_cx.pending_obligations() })
} else {
Err(TypeError::Mismatch)
}
}
res => res,
}
res
})
}
@ -625,19 +630,18 @@ fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceRe
let traits = [coerce_unsized_did, unsize_did];
while !queue.is_empty() {
let obligation = queue.remove(0);
debug!("coerce_unsized resolve step: {:?}", obligation);
let trait_pred = match obligation.predicate.kind().no_bound_vars() {
Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)))
if traits.contains(&trait_pred.def_id()) =>
{
trait_pred
self.resolve_vars_if_possible(trait_pred)
}
_ => {
coercion.obligations.push(obligation);
continue;
}
};
let trait_pred = self.resolve_vars_if_possible(trait_pred);
debug!("coerce_unsized resolve step: {:?}", trait_pred);
match selcx.select(&obligation.with(selcx.tcx(), trait_pred)) {
// Uncertain or unimplemented.
Ok(None) => {