@@ -124,11 +124,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
124124 }
125125 }
126126 } else {
127- let arm_span = if let hir:: ExprKind :: Block ( blk, _) = & arm. body . kind {
128- // Point at the block expr instead of the entire block
129- blk. expr . as_ref ( ) . map ( |e| e. span ) . unwrap_or ( arm. body . span )
127+ let ( arm_span, semi_span) = if let hir:: ExprKind :: Block ( blk, _) = & arm. body . kind {
128+ self . find_block_span ( blk, prior_arm_ty)
130129 } else {
131- arm. body . span
130+ ( arm. body . span , None )
132131 } ;
133132 let ( span, code) = match i {
134133 // The reason for the first arm to fail is not that the match arms diverge,
@@ -138,6 +137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
138137 expr. span ,
139138 ObligationCauseCode :: MatchExpressionArm ( box MatchExpressionArmCause {
140139 arm_span,
140+ semi_span,
141141 source : match_src,
142142 prior_arms : other_arms. clone ( ) ,
143143 last_ty : prior_arm_ty. unwrap ( ) ,
@@ -295,14 +295,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
295295
296296 let mut remove_semicolon = None ;
297297 let error_sp = if let ExprKind :: Block ( block, _) = & else_expr. kind {
298- if let Some ( expr) = & block. expr {
299- expr. span
300- } else if let Some ( stmt) = block. stmts . last ( ) {
301- // possibly incorrect trailing `;` in the else arm
302- remove_semicolon = self . could_remove_semicolon ( block, then_ty) ;
303- stmt. span
304- } else {
305- // empty block; point at its entirety
298+ let ( error_sp, semi_sp) = self . find_block_span ( block, Some ( then_ty) ) ;
299+ remove_semicolon = semi_sp;
300+ if block. expr . is_none ( ) && block. stmts . is_empty ( ) {
306301 // Avoid overlapping spans that aren't as readable:
307302 // ```
308303 // 2 | let x = if true {
@@ -333,26 +328,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
333328 if outer_sp. is_some ( ) {
334329 outer_sp = Some ( self . tcx . sess . source_map ( ) . guess_head_span ( span) ) ;
335330 }
336- else_expr. span
337331 }
332+ error_sp
338333 } else {
339334 // shouldn't happen unless the parser has done something weird
340335 else_expr. span
341336 } ;
342337
343338 // Compute `Span` of `then` part of `if`-expression.
344339 let then_sp = if let ExprKind :: Block ( block, _) = & then_expr. kind {
345- if let Some ( expr) = & block. expr {
346- expr. span
347- } else if let Some ( stmt) = block. stmts . last ( ) {
348- // possibly incorrect trailing `;` in the else arm
349- remove_semicolon = remove_semicolon. or ( self . could_remove_semicolon ( block, else_ty) ) ;
350- stmt. span
351- } else {
352- // empty block; point at its entirety
340+ let ( then_sp, semi_sp) = self . find_block_span ( block, Some ( else_ty) ) ;
341+ remove_semicolon = remove_semicolon. or ( semi_sp) ;
342+ if block. expr . is_none ( ) && block. stmts . is_empty ( ) {
353343 outer_sp = None ; // same as in `error_sp`; cleanup output
354- then_expr. span
355344 }
345+ then_sp
356346 } else {
357347 // shouldn't happen unless the parser has done something weird
358348 then_expr. span
@@ -450,4 +440,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
450440 scrut_ty
451441 }
452442 }
443+
444+ fn find_block_span (
445+ & self ,
446+ block : & ' tcx hir:: Block < ' tcx > ,
447+ expected_ty : Option < Ty < ' tcx > > ,
448+ ) -> ( Span , Option < Span > ) {
449+ if let Some ( expr) = & block. expr {
450+ ( expr. span , None )
451+ } else if let Some ( stmt) = block. stmts . last ( ) {
452+ // possibly incorrect trailing `;` in the else arm
453+ ( stmt. span , expected_ty. and_then ( |ty| self . could_remove_semicolon ( block, ty) ) )
454+ } else {
455+ // empty block; point at its entirety
456+ ( block. span , None )
457+ }
458+ }
453459}
0 commit comments