mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 22:41:50 +00:00
lint on unnecessary and plain wrong transmutes
This commit is contained in:
parent
5aea20da7f
commit
e06bc37477
@ -1,6 +1,9 @@
|
||||
# Change Log
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 0.0.78 - TBA
|
||||
* New lints: [`wrong_transmute`]
|
||||
|
||||
## 0.0.77 — 2016-06-21
|
||||
* Rustup to *rustc 1.11.0-nightly (5522e678b 2016-06-20)*
|
||||
* New lints: [`stutter`] and [`iter_nth`]
|
||||
@ -276,6 +279,7 @@ All notable changes to this project will be documented in this file.
|
||||
[`while_let_on_iterator`]: https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator
|
||||
[`wrong_pub_self_convention`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention
|
||||
[`wrong_self_convention`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention
|
||||
[`wrong_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_transmute
|
||||
[`zero_divided_by_zero`]: https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero
|
||||
[`zero_width_space`]: https://github.com/Manishearth/rust-clippy/wiki#zero_width_space
|
||||
<!-- end autogenerated links to wiki -->
|
||||
|
@ -17,7 +17,7 @@ Table of contents:
|
||||
|
||||
## Lints
|
||||
|
||||
There are 155 lints included in this crate:
|
||||
There are 156 lints included in this crate:
|
||||
|
||||
name | default | meaning
|
||||
---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -168,12 +168,13 @@ name
|
||||
[used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | allow | using a binding which is prefixed with an underscore
|
||||
[useless_format](https://github.com/Manishearth/rust-clippy/wiki#useless_format) | warn | useless use of `format!`
|
||||
[useless_let_if_seq](https://github.com/Manishearth/rust-clippy/wiki#useless_let_if_seq) | warn | Checks for unidiomatic `let mut` declaration followed by initialization in `if`
|
||||
[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types
|
||||
[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types or could be a cast/coercion
|
||||
[useless_vec](https://github.com/Manishearth/rust-clippy/wiki#useless_vec) | warn | useless `vec!`
|
||||
[while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop
|
||||
[while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator
|
||||
[wrong_pub_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_pub_self_convention) | allow | defining a public method named with an established prefix (like "into_") that takes `self` with the wrong convention
|
||||
[wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention) | warn | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention
|
||||
[wrong_transmute](https://github.com/Manishearth/rust-clippy/wiki#wrong_transmute) | warn | transmutes that are confusing at best, undefined behaviour at worst and always useless
|
||||
[zero_divided_by_zero](https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero) | warn | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN
|
||||
[zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space) | deny | using a zero-width space in a string literal, which is confusing
|
||||
|
||||
|
@ -403,6 +403,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
||||
transmute::CROSSPOINTER_TRANSMUTE,
|
||||
transmute::TRANSMUTE_PTR_TO_REF,
|
||||
transmute::USELESS_TRANSMUTE,
|
||||
transmute::WRONG_TRANSMUTE,
|
||||
types::ABSURD_EXTREME_COMPARISONS,
|
||||
types::BOX_VEC,
|
||||
types::CHAR_LIT_AS_U8,
|
||||
|
@ -1,11 +1,25 @@
|
||||
use rustc::lint::*;
|
||||
use rustc::ty::TypeVariants::{TyRawPtr, TyRef};
|
||||
use rustc::ty;
|
||||
use rustc::hir::*;
|
||||
use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then};
|
||||
|
||||
/// **What it does:** This lint checks for transmutes to the original type of the object.
|
||||
/// **What it does:** This lint checks for transmutes that can't ever be correct on any architecture
|
||||
///
|
||||
/// **Why is this bad?** Readability. The code tricks people into thinking that the original value was of some other type.
|
||||
/// **Why is this bad?** It's basically guaranteed to be undefined behaviour
|
||||
///
|
||||
/// **Known problems:** When accessing C, users might want to store pointer sized objects in `extradata` arguments to save an allocation.
|
||||
///
|
||||
/// **Example:** `let ptr: *const T = core::intrinsics::transmute('x')`.
|
||||
declare_lint! {
|
||||
pub WRONG_TRANSMUTE,
|
||||
Warn,
|
||||
"transmutes that are confusing at best, undefined behaviour at worst and always useless"
|
||||
}
|
||||
|
||||
/// **What it does:** This lint checks for transmutes to the original type of the object and transmutes that could be a cast.
|
||||
///
|
||||
/// **Why is this bad?** Readability. The code tricks people into thinking that something complex is going on
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
@ -13,7 +27,7 @@ use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then};
|
||||
declare_lint! {
|
||||
pub USELESS_TRANSMUTE,
|
||||
Warn,
|
||||
"transmutes that have the same to and from types"
|
||||
"transmutes that have the same to and from types or could be a cast/coercion"
|
||||
}
|
||||
|
||||
/// **What it does:*** This lint checks for transmutes between a type `T` and `*T`.
|
||||
@ -51,7 +65,7 @@ pub struct Transmute;
|
||||
|
||||
impl LintPass for Transmute {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array![CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, USELESS_TRANSMUTE]
|
||||
lint_array![CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, USELESS_TRANSMUTE, WRONG_TRANSMUTE]
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,6 +103,27 @@ impl LateLintPass for Transmute {
|
||||
}
|
||||
},
|
||||
),
|
||||
(&ty::TyInt(_), &TyRawPtr(_)) |
|
||||
(&ty::TyUint(_), &TyRawPtr(_)) => span_lint_and_then(
|
||||
cx,
|
||||
USELESS_TRANSMUTE,
|
||||
e.span,
|
||||
"transmute from an integer to a pointer",
|
||||
|db| {
|
||||
if let Some(arg) = snippet_opt(cx, args[0].span) {
|
||||
db.span_suggestion(e.span, "try", format!("{} as {}", arg, to_ty));
|
||||
}
|
||||
},
|
||||
),
|
||||
(&ty::TyFloat(_), &TyRef(..)) |
|
||||
(&ty::TyFloat(_), &TyRawPtr(_)) |
|
||||
(&ty::TyChar, &TyRef(..)) |
|
||||
(&ty::TyChar, &TyRawPtr(_)) => span_lint(
|
||||
cx,
|
||||
WRONG_TRANSMUTE,
|
||||
e.span,
|
||||
&format!("transmute from a `{}` to a pointer", from_ty),
|
||||
),
|
||||
(&TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint(
|
||||
cx,
|
||||
CROSSPOINTER_TRANSMUTE,
|
||||
|
@ -6,8 +6,8 @@ extern crate core;
|
||||
use std::mem::transmute as my_transmute;
|
||||
use std::vec::Vec as MyVec;
|
||||
|
||||
fn my_int() -> usize {
|
||||
42
|
||||
fn my_int() -> Usize {
|
||||
Usize(42)
|
||||
}
|
||||
|
||||
fn my_vec() -> MyVec<i32> {
|
||||
@ -100,27 +100,34 @@ fn useless() {
|
||||
let _: Vec<u32> = std::intrinsics::transmute(my_vec());
|
||||
let _: Vec<u32> = std::mem::transmute(my_vec());
|
||||
let _: Vec<u32> = my_transmute(my_vec());
|
||||
|
||||
let _: *const usize = std::mem::transmute(5_isize);
|
||||
//~^ ERROR transmute from an integer to a pointer
|
||||
//~| HELP try
|
||||
//~| SUGGESTION 5_isize as *const usize
|
||||
}
|
||||
}
|
||||
|
||||
struct Usize(usize);
|
||||
|
||||
#[deny(crosspointer_transmute)]
|
||||
fn crosspointer() {
|
||||
let mut int: usize = 0;
|
||||
let int_const_ptr: *const usize = &int as *const usize;
|
||||
let int_mut_ptr: *mut usize = &mut int as *mut usize;
|
||||
let mut int: Usize = Usize(0);
|
||||
let int_const_ptr: *const Usize = &int as *const Usize;
|
||||
let int_mut_ptr: *mut Usize = &mut int as *mut Usize;
|
||||
|
||||
unsafe {
|
||||
let _: usize = core::intrinsics::transmute(int_const_ptr);
|
||||
//~^ ERROR transmute from a type (`*const usize`) to the type that it points to (`usize`)
|
||||
let _: Usize = core::intrinsics::transmute(int_const_ptr);
|
||||
//~^ ERROR transmute from a type (`*const Usize`) to the type that it points to (`Usize`)
|
||||
|
||||
let _: usize = core::intrinsics::transmute(int_mut_ptr);
|
||||
//~^ ERROR transmute from a type (`*mut usize`) to the type that it points to (`usize`)
|
||||
let _: Usize = core::intrinsics::transmute(int_mut_ptr);
|
||||
//~^ ERROR transmute from a type (`*mut Usize`) to the type that it points to (`Usize`)
|
||||
|
||||
let _: *const usize = core::intrinsics::transmute(my_int());
|
||||
//~^ ERROR transmute from a type (`usize`) to a pointer to that type (`*const usize`)
|
||||
let _: *const Usize = core::intrinsics::transmute(my_int());
|
||||
//~^ ERROR transmute from a type (`Usize`) to a pointer to that type (`*const Usize`)
|
||||
|
||||
let _: *mut usize = core::intrinsics::transmute(my_int());
|
||||
//~^ ERROR transmute from a type (`usize`) to a pointer to that type (`*mut usize`)
|
||||
let _: *mut Usize = core::intrinsics::transmute(my_int());
|
||||
//~^ ERROR transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`)
|
||||
}
|
||||
}
|
||||
|
||||
|
20
tests/compile-fail/transmute_32bit.rs
Normal file
20
tests/compile-fail/transmute_32bit.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//ignore-x86_64
|
||||
#![feature(plugin)]
|
||||
#![plugin(clippy)]
|
||||
|
||||
#[deny(wrong_transmute)]
|
||||
fn main() {
|
||||
unsafe {
|
||||
let _: *const usize = std::mem::transmute(6.0f32);
|
||||
//~^ ERROR transmute from a `f32` to a pointer
|
||||
|
||||
let _: *mut usize = std::mem::transmute(6.0f32);
|
||||
//~^ ERROR transmute from a `f32` to a pointer
|
||||
|
||||
let _: *const usize = std::mem::transmute('x');
|
||||
//~^ ERROR transmute from a `char` to a pointer
|
||||
|
||||
let _: *mut usize = std::mem::transmute('x');
|
||||
//~^ ERROR transmute from a `char` to a pointer
|
||||
}
|
||||
}
|
15
tests/compile-fail/transmute_64bit.rs
Normal file
15
tests/compile-fail/transmute_64bit.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//ignore-x86
|
||||
//no-ignore-x86_64
|
||||
#![feature(plugin)]
|
||||
#![plugin(clippy)]
|
||||
|
||||
#[deny(wrong_transmute)]
|
||||
fn main() {
|
||||
unsafe {
|
||||
let _: *const usize = std::mem::transmute(6.0f64);
|
||||
//~^ ERROR transmute from a `f64` to a pointer
|
||||
|
||||
let _: *mut usize = std::mem::transmute(6.0f64);
|
||||
//~^ ERROR transmute from a `f64` to a pointer
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user