diff options
Diffstat (limited to 'compiler/rustc_hir_typeck/src/_match.rs')
-rw-r--r-- | compiler/rustc_hir_typeck/src/_match.rs | 46 |
1 files changed, 18 insertions, 28 deletions
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 7ad9f51ba..81fe0cc48 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -1,7 +1,8 @@ use crate::coercion::{AsCoercionSite, CoerceMany}; use crate::{Diverges, Expectation, FnCtxt, Needs}; -use rustc_errors::{Applicability, Diagnostic, MultiSpan}; +use rustc_errors::Diagnostic; use rustc_hir::{self as hir, ExprKind}; +use rustc_hir_pretty::ty_to_string; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; use rustc_middle::ty::{self, Ty}; @@ -225,24 +226,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } - let semi_span = expr.span.shrink_to_hi().with_hi(semi_span.hi()); - let mut ret_span: MultiSpan = semi_span.into(); - ret_span.push_span_label( - expr.span, - "this could be implicitly returned but it is a statement, not a tail expression", - ); - ret_span.push_span_label(ret, "the `match` arms can conform to this return type"); - ret_span.push_span_label( - semi_span, - "the `match` is a statement because of this semicolon, consider removing it", - ); - diag.span_note(ret_span, "you might have meant to return the `match` expression"); - diag.tool_only_span_suggestion( - semi_span, - "remove this semicolon", - "", - Applicability::MaybeIncorrect, - ); + let semi = expr.span.shrink_to_hi().with_hi(semi_span.hi()); + let sugg = crate::errors::RemoveSemiForCoerce { expr: expr.span, ret, semi }; + diag.subdiagnostic(sugg); } /// When the previously checked expression (the scrutinee) diverges, @@ -267,7 +253,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // If this `if` expr is the parent's function return expr, // the cause of the type coercion is the return type, point at it. (#25228) - let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, span); + let hir_id = self.tcx.hir().parent_id(self.tcx.hir().parent_id(then_expr.hir_id)); + let ret_reason = self.maybe_get_coercion_reason(hir_id, span); let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse); let mut error = false; coercion.coerce_forced_unit( @@ -290,11 +277,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error } - fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, sp: Span) -> Option<(Span, String)> { - let node = { - let rslt = self.tcx.hir().parent_id(self.tcx.hir().parent_id(hir_id)); - self.tcx.hir().get(rslt) - }; + pub fn maybe_get_coercion_reason( + &self, + hir_id: hir::HirId, + sp: Span, + ) -> Option<(Span, String)> { + let node = self.tcx.hir().get(hir_id); if let hir::Node::Block(block) = node { // check that the body's parent is an fn let parent = self.tcx.hir().get_parent(self.tcx.hir().parent_id(block.hir_id)); @@ -304,9 +292,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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 `{snippet}` because of this return type"))) + let (ty, span) = match fn_decl.output { + hir::FnRetTy::DefaultReturn(span) => ("()".to_string(), span), + hir::FnRetTy::Return(ty) => (ty_to_string(ty), ty.span), + }; + Some((span, format!("expected `{ty}` because of this return type"))) }); } } |