@@ -126,12 +126,13 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
126
126
self . fcx ,
127
127
ty,
128
128
hir_id,
129
- expr,
130
- source_span,
131
- yield_data. span ,
132
- "" ,
133
- "" ,
134
- 1 ,
129
+ SuspendCheckData {
130
+ expr,
131
+ source_span,
132
+ yield_span : yield_data. span ,
133
+ plural_len : 1 ,
134
+ ..Default :: default ( )
135
+ } ,
135
136
) ;
136
137
137
138
self . types . insert ( ty:: GeneratorInteriorTypeCause {
@@ -448,56 +449,43 @@ impl<'a, 'tcx> Visitor<'tcx> for ArmPatCollector<'a> {
448
449
}
449
450
}
450
451
452
+ #[ derive( Default ) ]
453
+ pub struct SuspendCheckData < ' a , ' tcx > {
454
+ expr : Option < & ' tcx Expr < ' tcx > > ,
455
+ source_span : Span ,
456
+ yield_span : Span ,
457
+ descr_pre : & ' a str ,
458
+ descr_post : & ' a str ,
459
+ plural_len : usize ,
460
+ }
461
+
451
462
// Returns whether it emitted a diagnostic or not
452
463
// Note that this fn and the proceding one are based on the code
453
464
// for creating must_use diagnostics
454
465
pub fn check_must_not_suspend_ty < ' tcx > (
455
466
fcx : & FnCtxt < ' _ , ' tcx > ,
456
467
ty : Ty < ' tcx > ,
457
468
hir_id : HirId ,
458
- expr : Option < & ' tcx Expr < ' tcx > > ,
459
- source_span : Span ,
460
- yield_span : Span ,
461
- descr_pre : & str ,
462
- descr_post : & str ,
463
- plural_len : usize ,
469
+ data : SuspendCheckData < ' _ , ' tcx > ,
464
470
) -> bool {
465
471
if ty. is_unit ( )
466
472
// FIXME: should this check `is_ty_uninhabited_from`. This query is not available in this stage
467
473
// of typeck (before ReVar and RePlaceholder are removed), but may remove noise, like in
468
474
// `must_use`
469
475
// || fcx.tcx.is_ty_uninhabited_from(fcx.tcx.parent_module(hir_id).to_def_id(), ty, fcx.param_env)
470
476
{
471
- return true ;
477
+ return false ;
472
478
}
473
479
474
- let plural_suffix = pluralize ! ( plural_len) ;
480
+ let plural_suffix = pluralize ! ( data . plural_len) ;
475
481
476
482
match * ty. kind ( ) {
477
483
ty:: Adt ( ..) if ty. is_box ( ) => {
478
484
let boxed_ty = ty. boxed_ty ( ) ;
479
- let descr_pre = & format ! ( "{}boxed " , descr_pre) ;
480
- check_must_not_suspend_ty (
481
- fcx,
482
- boxed_ty,
483
- hir_id,
484
- expr,
485
- source_span,
486
- yield_span,
487
- descr_pre,
488
- descr_post,
489
- plural_len,
490
- )
485
+ let descr_pre = & format ! ( "{}boxed " , data. descr_pre) ;
486
+ check_must_not_suspend_ty ( fcx, boxed_ty, hir_id, SuspendCheckData { descr_pre, ..data } )
491
487
}
492
- ty:: Adt ( def, _) => check_must_not_suspend_def (
493
- fcx. tcx ,
494
- def. did ,
495
- hir_id,
496
- source_span,
497
- yield_span,
498
- descr_pre,
499
- descr_post,
500
- ) ,
488
+ ty:: Adt ( def, _) => check_must_not_suspend_def ( fcx. tcx , def. did , hir_id, data) ,
501
489
// FIXME: support adding the attribute to TAITs
502
490
ty:: Opaque ( def, _) => {
503
491
let mut has_emitted = false ;
@@ -507,15 +495,12 @@ pub fn check_must_not_suspend_ty<'tcx>(
507
495
predicate. kind ( ) . skip_binder ( )
508
496
{
509
497
let def_id = poly_trait_predicate. trait_ref . def_id ;
510
- let descr_pre = & format ! ( "{}implementer{} of " , descr_pre, plural_suffix, ) ;
498
+ let descr_pre = & format ! ( "{}implementer{} of " , data . descr_pre, plural_suffix) ;
511
499
if check_must_not_suspend_def (
512
500
fcx. tcx ,
513
501
def_id,
514
502
hir_id,
515
- source_span,
516
- yield_span,
517
- descr_pre,
518
- descr_post,
503
+ SuspendCheckData { descr_pre, ..data } ,
519
504
) {
520
505
has_emitted = true ;
521
506
break ;
@@ -529,15 +514,12 @@ pub fn check_must_not_suspend_ty<'tcx>(
529
514
for predicate in binder. iter ( ) {
530
515
if let ty:: ExistentialPredicate :: Trait ( ref trait_ref) = predicate. skip_binder ( ) {
531
516
let def_id = trait_ref. def_id ;
532
- let descr_post = & format ! ( " trait object{}{}" , plural_suffix, descr_post, ) ;
517
+ let descr_post = & format ! ( " trait object{}{}" , plural_suffix, data . descr_post) ;
533
518
if check_must_not_suspend_def (
534
519
fcx. tcx ,
535
520
def_id,
536
521
hir_id,
537
- source_span,
538
- yield_span,
539
- descr_pre,
540
- descr_post,
522
+ SuspendCheckData { descr_post, ..data } ,
541
523
) {
542
524
has_emitted = true ;
543
525
break ;
@@ -548,35 +530,38 @@ pub fn check_must_not_suspend_ty<'tcx>(
548
530
}
549
531
ty:: Tuple ( ref tys) => {
550
532
let mut has_emitted = false ;
551
- let spans = if let Some ( hir:: ExprKind :: Tup ( comps) ) = expr. map ( |e| & e. kind ) {
533
+ let spans = if let Some ( hir:: ExprKind :: Tup ( comps) ) = data . expr . map ( |e| & e. kind ) {
552
534
debug_assert_eq ! ( comps. len( ) , tys. len( ) ) ;
553
535
comps. iter ( ) . map ( |e| e. span ) . collect ( )
554
536
} else {
555
537
vec ! [ ]
556
538
} ;
557
539
for ( i, ty) in tys. iter ( ) . map ( |k| k. expect_ty ( ) ) . enumerate ( ) {
558
540
let descr_post = & format ! ( " in tuple element {}" , i) ;
559
- let span = * spans. get ( i) . unwrap_or ( & source_span) ;
541
+ let span = * spans. get ( i) . unwrap_or ( & data . source_span ) ;
560
542
if check_must_not_suspend_ty (
561
- fcx, ty, hir_id, expr, span, yield_span, descr_pre, descr_post, plural_len,
543
+ fcx,
544
+ ty,
545
+ hir_id,
546
+ SuspendCheckData { descr_post, source_span : span, ..data } ,
562
547
) {
563
548
has_emitted = true ;
564
549
}
565
550
}
566
551
has_emitted
567
552
}
568
553
ty:: Array ( ty, len) => {
569
- let descr_pre = & format ! ( "{}array{} of " , descr_pre, plural_suffix, ) ;
554
+ let descr_pre = & format ! ( "{}array{} of " , data . descr_pre, plural_suffix) ;
570
555
check_must_not_suspend_ty (
571
556
fcx,
572
557
ty,
573
558
hir_id,
574
- expr ,
575
- source_span ,
576
- yield_span ,
577
- descr_pre ,
578
- descr_post ,
579
- len . try_eval_usize ( fcx . tcx , fcx . param_env ) . unwrap_or ( 0 ) as usize + 1 ,
559
+ SuspendCheckData {
560
+ descr_pre ,
561
+ plural_len : len . try_eval_usize ( fcx . tcx , fcx . param_env ) . unwrap_or ( 0 ) as usize
562
+ + 1 ,
563
+ ..data
564
+ } ,
580
565
)
581
566
}
582
567
_ => false ,
@@ -587,39 +572,38 @@ fn check_must_not_suspend_def(
587
572
tcx : TyCtxt < ' _ > ,
588
573
def_id : DefId ,
589
574
hir_id : HirId ,
590
- source_span : Span ,
591
- yield_span : Span ,
592
- descr_pre_path : & str ,
593
- descr_post_path : & str ,
575
+ data : SuspendCheckData < ' _ , ' _ > ,
594
576
) -> bool {
595
577
for attr in tcx. get_attrs ( def_id) . iter ( ) {
596
578
if attr. has_name ( sym:: must_not_suspend) {
597
579
tcx. struct_span_lint_hir (
598
580
rustc_session:: lint:: builtin:: MUST_NOT_SUSPEND ,
599
581
hir_id,
600
- source_span,
582
+ data . source_span ,
601
583
|lint| {
602
584
let msg = format ! (
603
- "{}`{}`{} held across a yield point, but should not be" ,
604
- descr_pre_path ,
585
+ "{}`{}`{} held across a suspend point, but should not be" ,
586
+ data . descr_pre ,
605
587
tcx. def_path_str( def_id) ,
606
- descr_post_path
588
+ data . descr_post ,
607
589
) ;
608
590
let mut err = lint. build ( & msg) ;
609
591
610
592
// add span pointing to the offending yield/await
611
- err. span_label ( yield_span, "the value is held across this yield point" ) ;
593
+ err. span_label ( data . yield_span , "the value is held across this suspend point" ) ;
612
594
613
595
// Add optional reason note
614
596
if let Some ( note) = attr. value_str ( ) {
615
- err. span_note ( source_span, & note. as_str ( ) ) ;
597
+ // FIXME(guswynn): consider formatting this better
598
+ err. span_note ( data. source_span , & note. as_str ( ) ) ;
616
599
}
617
600
618
601
// Add some quick suggestions on what to do
602
+ // FIXME: can `drop` work as a suggestion here as well?
619
603
err. span_help (
620
- source_span,
621
- "`drop` this value before the yield point, or use a block (`{ ... }`) \
622
- to shrink its scope",
604
+ data . source_span ,
605
+ "consider using a block (`{ ... }`) \
606
+ to shrink the value's scope, ending before the suspend point ",
623
607
) ;
624
608
625
609
err. emit ( ) ;
0 commit comments