From fffcd093b29a3fa4be22d3836f214cd810836c21 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 2 Oct 2018 12:41:40 +0200 Subject: [PATCH 01/11] relicensing: Remove fn_to_numeric_cast, fn_to_numeric_cast_with_truncation This removes the code added in https://github.com/rust-lang-nursery/rust-clippy/pull/2814 --- clippy_lints/src/lib.rs | 4 -- clippy_lints/src/types.rs | 67 --------------------------------- tests/ui/types_fn_to_int.rs | 22 ----------- tests/ui/types_fn_to_int.stderr | 66 -------------------------------- 4 files changed, 159 deletions(-) delete mode 100644 tests/ui/types_fn_to_int.rs delete mode 100644 tests/ui/types_fn_to_int.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9af4850b15c2..19564dbf9bee 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -697,8 +697,6 @@ 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::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, types::IMPLICIT_HASHER, types::LET_UNIT_VALUE, types::OPTION_OPTION, @@ -791,7 +789,6 @@ 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, @@ -921,7 +918,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { transmute::WRONG_TRANSMUTE, types::ABSURD_EXTREME_COMPARISONS, types::CAST_PTR_ALIGNMENT, - types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, types::UNIT_CMP, unicode::ZERO_WIDTH_SPACE, unused_io_amount::UNUSED_IO_AMOUNT, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 857238e9002b..b98a0f882420 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -700,40 +700,6 @@ declare_clippy_lint! { "cast to the same type, e.g. `x as i32` where `x: i32`" } -/// **What it does:** Checks for casts of a function pointer to a numeric type not enough to store address. -/// -/// **Why is this bad?** Casting a function pointer to not eligible type could truncate the address value. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// fn test_fn() -> i16; -/// let _ = test_fn as i32 -/// ``` -declare_clippy_lint! { - pub FN_TO_NUMERIC_CAST_WITH_TRUNCATION, - correctness, - "cast function pointer to the numeric type with value truncation" -} - -/// **What it does:** Checks for casts of a function pointer to a numeric type except `usize`. -/// -/// **Why is this bad?** Casting a function pointer to something other than `usize` is not a good style. -/// -/// **Known problems:** None. -/// -/// **Example:** -/// ```rust -/// fn test_fn() -> i16; -/// let _ = test_fn as i128 -/// ``` -declare_clippy_lint! { - pub FN_TO_NUMERIC_CAST, - style, - "cast function pointer to the numeric type" -} - /// **What it does:** Checks for casts from a less-strictly-aligned pointer to a /// more-strictly-aligned pointer /// @@ -947,8 +913,6 @@ impl LintPass for CastPass { CAST_LOSSLESS, UNNECESSARY_CAST, CAST_PTR_ALIGNMENT, - FN_TO_NUMERIC_CAST, - FN_TO_NUMERIC_CAST_WITH_TRUNCATION, ) } } @@ -1033,37 +997,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { } } - match &cast_from.sty { - ty::FnDef(..) | - ty::FnPtr(..) => { - if cast_to.is_numeric() && cast_to.sty != ty::Uint(UintTy::Usize){ - let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); - let pointer_nbits = cx.tcx.data_layout.pointer_size.bits(); - if to_nbits < pointer_nbits || (to_nbits == pointer_nbits && cast_to.is_signed()) { - span_lint_and_sugg( - cx, - FN_TO_NUMERIC_CAST_WITH_TRUNCATION, - expr.span, - &format!("casting a `{}` to `{}` may truncate the function address value.", cast_from, cast_to), - "if you need the address of the function, consider", - format!("{} as usize", &snippet(cx, ex.span, "x")) - ); - } else { - span_lint_and_sugg( - cx, - FN_TO_NUMERIC_CAST, - expr.span, - &format!("casting a `{}` to `{}` is bad style.", cast_from, cast_to), - "if you need the address of the function, consider", - format!("{} as usize", &snippet(cx, ex.span, "x")) - ); - - }; - } - } - _ => () - } - if_chain!{ if let ty::RawPtr(from_ptr_ty) = &cast_from.sty; if let ty::RawPtr(to_ptr_ty) = &cast_to.sty; diff --git a/tests/ui/types_fn_to_int.rs b/tests/ui/types_fn_to_int.rs deleted file mode 100644 index 8387586c3e94..000000000000 --- a/tests/ui/types_fn_to_int.rs +++ /dev/null @@ -1,22 +0,0 @@ -enum Foo { - A(usize), - B -} - -fn bar() -> i32 { - 0i32 -} - -fn main() { - let x = Foo::A; - let _y = x as i32; - let _y1 = Foo::A as i32; - let _y = x as u32; - let _z = bar as u32; - let _y = bar as i64; - let _y = bar as u64; - let _z = Foo::A as i128; - let _z = Foo::A as u128; - let _z = bar as i128; - let _z = bar as u128; -} diff --git a/tests/ui/types_fn_to_int.stderr b/tests/ui/types_fn_to_int.stderr deleted file mode 100644 index a06809b9bfd6..000000000000 --- a/tests/ui/types_fn_to_int.stderr +++ /dev/null @@ -1,66 +0,0 @@ -error: casting a `fn(usize) -> Foo {Foo::A}` to `i32` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:12:14 - | -12 | let _y = x as i32; - | ^^^^^^^^ help: if you need the address of the function, consider: `x as usize` - | - = note: #[deny(clippy::fn_to_numeric_cast_with_truncation)] on by default - -error: casting a `fn(usize) -> Foo {Foo::A}` to `i32` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:13:15 - | -13 | let _y1 = Foo::A as i32; - | ^^^^^^^^^^^^^ help: if you need the address of the function, consider: `Foo::A as usize` - -error: casting a `fn(usize) -> Foo {Foo::A}` to `u32` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:14:14 - | -14 | let _y = x as u32; - | ^^^^^^^^ help: if you need the address of the function, consider: `x as usize` - -error: casting a `fn() -> i32 {bar}` to `u32` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:15:14 - | -15 | let _z = bar as u32; - | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` - -error: casting a `fn() -> i32 {bar}` to `i64` may truncate the function address value. - --> $DIR/types_fn_to_int.rs:16:14 - | -16 | let _y = bar as i64; - | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` - -error: casting a `fn() -> i32 {bar}` to `u64` is bad style. - --> $DIR/types_fn_to_int.rs:17:14 - | -17 | let _y = bar as u64; - | ^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` - | - = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` - -error: casting a `fn(usize) -> Foo {Foo::A}` to `i128` is bad style. - --> $DIR/types_fn_to_int.rs:18:14 - | -18 | let _z = Foo::A as i128; - | ^^^^^^^^^^^^^^ help: if you need the address of the function, consider: `Foo::A as usize` - -error: casting a `fn(usize) -> Foo {Foo::A}` to `u128` is bad style. - --> $DIR/types_fn_to_int.rs:19:14 - | -19 | let _z = Foo::A as u128; - | ^^^^^^^^^^^^^^ help: if you need the address of the function, consider: `Foo::A as usize` - -error: casting a `fn() -> i32 {bar}` to `i128` is bad style. - --> $DIR/types_fn_to_int.rs:20:14 - | -20 | let _z = bar as i128; - | ^^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` - -error: casting a `fn() -> i32 {bar}` to `u128` is bad style. - --> $DIR/types_fn_to_int.rs:21:14 - | -21 | let _z = bar as u128; - | ^^^^^^^^^^^ help: if you need the address of the function, consider: `bar as usize` - -error: aborting due to 10 previous errors - From 057243f16b4f42337b6178a627dcf3ae4c09f056 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 2 Oct 2018 12:51:38 +0200 Subject: [PATCH 02/11] relicensing: Remove map_clone This removes the code added in https://github.com/rust-lang-nursery/rust-clippy/pull/427 --- clippy_lints/src/lib.rs | 4 - clippy_lints/src/map_clone.rs | 140 ---------------------------------- tests/ui/map_clone.rs | 105 ------------------------- tests/ui/map_clone.stderr | 102 ------------------------- 4 files changed, 351 deletions(-) delete mode 100644 clippy_lints/src/map_clone.rs delete mode 100644 tests/ui/map_clone.rs delete mode 100644 tests/ui/map_clone.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 19564dbf9bee..689dbfa7da96 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -129,7 +129,6 @@ pub mod let_if_seq; pub mod lifetimes; pub mod literal_representation; pub mod loops; -pub mod map_clone; pub mod map_unit_fn; pub mod matches; pub mod mem_forget; @@ -346,7 +345,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box needless_borrow::NeedlessBorrow); reg.register_late_lint_pass(box needless_borrowed_ref::NeedlessBorrowedRef); reg.register_late_lint_pass(box no_effect::Pass); - reg.register_late_lint_pass(box map_clone::Pass); reg.register_late_lint_pass(box temporary_assignment::Pass); reg.register_late_lint_pass(box transmute::Transmute); reg.register_late_lint_pass( @@ -585,7 +583,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::WHILE_IMMUTABLE_CONDITION, loops::WHILE_LET_LOOP, loops::WHILE_LET_ON_ITERATOR, - map_clone::MAP_CLONE, map_unit_fn::OPTION_MAP_UNIT_FN, map_unit_fn::RESULT_MAP_UNIT_FN, matches::MATCH_AS_REF, @@ -745,7 +742,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::FOR_KV_MAP, loops::NEEDLESS_RANGE_LOOP, loops::WHILE_LET_ON_ITERATOR, - map_clone::MAP_CLONE, matches::MATCH_BOOL, matches::MATCH_OVERLAPPING_ARM, matches::MATCH_REF_PATS, diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs deleted file mode 100644 index 239602c6db5e..000000000000 --- a/clippy_lints/src/map_clone.rs +++ /dev/null @@ -1,140 +0,0 @@ -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use if_chain::if_chain; -use crate::rustc::hir::*; -use crate::rustc::ty; -use crate::syntax::ast; -use crate::utils::{get_arg_ident, is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type, - paths, remove_blocks, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq}; - -/// **What it does:** Checks for mapping `clone()` over an iterator. -/// -/// **Why is this bad?** It makes the code less readable than using the -/// `.cloned()` adapter. -/// -/// **Known problems:** Sometimes `.cloned()` requires stricter trait -/// bound than `.map(|e| e.clone())` (which works because of the coercion). -/// See [#498](https://github.com/rust-lang-nursery/rust-clippy/issues/498). -/// -/// **Example:** -/// ```rust -/// x.map(|e| e.clone()); -/// ``` -declare_clippy_lint! { - pub MAP_CLONE, - style, - "using `.map(|x| x.clone())` to clone an iterator or option's contents" -} - -#[derive(Copy, Clone)] -pub struct Pass; - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - // call to .map() - if let ExprKind::MethodCall(ref method, _, ref args) = expr.node { - if method.ident.name == "map" && args.len() == 2 { - match args[1].node { - ExprKind::Closure(_, ref decl, closure_eid, _, _) => { - let body = cx.tcx.hir.body(closure_eid); - let closure_expr = remove_blocks(&body.value); - if_chain! { - // nothing special in the argument, besides reference bindings - // (e.g. .map(|&x| x) ) - if let Some(first_arg) = iter_input_pats(decl, body).next(); - if let Some(arg_ident) = get_arg_ident(&first_arg.pat); - // the method is being called on a known type (option or iterator) - if let Some(type_name) = get_type_name(cx, expr, &args[0]); - then { - // We know that body.arguments is not empty at this point - let ty = cx.tables.pat_ty(&body.arguments[0].pat); - // look for derefs, for .map(|x| *x) - if only_derefs(cx, &*closure_expr, arg_ident) && - // .cloned() only removes one level of indirection, don't lint on more - walk_ptrs_ty_depth(cx.tables.pat_ty(&first_arg.pat)).1 == 1 - { - // the argument is not an &mut T - if let ty::Ref(_, _, mutbl) = ty.sty { - if mutbl == MutImmutable { - span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( - "you seem to be using .map() to clone the contents of an {}, consider \ - using `.cloned()`", type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); - } - } - } - // explicit clone() calls ( .map(|x| x.clone()) ) - else if let ExprKind::MethodCall(ref clone_call, _, ref clone_args) = closure_expr.node { - if clone_call.ident.name == "clone" && - clone_args.len() == 1 && - match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) && - expr_eq_name(cx, &clone_args[0], arg_ident) - { - span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( - "you seem to be using .map() to clone the contents of an {}, consider \ - using `.cloned()`", type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); - } - } - } - } - }, - ExprKind::Path(ref path) => if match_qpath(path, &paths::CLONE) { - let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_"); - span_help_and_lint( - cx, - MAP_CLONE, - expr.span, - &format!( - "you seem to be using .map() to clone the contents of an \ - {}, consider using `.cloned()`", - type_name - ), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")), - ); - }, - _ => (), - } - } - } - } -} - -fn expr_eq_name(cx: &LateContext<'_, '_>, expr: &Expr, id: ast::Ident) -> bool { - match expr.node { - ExprKind::Path(QPath::Resolved(None, ref path)) => { - let arg_segment = [ - PathSegment { - ident: id, - args: None, - infer_types: true, - }, - ]; - !path.is_global() && SpanlessEq::new(cx).eq_path_segments(&path.segments[..], &arg_segment) - }, - _ => false, - } -} - -fn get_type_name(cx: &LateContext<'_, '_>, expr: &Expr, arg: &Expr) -> Option<&'static str> { - if match_trait_method(cx, expr, &paths::ITERATOR) { - Some("iterator") - } else if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(arg)), &paths::OPTION) { - Some("Option") - } else { - None - } -} - -fn only_derefs(cx: &LateContext<'_, '_>, expr: &Expr, id: ast::Ident) -> bool { - match expr.node { - ExprKind::Unary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id), - _ => expr_eq_name(cx, expr, id), - } -} - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(MAP_CLONE) - } -} diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs deleted file mode 100644 index 90c95be2c1c1..000000000000 --- a/tests/ui/map_clone.rs +++ /dev/null @@ -1,105 +0,0 @@ -#![feature(tool_lints)] - - -#![warn(clippy::map_clone)] - -#![allow(clippy::clone_on_copy, unused)] - -use std::ops::Deref; - -fn map_clone_iter() { - let x = [1,2,3]; - x.iter().map(|y| y.clone()); - - x.iter().map(|&y| y); - - x.iter().map(|y| *y); - - x.iter().map(|y| { y.clone() }); - - x.iter().map(|&y| { y }); - - x.iter().map(|y| { *y }); - - x.iter().map(Clone::clone); - -} - -fn map_clone_option() { - let x = Some(4); - x.as_ref().map(|y| y.clone()); - - x.as_ref().map(|&y| y); - - x.as_ref().map(|y| *y); - -} - -fn not_linted_option() { - let x = Some(5); - - // Not linted: other statements - x.as_ref().map(|y| { - println!("y: {}", y); - y.clone() - }); - - // Not linted: argument bindings - let x = Some((6, 7)); - x.map(|(y, _)| y.clone()); - - // Not linted: cloning something else - x.map(|y| y.0.clone()); - - // Not linted: no dereferences - x.map(|y| y); - - // Not linted: multiple dereferences - let _: Option<(i32, i32)> = x.as_ref().as_ref().map(|&&x| x); -} - -#[derive(Copy, Clone)] -struct Wrapper(T); -impl Wrapper { - fn map U>(self, f: F) -> Wrapper { - Wrapper(f(self.0)) - } -} - -fn map_clone_other() { - let eight = 8; - let x = Wrapper(&eight); - - // Not linted: not a linted type - x.map(|y| y.clone()); - x.map(|&y| y); - x.map(|y| *y); -} - -#[derive(Copy, Clone)] -struct UnusualDeref; -static NINE: i32 = 9; - -impl Deref for UnusualDeref { - type Target = i32; - fn deref(&self) -> &i32 { &NINE } -} - -fn map_clone_deref() { - let x = Some(UnusualDeref); - let _: Option = x.as_ref().map(|y| *y); - - - // Not linted: using deref conversion - let _: Option = x.map(|y| *y); - - // Not linted: using regular deref but also deref conversion - let _: Option = x.as_ref().map(|y| **y); -} - -// stuff that used to be a false positive -fn former_false_positive() { - vec![1].iter_mut().map(|x| *x); // #443 -} - -fn main() { } diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr deleted file mode 100644 index afad65b00710..000000000000 --- a/tests/ui/map_clone.stderr +++ /dev/null @@ -1,102 +0,0 @@ -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:12:5 - | -12 | x.iter().map(|y| y.clone()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::map-clone` implied by `-D warnings` - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:14:5 - | -14 | x.iter().map(|&y| y); - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:16:5 - | -16 | x.iter().map(|y| *y); - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:18:5 - | -18 | x.iter().map(|y| { y.clone() }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:20:5 - | -20 | x.iter().map(|&y| { y }); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:22:5 - | -22 | x.iter().map(|y| { *y }); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an iterator, consider using `.cloned()` - --> $DIR/map_clone.rs:24:5 - | -24 | x.iter().map(Clone::clone); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.iter().cloned() - -error: you seem to be using .map() to clone the contents of an Option, consider using `.cloned()` - --> $DIR/map_clone.rs:30:5 - | -30 | x.as_ref().map(|y| y.clone()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.as_ref().cloned() - -error: you seem to be using .map() to clone the contents of an Option, consider using `.cloned()` - --> $DIR/map_clone.rs:32:5 - | -32 | x.as_ref().map(|&y| y); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.as_ref().cloned() - -error: you seem to be using .map() to clone the contents of an Option, consider using `.cloned()` - --> $DIR/map_clone.rs:34:5 - | -34 | x.as_ref().map(|y| *y); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.as_ref().cloned() - -error: you seem to be using .map() to clone the contents of an Option, consider using `.cloned()` - --> $DIR/map_clone.rs:90:35 - | -90 | let _: Option = x.as_ref().map(|y| *y); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try - x.as_ref().cloned() - -error: aborting due to 11 previous errors - From b36bb0a68d70f091dd03f209f41b614ff1f015d0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 2 Oct 2018 15:13:43 +0200 Subject: [PATCH 03/11] Reimplement the `map_clone` lint from scratch --- CHANGELOG.md | 2 - README.md | 2 +- clippy_lints/src/lib.rs | 4 ++ clippy_lints/src/map_clone.rs | 100 ++++++++++++++++++++++++++++++++++ tests/ui/map_clone.rs | 9 +++ tests/ui/map_clone.stderr | 22 ++++++++ 6 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 clippy_lints/src/map_clone.rs create mode 100644 tests/ui/map_clone.rs create mode 100644 tests/ui/map_clone.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index c9bea1e8ef5e..013a508cc76e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -688,8 +688,6 @@ 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 -[`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 diff --git a/README.md b/README.md index 40ece34c6faf..a2b61703a820 100644 --- a/README.md +++ b/README.md @@ -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 279 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) +[There are 277 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: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 689dbfa7da96..8b1b626be443 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -129,6 +129,7 @@ pub mod let_if_seq; pub mod lifetimes; pub mod literal_representation; pub mod loops; +pub mod map_clone; pub mod map_unit_fn; pub mod matches; pub mod mem_forget; @@ -327,6 +328,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box strings::StringAdd); reg.register_early_lint_pass(box returns::ReturnPass); reg.register_late_lint_pass(box methods::Pass); + reg.register_late_lint_pass(box map_clone::Pass); reg.register_late_lint_pass(box shadow::Pass); reg.register_late_lint_pass(box types::LetPass); reg.register_late_lint_pass(box types::UnitCmp); @@ -583,6 +585,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::WHILE_IMMUTABLE_CONDITION, loops::WHILE_LET_LOOP, loops::WHILE_LET_ON_ITERATOR, + map_clone::MAP_CLONE, map_unit_fn::OPTION_MAP_UNIT_FN, map_unit_fn::RESULT_MAP_UNIT_FN, matches::MATCH_AS_REF, @@ -742,6 +745,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::FOR_KV_MAP, loops::NEEDLESS_RANGE_LOOP, loops::WHILE_LET_ON_ITERATOR, + map_clone::MAP_CLONE, matches::MATCH_BOOL, matches::MATCH_OVERLAPPING_ARM, matches::MATCH_REF_PATS, diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs new file mode 100644 index 000000000000..ddbb55a26fff --- /dev/null +++ b/clippy_lints/src/map_clone.rs @@ -0,0 +1,100 @@ +use crate::rustc::hir; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::syntax::source_map::Span; +use crate::utils::paths; +use crate::utils::{ + in_macro, match_trait_method, match_type, + remove_blocks, snippet, + span_lint_and_sugg, +}; +use if_chain::if_chain; +use crate::syntax::ast::Ident; + +#[derive(Clone)] +pub struct Pass; + +/// **What it does:** Checks for usage of `iterator.map(|x| x.clone())` and suggests +/// `iterator.cloned()` instead +/// +/// **Why is this bad?** Readability, this can be written more concisely +/// +/// **Known problems:** None. +/// +/// **Example:** +/// +/// ```rust +/// let x = vec![42, 43]; +/// let y = x.iter(); +/// let z = y.map(|i| *i); +/// ``` +/// +/// The correct use would be: +/// +/// ```rust +/// let x = vec![42, 43]; +/// let y = x.iter(); +/// let z = y.cloned(); +/// ``` +declare_clippy_lint! { + pub MAP_CLONE, + style, + "using `iterator.map(|x| x.clone())`, or dereferencing closures for `Copy` types" +} + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(MAP_CLONE) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr) { + if in_macro(e.span) { + return; + } + + if_chain! { + if let hir::ExprKind::MethodCall(ref method, _, ref args) = e.node; + if args.len() == 2; + if method.ident.as_str() == "map"; + let ty = cx.tables.expr_ty(&args[0]); + if match_type(cx, ty, &paths::OPTION) || match_trait_method(cx, e, &paths::ITERATOR); + if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].node; + let closure_body = cx.tcx.hir.body(body_id); + let closure_expr = remove_blocks(&closure_body.value); + then { + match closure_body.arguments[0].pat.node { + hir::PatKind::Ref(ref inner, _) => if let hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) = inner.node { + lint(cx, e.span, args[0].span, name, closure_expr); + }, + hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => match closure_expr.node { + hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => lint(cx, e.span, args[0].span, name, inner), + hir::ExprKind::MethodCall(ref method, _, ref obj) => if method.ident.as_str() == "clone" { + if match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) { + lint(cx, e.span, args[0].span, name, &obj[0]); + } + } + _ => {}, + }, + _ => {}, + } + } + } + } +} + +fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, name: Ident, path: &hir::Expr) { + if let hir::ExprKind::Path(hir::QPath::Resolved(None, ref path)) = path.node { + if path.segments.len() == 1 && path.segments[0].ident == name { + span_lint_and_sugg( + cx, + MAP_CLONE, + replace, + "You are using an explicit closure for cloning elements", + "Consider calling the dedicated `cloned` method", + format!("{}.cloned()", snippet(cx, root, "..")), + ) + } + } +} \ No newline at end of file diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs new file mode 100644 index 000000000000..11a5316a367e --- /dev/null +++ b/tests/ui/map_clone.rs @@ -0,0 +1,9 @@ +#![feature(tool_lints)] +#![warn(clippy::all, clippy::pedantic)] +#![allow(clippy::missing_docs_in_private_items)] + +fn main() { + let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); + let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); + let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); +} diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr new file mode 100644 index 000000000000..e80983cdbf7f --- /dev/null +++ b/tests/ui/map_clone.stderr @@ -0,0 +1,22 @@ +error: You are using an explicit closure for cloning elements + --> $DIR/map_clone.rs:6:22 + | +6 | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![5_i8; 6].iter().cloned()` + | + = note: `-D clippy::map-clone` implied by `-D warnings` + +error: You are using an explicit closure for cloning elements + --> $DIR/map_clone.rs:7:26 + | +7 | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` + +error: You are using an explicit closure for cloning elements + --> $DIR/map_clone.rs:8:23 + | +8 | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Consider calling the dedicated `cloned` method: `vec![42, 43].iter().cloned()` + +error: aborting due to 3 previous errors + From 696dc369df56e3a63ae7401959d0c1df0ff0296a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 2 Oct 2018 15:17:56 +0200 Subject: [PATCH 04/11] FIx dogfood --- clippy_lints/src/map_clone.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index ddbb55a26fff..5c733eb4f7a8 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -70,10 +70,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }, hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => match closure_expr.node { hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => lint(cx, e.span, args[0].span, name, inner), - hir::ExprKind::MethodCall(ref method, _, ref obj) => if method.ident.as_str() == "clone" { - if match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) { - lint(cx, e.span, args[0].span, name, &obj[0]); - } + hir::ExprKind::MethodCall(ref method, _, ref obj) => if method.ident.as_str() == "clone" && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) { + lint(cx, e.span, args[0].span, name, &obj[0]); } _ => {}, }, From 913a5c9b56d367e5a042a7159a8fd340d1709c51 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 2 Oct 2018 15:18:56 +0200 Subject: [PATCH 05/11] Trailing newline --- clippy_lints/src/map_clone.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 5c733eb4f7a8..e16a8af7641f 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -95,4 +95,4 @@ fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, name: Ident, path: ) } } -} \ No newline at end of file +} From f42272102a97e2f57e4d02c3a5a1defa3c800970 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 3 Oct 2018 12:02:06 +0200 Subject: [PATCH 06/11] Reimplement the `fn_to_numeric_cast` lint --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/types.rs | 45 +++++++++++++++++++++++++++++++ tests/ui/fn_to_numeric_cast.rs | 49 ++++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 tests/ui/fn_to_numeric_cast.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 013a508cc76e..2373cb87eedc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index a2b61703a820..f332a3f645d3 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8b1b626be443..b181a4c17caa 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -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, @@ -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, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index b98a0f882420..5d26e477c825 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -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 { @@ -913,6 +937,7 @@ impl LintPass for CastPass { CAST_LOSSLESS, UNNECESSARY_CAST, CAST_PTR_ALIGNMENT, + FN_TO_NUMERIC_CAST ) } } @@ -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 { @@ -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. /// diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs new file mode 100644 index 000000000000..d250af618473 --- /dev/null +++ b/tests/ui/fn_to_numeric_cast.rs @@ -0,0 +1,49 @@ +#![feature(tool_lints)] + +#[warn(clippy::fn_to_numeric_cast)] + +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() {} From 7adf24ebb04641941e47a0582e61461163f929f4 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 4 Oct 2018 18:09:09 +0200 Subject: [PATCH 07/11] Improve docs of fn_to_numeric_cast Closes #2980 --- clippy_lints/src/types.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 5d26e477c825..f39a26db5092 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -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** /// From c0ab8b2531f273f0ce93dc64df83d936fc505604 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 4 Oct 2018 21:44:16 +0200 Subject: [PATCH 08/11] Reimplement the `fn_to_numeric_cast_with_truncation` lint --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 2 + clippy_lints/src/types.rs | 40 ++++- tests/ui/fn_to_numeric_cast.rs | 2 +- tests/ui/fn_to_numeric_cast.stderr | 142 ++++++++++++++++++ .../ui/fn_to_numeric_cast_with_truncation.rs | 23 +++ .../fn_to_numeric_cast_with_truncation.stderr | 40 +++++ 8 files changed, 249 insertions(+), 3 deletions(-) create mode 100644 tests/ui/fn_to_numeric_cast.stderr create mode 100644 tests/ui/fn_to_numeric_cast_with_truncation.rs create mode 100644 tests/ui/fn_to_numeric_cast_with_truncation.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 2373cb87eedc..c9bea1e8ef5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index f332a3f645d3..40ece34c6faf 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b181a4c17caa..3779b09ecf33 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -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, @@ -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, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index f39a26db5092..d3aa8de825be 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -746,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 { @@ -1054,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, diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs index d250af618473..6d0fd3d8ab8e 100644 --- a/tests/ui/fn_to_numeric_cast.rs +++ b/tests/ui/fn_to_numeric_cast.rs @@ -1,6 +1,6 @@ #![feature(tool_lints)] -#[warn(clippy::fn_to_numeric_cast)] +#![warn(clippy::fn_to_numeric_cast)] fn foo() -> String { String::new() } diff --git a/tests/ui/fn_to_numeric_cast.stderr b/tests/ui/fn_to_numeric_cast.stderr new file mode 100644 index 000000000000..be8bc9058b4e --- /dev/null +++ b/tests/ui/fn_to_numeric_cast.stderr @@ -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 + diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.rs b/tests/ui/fn_to_numeric_cast_with_truncation.rs new file mode 100644 index 000000000000..82bbaec201f4 --- /dev/null +++ b/tests/ui/fn_to_numeric_cast_with_truncation.rs @@ -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? + // Running the tests on a different architechture will + // produce different results + let _ = foo as u64; + let _ = foo as i64; +} + +fn main() {} diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.stderr b/tests/ui/fn_to_numeric_cast_with_truncation.stderr new file mode 100644 index 000000000000..cae4b6fbd40a --- /dev/null +++ b/tests/ui/fn_to_numeric_cast_with_truncation.stderr @@ -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 + From 391d53db6657be45fb85835c3e042e2287035ece Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 4 Oct 2018 21:59:30 +0200 Subject: [PATCH 09/11] Add hidden lifetime parameters to fix warning --- clippy_lints/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index d3aa8de825be..a27bbb40e6ef 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1076,7 +1076,7 @@ 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) { +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"); From 8b3d2073fa8b1f48a27081944c1a7010a8d7b7b1 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 4 Oct 2018 22:26:54 +0200 Subject: [PATCH 10/11] Only run tests if pointer width is 64bit If the pointer width of the architechture is 32bit or something else, then the tests will most likely produce different results. --- .../ui/fn_to_numeric_cast_with_truncation.rs | 8 +++-- .../fn_to_numeric_cast_with_truncation.stderr | 32 +++++++++---------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.rs b/tests/ui/fn_to_numeric_cast_with_truncation.rs index 82bbaec201f4..4ebde4e8c1d5 100644 --- a/tests/ui/fn_to_numeric_cast_with_truncation.rs +++ b/tests/ui/fn_to_numeric_cast_with_truncation.rs @@ -1,3 +1,4 @@ +// only-64bit #![feature(tool_lints)] #![warn(clippy::fn_to_numeric_cast_with_truncation)] @@ -13,11 +14,12 @@ fn test_fn_to_numeric_cast_with_truncation() { let _ = foo as u16; let _ = foo as u32; - // TODO: Is it bad to have these tests? - // Running the tests on a different architechture will - // produce different results + // These should not lint, because because casting to these types + // does not truncate the function pointer address. let _ = foo as u64; let _ = foo as i64; + let _ = foo as u128; + let _ = foo as i128; } fn main() {} diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.stderr b/tests/ui/fn_to_numeric_cast_with_truncation.stderr index cae4b6fbd40a..65c996814ca5 100644 --- a/tests/ui/fn_to_numeric_cast_with_truncation.stderr +++ b/tests/ui/fn_to_numeric_cast_with_truncation.stderr @@ -1,39 +1,39 @@ 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` + --> $DIR/fn_to_numeric_cast_with_truncation.rs:10:13 + | +10 | 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 + --> $DIR/fn_to_numeric_cast_with_truncation.rs:11:13 | -10 | let _ = foo as i16; +11 | 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 + --> $DIR/fn_to_numeric_cast_with_truncation.rs:12:13 | -11 | let _ = foo as i32; +12 | 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 + --> $DIR/fn_to_numeric_cast_with_truncation.rs:13:13 | -12 | let _ = foo as u8; +13 | 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 + --> $DIR/fn_to_numeric_cast_with_truncation.rs:14:13 | -13 | let _ = foo as u16; +14 | 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 + --> $DIR/fn_to_numeric_cast_with_truncation.rs:15:13 | -14 | let _ = foo as u32; +15 | let _ = foo as u32; | ^^^^^^^^^^ help: try: `foo as usize` error: aborting due to 6 previous errors From 8407957ec64b94740f86d2079dc2d433f7f85e6a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 5 Oct 2018 07:49:08 +0200 Subject: [PATCH 11/11] Fix fn_to_numeric_cast UI tests This collapses both lint tests into one file. Somehow allowing the other lint in the respective files did not work correctly. Maybe that's fixed as part of fixing #3198. --- tests/ui/fn_to_numeric_cast.rs | 3 +- tests/ui/fn_to_numeric_cast.stderr | 126 +++++++++--------- .../ui/fn_to_numeric_cast_with_truncation.rs | 25 ---- .../fn_to_numeric_cast_with_truncation.stderr | 40 ------ 4 files changed, 66 insertions(+), 128 deletions(-) delete mode 100644 tests/ui/fn_to_numeric_cast_with_truncation.rs delete mode 100644 tests/ui/fn_to_numeric_cast_with_truncation.stderr diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs index 6d0fd3d8ab8e..fc8aa19dcf03 100644 --- a/tests/ui/fn_to_numeric_cast.rs +++ b/tests/ui/fn_to_numeric_cast.rs @@ -1,6 +1,7 @@ +// only-64bit #![feature(tool_lints)] -#![warn(clippy::fn_to_numeric_cast)] +#![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)] fn foo() -> String { String::new() } diff --git a/tests/ui/fn_to_numeric_cast.stderr b/tests/ui/fn_to_numeric_cast.stderr index be8bc9058b4e..29320f0d8ed8 100644 --- a/tests/ui/fn_to_numeric_cast.stderr +++ b/tests/ui/fn_to_numeric_cast.stderr @@ -1,141 +1,143 @@ -error: casting function pointer `foo` to `i8` - --> $DIR/fn_to_numeric_cast.rs:8:13 +error: casting function pointer `foo` to `i8`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:9:13 | -8 | let _ = foo as i8; +9 | let _ = foo as i8; | ^^^^^^^^^ help: try: `foo as usize` | - = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` + = note: `-D clippy::fn-to-numeric-cast-with-truncation` 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` +error: casting function pointer `foo` to `i16`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:10:13 | -10 | let _ = foo as i32; +10 | let _ = foo as i16; | ^^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `foo` to `i64` +error: casting function pointer `foo` to `i32`, which truncates the value --> $DIR/fn_to_numeric_cast.rs:11:13 | -11 | let _ = foo as i64; +11 | let _ = foo as i32; | ^^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `foo` to `i128` +error: casting function pointer `foo` to `i64` --> $DIR/fn_to_numeric_cast.rs:12:13 | -12 | let _ = foo as i128; +12 | let _ = foo as i64; + | ^^^^^^^^^^ help: try: `foo as usize` + | + = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` + +error: casting function pointer `foo` to `i128` + --> $DIR/fn_to_numeric_cast.rs:13:13 + | +13 | let _ = foo as i128; | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `isize` - --> $DIR/fn_to_numeric_cast.rs:13:13 + --> $DIR/fn_to_numeric_cast.rs:14:13 | -13 | let _ = foo as isize; +14 | let _ = foo as isize; | ^^^^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `foo` to `u8` - --> $DIR/fn_to_numeric_cast.rs:15:13 +error: casting function pointer `foo` to `u8`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:16:13 | -15 | let _ = foo as u8; +16 | let _ = foo as u8; | ^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `foo` to `u16` - --> $DIR/fn_to_numeric_cast.rs:16:13 +error: casting function pointer `foo` to `u16`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:17:13 | -16 | let _ = foo as u16; +17 | let _ = foo as u16; | ^^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `foo` to `u32` - --> $DIR/fn_to_numeric_cast.rs:17:13 +error: casting function pointer `foo` to `u32`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:18:13 | -17 | let _ = foo as u32; +18 | let _ = foo as u32; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u64` - --> $DIR/fn_to_numeric_cast.rs:18:13 + --> $DIR/fn_to_numeric_cast.rs:19:13 | -18 | let _ = foo as u64; +19 | let _ = foo as u64; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u128` - --> $DIR/fn_to_numeric_cast.rs:19:13 + --> $DIR/fn_to_numeric_cast.rs:20:13 | -19 | let _ = foo as u128; +20 | let _ = foo as u128; | ^^^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `abc` to `i8` - --> $DIR/fn_to_numeric_cast.rs:28:13 +error: casting function pointer `abc` to `i8`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:29:13 | -28 | let _ = abc as i8; +29 | let _ = abc as i8; | ^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `abc` to `i16` - --> $DIR/fn_to_numeric_cast.rs:29:13 +error: casting function pointer `abc` to `i16`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:30:13 | -29 | let _ = abc as i16; +30 | let _ = abc as i16; | ^^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `abc` to `i32` - --> $DIR/fn_to_numeric_cast.rs:30:13 +error: casting function pointer `abc` to `i32`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:31:13 | -30 | let _ = abc as i32; +31 | let _ = abc as i32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i64` - --> $DIR/fn_to_numeric_cast.rs:31:13 + --> $DIR/fn_to_numeric_cast.rs:32:13 | -31 | let _ = abc as i64; +32 | let _ = abc as i64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i128` - --> $DIR/fn_to_numeric_cast.rs:32:13 + --> $DIR/fn_to_numeric_cast.rs:33:13 | -32 | let _ = abc as i128; +33 | let _ = abc as i128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `isize` - --> $DIR/fn_to_numeric_cast.rs:33:13 + --> $DIR/fn_to_numeric_cast.rs:34:13 | -33 | let _ = abc as isize; +34 | let _ = abc as isize; | ^^^^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `abc` to `u8` - --> $DIR/fn_to_numeric_cast.rs:35:13 +error: casting function pointer `abc` to `u8`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:36:13 | -35 | let _ = abc as u8; +36 | let _ = abc as u8; | ^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `abc` to `u16` - --> $DIR/fn_to_numeric_cast.rs:36:13 +error: casting function pointer `abc` to `u16`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:37:13 | -36 | let _ = abc as u16; +37 | let _ = abc as u16; | ^^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `abc` to `u32` - --> $DIR/fn_to_numeric_cast.rs:37:13 +error: casting function pointer `abc` to `u32`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:38:13 | -37 | let _ = abc as u32; +38 | let _ = abc as u32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u64` - --> $DIR/fn_to_numeric_cast.rs:38:13 + --> $DIR/fn_to_numeric_cast.rs:39:13 | -38 | let _ = abc as u64; +39 | let _ = abc as u64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u128` - --> $DIR/fn_to_numeric_cast.rs:39:13 + --> $DIR/fn_to_numeric_cast.rs:40:13 | -39 | let _ = abc as u128; +40 | let _ = abc as u128; | ^^^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `f` to `i32` - --> $DIR/fn_to_numeric_cast.rs:46:5 +error: casting function pointer `f` to `i32`, which truncates the value + --> $DIR/fn_to_numeric_cast.rs:47:5 | -46 | f as i32 +47 | f as i32 | ^^^^^^^^ help: try: `f as usize` error: aborting due to 23 previous errors diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.rs b/tests/ui/fn_to_numeric_cast_with_truncation.rs deleted file mode 100644 index 4ebde4e8c1d5..000000000000 --- a/tests/ui/fn_to_numeric_cast_with_truncation.rs +++ /dev/null @@ -1,25 +0,0 @@ -// only-64bit -#![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; - - // These should not lint, because because casting to these types - // does not truncate the function pointer address. - let _ = foo as u64; - let _ = foo as i64; - let _ = foo as u128; - let _ = foo as i128; -} - -fn main() {} diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.stderr b/tests/ui/fn_to_numeric_cast_with_truncation.stderr deleted file mode 100644 index 65c996814ca5..000000000000 --- a/tests/ui/fn_to_numeric_cast_with_truncation.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error: casting function pointer `foo` to `i8`, which truncates the value - --> $DIR/fn_to_numeric_cast_with_truncation.rs:10:13 - | -10 | 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:11:13 - | -11 | 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:12:13 - | -12 | 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:13:13 - | -13 | 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:14:13 - | -14 | 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:15:13 - | -15 | let _ = foo as u32; - | ^^^^^^^^^^ help: try: `foo as usize` - -error: aborting due to 6 previous errors -