@@ -126,12 +126,13 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
126126 self . fcx ,
127127 ty,
128128 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+ } ,
135136 ) ;
136137
137138 self . types . insert ( ty:: GeneratorInteriorTypeCause {
@@ -448,56 +449,43 @@ impl<'a, 'tcx> Visitor<'tcx> for ArmPatCollector<'a> {
448449 }
449450}
450451
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+
451462// Returns whether it emitted a diagnostic or not
452463// Note that this fn and the proceding one are based on the code
453464// for creating must_use diagnostics
454465pub fn check_must_not_suspend_ty < ' tcx > (
455466 fcx : & FnCtxt < ' _ , ' tcx > ,
456467 ty : Ty < ' tcx > ,
457468 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 > ,
464470) -> bool {
465471 if ty. is_unit ( )
466472 // FIXME: should this check `is_ty_uninhabited_from`. This query is not available in this stage
467473 // of typeck (before ReVar and RePlaceholder are removed), but may remove noise, like in
468474 // `must_use`
469475 // || fcx.tcx.is_ty_uninhabited_from(fcx.tcx.parent_module(hir_id).to_def_id(), ty, fcx.param_env)
470476 {
471- return true ;
477+ return false ;
472478 }
473479
474- let plural_suffix = pluralize ! ( plural_len) ;
480+ let plural_suffix = pluralize ! ( data . plural_len) ;
475481
476482 match * ty. kind ( ) {
477483 ty:: Adt ( ..) if ty. is_box ( ) => {
478484 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 } )
491487 }
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) ,
501489 // FIXME: support adding the attribute to TAITs
502490 ty:: Opaque ( def, _) => {
503491 let mut has_emitted = false ;
@@ -507,15 +495,12 @@ pub fn check_must_not_suspend_ty<'tcx>(
507495 predicate. kind ( ) . skip_binder ( )
508496 {
509497 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) ;
511499 if check_must_not_suspend_def (
512500 fcx. tcx ,
513501 def_id,
514502 hir_id,
515- source_span,
516- yield_span,
517- descr_pre,
518- descr_post,
503+ SuspendCheckData { descr_pre, ..data } ,
519504 ) {
520505 has_emitted = true ;
521506 break ;
@@ -529,15 +514,12 @@ pub fn check_must_not_suspend_ty<'tcx>(
529514 for predicate in binder. iter ( ) {
530515 if let ty:: ExistentialPredicate :: Trait ( ref trait_ref) = predicate. skip_binder ( ) {
531516 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) ;
533518 if check_must_not_suspend_def (
534519 fcx. tcx ,
535520 def_id,
536521 hir_id,
537- source_span,
538- yield_span,
539- descr_pre,
540- descr_post,
522+ SuspendCheckData { descr_post, ..data } ,
541523 ) {
542524 has_emitted = true ;
543525 break ;
@@ -548,35 +530,38 @@ pub fn check_must_not_suspend_ty<'tcx>(
548530 }
549531 ty:: Tuple ( ref tys) => {
550532 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 ) {
552534 debug_assert_eq ! ( comps. len( ) , tys. len( ) ) ;
553535 comps. iter ( ) . map ( |e| e. span ) . collect ( )
554536 } else {
555537 vec ! [ ]
556538 } ;
557539 for ( i, ty) in tys. iter ( ) . map ( |k| k. expect_ty ( ) ) . enumerate ( ) {
558540 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 ) ;
560542 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 } ,
562547 ) {
563548 has_emitted = true ;
564549 }
565550 }
566551 has_emitted
567552 }
568553 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) ;
570555 check_must_not_suspend_ty (
571556 fcx,
572557 ty,
573558 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+ } ,
580565 )
581566 }
582567 _ => false ,
@@ -587,39 +572,38 @@ fn check_must_not_suspend_def(
587572 tcx : TyCtxt < ' _ > ,
588573 def_id : DefId ,
589574 hir_id : HirId ,
590- source_span : Span ,
591- yield_span : Span ,
592- descr_pre_path : & str ,
593- descr_post_path : & str ,
575+ data : SuspendCheckData < ' _ , ' _ > ,
594576) -> bool {
595577 for attr in tcx. get_attrs ( def_id) . iter ( ) {
596578 if attr. has_name ( sym:: must_not_suspend) {
597579 tcx. struct_span_lint_hir (
598580 rustc_session:: lint:: builtin:: MUST_NOT_SUSPEND ,
599581 hir_id,
600- source_span,
582+ data . source_span ,
601583 |lint| {
602584 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 ,
605587 tcx. def_path_str( def_id) ,
606- descr_post_path
588+ data . descr_post ,
607589 ) ;
608590 let mut err = lint. build ( & msg) ;
609591
610592 // 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" ) ;
612594
613595 // Add optional reason note
614596 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 ( ) ) ;
616599 }
617600
618601 // Add some quick suggestions on what to do
602+ // FIXME: can `drop` work as a suggestion here as well?
619603 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 ",
623607 ) ;
624608
625609 err. emit ( ) ;
0 commit comments