diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index adb37cc9d..b8a80d4ad 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1916,7 +1916,17 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { .. }, .., - ) => cx.typeck_results().qpath_res(qpath, *path_hir_id).opt_def_id(), + ) => { + // Only return Fn-like DefIds, not the DefIds of statics/consts/etc that contain or + // deref to fn pointers, dyn Fn, impl Fn - #8850 + if let Res::Def(DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn, id) = + cx.typeck_results().qpath_res(qpath, *path_hir_id) + { + Some(id) + } else { + None + } + }, _ => None, } } diff --git a/tests/ui/crashes/ice-8850.rs b/tests/ui/crashes/ice-8850.rs new file mode 100644 index 000000000..f2747ab22 --- /dev/null +++ b/tests/ui/crashes/ice-8850.rs @@ -0,0 +1,27 @@ +fn fn_pointer_static() -> usize { + static FN: fn() -> usize = || 1; + let res = FN() + 1; + res +} + +fn fn_pointer_const() -> usize { + const FN: fn() -> usize = || 1; + let res = FN() + 1; + res +} + +fn deref_to_dyn_fn() -> usize { + struct Derefs; + impl std::ops::Deref for Derefs { + type Target = dyn Fn() -> usize; + + fn deref(&self) -> &Self::Target { + &|| 2 + } + } + static FN: Derefs = Derefs; + let res = FN() + 1; + res +} + +fn main() {} diff --git a/tests/ui/crashes/ice-8850.stderr b/tests/ui/crashes/ice-8850.stderr new file mode 100644 index 000000000..620fd1eda --- /dev/null +++ b/tests/ui/crashes/ice-8850.stderr @@ -0,0 +1,45 @@ +error: returning the result of a `let` binding from a block + --> $DIR/ice-8850.rs:4:5 + | +LL | let res = FN() + 1; + | ------------------- unnecessary `let` binding +LL | res + | ^^^ + | + = note: `-D clippy::let-and-return` implied by `-D warnings` +help: return the expression directly + | +LL ~ +LL ~ FN() + 1 + | + +error: returning the result of a `let` binding from a block + --> $DIR/ice-8850.rs:10:5 + | +LL | let res = FN() + 1; + | ------------------- unnecessary `let` binding +LL | res + | ^^^ + | +help: return the expression directly + | +LL ~ +LL ~ FN() + 1 + | + +error: returning the result of a `let` binding from a block + --> $DIR/ice-8850.rs:24:5 + | +LL | let res = FN() + 1; + | ------------------- unnecessary `let` binding +LL | res + | ^^^ + | +help: return the expression directly + | +LL ~ +LL ~ FN() + 1 + | + +error: aborting due to 3 previous errors +