1
1
use crate :: lints:: {
2
2
PathStatementDrop , PathStatementDropSub , PathStatementNoEffect , UnusedAllocationDiag ,
3
3
UnusedAllocationMutDiag , UnusedClosure , UnusedDef , UnusedDefSuggestion , UnusedDelim ,
4
- UnusedDelimSuggestion , UnusedGenerator , UnusedImportBracesDiag , UnusedOp , UnusedResult ,
4
+ UnusedDelimSuggestion , UnusedGenerator , UnusedImportBracesDiag , UnusedOp , UnusedOpSuggestion ,
5
+ UnusedResult ,
5
6
} ;
6
7
use crate :: Lint ;
7
8
use crate :: { EarlyContext , EarlyLintPass , LateContext , LateLintPass , LintContext } ;
@@ -93,7 +94,15 @@ declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
93
94
94
95
impl < ' tcx > LateLintPass < ' tcx > for UnusedResults {
95
96
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
+ }
97
106
98
107
if let hir:: ExprKind :: Ret ( ..) = expr. kind {
99
108
return ;
@@ -113,6 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
113
122
expr. span ,
114
123
"output of future returned by " ,
115
124
"" ,
125
+ expr_is_from_block,
116
126
)
117
127
{
118
128
// 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 {
125
135
let must_use_result = is_ty_must_use ( cx, ty, & expr, expr. span ) ;
126
136
let type_lint_emitted_or_suppressed = match must_use_result {
127
137
Some ( path) => {
128
- emit_must_use_untranslated ( cx, & path, "" , "" , 1 , false ) ;
138
+ emit_must_use_untranslated ( cx, & path, "" , "" , 1 , false , expr_is_from_block ) ;
129
139
true
130
140
}
131
141
None => false ,
132
142
} ;
133
143
134
- let fn_warned = check_fn_must_use ( cx, expr) ;
144
+ let fn_warned = check_fn_must_use ( cx, expr, expr_is_from_block ) ;
135
145
136
146
if !fn_warned && type_lint_emitted_or_suppressed {
137
147
// We don't warn about unused unit or uninhabited types.
@@ -176,7 +186,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
176
186
UnusedOp {
177
187
op : must_use_op,
178
188
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
+ } ,
180
197
} ,
181
198
) ;
182
199
op_warned = true ;
@@ -186,7 +203,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
186
203
cx. emit_spanned_lint ( UNUSED_RESULTS , s. span , UnusedResult { ty } ) ;
187
204
}
188
205
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 {
190
211
let maybe_def_id = match expr. kind {
191
212
hir:: ExprKind :: Call ( ref callee, _) => {
192
213
match callee. kind {
@@ -207,7 +228,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
207
228
_ => None ,
208
229
} ;
209
230
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
+ )
211
239
} else {
212
240
false
213
241
}
@@ -350,6 +378,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
350
378
span : Span ,
351
379
descr_pre_path : & str ,
352
380
descr_post_path : & str ,
381
+ expr_is_from_block : bool ,
353
382
) -> bool {
354
383
is_def_must_use ( cx, def_id, span)
355
384
. map ( |must_use_path| {
@@ -360,6 +389,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
360
389
descr_post_path,
361
390
1 ,
362
391
false ,
392
+ expr_is_from_block,
363
393
)
364
394
} )
365
395
. is_some ( )
@@ -373,28 +403,59 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
373
403
descr_post : & str ,
374
404
plural_len : usize ,
375
405
is_inner : bool ,
406
+ expr_is_from_block : bool ,
376
407
) {
377
408
let plural_suffix = pluralize ! ( plural_len) ;
378
409
379
410
match path {
380
411
MustUsePath :: Suppressed => { }
381
412
MustUsePath :: Boxed ( path) => {
382
413
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
+ ) ;
384
423
}
385
424
MustUsePath :: Opaque ( path) => {
386
425
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
+ ) ;
388
435
}
389
436
MustUsePath :: TraitObject ( path) => {
390
437
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
+ ) ;
392
447
}
393
448
MustUsePath :: TupleElement ( elems) => {
394
449
for ( index, path) in elems {
395
450
let descr_post = & format ! ( " in tuple element {}" , index) ;
396
451
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,
398
459
) ;
399
460
}
400
461
}
@@ -407,6 +468,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
407
468
descr_post,
408
469
plural_len. saturating_add ( usize:: try_from ( * len) . unwrap_or ( usize:: MAX ) ) ,
409
470
true ,
471
+ expr_is_from_block,
410
472
) ;
411
473
}
412
474
MustUsePath :: Closure ( span) => {
@@ -433,8 +495,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
433
495
cx,
434
496
def_id : * def_id,
435
497
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
+ } ) ,
438
506
} ,
439
507
) ;
440
508
}
0 commit comments