diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index d5f03a6aaed..c2d987a95cf 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -136,15 +136,7 @@ pub fn check_match( &cause, Some(&arm.body), arm_ty, - Some(&mut |err| { - self.suggest_removing_semicolon_for_coerce( - err, - expr, - orig_expected, - arm_ty, - prior_arm, - ) - }), + |err| self.suggest_removing_semicolon_for_coerce(err, expr, arm_ty, prior_arm), false, ); @@ -181,7 +173,6 @@ fn suggest_removing_semicolon_for_coerce( &self, diag: &mut Diagnostic, expr: &hir::Expr<'tcx>, - expectation: Expectation<'tcx>, arm_ty: Ty<'tcx>, prior_arm: Option<(Option, Ty<'tcx>, Span)>, ) { @@ -195,7 +186,7 @@ fn suggest_removing_semicolon_for_coerce( let hir::ExprKind::Block(block, _) = body.value.kind else { return; }; - let Some(hir::Stmt { kind: hir::StmtKind::Semi(last_expr), .. }) = + let Some(hir::Stmt { kind: hir::StmtKind::Semi(last_expr), span: semi_span, .. }) = block.innermost_block().stmts.last() else { return; @@ -212,9 +203,6 @@ fn suggest_removing_semicolon_for_coerce( else { return; }; - let Expectation::IsLast(stmt) = expectation else { - return; - }; let can_coerce_to_return_ty = match self.ret_coercion.as_ref() { Some(ret_coercion) => { @@ -231,7 +219,7 @@ fn suggest_removing_semicolon_for_coerce( return; } - let semi_span = expr.span.shrink_to_hi().with_hi(stmt.hi()); + 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, @@ -279,7 +267,7 @@ pub(super) fn if_fallback_coercion( coercion.coerce_forced_unit( self, &cause, - &mut |err| { + |err| { if let Some((span, msg)) = &ret_reason { err.span_label(*span, msg.clone()); } else if let ExprKind::Block(block, _) = &then_expr.kind diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 4fdfc51bc86..fa6bad84376 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1418,7 +1418,7 @@ pub fn coerce<'a>( expression: &'tcx hir::Expr<'tcx>, expression_ty: Ty<'tcx>, ) { - self.coerce_inner(fcx, cause, Some(expression), expression_ty, None, false) + self.coerce_inner(fcx, cause, Some(expression), expression_ty, |_| {}, false) } /// Indicates that one of the inputs is a "forced unit". This @@ -1437,7 +1437,7 @@ pub fn coerce_forced_unit<'a>( &mut self, fcx: &FnCtxt<'a, 'tcx>, cause: &ObligationCause<'tcx>, - augment_error: &mut dyn FnMut(&mut Diagnostic), + augment_error: impl FnOnce(&mut Diagnostic), label_unit_as_expected: bool, ) { self.coerce_inner( @@ -1445,7 +1445,7 @@ pub fn coerce_forced_unit<'a>( cause, None, Ty::new_unit(fcx.tcx), - Some(augment_error), + augment_error, label_unit_as_expected, ) } @@ -1460,7 +1460,7 @@ pub(crate) fn coerce_inner<'a>( cause: &ObligationCause<'tcx>, expression: Option<&'tcx hir::Expr<'tcx>>, mut expression_ty: Ty<'tcx>, - augment_error: Option<&mut dyn FnMut(&mut Diagnostic)>, + augment_error: impl FnOnce(&mut Diagnostic), label_expression_as_expected: bool, ) { // Incorporate whatever type inference information we have @@ -1639,9 +1639,7 @@ pub(crate) fn coerce_inner<'a>( } } - if let Some(augment_error) = augment_error { - augment_error(&mut err); - } + augment_error(&mut err); let is_insufficiently_polymorphic = matches!(coercion_error, TypeError::RegionsInsufficientlyPolymorphic(..)); diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs index 4f086cf597d..35e5fb769a5 100644 --- a/compiler/rustc_hir_typeck/src/expectation.rs +++ b/compiler/rustc_hir_typeck/src/expectation.rs @@ -21,8 +21,6 @@ pub enum Expectation<'tcx> { /// This rvalue expression will be wrapped in `&` or `Box` and coerced /// to `&Ty` or `Box`, respectively. `Ty` is `[A]` or `Trait`. ExpectRvalueLikeUnsized(Ty<'tcx>), - - IsLast(Span), } impl<'a, 'tcx> Expectation<'tcx> { @@ -88,13 +86,12 @@ fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> { ExpectCastableToType(t) => ExpectCastableToType(fcx.resolve_vars_if_possible(t)), ExpectHasType(t) => ExpectHasType(fcx.resolve_vars_if_possible(t)), ExpectRvalueLikeUnsized(t) => ExpectRvalueLikeUnsized(fcx.resolve_vars_if_possible(t)), - IsLast(sp) => IsLast(sp), } } pub(super) fn to_option(self, fcx: &FnCtxt<'a, 'tcx>) -> Option> { match self.resolve(fcx) { - NoExpectation | IsLast(_) => None, + NoExpectation => None, ExpectCastableToType(ty) | ExpectHasType(ty) | ExpectRvalueLikeUnsized(ty) => Some(ty), } } @@ -106,9 +103,7 @@ pub(super) fn to_option(self, fcx: &FnCtxt<'a, 'tcx>) -> Option> { pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option> { match self { ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(ty)), - NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) | IsLast(_) => { - None - } + NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) => None, } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index eb6359ed72f..80d7cc57edb 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -60,28 +60,13 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - fn check_expr_eq_type(&self, expr: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>) { - let ty = self.check_expr_with_hint(expr, expected); - self.demand_eqtype(expr.span, expected, ty); - } - pub fn check_expr_has_type_or_error( &self, expr: &'tcx hir::Expr<'tcx>, - expected: Ty<'tcx>, - extend_err: impl FnMut(&mut Diagnostic), + expected_ty: Ty<'tcx>, + extend_err: impl FnOnce(&mut Diagnostic), ) -> Ty<'tcx> { - self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected), extend_err) - } - - fn check_expr_meets_expectation_or_error( - &self, - expr: &'tcx hir::Expr<'tcx>, - expected: Expectation<'tcx>, - mut extend_err: impl FnMut(&mut Diagnostic), - ) -> Ty<'tcx> { - let expected_ty = expected.to_option(&self).unwrap_or(self.tcx.types.bool); - let mut ty = self.check_expr_with_expectation(expr, expected); + let mut ty = self.check_expr_with_expectation(expr, ExpectHasType(expected_ty)); // While we don't allow *arbitrary* coercions here, we *do* allow // coercions from ! to `expected`. @@ -341,9 +326,10 @@ fn check_expr_kind( } ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr), ExprKind::Type(e, t) => { - let ty = self.to_ty_saving_user_provided_ty(&t); - self.check_expr_eq_type(&e, ty); - ty + let ascribed_ty = self.to_ty_saving_user_provided_ty(&t); + let ty = self.check_expr_with_hint(e, ascribed_ty); + self.demand_eqtype(e.span, ascribed_ty, ty); + ascribed_ty } ExprKind::If(cond, then_expr, opt_else_expr) => { self.check_then_else(cond, then_expr, opt_else_expr, expr.span, expected) @@ -666,7 +652,7 @@ fn check_expr_break( coerce.coerce_forced_unit( self, &cause, - &mut |mut err| { + |mut err| { self.suggest_mismatched_types_on_tail( &mut err, expr, ty, e_ty, target_id, ); @@ -762,7 +748,7 @@ fn check_expr_return( coercion.coerce_forced_unit( self, &cause, - &mut |db| { + |db| { let span = fn_decl.output.span(); if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { db.span_label( @@ -774,7 +760,7 @@ fn check_expr_return( true, ); } else { - coercion.coerce_forced_unit(self, &cause, &mut |_| (), true); + coercion.coerce_forced_unit(self, &cause, |_| (), true); } } self.tcx.types.never diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index e3d97b41980..94c54197294 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1485,7 +1485,7 @@ pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) { self.check_decl(local.into()); } - pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) { + pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) { // Don't do all the complex logic below for `DeclItem`. match stmt.kind { hir::StmtKind::Item(..) => return, @@ -1512,14 +1512,7 @@ pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) { }); } hir::StmtKind::Semi(ref expr) => { - // All of this is equivalent to calling `check_expr`, but it is inlined out here - // in order to capture the fact that this `match` is the last statement in its - // function. This is done for better suggestions to remove the `;`. - let expectation = match expr.kind { - hir::ExprKind::Match(..) if is_last => IsLast(stmt.span), - _ => NoExpectation, - }; - self.check_expr_with_expectation(expr, expectation); + self.check_expr(expr); } } @@ -1570,8 +1563,8 @@ pub(in super::super) fn check_block_with_expected( let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false }; let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || { - for (pos, s) in blk.stmts.iter().enumerate() { - self.check_stmt(s, blk.stmts.len() - 1 == pos); + for s in blk.stmts { + self.check_stmt(s); } // check the tail expression **without** holding the @@ -1594,9 +1587,9 @@ pub(in super::super) fn check_block_with_expected( &cause, Some(tail_expr), tail_expr_ty, - Some(&mut |diag: &mut Diagnostic| { + |diag| { self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic); - }), + }, false, ); } else { @@ -1633,7 +1626,7 @@ pub(in super::super) fn check_block_with_expected( coerce.coerce_forced_unit( self, &self.misc(sp), - &mut |err| { + |err| { if let Some(expected_ty) = expected.only_has_type(self) { if blk.stmts.is_empty() && blk.expr.is_none() { self.suggest_boxing_when_appropriate(