@@ -216,13 +216,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
216
216
) -> ( Span , Option < ( Span , StatementAsExpression ) > ) {
217
217
let arm = & arms[ i] ;
218
218
let ( arm_span, mut semi_span) = if let hir:: ExprKind :: Block ( blk, _) = & arm. body . kind {
219
- self . find_block_span ( blk, prior_arm_ty)
219
+ (
220
+ self . find_block_span ( blk) ,
221
+ prior_arm_ty
222
+ . and_then ( |prior_arm_ty| self . could_remove_semicolon ( blk, prior_arm_ty) ) ,
223
+ )
220
224
} else {
221
225
( arm. body . span , None )
222
226
} ;
223
227
if semi_span. is_none ( ) && i > 0 {
224
228
if let hir:: ExprKind :: Block ( blk, _) = & arms[ i - 1 ] . body . kind {
225
- let ( _ , semi_span_prev) = self . find_block_span ( blk, Some ( arm_ty) ) ;
229
+ let semi_span_prev = self . could_remove_semicolon ( blk, arm_ty) ;
226
230
semi_span = semi_span_prev;
227
231
}
228
232
}
@@ -313,7 +317,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
313
317
else_ty : Ty < ' tcx > ,
314
318
opt_suggest_box_span : Option < Span > ,
315
319
) -> ObligationCause < ' tcx > {
316
- let mut outer_sp = if self . tcx . sess . source_map ( ) . is_multiline ( span) {
320
+ let mut outer_span = if self . tcx . sess . source_map ( ) . is_multiline ( span) {
317
321
// The `if`/`else` isn't in one line in the output, include some context to make it
318
322
// clear it is an if/else expression:
319
323
// ```
@@ -339,69 +343,67 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
339
343
None
340
344
} ;
341
345
342
- let mut remove_semicolon = None ;
343
- let error_sp = if let ExprKind :: Block ( block, _) = & else_expr. kind {
344
- let ( error_sp, semi_sp) = self . find_block_span ( block, Some ( then_ty) ) ;
345
- remove_semicolon = semi_sp;
346
- if block. expr . is_none ( ) && block. stmts . is_empty ( ) {
347
- // Avoid overlapping spans that aren't as readable:
348
- // ```
349
- // 2 | let x = if true {
350
- // | _____________-
351
- // 3 | | 3
352
- // | | - expected because of this
353
- // 4 | | } else {
354
- // | |____________^
355
- // 5 | ||
356
- // 6 | || };
357
- // | || ^
358
- // | ||_____|
359
- // | |______if and else have incompatible types
360
- // | expected integer, found `()`
361
- // ```
362
- // by not pointing at the entire expression:
363
- // ```
364
- // 2 | let x = if true {
365
- // | ------- `if` and `else` have incompatible types
366
- // 3 | 3
367
- // | - expected because of this
368
- // 4 | } else {
369
- // | ____________^
370
- // 5 | |
371
- // 6 | | };
372
- // | |_____^ expected integer, found `()`
373
- // ```
374
- if outer_sp. is_some ( ) {
375
- outer_sp = Some ( self . tcx . sess . source_map ( ) . guess_head_span ( span) ) ;
376
- }
346
+ let ( error_sp, else_id) = if let ExprKind :: Block ( block, _) = & else_expr. kind {
347
+ let block = block. peel_blocks ( ) ;
348
+
349
+ // Avoid overlapping spans that aren't as readable:
350
+ // ```
351
+ // 2 | let x = if true {
352
+ // | _____________-
353
+ // 3 | | 3
354
+ // | | - expected because of this
355
+ // 4 | | } else {
356
+ // | |____________^
357
+ // 5 | ||
358
+ // 6 | || };
359
+ // | || ^
360
+ // | ||_____|
361
+ // | |______if and else have incompatible types
362
+ // | expected integer, found `()`
363
+ // ```
364
+ // by not pointing at the entire expression:
365
+ // ```
366
+ // 2 | let x = if true {
367
+ // | ------- `if` and `else` have incompatible types
368
+ // 3 | 3
369
+ // | - expected because of this
370
+ // 4 | } else {
371
+ // | ____________^
372
+ // 5 | |
373
+ // 6 | | };
374
+ // | |_____^ expected integer, found `()`
375
+ // ```
376
+ if block. expr . is_none ( ) && block. stmts . is_empty ( )
377
+ && let Some ( outer_span) = & mut outer_span
378
+ {
379
+ * outer_span = self . tcx . sess . source_map ( ) . guess_head_span ( * outer_span) ;
377
380
}
378
- error_sp
381
+
382
+ ( self . find_block_span ( block) , block. hir_id )
379
383
} else {
380
- // shouldn't happen unless the parser has done something weird
381
- else_expr. span
384
+ ( else_expr. span , else_expr. hir_id )
382
385
} ;
383
386
384
- // Compute `Span` of `then` part of `if`-expression.
385
- let then_sp = if let ExprKind :: Block ( block, _) = & then_expr. kind {
386
- let ( then_sp, semi_sp) = self . find_block_span ( block, Some ( else_ty) ) ;
387
- remove_semicolon = remove_semicolon. or ( semi_sp) ;
387
+ let then_id = if let ExprKind :: Block ( block, _) = & then_expr. kind {
388
+ let block = block. peel_blocks ( ) ;
389
+ // Exclude overlapping spans
388
390
if block. expr . is_none ( ) && block. stmts . is_empty ( ) {
389
- outer_sp = None ; // same as in `error_sp`; cleanup output
391
+ outer_span = None ;
390
392
}
391
- then_sp
393
+ block . hir_id
392
394
} else {
393
- // shouldn't happen unless the parser has done something weird
394
- then_expr. span
395
+ then_expr. hir_id
395
396
} ;
396
397
397
398
// Finally construct the cause:
398
399
self . cause (
399
400
error_sp,
400
401
ObligationCauseCode :: IfExpression ( Box :: new ( IfExpressionCause {
401
- then : then_sp,
402
- else_sp : error_sp,
403
- outer : outer_sp,
404
- semicolon : remove_semicolon,
402
+ else_id,
403
+ then_id,
404
+ then_ty,
405
+ else_ty,
406
+ outer_span,
405
407
opt_suggest_box_span,
406
408
} ) ) ,
407
409
)
@@ -482,22 +484,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
482
484
}
483
485
}
484
486
485
- fn find_block_span (
486
- & self ,
487
- block : & ' tcx hir:: Block < ' tcx > ,
488
- expected_ty : Option < Ty < ' tcx > > ,
489
- ) -> ( Span , Option < ( Span , StatementAsExpression ) > ) {
490
- if let Some ( expr) = & block. expr {
491
- ( expr. span , None )
492
- } else if let Some ( stmt) = block. stmts . last ( ) {
493
- // possibly incorrect trailing `;` in the else arm
494
- ( stmt. span , expected_ty. and_then ( |ty| self . could_remove_semicolon ( block, ty) ) )
495
- } else {
496
- // empty block; point at its entirety
497
- ( block. span , None )
498
- }
499
- }
500
-
501
487
// When we have a `match` as a tail expression in a `fn` with a returned `impl Trait`
502
488
// we check if the different arms would work with boxed trait objects instead and
503
489
// provide a structured suggestion in that case.
0 commit comments