@@ -22,6 +22,14 @@ use std::fmt;
22
22
use super :: InferCtxtPrivExt ;
23
23
use crate :: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
24
24
25
+ #[ derive( Debug ) ]
26
+ pub enum GeneratorInteriorOrUpvar {
27
+ // span of interior type
28
+ Interior ( Span ) ,
29
+ // span of upvar
30
+ Upvar ( Span ) ,
31
+ }
32
+
25
33
// This trait is public to expose the diagnostics methods to clippy.
26
34
pub trait InferCtxtExt < ' tcx > {
27
35
fn suggest_restricting_param_bound (
@@ -125,8 +133,8 @@ pub trait InferCtxtExt<'tcx> {
125
133
fn note_obligation_cause_for_async_await (
126
134
& self ,
127
135
err : & mut DiagnosticBuilder < ' _ > ,
128
- interior : Option < ( Span , Option < Span > , Option < Span > , Option < hir :: HirId > , Option < Span > ) > ,
129
- upvar : Option < ( Ty < ' tcx > , Span ) > ,
136
+ interior_or_upvar_span : GeneratorInteriorOrUpvar ,
137
+ interior_extra_info : Option < ( Option < Span > , Span , Option < hir :: HirId > , Option < Span > ) > ,
130
138
inner_generator_body : Option < & hir:: Body < ' _ > > ,
131
139
outer_generator : Option < DefId > ,
132
140
trait_ref : ty:: TraitRef < ' _ > ,
@@ -1280,7 +1288,23 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
1280
1288
) ;
1281
1289
eq
1282
1290
} ;
1283
- let interior = tables
1291
+
1292
+ let mut interior_or_upvar_span = None ;
1293
+ let mut interior_extra_info = None ;
1294
+
1295
+ if let Some ( upvars) = self . tcx . upvars ( generator_did) {
1296
+ interior_or_upvar_span = upvars. iter ( ) . find_map ( |( upvar_id, upvar) | {
1297
+ let upvar_ty = tables. node_type ( * upvar_id) ;
1298
+ let upvar_ty = self . resolve_vars_if_possible ( & upvar_ty) ;
1299
+ if ty_matches ( & upvar_ty) {
1300
+ Some ( GeneratorInteriorOrUpvar :: Upvar ( upvar. span ) )
1301
+ } else {
1302
+ None
1303
+ }
1304
+ } ) ;
1305
+ } ;
1306
+
1307
+ tables
1284
1308
. generator_interior_types
1285
1309
. iter ( )
1286
1310
. find ( |ty:: GeneratorInteriorTypeCause { ty, .. } | ty_matches ( ty) )
@@ -1301,29 +1325,21 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
1301
1325
. map ( |expr| expr. span ) ;
1302
1326
let ty:: GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } =
1303
1327
cause;
1304
- ( * span, * scope_span, * yield_span, * expr, from_awaited_ty)
1305
- } ) ;
1306
1328
1307
- let upvar = if let Some ( upvars) = self . tcx . upvars ( generator_did) {
1308
- upvars. iter ( ) . find_map ( |( upvar_id, upvar) | {
1309
- let upvar_ty = tables. node_type ( * upvar_id) ;
1310
- let upvar_ty = self . resolve_vars_if_possible ( & upvar_ty) ;
1311
- if ty_matches ( & upvar_ty) { Some ( ( upvar_ty, upvar. span ) ) } else { None }
1312
- } )
1313
- } else {
1314
- None
1315
- } ;
1329
+ interior_or_upvar_span = Some ( GeneratorInteriorOrUpvar :: Interior ( * span) ) ;
1330
+ interior_extra_info = Some ( ( * scope_span, * yield_span, * expr, from_awaited_ty) ) ;
1331
+ } ) ;
1316
1332
1317
1333
debug ! (
1318
- "maybe_note_obligation_cause_for_async_await: interior ={:?} \
1319
- generator_interior_types={:?} upvar: {:?} ",
1320
- interior , tables. generator_interior_types, upvar
1334
+ "maybe_note_obligation_cause_for_async_await: interior_or_upvar ={:?} \
1335
+ generator_interior_types={:?}",
1336
+ interior_or_upvar_span , tables. generator_interior_types
1321
1337
) ;
1322
- if interior . is_some ( ) || upvar . is_some ( ) {
1338
+ if let Some ( interior_or_upvar_span ) = interior_or_upvar_span {
1323
1339
self . note_obligation_cause_for_async_await (
1324
1340
err,
1325
- interior ,
1326
- upvar ,
1341
+ interior_or_upvar_span ,
1342
+ interior_extra_info ,
1327
1343
generator_body,
1328
1344
outer_generator,
1329
1345
trait_ref,
@@ -1343,8 +1359,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
1343
1359
fn note_obligation_cause_for_async_await (
1344
1360
& self ,
1345
1361
err : & mut DiagnosticBuilder < ' _ > ,
1346
- interior : Option < ( Span , Option < Span > , Option < Span > , Option < hir :: HirId > , Option < Span > ) > ,
1347
- upvar : Option < ( Ty < ' tcx > , Span ) > ,
1362
+ interior_or_upvar_span : GeneratorInteriorOrUpvar ,
1363
+ interior_extra_info : Option < ( Option < Span > , Span , Option < hir :: HirId > , Option < Span > ) > ,
1348
1364
inner_generator_body : Option < & hir:: Body < ' _ > > ,
1349
1365
outer_generator : Option < DefId > ,
1350
1366
trait_ref : ty:: TraitRef < ' _ > ,
@@ -1412,121 +1428,118 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
1412
1428
format ! ( "does not implement `{}`" , trait_ref. print_only_trait_path( ) )
1413
1429
} ;
1414
1430
1415
- if let Some ( ( target_span , scope_span , yield_span , expr , from_awaited_ty ) ) = interior {
1416
- if let Some ( await_span ) = from_awaited_ty {
1417
- // The type causing this obligation is one being awaited at await_span.
1418
- let mut span = MultiSpan :: from_span ( await_span ) ;
1419
-
1431
+ let mut explain_yield = | interior_span : Span ,
1432
+ yield_span : Span ,
1433
+ scope_span : Option < Span > | {
1434
+ let mut span = MultiSpan :: from_span ( yield_span ) ;
1435
+ if let Ok ( snippet ) = source_map . span_to_snippet ( interior_span ) {
1420
1436
span. push_span_label (
1421
- await_span,
1422
- format ! (
1423
- "await occurs here on type `{}`, which {}" ,
1424
- target_ty, trait_explanation
1425
- ) ,
1426
- ) ;
1427
-
1428
- err. span_note (
1429
- span,
1430
- & format ! (
1431
- "future {not_trait} as it awaits another future which {not_trait}" ,
1432
- not_trait = trait_explanation
1433
- ) ,
1434
- ) ;
1435
- } else {
1436
- // Look at the last interior type to get a span for the `.await`.
1437
- debug ! (
1438
- "note_obligation_cause_for_async_await generator_interior_types: {:#?}" ,
1439
- tables. generator_interior_types
1437
+ yield_span,
1438
+ format ! ( "{} occurs here, with `{}` maybe used later" , await_or_yield, snippet) ,
1440
1439
) ;
1440
+ // If available, use the scope span to annotate the drop location.
1441
+ if let Some ( scope_span) = scope_span {
1442
+ span. push_span_label (
1443
+ source_map. end_point ( scope_span) ,
1444
+ format ! ( "`{}` is later dropped here" , snippet) ,
1445
+ ) ;
1446
+ }
1447
+ }
1448
+ span. push_span_label (
1449
+ interior_span,
1450
+ format ! ( "has type `{}` which {}" , target_ty, trait_explanation) ,
1451
+ ) ;
1441
1452
1442
- if let Some ( yield_span) = yield_span {
1443
- let mut span = MultiSpan :: from_span ( yield_span) ;
1444
- if let Ok ( snippet) = source_map. span_to_snippet ( target_span) {
1453
+ err. span_note (
1454
+ span,
1455
+ & format ! (
1456
+ "{} {} as this value is used across {}" ,
1457
+ future_or_generator, trait_explanation, an_await_or_yield
1458
+ ) ,
1459
+ ) ;
1460
+ } ;
1461
+ match interior_or_upvar_span {
1462
+ GeneratorInteriorOrUpvar :: Interior ( interior_span) => {
1463
+ if let Some ( ( scope_span, yield_span, expr, from_awaited_ty) ) = interior_extra_info {
1464
+ if let Some ( await_span) = from_awaited_ty {
1465
+ // The type causing this obligation is one being awaited at await_span.
1466
+ let mut span = MultiSpan :: from_span ( await_span) ;
1445
1467
span. push_span_label (
1446
- yield_span ,
1468
+ await_span ,
1447
1469
format ! (
1448
- "{} occurs here, with `{}` maybe used later " ,
1449
- await_or_yield , snippet
1470
+ "await occurs here on type `{}`, which {} " ,
1471
+ target_ty , trait_explanation
1450
1472
) ,
1451
1473
) ;
1452
- // If available, use the scope span to annotate the drop location.
1453
- if let Some ( scope_span) = scope_span {
1454
- span. push_span_label (
1455
- source_map. end_point ( scope_span) ,
1456
- format ! ( "`{}` is later dropped here" , snippet) ,
1457
- ) ;
1458
- }
1474
+ err. span_note (
1475
+ span,
1476
+ & format ! (
1477
+ "future {not_trait} as it awaits another future which {not_trait}" ,
1478
+ not_trait = trait_explanation
1479
+ ) ,
1480
+ ) ;
1481
+ } else {
1482
+ // Look at the last interior type to get a span for the `.await`.
1483
+ debug ! (
1484
+ "note_obligation_cause_for_async_await generator_interior_types: {:#?}" ,
1485
+ tables. generator_interior_types
1486
+ ) ;
1487
+ explain_yield ( interior_span, yield_span, scope_span) ;
1459
1488
}
1460
- span. push_span_label (
1461
- target_span,
1462
- format ! ( "has type `{}` which {}" , target_ty, trait_explanation) ,
1463
- ) ;
1464
1489
1465
- err. span_note (
1466
- span,
1467
- & format ! (
1468
- "{} {} as this value is used across {}" ,
1469
- future_or_generator, trait_explanation, an_await_or_yield
1470
- ) ,
1471
- ) ;
1472
- }
1473
- }
1474
- if let Some ( ( _, upvar_span) ) = upvar {
1475
- let mut span = MultiSpan :: from_span ( upvar_span) ;
1476
- span. push_span_label (
1477
- upvar_span,
1478
- format ! ( "has type `{}` which {}" , target_ty, trait_explanation) ,
1479
- ) ;
1480
- }
1481
- if let Some ( expr_id) = expr {
1482
- let expr = hir. expect_expr ( expr_id) ;
1483
- debug ! ( "target_ty evaluated from {:?}" , expr) ;
1484
-
1485
- let parent = hir. get_parent_node ( expr_id) ;
1486
- if let Some ( hir:: Node :: Expr ( e) ) = hir. find ( parent) {
1487
- let parent_span = hir. span ( parent) ;
1488
- let parent_did = parent. owner . to_def_id ( ) ;
1489
- // ```rust
1490
- // impl T {
1491
- // fn foo(&self) -> i32 {}
1492
- // }
1493
- // T.foo();
1494
- // ^^^^^^^ a temporary `&T` created inside this method call due to `&self`
1495
- // ```
1496
- //
1497
- let is_region_borrow =
1498
- tables. expr_adjustments ( expr) . iter ( ) . any ( |adj| adj. is_region_borrow ( ) ) ;
1499
-
1500
- // ```rust
1501
- // struct Foo(*const u8);
1502
- // bar(Foo(std::ptr::null())).await;
1503
- // ^^^^^^^^^^^^^^^^^^^^^ raw-ptr `*T` created inside this struct ctor.
1504
- // ```
1505
- debug ! ( "parent_def_kind: {:?}" , self . tcx. def_kind( parent_did) ) ;
1506
- let is_raw_borrow_inside_fn_like_call = match self . tcx . def_kind ( parent_did) {
1507
- DefKind :: Fn | DefKind :: Ctor ( ..) => target_ty. is_unsafe_ptr ( ) ,
1508
- _ => false ,
1509
- } ;
1510
-
1511
- if ( tables. is_method_call ( e) && is_region_borrow)
1512
- || is_raw_borrow_inside_fn_like_call
1513
- {
1514
- err. span_help (
1515
- parent_span,
1516
- "consider moving this into a `let` \
1490
+ if let Some ( expr_id) = expr {
1491
+ let expr = hir. expect_expr ( expr_id) ;
1492
+ debug ! ( "target_ty evaluated from {:?}" , expr) ;
1493
+
1494
+ let parent = hir. get_parent_node ( expr_id) ;
1495
+ if let Some ( hir:: Node :: Expr ( e) ) = hir. find ( parent) {
1496
+ let parent_span = hir. span ( parent) ;
1497
+ let parent_did = parent. owner . to_def_id ( ) ;
1498
+ // ```rust
1499
+ // impl T {
1500
+ // fn foo(&self) -> i32 {}
1501
+ // }
1502
+ // T.foo();
1503
+ // ^^^^^^^ a temporary `&T` created inside this method call due to `&self`
1504
+ // ```
1505
+ //
1506
+ let is_region_borrow = tables
1507
+ . expr_adjustments ( expr)
1508
+ . iter ( )
1509
+ . any ( |adj| adj. is_region_borrow ( ) ) ;
1510
+
1511
+ // ```rust
1512
+ // struct Foo(*const u8);
1513
+ // bar(Foo(std::ptr::null())).await;
1514
+ // ^^^^^^^^^^^^^^^^^^^^^ raw-ptr `*T` created inside this struct ctor.
1515
+ // ```
1516
+ debug ! ( "parent_def_kind: {:?}" , self . tcx. def_kind( parent_did) ) ;
1517
+ let is_raw_borrow_inside_fn_like_call =
1518
+ match self . tcx . def_kind ( parent_did) {
1519
+ DefKind :: Fn | DefKind :: Ctor ( ..) => target_ty. is_unsafe_ptr ( ) ,
1520
+ _ => false ,
1521
+ } ;
1522
+
1523
+ if ( tables. is_method_call ( e) && is_region_borrow)
1524
+ || is_raw_borrow_inside_fn_like_call
1525
+ {
1526
+ err. span_help (
1527
+ parent_span,
1528
+ "consider moving this into a `let` \
1517
1529
binding to create a shorter lived borrow",
1518
- ) ;
1530
+ ) ;
1531
+ }
1532
+ }
1519
1533
}
1520
1534
}
1521
1535
}
1522
- } else {
1523
- if let Some ( ( _, upvar_span) ) = upvar {
1536
+ GeneratorInteriorOrUpvar :: Upvar ( upvar_span) => {
1524
1537
let mut span = MultiSpan :: from_span ( upvar_span) ;
1525
1538
span. push_span_label (
1526
1539
upvar_span,
1527
1540
format ! ( "has type `{}` which {}" , target_ty, trait_explanation) ,
1528
1541
) ;
1529
- err. span_note ( span, & format ! ( "captured outer value {}" , trait_explanation) ) ;
1542
+ err. span_note ( span, & format ! ( "captured value {}" , trait_explanation) ) ;
1530
1543
}
1531
1544
}
1532
1545
0 commit comments