diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 6dae8f320436..a63c9fe959c3 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -3,6 +3,7 @@ use clippy_utils::is_lint_allowed; use clippy_utils::source::snippet_opt; use clippy_utils::ty::has_drop; use rustc_errors::Applicability; +use rustc_hir::def::CtorKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, PatKind, Stmt, StmtKind, UnsafeSource}; use rustc_lint::{LateContext, LateLintPass}; @@ -130,10 +131,12 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { }, ExprKind::Call(callee, args) => { if let ExprKind::Path(ref qpath) = callee.kind { - let res = cx.qpath_res(qpath, callee.hir_id); let def_matched = matches!( - res, - Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..) + cx.qpath_res(qpath, callee.hir_id), + Res::Def( + DefKind::Struct | DefKind::Variant | DefKind::Ctor(_, CtorKind::Fn | CtorKind::Fictive), + .. + ) ); if def_matched || is_range_literal(expr) { !has_drop(cx, cx.typeck_results().expr_ty(expr)) && args.iter().all(|arg| has_no_effect(cx, arg)) @@ -235,13 +238,11 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option { if let ExprKind::Path(ref qpath) = callee.kind { - let res = cx.qpath_res(qpath, callee.hir_id); - match res { - Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..) - if !has_drop(cx, cx.typeck_results().expr_ty(expr)) => - { - Some(args.iter().collect()) - }, + match cx.qpath_res(qpath, callee.hir_id) { + Res::Def( + DefKind::Struct | DefKind::Variant | DefKind::Ctor(_, CtorKind::Fn | CtorKind::Fictive), + .., + ) if !has_drop(cx, cx.typeck_results().expr_ty(expr)) => Some(args.iter().collect()), _ => None, } } else { diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 7bcc4cad0d36..5427c88faf34 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -1,4 +1,4 @@ -#![feature(box_syntax)] +#![feature(box_syntax, fn_traits, unboxed_closures)] #![warn(clippy::no_effect_underscore_binding)] #![allow(dead_code)] #![allow(path_statements)] @@ -58,6 +58,36 @@ unsafe fn unsafe_fn() -> i32 { 0 } +struct GreetStruct1; + +impl FnOnce<(&str,)> for GreetStruct1 { + type Output = (); + + extern "rust-call" fn call_once(self, (who,): (&str,)) -> Self::Output { + println!("hello {}", who); + } +} + +struct GreetStruct2(); + +impl FnOnce<(&str,)> for GreetStruct2 { + type Output = (); + + extern "rust-call" fn call_once(self, (who,): (&str,)) -> Self::Output { + println!("hello {}", who); + } +} + +struct GreetStruct3 {} + +impl FnOnce<(&str,)> for GreetStruct3 { + type Output = (); + + extern "rust-call" fn call_once(self, (who,): (&str,)) -> Self::Output { + println!("hello {}", who); + } +} + fn main() { let s = get_struct(); let s2 = get_struct(); @@ -108,4 +138,7 @@ fn main() { DropTuple(0); DropEnum::Tuple(0); DropEnum::Struct { field: 0 }; + GreetStruct1("world"); + GreetStruct2()("world"); + GreetStruct3 {}("world"); } diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index a5dbc9fef455..06b88bb5bee7 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,5 +1,5 @@ error: statement with no effect - --> $DIR/no_effect.rs:65:5 + --> $DIR/no_effect.rs:95:5 | LL | 0; | ^^ @@ -7,157 +7,157 @@ LL | 0; = note: `-D clippy::no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:66:5 + --> $DIR/no_effect.rs:96:5 | LL | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:67:5 + --> $DIR/no_effect.rs:97:5 | LL | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:68:5 + --> $DIR/no_effect.rs:98:5 | LL | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:69:5 + --> $DIR/no_effect.rs:99:5 | LL | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:70:5 + --> $DIR/no_effect.rs:100:5 | LL | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:71:5 + --> $DIR/no_effect.rs:101:5 | LL | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:72:5 + --> $DIR/no_effect.rs:102:5 | LL | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:73:5 + --> $DIR/no_effect.rs:103:5 | LL | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:74:5 + --> $DIR/no_effect.rs:104:5 | LL | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:75:5 + --> $DIR/no_effect.rs:105:5 | LL | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:76:5 + --> $DIR/no_effect.rs:106:5 | LL | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:77:5 + --> $DIR/no_effect.rs:107:5 | LL | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:78:5 + --> $DIR/no_effect.rs:108:5 | LL | box 42; | ^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:79:5 + --> $DIR/no_effect.rs:109:5 | LL | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:80:5 + --> $DIR/no_effect.rs:110:5 | LL | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:81:5 + --> $DIR/no_effect.rs:111:5 | LL | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:82:5 + --> $DIR/no_effect.rs:112:5 | LL | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:83:5 + --> $DIR/no_effect.rs:113:5 | LL | 5..=6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:84:5 + --> $DIR/no_effect.rs:114:5 | LL | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:85:5 + --> $DIR/no_effect.rs:115:5 | LL | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:86:5 + --> $DIR/no_effect.rs:116:5 | LL | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:87:5 + --> $DIR/no_effect.rs:117:5 | LL | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:88:5 + --> $DIR/no_effect.rs:118:5 | LL | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:90:5 + --> $DIR/no_effect.rs:120:5 | LL | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:92:5 + --> $DIR/no_effect.rs:122:5 | LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:93:5 + --> $DIR/no_effect.rs:123:5 | LL | let _unused = 1; | ^^^^^^^^^^^^^^^^ @@ -165,19 +165,19 @@ LL | let _unused = 1; = note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings` error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:94:5 + --> $DIR/no_effect.rs:124:5 | LL | let _penguin = || println!("Some helpful closure"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:95:5 + --> $DIR/no_effect.rs:125:5 | LL | let _duck = Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:96:5 + --> $DIR/no_effect.rs:126:5 | LL | let _cat = [2, 4, 6, 8][2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^