@@ -272,11 +272,12 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
272
272
}
273
273
274
274
fn check_unnecessary_operation ( cx : & LateContext < ' _ > , stmt : & Stmt < ' _ > ) {
275
+ let mut applicability = Applicability :: MachineApplicable ;
275
276
if let StmtKind :: Semi ( expr) = stmt. kind
276
277
&& !stmt. span . in_external_macro ( cx. sess ( ) . source_map ( ) )
277
278
&& let ctxt = stmt. span . ctxt ( )
278
279
&& expr. span . ctxt ( ) == ctxt
279
- && let Some ( reduced) = reduce_expression ( cx, expr)
280
+ && let Some ( reduced) = reduce_expression ( cx, expr, & mut applicability )
280
281
&& reduced. iter ( ) . all ( |e| e. span . ctxt ( ) == ctxt)
281
282
{
282
283
if let ExprKind :: Index ( ..) = & expr. kind {
@@ -318,19 +319,18 @@ fn check_unnecessary_operation(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
318
319
stmt. span ,
319
320
"unnecessary operation" ,
320
321
|diag| {
321
- diag. span_suggestion (
322
- stmt. span ,
323
- "statement can be reduced to" ,
324
- snippet,
325
- Applicability :: MachineApplicable ,
326
- ) ;
322
+ diag. span_suggestion ( stmt. span , "statement can be reduced to" , snippet, applicability) ;
327
323
} ,
328
324
) ;
329
325
}
330
326
}
331
327
}
332
328
333
- fn reduce_expression < ' a > ( cx : & LateContext < ' _ > , expr : & ' a Expr < ' a > ) -> Option < Vec < & ' a Expr < ' a > > > {
329
+ fn reduce_expression < ' a > (
330
+ cx : & LateContext < ' _ > ,
331
+ expr : & ' a Expr < ' a > ,
332
+ applicability : & mut Applicability ,
333
+ ) -> Option < Vec < & ' a Expr < ' a > > > {
334
334
if expr. span . from_expansion ( ) {
335
335
return None ;
336
336
}
@@ -344,9 +344,9 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
344
344
| ExprKind :: Type ( inner, _)
345
345
| ExprKind :: Unary ( _, inner)
346
346
| ExprKind :: Field ( inner, _)
347
- | ExprKind :: AddrOf ( _, _, inner) => reduce_expression ( cx, inner) . or_else ( || Some ( vec ! [ inner] ) ) ,
347
+ | ExprKind :: AddrOf ( _, _, inner) => reduce_expression ( cx, inner, applicability ) . or_else ( || Some ( vec ! [ inner] ) ) ,
348
348
ExprKind :: Cast ( inner, _) if expr_type_is_certain ( cx, inner) => {
349
- reduce_expression ( cx, inner) . or_else ( || Some ( vec ! [ inner] ) )
349
+ reduce_expression ( cx, inner, applicability ) . or_else ( || Some ( vec ! [ inner] ) )
350
350
} ,
351
351
// In the normal `Struct` case, we bail out if any of the fields has an uncertain type.
352
352
// But for two-sided ranges, we know that if the type of one of the sides is certain, then so is the other
@@ -366,9 +366,12 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
366
366
}
367
367
} ,
368
368
ExprKind :: Struct ( _, fields, ref base) => {
369
- if fields. iter ( ) . any ( |f| !expr_type_is_certain ( cx, & f. expr ) )
370
- || has_drop ( cx, cx. typeck_results ( ) . expr_ty ( expr) )
371
- {
369
+ if fields. iter ( ) . any ( |f| !expr_type_is_certain ( cx, f. expr ) ) {
370
+ // there's a risk that if we take the field exprs out of the context of the struct constructor,
371
+ // their types might become ambiguous
372
+ * applicability = Applicability :: MaybeIncorrect ;
373
+ }
374
+ if has_drop ( cx, cx. typeck_results ( ) . expr_ty ( expr) ) {
372
375
None
373
376
} else {
374
377
let base = match base {
@@ -404,7 +407,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
404
407
BlockCheckMode :: UnsafeBlock ( UnsafeSource :: UserProvided ) => None ,
405
408
BlockCheckMode :: DefaultBlock => Some ( vec ! [ & * * e] ) ,
406
409
// in case of compiler-inserted signaling blocks
407
- BlockCheckMode :: UnsafeBlock ( _) => reduce_expression ( cx, e) ,
410
+ BlockCheckMode :: UnsafeBlock ( _) => reduce_expression ( cx, e, applicability ) ,
408
411
}
409
412
} )
410
413
} else {
0 commit comments