about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduardo Broto <ebroto@tutanota.com>2020-08-18 01:00:11 +0200
committerEduardo Broto <ebroto@tutanota.com>2020-08-18 21:55:56 +0200
commitdf4d42fc2debf7a7d43226c79480c71037be42b8 (patch)
tree7f417dc42b0a431e9bf72d12f06889f1a1ab5c3e
parent6220dff504b1ac1a949e34562db47fd058378f5d (diff)
downloadrust-df4d42fc2debf7a7d43226c79480c71037be42b8.tar.gz
rust-df4d42fc2debf7a7d43226c79480c71037be42b8.zip
transmute: avoid suggesting from/to bits in const
-rw-r--r--clippy_lints/src/transmute.rs10
-rw-r--r--tests/ui/transmute.rs15
-rw-r--r--tests/ui/transmute.stderr52
-rw-r--r--tests/ui/transmute_float_to_int.rs11
-rw-r--r--tests/ui/transmute_float_to_int.stderr12
5 files changed, 61 insertions, 39 deletions
diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs
index 28fd55f6ff0..1d238b242b0 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 bb853d23704..7caad34edb3 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 8582080498f..d817c08b52f 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<i32>`) to itself
-  --> $DIR/transmute.rs:33:27
+  --> $DIR/transmute.rs:34:27
    |
 LL |         let _: Vec<i32> = core::intrinsics::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> $DIR/transmute.rs:35:27
+  --> $DIR/transmute.rs:36:27
    |
 LL |         let _: Vec<i32> = core::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> $DIR/transmute.rs:37:27
+  --> $DIR/transmute.rs:38:27
    |
 LL |         let _: Vec<i32> = std::intrinsics::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> $DIR/transmute.rs:39:27
+  --> $DIR/transmute.rs:40:27
    |
 LL |         let _: Vec<i32> = std::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> $DIR/transmute.rs:41:27
+  --> $DIR/transmute.rs:42:27
    |
 LL |         let _: Vec<i32> = 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 ce942751ada..8173944d959 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 eb786bb39f9..5a40cf381d6 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()`