11use crate :: lints:: {
22 PathStatementDrop , PathStatementDropSub , PathStatementNoEffect , UnusedAllocationDiag ,
33 UnusedAllocationMutDiag , UnusedClosure , UnusedDef , UnusedDefSuggestion , UnusedDelim ,
4- UnusedDelimSuggestion , UnusedGenerator , UnusedImportBracesDiag , UnusedOp , UnusedResult ,
4+ UnusedDelimSuggestion , UnusedGenerator , UnusedImportBracesDiag , UnusedOp , UnusedOpSuggestion ,
5+ UnusedResult ,
56} ;
67use crate :: Lint ;
78use crate :: { EarlyContext , EarlyLintPass , LateContext , LateLintPass , LintContext } ;
@@ -93,7 +94,15 @@ declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
9394
9495impl < ' tcx > LateLintPass < ' tcx > for UnusedResults {
9596 fn check_stmt ( & mut self , cx : & LateContext < ' _ > , s : & hir:: Stmt < ' _ > ) {
96- let hir:: StmtKind :: Semi ( expr) = s. kind else { return ; } ;
97+ let hir:: StmtKind :: Semi ( mut expr) = s. kind else { return ; } ;
98+
99+ let mut expr_is_from_block = false ;
100+ while let hir:: ExprKind :: Block ( blk, ..) = expr. kind
101+ && let hir:: Block { expr : Some ( e) , .. } = blk
102+ {
103+ expr = e;
104+ expr_is_from_block = true ;
105+ }
97106
98107 if let hir:: ExprKind :: Ret ( ..) = expr. kind {
99108 return ;
@@ -113,6 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
113122 expr. span ,
114123 "output of future returned by " ,
115124 "" ,
125+ expr_is_from_block,
116126 )
117127 {
118128 // We have a bare `foo().await;` on an opaque type from an async function that was
@@ -125,13 +135,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
125135 let must_use_result = is_ty_must_use ( cx, ty, & expr, expr. span ) ;
126136 let type_lint_emitted_or_suppressed = match must_use_result {
127137 Some ( path) => {
128- emit_must_use_untranslated ( cx, & path, "" , "" , 1 , false ) ;
138+ emit_must_use_untranslated ( cx, & path, "" , "" , 1 , false , expr_is_from_block ) ;
129139 true
130140 }
131141 None => false ,
132142 } ;
133143
134- let fn_warned = check_fn_must_use ( cx, expr) ;
144+ let fn_warned = check_fn_must_use ( cx, expr, expr_is_from_block ) ;
135145
136146 if !fn_warned && type_lint_emitted_or_suppressed {
137147 // We don't warn about unused unit or uninhabited types.
@@ -176,7 +186,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
176186 UnusedOp {
177187 op : must_use_op,
178188 label : expr. span ,
179- suggestion : expr. span . shrink_to_lo ( ) ,
189+ suggestion : if expr_is_from_block {
190+ UnusedOpSuggestion :: BlockTailExpr {
191+ before_span : expr. span . shrink_to_lo ( ) ,
192+ after_span : expr. span . shrink_to_hi ( ) ,
193+ }
194+ } else {
195+ UnusedOpSuggestion :: NormalExpr { span : expr. span . shrink_to_lo ( ) }
196+ } ,
180197 } ,
181198 ) ;
182199 op_warned = true ;
@@ -186,7 +203,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
186203 cx. emit_spanned_lint ( UNUSED_RESULTS , s. span , UnusedResult { ty } ) ;
187204 }
188205
189- fn check_fn_must_use ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > ) -> bool {
206+ fn check_fn_must_use (
207+ cx : & LateContext < ' _ > ,
208+ expr : & hir:: Expr < ' _ > ,
209+ expr_is_from_block : bool ,
210+ ) -> bool {
190211 let maybe_def_id = match expr. kind {
191212 hir:: ExprKind :: Call ( ref callee, _) => {
192213 match callee. kind {
@@ -207,7 +228,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
207228 _ => None ,
208229 } ;
209230 if let Some ( def_id) = maybe_def_id {
210- check_must_use_def ( cx, def_id, expr. span , "return value of " , "" )
231+ check_must_use_def (
232+ cx,
233+ def_id,
234+ expr. span ,
235+ "return value of " ,
236+ "" ,
237+ expr_is_from_block,
238+ )
211239 } else {
212240 false
213241 }
@@ -350,6 +378,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
350378 span : Span ,
351379 descr_pre_path : & str ,
352380 descr_post_path : & str ,
381+ expr_is_from_block : bool ,
353382 ) -> bool {
354383 is_def_must_use ( cx, def_id, span)
355384 . map ( |must_use_path| {
@@ -360,6 +389,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
360389 descr_post_path,
361390 1 ,
362391 false ,
392+ expr_is_from_block,
363393 )
364394 } )
365395 . is_some ( )
@@ -373,28 +403,59 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
373403 descr_post : & str ,
374404 plural_len : usize ,
375405 is_inner : bool ,
406+ expr_is_from_block : bool ,
376407 ) {
377408 let plural_suffix = pluralize ! ( plural_len) ;
378409
379410 match path {
380411 MustUsePath :: Suppressed => { }
381412 MustUsePath :: Boxed ( path) => {
382413 let descr_pre = & format ! ( "{}boxed " , descr_pre) ;
383- emit_must_use_untranslated ( cx, path, descr_pre, descr_post, plural_len, true ) ;
414+ emit_must_use_untranslated (
415+ cx,
416+ path,
417+ descr_pre,
418+ descr_post,
419+ plural_len,
420+ true ,
421+ expr_is_from_block,
422+ ) ;
384423 }
385424 MustUsePath :: Opaque ( path) => {
386425 let descr_pre = & format ! ( "{}implementer{} of " , descr_pre, plural_suffix) ;
387- emit_must_use_untranslated ( cx, path, descr_pre, descr_post, plural_len, true ) ;
426+ emit_must_use_untranslated (
427+ cx,
428+ path,
429+ descr_pre,
430+ descr_post,
431+ plural_len,
432+ true ,
433+ expr_is_from_block,
434+ ) ;
388435 }
389436 MustUsePath :: TraitObject ( path) => {
390437 let descr_post = & format ! ( " trait object{}{}" , plural_suffix, descr_post) ;
391- emit_must_use_untranslated ( cx, path, descr_pre, descr_post, plural_len, true ) ;
438+ emit_must_use_untranslated (
439+ cx,
440+ path,
441+ descr_pre,
442+ descr_post,
443+ plural_len,
444+ true ,
445+ expr_is_from_block,
446+ ) ;
392447 }
393448 MustUsePath :: TupleElement ( elems) => {
394449 for ( index, path) in elems {
395450 let descr_post = & format ! ( " in tuple element {}" , index) ;
396451 emit_must_use_untranslated (
397- cx, path, descr_pre, descr_post, plural_len, true ,
452+ cx,
453+ path,
454+ descr_pre,
455+ descr_post,
456+ plural_len,
457+ true ,
458+ expr_is_from_block,
398459 ) ;
399460 }
400461 }
@@ -407,6 +468,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
407468 descr_post,
408469 plural_len. saturating_add ( usize:: try_from ( * len) . unwrap_or ( usize:: MAX ) ) ,
409470 true ,
471+ expr_is_from_block,
410472 ) ;
411473 }
412474 MustUsePath :: Closure ( span) => {
@@ -433,8 +495,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
433495 cx,
434496 def_id : * def_id,
435497 note : * reason,
436- suggestion : ( !is_inner)
437- . then_some ( UnusedDefSuggestion { span : span. shrink_to_lo ( ) } ) ,
498+ suggestion : ( !is_inner) . then_some ( if expr_is_from_block {
499+ UnusedDefSuggestion :: BlockTailExpr {
500+ before_span : span. shrink_to_lo ( ) ,
501+ after_span : span. shrink_to_hi ( ) ,
502+ }
503+ } else {
504+ UnusedDefSuggestion :: NormalExpr { span : span. shrink_to_lo ( ) }
505+ } ) ,
438506 } ,
439507 ) ;
440508 }
0 commit comments