]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_hir_typeck/src/closure.rs
reverse obligations for better diagnostics on multiple conflicting fn bounds
[rust.git] / compiler / rustc_hir_typeck / src / closure.rs
index cc1191d32458f607694ce6b00effb0fc555d7d9f..14f6e7d36be2cf1299b31d801899cd804353450c 100644 (file)
@@ -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;
@@ -226,27 +227,33 @@ fn deduce_expectations_from_obligations(
         expected_vid: ty::TyVid,
     ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
         let mut expected_sig = None;
-        // 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<A>`. Note that due to subtyping we could encounter
-        // many viable options, so pick the most restrictive.
         let mut expected_kind = None;
 
-        for obligation in self.obligations_for_self_ty(expected_vid) {
+        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()
             {
-                // Given a Projection predicate, we can potentially infer
-                // the complete signature.
                 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<A>`. 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))