From a7b4d667feb6149b512da227117baa527529dcaf Mon Sep 17 00:00:00 2001
From: Caio <c410.f3r@gmail.com>
Date: Tue, 1 Mar 2022 18:34:35 -0300
Subject: [PATCH] 9 - Make more use of `let_chains`

Continuation of #94376.

cc #53667
---
 compiler/rustc_trait_selection/src/lib.rs     |  9 +-
 .../src/traits/error_reporting/mod.rs         | 90 +++++++++----------
 .../src/traits/error_reporting/suggestions.rs | 85 ++++++++----------
 .../src/traits/on_unimplemented.rs            | 38 ++++----
 .../src/traits/query/dropck_outlives.rs       | 28 +++---
 .../src/traits/relationships.rs               | 72 +++++++--------
 .../src/traits/select/mod.rs                  | 34 ++++---
 .../rustc_trait_selection/src/traits/wf.rs    | 38 ++++----
 8 files changed, 176 insertions(+), 218 deletions(-)

diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index 5569334ff3d20..7523b8441013a 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -10,19 +10,20 @@
 //!
 //! This API is completely unstable and subject to change.
 
+#![allow(rustc::potential_query_instability)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
-#![feature(drain_filter)]
+#![feature(control_flow_enum)]
+#![feature(crate_visibility_modifier)]
 #![feature(derive_default_enum)]
+#![feature(drain_filter)]
 #![feature(hash_drain_filter)]
 #![feature(label_break_value)]
+#![feature(let_chains)]
 #![feature(let_else)]
 #![feature(never_type)]
-#![feature(crate_visibility_modifier)]
-#![feature(control_flow_enum)]
 #![recursion_limit = "512"] // For rustdoc
-#![allow(rustc::potential_query_instability)]
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 82c3f79a4fa7b..8e42a41c8cf61 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1098,42 +1098,43 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     );
                 }
             }
-            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
-                if fields.len() == found_args.len() && is_closure {
-                    let sugg = format!(
-                        "|({}){}|",
-                        found_args
-                            .iter()
-                            .map(|arg| match arg {
-                                ArgKind::Arg(name, _) => name.to_owned(),
-                                _ => "_".to_owned(),
-                            })
-                            .collect::<Vec<String>>()
-                            .join(", "),
-                        // add type annotations if available
-                        if found_args.iter().any(|arg| match arg {
-                            ArgKind::Arg(_, ty) => ty != "_",
-                            _ => false,
-                        }) {
-                            format!(
-                                ": ({})",
-                                fields
-                                    .iter()
-                                    .map(|(_, ty)| ty.to_owned())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            )
-                        } else {
-                            String::new()
-                        },
-                    );
-                    err.span_suggestion_verbose(
-                        found_span,
-                        "change the closure to accept a tuple instead of individual arguments",
-                        sugg,
-                        Applicability::MachineApplicable,
-                    );
-                }
+            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..]
+                && fields.len() == found_args.len()
+                && is_closure
+            {
+                let sugg = format!(
+                    "|({}){}|",
+                    found_args
+                        .iter()
+                        .map(|arg| match arg {
+                            ArgKind::Arg(name, _) => name.to_owned(),
+                            _ => "_".to_owned(),
+                        })
+                        .collect::<Vec<String>>()
+                        .join(", "),
+                    // add type annotations if available
+                    if found_args.iter().any(|arg| match arg {
+                        ArgKind::Arg(_, ty) => ty != "_",
+                        _ => false,
+                    }) {
+                        format!(
+                            ": ({})",
+                            fields
+                                .iter()
+                                .map(|(_, ty)| ty.to_owned())
+                                .collect::<Vec<String>>()
+                                .join(", ")
+                        )
+                    } else {
+                        String::new()
+                    },
+                );
+                err.span_suggestion_verbose(
+                    found_span,
+                    "change the closure to accept a tuple instead of individual arguments",
+                    sugg,
+                    Applicability::MachineApplicable,
+                );
             }
         }
 
@@ -2231,16 +2232,13 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
             if obligated_types.iter().any(|ot| ot == &self_ty) {
                 return true;
             }
-            if let ty::Adt(def, substs) = self_ty.kind() {
-                if let [arg] = &substs[..] {
-                    if let ty::subst::GenericArgKind::Type(ty) = arg.unpack() {
-                        if let ty::Adt(inner_def, _) = ty.kind() {
-                            if inner_def == def {
-                                return true;
-                            }
-                        }
-                    }
-                }
+            if let ty::Adt(def, substs) = self_ty.kind()
+                && let [arg] = &substs[..]
+                && let ty::subst::GenericArgKind::Type(ty) = arg.unpack()
+                && let ty::Adt(inner_def, _) = ty.kind()
+                && inner_def == def
+            {
+                return true;
             }
         }
         false
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 45bfb2b1e9413..7af2ba8b30f87 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -891,23 +891,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         }
                         if let Some(typeck_results) =
                             self.in_progress_typeck_results.map(|t| t.borrow())
+                            && let ty = typeck_results.expr_ty_adjusted(base)
+                            && let ty::FnDef(def_id, _substs) = ty.kind()
+                            && let Some(hir::Node::Item(hir::Item { span, ident, .. })) =
+                                hir.get_if_local(*def_id)
                         {
-                            let ty = typeck_results.expr_ty_adjusted(base);
-                            if let ty::FnDef(def_id, _substs) = ty.kind() {
-                                if let Some(hir::Node::Item(hir::Item { span, ident, .. })) =
-                                    hir.get_if_local(*def_id)
-                                {
-                                    err.span_suggestion_verbose(
-                                        span.shrink_to_lo(),
-                                        &format!(
-                                            "alternatively, consider making `fn {}` asynchronous",
-                                            ident
-                                        ),
-                                        "async ".to_string(),
-                                        Applicability::MaybeIncorrect,
-                                    );
-                                }
-                            }
+                            err.span_suggestion_verbose(
+                                span.shrink_to_lo(),
+                                &format!(
+                                    "alternatively, consider making `fn {}` asynchronous",
+                                    ident
+                                ),
+                                "async ".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
                         }
                     }
                 }
@@ -1000,34 +997,24 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         span: Span,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) {
-        let is_empty_tuple =
-            |ty: ty::Binder<'tcx, Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty());
-
         let hir = self.tcx.hir();
         let parent_node = hir.get_parent_node(obligation.cause.body_id);
         let node = hir.find(parent_node);
-        if let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(sig, _, body_id), ..
-        })) = node
+        if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node
+            && let body = hir.body(*body_id)
+            && let hir::ExprKind::Block(blk, _) = &body.value.kind
+            && sig.decl.output.span().overlaps(span)
+            && blk.expr.is_none()
+            && *trait_pred.self_ty().skip_binder().kind() == ty::Tuple(ty::List::empty())
+            // FIXME(estebank): When encountering a method with a trait
+            // bound not satisfied in the return type with a body that has
+            // no return, suggest removal of semicolon on last statement.
+            // Once that is added, close #54771.
+            && let Some(stmt) = blk.stmts.last()
+            && let hir::StmtKind::Semi(_) = stmt.kind
         {
-            let body = hir.body(*body_id);
-            if let hir::ExprKind::Block(blk, _) = &body.value.kind {
-                if sig.decl.output.span().overlaps(span)
-                    && blk.expr.is_none()
-                    && is_empty_tuple(trait_pred.self_ty())
-                {
-                    // FIXME(estebank): When encountering a method with a trait
-                    // bound not satisfied in the return type with a body that has
-                    // no return, suggest removal of semicolon on last statement.
-                    // Once that is added, close #54771.
-                    if let Some(ref stmt) = blk.stmts.last() {
-                        if let hir::StmtKind::Semi(_) = stmt.kind {
-                            let sp = self.tcx.sess.source_map().end_point(stmt.span);
-                            err.span_label(sp, "consider removing this semicolon");
-                        }
-                    }
-                }
-            }
+            let sp = self.tcx.sess.source_map().end_point(stmt.span);
+            err.span_label(sp, "consider removing this semicolon");
         }
     }
 
@@ -2481,17 +2468,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation);
                 if self.predicate_may_hold(&try_obligation)
                     && impls_future.must_apply_modulo_regions()
+                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+                    && snippet.ends_with('?')
                 {
-                    if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                        if snippet.ends_with('?') {
-                            err.span_suggestion_verbose(
-                                span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
-                                "consider `await`ing on the `Future`",
-                                ".await".to_string(),
-                                Applicability::MaybeIncorrect,
-                            );
-                        }
-                    }
+                    err.span_suggestion_verbose(
+                        span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
+                        "consider `await`ing on the `Future`",
+                        ".await".to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
                 }
             }
         }
diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
index b05dbbe898a41..7fbdd3689a7eb 100644
--- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
@@ -91,10 +91,8 @@ impl<'tcx> OnUnimplementedDirective {
                     )
                 })?;
             attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
-                if let Some(symbol) = item.value_str() {
-                    if parse_value(symbol).is_err() {
-                        errored = true;
-                    }
+                if let Some(symbol) = item.value_str() && parse_value(symbol).is_err() {
+                    errored = true;
                 }
                 true
             });
@@ -232,24 +230,22 @@ impl<'tcx> OnUnimplementedDirective {
             options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
 
         for command in self.subcommands.iter().chain(Some(self)).rev() {
-            if let Some(ref condition) = command.condition {
-                if !attr::eval_condition(
-                    condition,
-                    &tcx.sess.parse_sess,
-                    Some(tcx.features()),
-                    &mut |c| {
-                        c.ident().map_or(false, |ident| {
-                            let value = c.value_str().map(|s| {
-                                OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
-                            });
+            if let Some(ref condition) = command.condition && !attr::eval_condition(
+                condition,
+                &tcx.sess.parse_sess,
+                Some(tcx.features()),
+                &mut |c| {
+                    c.ident().map_or(false, |ident| {
+                        let value = c.value_str().map(|s| {
+                            OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
+                        });
 
-                            options.contains(&(ident.name, value))
-                        })
-                    },
-                ) {
-                    debug!("evaluate: skipping {:?} due to condition", command);
-                    continue;
-                }
+                        options.contains(&(ident.name, value))
+                    })
+                },
+            ) {
+                debug!("evaluate: skipping {:?} due to condition", command);
+                continue;
             }
             debug!("evaluate: {:?} succeeded", command);
             if let Some(ref message_) = command.message {
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 066f3ffada57a..435d709d37e60 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -43,21 +43,19 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
         let c_ty = self.infcx.canonicalize_query(self.param_env.and(ty), &mut orig_values);
         let span = self.cause.span;
         debug!("c_ty = {:?}", c_ty);
-        if let Ok(result) = tcx.dropck_outlives(c_ty) {
-            if result.is_proven() {
-                if let Ok(InferOk { value, obligations }) =
-                    self.infcx.instantiate_query_response_and_region_obligations(
-                        self.cause,
-                        self.param_env,
-                        &orig_values,
-                        result,
-                    )
-                {
-                    let ty = self.infcx.resolve_vars_if_possible(ty);
-                    let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
-                    return InferOk { value: kinds, obligations };
-                }
-            }
+        if let Ok(result) = tcx.dropck_outlives(c_ty)
+            && result.is_proven()
+            && let Ok(InferOk { value, obligations }) =
+                self.infcx.instantiate_query_response_and_region_obligations(
+                    self.cause,
+                    self.param_env,
+                    &orig_values,
+                    result,
+                )
+        {
+            let ty = self.infcx.resolve_vars_if_possible(ty);
+            let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
+            return InferOk { value: kinds, obligations };
         }
 
         // Errors and ambiuity in dropck occur in two cases:
diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs
index aea44841b8f12..b13646ba1a0c2 100644
--- a/compiler/rustc_trait_selection/src/traits/relationships.rs
+++ b/compiler/rustc_trait_selection/src/traits/relationships.rs
@@ -12,50 +12,38 @@ pub(crate) fn update<'tcx, T>(
     T: TraitEngine<'tcx>,
 {
     // (*) binder skipped
-    if let ty::PredicateKind::Trait(predicate) = obligation.predicate.kind().skip_binder() {
-        if let Some(ty) =
-            infcx.shallow_resolve(predicate.self_ty()).ty_vid().map(|t| infcx.root_var(t))
-        {
-            if infcx
-                .tcx
-                .lang_items()
-                .sized_trait()
-                .map_or(false, |st| st != predicate.trait_ref.def_id)
-            {
-                let new_self_ty = infcx.tcx.types.unit;
+    if let ty::PredicateKind::Trait(tpred) = obligation.predicate.kind().skip_binder()
+        && let Some(ty) = infcx.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| infcx.root_var(t))
+        && infcx.tcx.lang_items().sized_trait().map_or(false, |st| st != tpred.trait_ref.def_id)
+    {
+        let new_self_ty = infcx.tcx.types.unit;
 
-                let trait_ref = ty::TraitRef {
-                    substs: infcx
-                        .tcx
-                        .mk_substs_trait(new_self_ty, &predicate.trait_ref.substs[1..]),
-                    ..predicate.trait_ref
-                };
+        let trait_ref = ty::TraitRef {
+            substs: infcx.tcx.mk_substs_trait(new_self_ty, &tpred.trait_ref.substs[1..]),
+            ..tpred.trait_ref
+        };
 
-                // Then contstruct a new obligation with Self = () added
-                // to the ParamEnv, and see if it holds.
-                let o = rustc_infer::traits::Obligation::new(
-                    ObligationCause::dummy(),
-                    obligation.param_env,
-                    obligation
-                        .predicate
-                        .kind()
-                        .map_bound(|_| {
-                            // (*) binder moved here
-                            ty::PredicateKind::Trait(ty::TraitPredicate {
-                                trait_ref,
-                                constness: predicate.constness,
-                                polarity: predicate.polarity,
-                            })
-                        })
-                        .to_predicate(infcx.tcx),
-                );
-                // Don't report overflow errors. Otherwise equivalent to may_hold.
-                if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) {
-                    if result.may_apply() {
-                        engine.relationships().entry(ty).or_default().self_in_trait = true;
-                    }
-                }
-            }
+        // Then contstruct a new obligation with Self = () added
+        // to the ParamEnv, and see if it holds.
+        let o = rustc_infer::traits::Obligation::new(
+            ObligationCause::dummy(),
+            obligation.param_env,
+            obligation
+                .predicate
+                .kind()
+                .map_bound(|_| {
+                    // (*) binder moved here
+                    ty::PredicateKind::Trait(ty::TraitPredicate {
+                        trait_ref,
+                        constness: tpred.constness,
+                        polarity: tpred.polarity,
+                    })
+                })
+                .to_predicate(infcx.tcx),
+        );
+        // Don't report overflow errors. Otherwise equivalent to may_hold.
+        if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) && result.may_apply() {
+            engine.relationships().entry(ty).or_default().self_in_trait = true;
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 8bcb1ccb5846d..f3c7642f7a318 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -579,24 +579,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                     previous_stack,
                                     subobligations,
                                 );
-                                if let Ok(res) = res {
-                                    if res == EvaluatedToOk || res == EvaluatedToOkModuloRegions {
-                                        if let Some(key) =
-                                            ProjectionCacheKey::from_poly_projection_predicate(
-                                                self, data,
-                                            )
-                                        {
-                                            // If the result is something that we can cache, then mark this
-                                            // entry as 'complete'. This will allow us to skip evaluating the
-                                            // suboligations at all the next time we evaluate the projection
-                                            // predicate.
-                                            self.infcx
-                                                .inner
-                                                .borrow_mut()
-                                                .projection_cache()
-                                                .complete(key, res);
-                                        }
-                                    }
+                                if let Ok(eval_rslt) = res
+                                    && (eval_rslt == EvaluatedToOk || eval_rslt == EvaluatedToOkModuloRegions)
+                                    && let Some(key) =
+                                        ProjectionCacheKey::from_poly_projection_predicate(
+                                            self, data,
+                                        )
+                                {
+                                    // If the result is something that we can cache, then mark this
+                                    // entry as 'complete'. This will allow us to skip evaluating the
+                                    // suboligations at all the next time we evaluate the projection
+                                    // predicate.
+                                    self.infcx
+                                        .inner
+                                        .borrow_mut()
+                                        .projection_cache()
+                                        .complete(key, eval_rslt);
                                 }
                                 res
                             }
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 7da5c50d2307d..943f36efc153f 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -224,36 +224,30 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
             // projection coming from another associated type. See
             // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
             // `traits-assoc-type-in-supertrait-bad.rs`.
-            if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind()) {
-                if let Some(&impl_item_id) =
+            if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind())
+                && let Some(&impl_item_id) =
                     tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
-                {
-                    if let Some(impl_item_span) = items
-                        .iter()
-                        .find(|item| item.id.def_id.to_def_id() == impl_item_id)
-                        .map(fix_span)
-                    {
-                        cause.span = impl_item_span;
-                    }
-                }
+                && let Some(impl_item_span) = items
+                    .iter()
+                    .find(|item| item.id.def_id.to_def_id() == impl_item_id)
+                    .map(fix_span)
+            {
+                cause.span = impl_item_span;
             }
         }
         ty::PredicateKind::Trait(pred) => {
             // An associated item obligation born out of the `trait` failed to be met. An example
             // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
             debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
-            if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind() {
-                if let Some(&impl_item_id) =
+            if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind()
+                && let Some(&impl_item_id) =
                     tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id)
-                {
-                    if let Some(impl_item_span) = items
-                        .iter()
-                        .find(|item| item.id.def_id.to_def_id() == impl_item_id)
-                        .map(fix_span)
-                    {
-                        cause.span = impl_item_span;
-                    }
-                }
+                && let Some(impl_item_span) = items
+                    .iter()
+                    .find(|item| item.id.def_id.to_def_id() == impl_item_id)
+                    .map(fix_span)
+            {
+                cause.span = impl_item_span;
             }
         }
         _ => {}