X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=sidebyside;f=compiler%2Frustc_hir_typeck%2Fsrc%2Fclosure.rs;h=14f6e7d36be2cf1299b31d801899cd804353450c;hb=bc3516d474a6ab5e5116a2ec32f5d236d479cab3;hp=a5a45f75e0e240c25a0ec8fb1bcad01d5b6dfa14;hpb=5ab74459b86465e751fc8f6fa9934687423ce2a6;p=rust.git diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index a5a45f75e0e..14f6e7d36be 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -15,6 +15,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_span::source_map::Span; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::ArgKind; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use std::cmp; @@ -225,33 +226,50 @@ fn deduce_expectations_from_obligations( &self, expected_vid: ty::TyVid, ) -> (Option>, Option) { - let expected_sig = - self.obligations_for_self_ty(expected_vid).find_map(|(_, obligation)| { - debug!(?obligation.predicate); - - let bound_predicate = obligation.predicate.kind(); - if let ty::PredicateKind::Projection(proj_predicate) = - obligation.predicate.kind().skip_binder() - { - // Given a Projection predicate, we can potentially infer - // the complete signature. - self.deduce_sig_from_projection( - Some(obligation.cause.span), - bound_predicate.rebind(proj_predicate), - ) - } else { - None - } - }); + let mut expected_sig = None; + let mut expected_kind = None; + + for obligation in traits::elaborate_obligations( + self.tcx, + // Reverse the obligations here, since `elaborate_*` uses a stack, + // and we want to keep inference generally in the same order of + // the registered obligations. + self.obligations_for_self_ty(expected_vid).rev().collect(), + ) { + debug!(?obligation.predicate); + let bound_predicate = obligation.predicate.kind(); + + // Given a Projection predicate, we can potentially infer + // the complete signature. + if expected_sig.is_none() + && let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() + { + expected_sig = self.deduce_sig_from_projection( + Some(obligation.cause.span), + bound_predicate.rebind(proj_predicate), + ); + } - // Even if we can't infer the full signature, we may be able to - // infer the kind. This can occur when we elaborate a predicate - // like `F : Fn`. Note that due to subtyping we could encounter - // many viable options, so pick the most restrictive. - let expected_kind = self - .obligations_for_self_ty(expected_vid) - .filter_map(|(tr, _)| self.tcx.fn_trait_kind_from_lang_item(tr.def_id())) - .fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur)))); + // Even if we can't infer the full signature, we may be able to + // infer the kind. This can occur when we elaborate a predicate + // like `F : Fn`. Note that due to subtyping we could encounter + // many viable options, so pick the most restrictive. + let trait_def_id = match bound_predicate.skip_binder() { + ty::PredicateKind::Projection(data) => { + Some(data.projection_ty.trait_def_id(self.tcx)) + } + ty::PredicateKind::Trait(data) => Some(data.def_id()), + _ => None, + }; + if let Some(closure_kind) = + trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_lang_item(def_id)) + { + expected_kind = Some( + expected_kind + .map_or_else(|| closure_kind, |current| cmp::min(current, closure_kind)), + ); + } + } (expected_sig, expected_kind) } @@ -689,7 +707,7 @@ fn deduce_future_output_from_obligations( let output_ty = match *ret_ty.kind() { ty::Infer(ty::TyVar(ret_vid)) => { - self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| { + self.obligations_for_self_ty(ret_vid).find_map(|obligation| { get_future_output(obligation.predicate, obligation.cause.span) })? }