From 8746b79a384cdb30ecc2dae3ca0f0ece4dc56eed Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 29 Jul 2021 13:13:37 -0500 Subject: [PATCH 1/2] Inline create_maybe_get_coercion_reason macro --- compiler/rustc_typeck/src/check/_match.rs | 100 +++++++++++----------- compiler/rustc_typeck/src/check/expr.rs | 2 +- 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. From 02cd72e34b36d7bf2e27b9eaedf2af4e19cc2d85 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sun, 1 Aug 2021 17:44:31 -0500 Subject: [PATCH 2/2] Inline make_if macro --- compiler/rustc_ast_lowering/src/expr.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 7fecf537cfb..bacf5662bc0 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -442,18 +442,10 @@ impl<'hir> LoweringContext<'_, 'hir> { then: &Block, else_opt: Option<&Expr>, ) -> hir::ExprKind<'hir> { - macro_rules! make_if { - ($opt:expr) => {{ - let cond = self.lower_expr(cond); - let then_expr = self.lower_block_expr(then); - hir::ExprKind::If(cond, self.arena.alloc(then_expr), $opt) - }}; - } - if let Some(rslt) = else_opt { - make_if!(Some(self.lower_expr(rslt))) - } else { - make_if!(None) - } + let cond = self.lower_expr(cond); + let then = self.arena.alloc(self.lower_block_expr(then)); + let els = else_opt.map(|els| self.lower_expr(els)); + hir::ExprKind::If(cond, then, els) } fn lower_expr_if_let(