Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Restriction lint for function pointer casts
- Loading branch information
1 parent
11492c7
commit fbd0fb9
Showing
7 changed files
with
258 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
use clippy_utils::diagnostics::span_lint_and_sugg; | ||
use clippy_utils::source::snippet_with_applicability; | ||
use rustc_errors::Applicability; | ||
use rustc_hir::Expr; | ||
use rustc_lint::LateContext; | ||
use rustc_middle::ty::{self, Ty}; | ||
|
||
use super::FN_TO_NUMERIC_CAST_ANY; | ||
|
||
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { | ||
// We allow casts from any function type to any function type. | ||
match cast_to.kind() { | ||
ty::FnDef(..) | ty::FnPtr(..) => return, | ||
_ => { /* continue to checks */ }, | ||
} | ||
|
||
match cast_from.kind() { | ||
ty::FnDef(..) | ty::FnPtr(_) => { | ||
let mut applicability = Applicability::MaybeIncorrect; | ||
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "..", &mut applicability); | ||
|
||
span_lint_and_sugg( | ||
cx, | ||
FN_TO_NUMERIC_CAST_ANY, | ||
expr.span, | ||
&format!("casting function pointer `{}` to `{}`", from_snippet, cast_to), | ||
"did you mean to invoke the function?", | ||
format!("{}() as {}", from_snippet, cast_to), | ||
applicability, | ||
); | ||
}, | ||
_ => {}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#![warn(clippy::fn_to_numeric_cast_any)] | ||
#![allow(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)] | ||
|
||
fn foo() -> u8 { | ||
0 | ||
} | ||
|
||
fn generic_foo<T>(x: T) -> T { | ||
x | ||
} | ||
|
||
trait Trait { | ||
fn static_method() -> u32 { | ||
2 | ||
} | ||
} | ||
|
||
struct Struct; | ||
|
||
impl Trait for Struct {} | ||
|
||
fn fn_pointer_to_integer() { | ||
let _ = foo as i8; | ||
let _ = foo as i16; | ||
let _ = foo as i32; | ||
let _ = foo as i64; | ||
let _ = foo as i128; | ||
let _ = foo as isize; | ||
|
||
let _ = foo as u8; | ||
let _ = foo as u16; | ||
let _ = foo as u32; | ||
let _ = foo as u64; | ||
let _ = foo as u128; | ||
let _ = foo as usize; | ||
} | ||
|
||
fn static_method_to_integer() { | ||
let _ = Struct::static_method as usize; | ||
} | ||
|
||
fn fn_with_fn_arg(f: fn(i32) -> u32) -> usize { | ||
f as usize | ||
} | ||
|
||
fn fn_with_generic_static_trait_method<T: Trait>() -> usize { | ||
T::static_method as usize | ||
} | ||
|
||
fn closure_to_fn_to_integer() { | ||
let clos = |x| x * 2_u32; | ||
|
||
let _ = (clos as fn(u32) -> u32) as usize; | ||
} | ||
|
||
fn fn_to_raw_ptr() { | ||
let _ = foo as *const (); | ||
} | ||
|
||
fn cast_fn_to_self() { | ||
// Casting to the same function pointer type should be permitted. | ||
let _ = foo as fn() -> u8; | ||
} | ||
|
||
fn cast_generic_to_concrete() { | ||
// Casting to a more concrete function pointer type should be permitted. | ||
let _ = generic_foo as fn(usize) -> usize; | ||
} | ||
|
||
fn cast_closure_to_fn() { | ||
// Casting a closure to a function pointer should be permitted. | ||
let id = |x| x; | ||
let _ = id as fn(usize) -> usize; | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
error: casting function pointer `foo` to `i8` | ||
--> $DIR/fn_to_numeric_cast_any.rs:23:13 | ||
| | ||
LL | let _ = foo as i8; | ||
| ^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i8` | ||
| | ||
= note: `-D clippy::fn-to-numeric-cast-any` implied by `-D warnings` | ||
|
||
error: casting function pointer `foo` to `i16` | ||
--> $DIR/fn_to_numeric_cast_any.rs:24:13 | ||
| | ||
LL | let _ = foo as i16; | ||
| ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i16` | ||
|
||
error: casting function pointer `foo` to `i32` | ||
--> $DIR/fn_to_numeric_cast_any.rs:25:13 | ||
| | ||
LL | let _ = foo as i32; | ||
| ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i32` | ||
|
||
error: casting function pointer `foo` to `i64` | ||
--> $DIR/fn_to_numeric_cast_any.rs:26:13 | ||
| | ||
LL | let _ = foo as i64; | ||
| ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i64` | ||
|
||
error: casting function pointer `foo` to `i128` | ||
--> $DIR/fn_to_numeric_cast_any.rs:27:13 | ||
| | ||
LL | let _ = foo as i128; | ||
| ^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i128` | ||
|
||
error: casting function pointer `foo` to `isize` | ||
--> $DIR/fn_to_numeric_cast_any.rs:28:13 | ||
| | ||
LL | let _ = foo as isize; | ||
| ^^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as isize` | ||
|
||
error: casting function pointer `foo` to `u8` | ||
--> $DIR/fn_to_numeric_cast_any.rs:30:13 | ||
| | ||
LL | let _ = foo as u8; | ||
| ^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u8` | ||
|
||
error: casting function pointer `foo` to `u16` | ||
--> $DIR/fn_to_numeric_cast_any.rs:31:13 | ||
| | ||
LL | let _ = foo as u16; | ||
| ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u16` | ||
|
||
error: casting function pointer `foo` to `u32` | ||
--> $DIR/fn_to_numeric_cast_any.rs:32:13 | ||
| | ||
LL | let _ = foo as u32; | ||
| ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u32` | ||
|
||
error: casting function pointer `foo` to `u64` | ||
--> $DIR/fn_to_numeric_cast_any.rs:33:13 | ||
| | ||
LL | let _ = foo as u64; | ||
| ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u64` | ||
|
||
error: casting function pointer `foo` to `u128` | ||
--> $DIR/fn_to_numeric_cast_any.rs:34:13 | ||
| | ||
LL | let _ = foo as u128; | ||
| ^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u128` | ||
|
||
error: casting function pointer `foo` to `usize` | ||
--> $DIR/fn_to_numeric_cast_any.rs:35:13 | ||
| | ||
LL | let _ = foo as usize; | ||
| ^^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as usize` | ||
|
||
error: casting function pointer `Struct::static_method` to `usize` | ||
--> $DIR/fn_to_numeric_cast_any.rs:39:13 | ||
| | ||
LL | let _ = Struct::static_method as usize; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `Struct::static_method() as usize` | ||
|
||
error: casting function pointer `f` to `usize` | ||
--> $DIR/fn_to_numeric_cast_any.rs:43:5 | ||
| | ||
LL | f as usize | ||
| ^^^^^^^^^^ help: did you mean to invoke the function?: `f() as usize` | ||
|
||
error: casting function pointer `T::static_method` to `usize` | ||
--> $DIR/fn_to_numeric_cast_any.rs:47:5 | ||
| | ||
LL | T::static_method as usize | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `T::static_method() as usize` | ||
|
||
error: casting function pointer `(clos as fn(u32) -> u32)` to `usize` | ||
--> $DIR/fn_to_numeric_cast_any.rs:53:13 | ||
| | ||
LL | let _ = (clos as fn(u32) -> u32) as usize; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `(clos as fn(u32) -> u32)() as usize` | ||
|
||
error: casting function pointer `foo` to `*const ()` | ||
--> $DIR/fn_to_numeric_cast_any.rs:57:13 | ||
| | ||
LL | let _ = foo as *const (); | ||
| ^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as *const ()` | ||
|
||
error: aborting due to 17 previous errors | ||
|