@@ -1199,7 +1199,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
1199
1199
( self . final_ty . unwrap_or ( self . expected_ty ) , expression_ty)
1200
1200
} ;
1201
1201
1202
- let reason_label = "expected because of this statement" ;
1203
1202
let mut db;
1204
1203
match cause. code {
1205
1204
ObligationCauseCode :: ReturnNoExpression => {
@@ -1209,63 +1208,20 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
1209
1208
db. span_label ( cause. span , "return type is not `()`" ) ;
1210
1209
}
1211
1210
ObligationCauseCode :: BlockTailExpression ( blk_id) => {
1212
- db = fcx. report_mismatched_types ( cause, expected, found, err) ;
1213
-
1214
- let expr = expression. unwrap_or_else ( || {
1215
- span_bug ! ( cause. span,
1216
- "supposed to be part of a block tail expression, but the \
1217
- expression is empty") ;
1218
- } ) ;
1219
- let pointing_at_return_type = fcx. suggest_mismatched_types_on_tail (
1220
- & mut db,
1221
- expr,
1211
+ let parent_id = fcx. tcx . hir ( ) . get_parent_node ( blk_id) ;
1212
+ db = self . report_return_mismatched_types (
1213
+ cause,
1222
1214
expected,
1223
1215
found,
1224
- cause. span ,
1225
- blk_id,
1216
+ err,
1217
+ fcx,
1218
+ parent_id,
1219
+ expression. map ( |expr| ( expr, blk_id) ) ,
1226
1220
) ;
1227
- // FIXME: replace with navigating up the chain until hitting an fn or
1228
- // bailing if no "pass-through" Node is found, in order to provide a
1229
- // suggestion when encountering something like:
1230
- // ```
1231
- // fn foo(a: bool) -> impl Debug {
1232
- // if a {
1233
- // bar()?;
1234
- // }
1235
- // {
1236
- // let x = unsafe { bar() };
1237
- // x
1238
- // }
1239
- // }
1240
- // ```
1241
- //
1242
- // Verify that this is a tail expression of a function, otherwise the
1243
- // label pointing out the cause for the type coercion will be wrong
1244
- // as prior return coercions would not be relevant (#57664).
1245
- let parent_id = fcx. tcx . hir ( ) . get_parent_node ( blk_id) ;
1246
- let parent = fcx. tcx . hir ( ) . get ( fcx. tcx . hir ( ) . get_parent_node ( parent_id) ) ;
1247
- if fcx. get_node_fn_decl ( parent) . is_some ( ) && !pointing_at_return_type {
1248
- if let Some ( sp) = fcx. ret_coercion_span . borrow ( ) . as_ref ( ) {
1249
- db. span_label ( * sp, reason_label) ;
1250
- }
1251
- }
1252
1221
}
1253
- ObligationCauseCode :: ReturnType ( _id) => {
1254
- db = fcx. report_mismatched_types ( cause, expected, found, err) ;
1255
- let _id = fcx. tcx . hir ( ) . get_parent_node ( _id) ;
1256
- let mut pointing_at_return_type = false ;
1257
- if let Some ( ( fn_decl, can_suggest) ) = fcx. get_fn_decl ( _id) {
1258
- pointing_at_return_type = fcx. suggest_missing_return_type (
1259
- & mut db, & fn_decl, expected, found, can_suggest) ;
1260
- }
1261
- if let ( Some ( sp) , false ) = (
1262
- fcx. ret_coercion_span . borrow ( ) . as_ref ( ) ,
1263
- pointing_at_return_type,
1264
- ) {
1265
- if !sp. overlaps ( cause. span ) {
1266
- db. span_label ( * sp, reason_label) ;
1267
- }
1268
- }
1222
+ ObligationCauseCode :: ReturnType ( id) => {
1223
+ db = self . report_return_mismatched_types (
1224
+ cause, expected, found, err, fcx, id, None ) ;
1269
1225
}
1270
1226
_ => {
1271
1227
db = fcx. report_mismatched_types ( cause, expected, found, err) ;
@@ -1283,6 +1239,59 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
1283
1239
}
1284
1240
}
1285
1241
1242
+ fn report_return_mismatched_types < ' a > (
1243
+ & self ,
1244
+ cause : & ObligationCause < ' tcx > ,
1245
+ expected : Ty < ' tcx > ,
1246
+ found : Ty < ' tcx > ,
1247
+ err : TypeError < ' tcx > ,
1248
+ fcx : & FnCtxt < ' a , ' gcx , ' tcx > ,
1249
+ id : syntax:: ast:: NodeId ,
1250
+ expression : Option < ( & ' gcx hir:: Expr , syntax:: ast:: NodeId ) > ,
1251
+ ) -> DiagnosticBuilder < ' a > {
1252
+ let mut db = fcx. report_mismatched_types ( cause, expected, found, err) ;
1253
+
1254
+ let mut pointing_at_return_type = false ;
1255
+ let mut return_sp = None ;
1256
+
1257
+ // Verify that this is a tail expression of a function, otherwise the
1258
+ // label pointing out the cause for the type coercion will be wrong
1259
+ // as prior return coercions would not be relevant (#57664).
1260
+ let parent_id = fcx. tcx . hir ( ) . get_parent_node ( id) ;
1261
+ let fn_decl = if let Some ( ( expr, blk_id) ) = expression {
1262
+ pointing_at_return_type = fcx. suggest_mismatched_types_on_tail (
1263
+ & mut db,
1264
+ expr,
1265
+ expected,
1266
+ found,
1267
+ cause. span ,
1268
+ blk_id,
1269
+ ) ;
1270
+ let parent = fcx. tcx . hir ( ) . get ( parent_id) ;
1271
+ fcx. get_node_fn_decl ( parent) . map ( |( fn_decl, _, is_main) | ( fn_decl, is_main) )
1272
+ } else {
1273
+ fcx. get_fn_decl ( parent_id)
1274
+ } ;
1275
+
1276
+ if let ( Some ( ( fn_decl, can_suggest) ) , _) = ( fn_decl, pointing_at_return_type) {
1277
+ if expression. is_none ( ) {
1278
+ pointing_at_return_type |= fcx. suggest_missing_return_type (
1279
+ & mut db, & fn_decl, expected, found, can_suggest) ;
1280
+ }
1281
+ if !pointing_at_return_type {
1282
+ return_sp = Some ( fn_decl. output . span ( ) ) ; // `impl Trait` return type
1283
+ }
1284
+ }
1285
+ if let ( Some ( sp) , Some ( return_sp) ) = ( fcx. ret_coercion_span . borrow ( ) . as_ref ( ) , return_sp) {
1286
+ db. span_label ( return_sp, "expected because this return type..." ) ;
1287
+ db. span_label ( * sp, format ! (
1288
+ "...is found to be `{}` here" ,
1289
+ fcx. resolve_type_vars_with_obligations( expected) ,
1290
+ ) ) ;
1291
+ }
1292
+ db
1293
+ }
1294
+
1286
1295
pub fn complete < ' a > ( self , fcx : & FnCtxt < ' a , ' gcx , ' tcx > ) -> Ty < ' tcx > {
1287
1296
if let Some ( final_ty) = self . final_ty {
1288
1297
final_ty
0 commit comments