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 @@ -689,6 +689,7 @@ All notable changes to this project will be documented in this file.
[`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
[`fn_to_numeric_cast_with_truncation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation
[`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 278 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)
[There are 279 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 @@ -698,6 +698,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
types::CAST_PTR_ALIGNMENT,
types::CHAR_LIT_AS_U8,
types::FN_TO_NUMERIC_CAST,
types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
types::IMPLICIT_HASHER,
types::LET_UNIT_VALUE,
types::OPTION_OPTION,
Expand Down Expand Up @@ -791,6 +792,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
returns::NEEDLESS_RETURN,
strings::STRING_LIT_AS_BYTES,
types::FN_TO_NUMERIC_CAST,
types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
types::IMPLICIT_HASHER,
types::LET_UNIT_VALUE,
unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
Expand Down
49 changes: 45 additions & 4 deletions clippy_lints/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,9 +722,12 @@ declare_clippy_lint! {
/// **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.
/// Casting a function pointer to anything other than usize/isize is not portable across
/// architectures, because you end up losing bits if the target type is too small or end up with a
/// bunch of extra bits that waste space and add more instructions to the final binary than
/// strictly necessary for the problem
///
/// Casting to isize also doesn't make sense since there are no signed addresses.
///
/// **Example**
///
Expand All @@ -743,6 +746,32 @@ declare_clippy_lint! {
"casting a function pointer to a numeric type other than usize"
}

/// **What it does:** Checks for casts of a function pointer to a numeric type not wide enough to
/// store address.
///
/// **Why is this bad?**
/// Such a cast discards some bits of the function's address. If this is intended, it would be more
/// clearly expressed by casting to usize first, then casting the usize to the intended type (with
/// a comment) to perform the truncation.
///
/// **Example**
///
/// ```rust
/// // Bad
/// fn fn1() -> i16 { 1 };
/// let _ = fn1 as i32;
///
/// // Better: Cast to usize first, then comment with the reason for the truncation
/// fn fn2() -> i16 { 1 };
/// let fn_ptr = fn2 as usize;
/// let fn_ptr_truncated = fn_ptr as i32;
/// ```
declare_clippy_lint! {
pub FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
style,
"casting a function pointer to a numeric type not wide enough to store the address"
}

/// 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 @@ -1051,7 +1080,19 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex
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) {

let to_nbits = int_ty_to_nbits(cast_to, cx.tcx);
if to_nbits < cx.tcx.data_layout.pointer_size.bits() {
span_lint_and_sugg(
cx,
FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
expr.span,
&format!("casting function pointer `{}` to `{}`, which truncates the value", from_snippet, cast_to),
"try",
format!("{} as usize", from_snippet)
);

} else if cast_to.sty != ty::Uint(UintTy::Usize) {
span_lint_and_sugg(
cx,
FN_TO_NUMERIC_CAST,
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/fn_to_numeric_cast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![feature(tool_lints)]

#[warn(clippy::fn_to_numeric_cast)]
#![warn(clippy::fn_to_numeric_cast)]

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

Expand Down
142 changes: 142 additions & 0 deletions tests/ui/fn_to_numeric_cast.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
error: casting function pointer `foo` to `i8`
--> $DIR/fn_to_numeric_cast.rs:8:13
|
8 | let _ = foo as i8;
| ^^^^^^^^^ help: try: `foo as usize`
|
= note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings`

error: casting function pointer `foo` to `i16`
--> $DIR/fn_to_numeric_cast.rs:9:13
|
9 | let _ = foo as i16;
| ^^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `i32`
--> $DIR/fn_to_numeric_cast.rs:10:13
|
10 | let _ = foo as i32;
| ^^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `i64`
--> $DIR/fn_to_numeric_cast.rs:11:13
|
11 | let _ = foo as i64;
| ^^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `i128`
--> $DIR/fn_to_numeric_cast.rs:12:13
|
12 | let _ = foo as i128;
| ^^^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `isize`
--> $DIR/fn_to_numeric_cast.rs:13:13
|
13 | let _ = foo as isize;
| ^^^^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `u8`
--> $DIR/fn_to_numeric_cast.rs:15:13
|
15 | let _ = foo as u8;
| ^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `u16`
--> $DIR/fn_to_numeric_cast.rs:16:13
|
16 | let _ = foo as u16;
| ^^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `u32`
--> $DIR/fn_to_numeric_cast.rs:17:13
|
17 | let _ = foo as u32;
| ^^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `u64`
--> $DIR/fn_to_numeric_cast.rs:18:13
|
18 | let _ = foo as u64;
| ^^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `u128`
--> $DIR/fn_to_numeric_cast.rs:19:13
|
19 | let _ = foo as u128;
| ^^^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `abc` to `i8`
--> $DIR/fn_to_numeric_cast.rs:28:13
|
28 | let _ = abc as i8;
| ^^^^^^^^^ help: try: `abc as usize`

error: casting function pointer `abc` to `i16`
--> $DIR/fn_to_numeric_cast.rs:29:13
|
29 | let _ = abc as i16;
| ^^^^^^^^^^ help: try: `abc as usize`

error: casting function pointer `abc` to `i32`
--> $DIR/fn_to_numeric_cast.rs:30:13
|
30 | let _ = abc as i32;
| ^^^^^^^^^^ help: try: `abc as usize`

error: casting function pointer `abc` to `i64`
--> $DIR/fn_to_numeric_cast.rs:31:13
|
31 | let _ = abc as i64;
| ^^^^^^^^^^ help: try: `abc as usize`

error: casting function pointer `abc` to `i128`
--> $DIR/fn_to_numeric_cast.rs:32:13
|
32 | let _ = abc as i128;
| ^^^^^^^^^^^ help: try: `abc as usize`

error: casting function pointer `abc` to `isize`
--> $DIR/fn_to_numeric_cast.rs:33:13
|
33 | let _ = abc as isize;
| ^^^^^^^^^^^^ help: try: `abc as usize`

error: casting function pointer `abc` to `u8`
--> $DIR/fn_to_numeric_cast.rs:35:13
|
35 | let _ = abc as u8;
| ^^^^^^^^^ help: try: `abc as usize`

error: casting function pointer `abc` to `u16`
--> $DIR/fn_to_numeric_cast.rs:36:13
|
36 | let _ = abc as u16;
| ^^^^^^^^^^ help: try: `abc as usize`

error: casting function pointer `abc` to `u32`
--> $DIR/fn_to_numeric_cast.rs:37:13
|
37 | let _ = abc as u32;
| ^^^^^^^^^^ help: try: `abc as usize`

error: casting function pointer `abc` to `u64`
--> $DIR/fn_to_numeric_cast.rs:38:13
|
38 | let _ = abc as u64;
| ^^^^^^^^^^ help: try: `abc as usize`

error: casting function pointer `abc` to `u128`
--> $DIR/fn_to_numeric_cast.rs:39:13
|
39 | let _ = abc as u128;
| ^^^^^^^^^^^ help: try: `abc as usize`

error: casting function pointer `f` to `i32`
--> $DIR/fn_to_numeric_cast.rs:46:5
|
46 | f as i32
| ^^^^^^^^ help: try: `f as usize`

error: aborting due to 23 previous errors

23 changes: 23 additions & 0 deletions tests/ui/fn_to_numeric_cast_with_truncation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#![feature(tool_lints)]

#![warn(clippy::fn_to_numeric_cast_with_truncation)]
#![allow(clippy::fn_to_numeric_cast)]

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

fn test_fn_to_numeric_cast_with_truncation() {
let _ = foo as i8;
let _ = foo as i16;
let _ = foo as i32;
let _ = foo as u8;
let _ = foo as u16;
let _ = foo as u32;

// TODO: Is it bad to have these tests?
Copy link
Member

Choose a reason for hiding this comment

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

There are compile-test flags you can set to ignore tests on specific architectures.

// Running the tests on a different architechture will
// produce different results
let _ = foo as u64;
let _ = foo as i64;
}

fn main() {}
40 changes: 40 additions & 0 deletions tests/ui/fn_to_numeric_cast_with_truncation.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
error: casting function pointer `foo` to `i8`, which truncates the value
--> $DIR/fn_to_numeric_cast_with_truncation.rs:9:13
|
9 | let _ = foo as i8;
| ^^^^^^^^^ help: try: `foo as usize`
|
= note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings`

error: casting function pointer `foo` to `i16`, which truncates the value
--> $DIR/fn_to_numeric_cast_with_truncation.rs:10:13
|
10 | let _ = foo as i16;
| ^^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `i32`, which truncates the value
--> $DIR/fn_to_numeric_cast_with_truncation.rs:11:13
|
11 | let _ = foo as i32;
| ^^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `u8`, which truncates the value
--> $DIR/fn_to_numeric_cast_with_truncation.rs:12:13
|
12 | let _ = foo as u8;
| ^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `u16`, which truncates the value
--> $DIR/fn_to_numeric_cast_with_truncation.rs:13:13
|
13 | let _ = foo as u16;
| ^^^^^^^^^^ help: try: `foo as usize`

error: casting function pointer `foo` to `u32`, which truncates the value
--> $DIR/fn_to_numeric_cast_with_truncation.rs:14:13
|
14 | let _ = foo as u32;
| ^^^^^^^^^^ help: try: `foo as usize`

error: aborting due to 6 previous errors