Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

transmute: avoid suggesting from/to bits in const #5919

Merged
merged 2 commits into from
Aug 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions clippy_lints/src/transmute.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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 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);

Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down
24 changes: 21 additions & 3 deletions tests/ui/transmute.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![feature(const_fn_transmute)]
#![allow(dead_code)]

extern crate core;
Expand Down Expand Up @@ -81,9 +82,26 @@ 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) };
let _: f64 = unsafe { std::mem::transmute(0_u64) };
let _: f64 = unsafe { std::mem::transmute(0_i64) };
}

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) }
}
}
}

fn bytes_to_str(b: &[u8], mb: &mut [u8]) {
Expand Down
66 changes: 39 additions & 27 deletions tests/ui/transmute.stderr
Original file line number Diff line number Diff line change
@@ -1,146 +1,158 @@
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);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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()`
|
= 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`
|
= 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)`

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 _: f32 = unsafe { std::mem::transmute(0_i32) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)`
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:90:28
--> $DIR/transmute.rs:108:28
|
LL | let _: &str = unsafe { std::mem::transmute(b) };
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()`
|
= 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: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

16 changes: 15 additions & 1 deletion tests/ui/transmute_float_to_int.rs
Original file line number Diff line number Diff line change
@@ -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) };
Expand All @@ -9,4 +10,17 @@ fn float_to_int() {
let _: u64 = unsafe { std::mem::transmute(-1.0) };
}

mod issue_5747 {
const VALUE32: i32 = unsafe { std::mem::transmute(1f32) };
const VALUE64: u64 = unsafe { std::mem::transmute(1f64) };

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) }
}
}

fn main() {}
12 changes: 6 additions & 6 deletions tests/ui/transmute_float_to_int.stderr
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
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()`
|
= 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()`
Expand Down