From df4d42fc2debf7a7d43226c79480c71037be42b8 Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Tue, 18 Aug 2020 01:00:11 +0200 Subject: [PATCH 1/2] transmute: avoid suggesting from/to bits in const --- clippy_lints/src/transmute.rs | 10 +++-- tests/ui/transmute.rs | 15 ++++++-- tests/ui/transmute.stderr | 52 +++++++++++++------------- tests/ui/transmute_float_to_int.rs | 11 +++++- tests/ui/transmute_float_to_int.stderr | 12 +++--- 5 files changed, 61 insertions(+), 39 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 28fd55f6ff0a..1d238b242b05 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,5 +1,5 @@ use crate::utils::{ - is_normalizable, last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_sugg, + in_constant, is_normalizable, last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_sugg, span_lint_and_then, sugg, }; use if_chain::if_chain; @@ -331,6 +331,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::TRANSMUTE); then { + // Avoid suggesting f32::(from|to)_bits in const contexts. + // See https://github.com/rust-lang/rust/issues/73736 for progress on making them `const fn`. + let const_context = in_constant(cx, e.hir_id); + let from_ty = cx.typeck_results().expr_ty(&args[0]); let to_ty = cx.typeck_results().expr_ty(e); @@ -544,7 +548,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { }, ) }, - (ty::Int(_) | ty::Uint(_), ty::Float(_)) => span_lint_and_then( + (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context => span_lint_and_then( cx, TRANSMUTE_INT_TO_FLOAT, e.span, @@ -567,7 +571,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { ); }, ), - (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) => span_lint_and_then( + (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) if !const_context => span_lint_and_then( cx, TRANSMUTE_FLOAT_TO_INT, e.span, diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index bb853d237047..7caad34edb3a 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -1,3 +1,4 @@ +#![feature(const_fn_transmute)] #![allow(dead_code)] extern crate core; @@ -81,9 +82,17 @@ fn int_to_bool() { } #[warn(clippy::transmute_int_to_float)] -fn int_to_float() { - let _: f32 = unsafe { std::mem::transmute(0_u32) }; - let _: f32 = unsafe { std::mem::transmute(0_i32) }; +mod int_to_float { + fn test() { + let _: f32 = unsafe { std::mem::transmute(0_u32) }; + let _: f32 = unsafe { std::mem::transmute(0_i32) }; + } + + // See issue #5747 + const VALUE: f32 = unsafe { std::mem::transmute(0_u32) }; + const fn from_bits(v: u32) -> f32 { + unsafe { std::mem::transmute(v) } + } } fn bytes_to_str(b: &[u8], mb: &mut [u8]) { diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index 8582080498f3..d817c08b52fe 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -1,5 +1,5 @@ error: transmute from a type (`&T`) to itself - --> $DIR/transmute.rs:19:20 + --> $DIR/transmute.rs:20:20 | LL | let _: &'a T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,67 +7,67 @@ LL | let _: &'a T = core::intrinsics::transmute(t); = note: `-D clippy::useless-transmute` implied by `-D warnings` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:23:23 + --> $DIR/transmute.rs:24:23 | LL | let _: *const T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:25:21 + --> $DIR/transmute.rs:26:21 | LL | let _: *mut T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:27:23 + --> $DIR/transmute.rs:28:23 | LL | let _: *const U = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U` error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:33:27 + --> $DIR/transmute.rs:34:27 | LL | let _: Vec = core::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:35:27 + --> $DIR/transmute.rs:36:27 | LL | let _: Vec = core::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:37:27 + --> $DIR/transmute.rs:38:27 | LL | let _: Vec = std::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:39:27 + --> $DIR/transmute.rs:40:27 | LL | let _: Vec = std::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:41:27 + --> $DIR/transmute.rs:42:27 | LL | let _: Vec = my_transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^ error: transmute from an integer to a pointer - --> $DIR/transmute.rs:43:31 + --> $DIR/transmute.rs:44:31 | LL | let _: *const usize = std::mem::transmute(5_isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize` error: transmute from an integer to a pointer - --> $DIR/transmute.rs:47:31 + --> $DIR/transmute.rs:48:31 | LL | let _: *const usize = std::mem::transmute(1 + 1usize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize` error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:62:24 + --> $DIR/transmute.rs:63:24 | LL | let _: Usize = core::intrinsics::transmute(int_const_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -75,25 +75,25 @@ LL | let _: Usize = core::intrinsics::transmute(int_const_ptr); = note: `-D clippy::crosspointer-transmute` implied by `-D warnings` error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:64:24 + --> $DIR/transmute.rs:65:24 | LL | let _: Usize = core::intrinsics::transmute(int_mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`) - --> $DIR/transmute.rs:66:31 + --> $DIR/transmute.rs:67:31 | LL | let _: *const Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) - --> $DIR/transmute.rs:68:29 + --> $DIR/transmute.rs:69:29 | LL | let _: *mut Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a `u32` to a `char` - --> $DIR/transmute.rs:74:28 + --> $DIR/transmute.rs:75:28 | LL | let _: char = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` @@ -101,13 +101,13 @@ LL | let _: char = unsafe { std::mem::transmute(0_u32) }; = note: `-D clippy::transmute-int-to-char` implied by `-D warnings` error: transmute from a `i32` to a `char` - --> $DIR/transmute.rs:75:28 + --> $DIR/transmute.rs:76:28 | LL | let _: char = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` error: transmute from a `u8` to a `bool` - --> $DIR/transmute.rs:80:28 + --> $DIR/transmute.rs:81:28 | LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` @@ -115,21 +115,21 @@ LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; = note: `-D clippy::transmute-int-to-bool` implied by `-D warnings` error: transmute from a `u32` to a `f32` - --> $DIR/transmute.rs:85:27 + --> $DIR/transmute.rs:87:31 | -LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` +LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` | = note: `-D clippy::transmute-int-to-float` implied by `-D warnings` error: transmute from a `i32` to a `f32` - --> $DIR/transmute.rs:86:27 + --> $DIR/transmute.rs:88:31 | -LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` +LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:90:28 + --> $DIR/transmute.rs:99:28 | LL | let _: &str = unsafe { std::mem::transmute(b) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` @@ -137,7 +137,7 @@ LL | let _: &str = unsafe { std::mem::transmute(b) }; = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:91:32 + --> $DIR/transmute.rs:100:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` diff --git a/tests/ui/transmute_float_to_int.rs b/tests/ui/transmute_float_to_int.rs index ce942751ada8..8173944d9591 100644 --- a/tests/ui/transmute_float_to_int.rs +++ b/tests/ui/transmute_float_to_int.rs @@ -1,4 +1,5 @@ -#[warn(clippy::transmute_float_to_int)] +#![feature(const_fn_transmute)] +#![warn(clippy::transmute_float_to_int)] fn float_to_int() { let _: u32 = unsafe { std::mem::transmute(1f32) }; @@ -9,4 +10,12 @@ fn float_to_int() { let _: u64 = unsafe { std::mem::transmute(-1.0) }; } +mod issue_5747 { + const VALUE: u32 = unsafe { std::mem::transmute(1f32) }; + + const fn to_bits(v: f32) -> u32 { + unsafe { std::mem::transmute(v) } + } +} + fn main() {} diff --git a/tests/ui/transmute_float_to_int.stderr b/tests/ui/transmute_float_to_int.stderr index eb786bb39f95..5a40cf381d61 100644 --- a/tests/ui/transmute_float_to_int.stderr +++ b/tests/ui/transmute_float_to_int.stderr @@ -1,5 +1,5 @@ error: transmute from a `f32` to a `u32` - --> $DIR/transmute_float_to_int.rs:4:27 + --> $DIR/transmute_float_to_int.rs:5:27 | LL | let _: u32 = unsafe { std::mem::transmute(1f32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits()` @@ -7,31 +7,31 @@ LL | let _: u32 = unsafe { std::mem::transmute(1f32) }; = note: `-D clippy::transmute-float-to-int` implied by `-D warnings` error: transmute from a `f32` to a `i32` - --> $DIR/transmute_float_to_int.rs:5:27 + --> $DIR/transmute_float_to_int.rs:6:27 | LL | let _: i32 = unsafe { std::mem::transmute(1f32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits() as i32` error: transmute from a `f64` to a `u64` - --> $DIR/transmute_float_to_int.rs:6:27 + --> $DIR/transmute_float_to_int.rs:7:27 | LL | let _: u64 = unsafe { std::mem::transmute(1f64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()` error: transmute from a `f64` to a `i64` - --> $DIR/transmute_float_to_int.rs:7:27 + --> $DIR/transmute_float_to_int.rs:8:27 | LL | let _: i64 = unsafe { std::mem::transmute(1f64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits() as i64` error: transmute from a `f64` to a `u64` - --> $DIR/transmute_float_to_int.rs:8:27 + --> $DIR/transmute_float_to_int.rs:9:27 | LL | let _: u64 = unsafe { std::mem::transmute(1.0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1.0f64.to_bits()` error: transmute from a `f64` to a `u64` - --> $DIR/transmute_float_to_int.rs:9:27 + --> $DIR/transmute_float_to_int.rs:10:27 | LL | let _: u64 = unsafe { std::mem::transmute(-1.0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-1.0f64).to_bits()` From 6a12bae1941bdef7c2716ffefed5594e5d7e9f8e Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Tue, 18 Aug 2020 22:19:30 +0200 Subject: [PATCH 2/2] no from/to bits in const: add tests cases for f64 --- clippy_lints/src/transmute.rs | 2 +- tests/ui/transmute.rs | 17 +++++++++++++---- tests/ui/transmute.stderr | 18 +++++++++++++++--- tests/ui/transmute_float_to_int.rs | 9 +++++++-- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 1d238b242b05..50d9c93f9d40 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -331,7 +331,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::TRANSMUTE); then { - // Avoid suggesting f32::(from|to)_bits in const contexts. + // Avoid suggesting from/to bits in const contexts. // See https://github.com/rust-lang/rust/issues/73736 for progress on making them `const fn`. let const_context = in_constant(cx, e.hir_id); diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 7caad34edb3a..9f1948359e7d 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -86,12 +86,21 @@ mod int_to_float { fn test() { let _: f32 = unsafe { std::mem::transmute(0_u32) }; let _: f32 = unsafe { std::mem::transmute(0_i32) }; + let _: f64 = unsafe { std::mem::transmute(0_u64) }; + let _: f64 = unsafe { std::mem::transmute(0_i64) }; } - // See issue #5747 - const VALUE: f32 = unsafe { std::mem::transmute(0_u32) }; - const fn from_bits(v: u32) -> f32 { - unsafe { std::mem::transmute(v) } + mod issue_5747 { + const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) }; + const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) }; + + const fn from_bits_32(v: i32) -> f32 { + unsafe { std::mem::transmute(v) } + } + + const fn from_bits_64(v: u64) -> f64 { + unsafe { std::mem::transmute(v) } + } } } diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index d817c08b52fe..ad9953d12bcc 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -128,8 +128,20 @@ error: transmute from a `i32` to a `f32` LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` +error: transmute from a `u64` to a `f64` + --> $DIR/transmute.rs:89:31 + | +LL | let _: f64 = unsafe { std::mem::transmute(0_u64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_u64)` + +error: transmute from a `i64` to a `f64` + --> $DIR/transmute.rs:90:31 + | +LL | let _: f64 = unsafe { std::mem::transmute(0_i64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)` + error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:99:28 + --> $DIR/transmute.rs:108:28 | LL | let _: &str = unsafe { std::mem::transmute(b) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` @@ -137,10 +149,10 @@ LL | let _: &str = unsafe { std::mem::transmute(b) }; = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:100:32 + --> $DIR/transmute.rs:109:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` -error: aborting due to 22 previous errors +error: aborting due to 24 previous errors diff --git a/tests/ui/transmute_float_to_int.rs b/tests/ui/transmute_float_to_int.rs index 8173944d9591..1040fee4b34d 100644 --- a/tests/ui/transmute_float_to_int.rs +++ b/tests/ui/transmute_float_to_int.rs @@ -11,9 +11,14 @@ fn float_to_int() { } mod issue_5747 { - const VALUE: u32 = unsafe { std::mem::transmute(1f32) }; + const VALUE32: i32 = unsafe { std::mem::transmute(1f32) }; + const VALUE64: u64 = unsafe { std::mem::transmute(1f64) }; - const fn to_bits(v: f32) -> u32 { + const fn to_bits_32(v: f32) -> u32 { + unsafe { std::mem::transmute(v) } + } + + const fn to_bits_64(v: f64) -> i64 { unsafe { std::mem::transmute(v) } } }