From a788be0aae7558b41beb344c090470da4a60f277 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 26 Feb 2024 10:19:03 +0100 Subject: [PATCH] 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`. --- compiler/rustc_hir_typeck/src/coercion.rs | 26 +++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 9f6175eac13..ba3000d8037 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -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 = >::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) => {