@@ -272,11 +272,12 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
272272}
273273
274274fn check_unnecessary_operation ( cx : & LateContext < ' _ > , stmt : & Stmt < ' _ > ) {
275+ let mut applicability = Applicability :: MachineApplicable ;
275276 if let StmtKind :: Semi ( expr) = stmt. kind
276277 && !stmt. span . in_external_macro ( cx. sess ( ) . source_map ( ) )
277278 && let ctxt = stmt. span . ctxt ( )
278279 && expr. span . ctxt ( ) == ctxt
279- && let Some ( reduced) = reduce_expression ( cx, expr)
280+ && let Some ( reduced) = reduce_expression ( cx, expr, & mut applicability )
280281 && reduced. iter ( ) . all ( |e| e. span . ctxt ( ) == ctxt)
281282 {
282283 if let ExprKind :: Index ( ..) = & expr. kind {
@@ -318,19 +319,18 @@ fn check_unnecessary_operation(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
318319 stmt. span ,
319320 "unnecessary operation" ,
320321 |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) ;
327323 } ,
328324 ) ;
329325 }
330326 }
331327}
332328
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 > > > {
334334 if expr. span . from_expansion ( ) {
335335 return None ;
336336 }
@@ -344,9 +344,9 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
344344 | ExprKind :: Type ( inner, _)
345345 | ExprKind :: Unary ( _, inner)
346346 | 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] ) ) ,
348348 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] ) )
350350 } ,
351351 // In the normal `Struct` case, we bail out if any of the fields has an uncertain type.
352352 // 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
366366 }
367367 } ,
368368 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) ) {
372375 None
373376 } else {
374377 let base = match base {
@@ -404,7 +407,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
404407 BlockCheckMode :: UnsafeBlock ( UnsafeSource :: UserProvided ) => None ,
405408 BlockCheckMode :: DefaultBlock => Some ( vec ! [ & * * e] ) ,
406409 // in case of compiler-inserted signaling blocks
407- BlockCheckMode :: UnsafeBlock ( _) => reduce_expression ( cx, e) ,
410+ BlockCheckMode :: UnsafeBlock ( _) => reduce_expression ( cx, e, applicability ) ,
408411 }
409412 } )
410413 } else {
0 commit comments