Skip to content

[do not merge] Relicensing rewrite #3251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Oct 5, 2018
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,7 @@ All notable changes to this project will be documented in this file.
[`float_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_arithmetic
[`float_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp
[`float_cmp_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp_const
[`fn_to_numeric_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast
[`for_kv_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_kv_map
[`for_loop_over_option`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_option
[`for_loop_over_result`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_result
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in

A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.

[There are 277 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)
[There are 278 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)

We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:

Expand Down
2 changes: 2 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
types::CAST_LOSSLESS,
types::CAST_PTR_ALIGNMENT,
types::CHAR_LIT_AS_U8,
types::FN_TO_NUMERIC_CAST,
types::IMPLICIT_HASHER,
types::LET_UNIT_VALUE,
types::OPTION_OPTION,
Expand Down Expand Up @@ -789,6 +790,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
returns::LET_AND_RETURN,
returns::NEEDLESS_RETURN,
strings::STRING_LIT_AS_BYTES,
types::FN_TO_NUMERIC_CAST,
types::IMPLICIT_HASHER,
types::LET_UNIT_VALUE,
unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
Expand Down
45 changes: 45 additions & 0 deletions clippy_lints/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,30 @@ declare_clippy_lint! {
"cast from a pointer to a more-strictly-aligned pointer"
}

/// **What it does:** Checks for casts of function pointers to something other than usize
///
/// **Why is this bad?**
/// Depending on the system architechture, casting a function pointer to something other than
/// `usize` will result in incorrect pointer addresses.
/// `usize` will always be able to store the function pointer on the given architechture.
///
/// **Example**
///
/// ```rust
/// // Bad
/// fn fun() -> i32 {}
/// let a = fun as i64;
///
/// // Good
/// fn fun2() -> i32 {}
/// let a = fun2 as usize;
/// ```
declare_clippy_lint! {
pub FN_TO_NUMERIC_CAST,
style,
"casting a function pointer to a numeric type other than usize"
}

/// Returns the size in bits of an integral type.
/// Will return 0 if the type is not an int or uint variant
fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_, '_, '_>) -> u64 {
Expand Down Expand Up @@ -913,6 +937,7 @@ impl LintPass for CastPass {
CAST_LOSSLESS,
UNNECESSARY_CAST,
CAST_PTR_ALIGNMENT,
FN_TO_NUMERIC_CAST
)
}
}
Expand All @@ -921,6 +946,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprKind::Cast(ref ex, _) = expr.node {
let (cast_from, cast_to) = (cx.tables.expr_ty(ex), cx.tables.expr_ty(expr));
lint_fn_to_numeric_cast(cx, expr, ex, cast_from, cast_to);
if let ExprKind::Lit(ref lit) = ex.node {
use crate::syntax::ast::{LitIntType, LitKind};
match lit.node {
Expand Down Expand Up @@ -1021,6 +1047,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass {
}
}

fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Expr, cast_from: Ty, cast_to: Ty) {
match cast_from.sty {
ty::FnDef(..) | ty::FnPtr(_) => {
let from_snippet = snippet(cx, cast_expr.span, "x");
if cast_to.sty != ty::Uint(UintTy::Usize) {
span_lint_and_sugg(
cx,
FN_TO_NUMERIC_CAST,
expr.span,
&format!("casting function pointer `{}` to `{}`", from_snippet, cast_to),
"try",
format!("{} as usize", from_snippet)
);
}
},
_ => {}
}
}

/// **What it does:** Checks for types used in structs, parameters and `let`
/// declarations above a certain complexity threshold.
///
Expand Down
49 changes: 49 additions & 0 deletions tests/ui/fn_to_numeric_cast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#![feature(tool_lints)]

#[warn(clippy::fn_to_numeric_cast)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[warn()] -> #![warn()]


fn foo() -> String { String::new() }

fn test_function_to_numeric_cast() {
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;

// Casting to usize is OK and should not warn
let _ = foo as usize;
}

fn test_function_var_to_numeric_cast() {
let abc: fn() -> String = foo;

let _ = abc as i8;
let _ = abc as i16;
let _ = abc as i32;
let _ = abc as i64;
let _ = abc as i128;
let _ = abc as isize;

let _ = abc as u8;
let _ = abc as u16;
let _ = abc as u32;
let _ = abc as u64;
let _ = abc as u128;

// Casting to usize is OK and should not warn
let _ = abc as usize;
}

fn fn_with_fn_args(f: fn(i32) -> i32) -> i32 {
f as i32
}

fn main() {}