about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/check/_match.rs100
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs2
2 files changed, 50 insertions, 52 deletions
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs
index d056f2c90f9..dee81510b79 100644
--- a/compiler/rustc_typeck/src/check/_match.rs
+++ b/compiler/rustc_typeck/src/check/_match.rs
@@ -13,41 +13,6 @@ use rustc_trait_selection::traits::{
     StatementAsExpression,
 };
 
-macro_rules! create_maybe_get_coercion_reason {
-    ($fn_name:ident, $node:expr) => {
-        pub(crate) fn $fn_name(&self, hir_id: hir::HirId, sp: Span) -> Option<(Span, String)> {
-            let node = $node(self.tcx.hir(), hir_id);
-            if let hir::Node::Block(block) = node {
-                // check that the body's parent is an fn
-                let parent = self.tcx.hir().get(
-                    self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(block.hir_id)),
-                );
-                if let (
-                    Some(expr),
-                    hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }),
-                ) = (&block.expr, parent)
-                {
-                    // check that the `if` expr without `else` is the fn body's expr
-                    if expr.span == sp {
-                        return self.get_fn_decl(hir_id).and_then(|(fn_decl, _)| {
-                            let span = fn_decl.output.span();
-                            let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?;
-                            Some((
-                                span,
-                                format!("expected `{}` because of this return type", snippet),
-                            ))
-                        });
-                    }
-                }
-            }
-            if let hir::Node::Local(hir::Local { ty: Some(_), pat, .. }) = node {
-                return Some((pat.span, "expected because of this assignment".to_string()));
-            }
-            None
-        }
-    };
-}
-
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn check_match(
         &self,
@@ -154,7 +119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     expr.span,
                     &arms[0].body,
                     &mut coercion,
-                    |hir_id, span| self.maybe_get_coercion_reason(hir_id, span),
+                    |hir_id, span| self.coercion_reason_match(hir_id, span),
                 ) {
                 tcx.ty_error()
             } else {
@@ -373,23 +338,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         error
     }
 
-    create_maybe_get_coercion_reason!(
-        maybe_get_coercion_reason,
-        |hir: rustc_middle::hir::map::Map<'a>, id| {
-            let arm_id = hir.get_parent_node(id);
-            let match_id = hir.get_parent_node(arm_id);
-            let containing_id = hir.get_parent_node(match_id);
-            hir.get(containing_id)
-        }
-    );
+    pub(crate) fn coercion_reason_if(
+        &self,
+        hir_id: hir::HirId,
+        span: Span,
+    ) -> Option<(Span, String)> {
+        self.coercion_reason_inner(hir_id, span, 1)
+    }
 
-    create_maybe_get_coercion_reason!(
-        maybe_get_coercion_reason_if,
-        |hir: rustc_middle::hir::map::Map<'a>, id| {
-            let rslt = hir.get_parent_node(hir.get_parent_node(id));
-            hir.get(rslt)
+    pub(crate) fn coercion_reason_match(
+        &self,
+        hir_id: hir::HirId,
+        span: Span,
+    ) -> Option<(Span, String)> {
+        self.coercion_reason_inner(hir_id, span, 2)
+    }
+
+    fn coercion_reason_inner(
+        &self,
+        hir_id: hir::HirId,
+        span: Span,
+        parent_index: usize,
+    ) -> Option<(Span, String)> {
+        let hir = self.tcx.hir();
+        let mut parent_iter = hir.parent_iter(hir_id);
+        let (_, node) = parent_iter.nth(parent_index)?;
+        match node {
+            hir::Node::Block(block) => {
+                let expr = block.expr?;
+                // check that the body's parent is an fn
+                let (_, parent) = parent_iter.nth(1)?;
+                if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }) = parent {
+                    // check that the `if` expr without `else` is the fn body's expr
+                    if expr.span == span {
+                        let (fn_decl, _) = self.get_fn_decl(hir_id)?;
+                        let span = fn_decl.output.span();
+                        let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?;
+                        return Some((
+                            span,
+                            format!("expected `{}` because of this return type", snippet),
+                        ));
+                    }
+                }
+                None
+            }
+            hir::Node::Local(hir::Local { ty: Some(_), pat, .. }) => {
+                Some((pat.span, "expected because of this assignment".to_string()))
+            }
+            _ => None,
         }
-    );
+    }
 
     pub(crate) fn if_cause(
         &self,
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 08258aac96f..e95884ae23b 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -838,7 +838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.diverges.set(cond_diverges | then_diverges & else_diverges);
         } else {
             self.if_fallback_coercion(sp, then_expr, &mut coerce, |hir_id, span| {
-                self.maybe_get_coercion_reason_if(hir_id, span)
+                self.coercion_reason_if(hir_id, span)
             });
 
             // If the condition is false we can't diverge.