Auto merge of #8896 - Alexendoo:fn_sig_ice, r=llogiq

Only return `DefId`s to `Fn`-like definitions in `clippy_utils::fn_def_id`

Fixes #8850

in `returns.rs` `tcx.fn_sig` is called on the result of `fn_def_id`, which panics if the def is a `const`/`static`/etc rather than a functions definition

bc4d39e5fe/clippy_lints/src/returns.rs (L294-L303)

changelog: Fix ICE due to callable `static`/`const`s
This commit is contained in:
bors 2022-05-26 16:33:30 +00:00
commit 6553b98540
3 changed files with 83 additions and 1 deletions

View file

@ -1916,7 +1916,17 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
..
},
..,
) => 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,
}
}

View file

@ -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() {}

View file

@ -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