mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 15:14:29 +00:00
Add lints transmute_int_to_*
This commit is contained in:
parent
6f36f214a5
commit
47df717229
4 changed files with 165 additions and 1 deletions
|
@ -544,6 +544,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
|||
transmute::TRANSMUTE_PTR_TO_REF,
|
||||
transmute::USELESS_TRANSMUTE,
|
||||
transmute::WRONG_TRANSMUTE,
|
||||
transmute::TRANSMUTE_INT_TO_CHAR,
|
||||
transmute::TRANSMUTE_INT_TO_BOOL,
|
||||
transmute::TRANSMUTE_INT_TO_FLOAT,
|
||||
types::ABSURD_EXTREME_COMPARISONS,
|
||||
types::BORROWED_BOX,
|
||||
types::BOX_VEC,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use rustc::lint::*;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::hir::*;
|
||||
use std::borrow::Cow;
|
||||
use syntax::ast;
|
||||
use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then};
|
||||
use utils::{sugg, opt_def_id};
|
||||
|
||||
|
@ -76,11 +78,73 @@ declare_lint! {
|
|||
"transmutes from a pointer to a reference type"
|
||||
}
|
||||
|
||||
/// **What it does:** Checks for transmutes from an integer to a `char`.
|
||||
///
|
||||
/// **Why is this bad?** Not every integer is a unicode scalar value.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
/// let _: char = std::mem::transmute(x); // where x: u32
|
||||
/// // should be:
|
||||
/// let _: Option<char> = std::char::from_u32(x);
|
||||
/// ```
|
||||
declare_lint! {
|
||||
pub TRANSMUTE_INT_TO_CHAR,
|
||||
Warn,
|
||||
"transmutes from an integer to a `char`"
|
||||
}
|
||||
|
||||
/// **What it does:** Checks for transmutes from an integer to a `bool`.
|
||||
///
|
||||
/// **Why is this bad?** This might result in an invalid in-memory representation of a `bool`.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
/// let _: bool = std::mem::transmute(x); // where x: u8
|
||||
/// // should be:
|
||||
/// let _: bool = x != 0;
|
||||
/// ```
|
||||
declare_lint! {
|
||||
pub TRANSMUTE_INT_TO_BOOL,
|
||||
Warn,
|
||||
"transmutes from an integer to a `bool`"
|
||||
}
|
||||
|
||||
/// **What it does:** Checks for transmutes from an integer to a float.
|
||||
///
|
||||
/// **Why is this bad?** This might result in an invalid in-memory representation of a float.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
/// let _: f32 = std::mem::transmute(x); // where x: u32
|
||||
/// // should be:
|
||||
/// let _: f32 = f32::from_bits(x);
|
||||
/// ```
|
||||
declare_lint! {
|
||||
pub TRANSMUTE_INT_TO_FLOAT,
|
||||
Warn,
|
||||
"transmutes from an integer to a float"
|
||||
}
|
||||
|
||||
pub struct Transmute;
|
||||
|
||||
impl LintPass for Transmute {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, USELESS_TRANSMUTE, WRONG_TRANSMUTE)
|
||||
lint_array!(
|
||||
CROSSPOINTER_TRANSMUTE,
|
||||
TRANSMUTE_PTR_TO_REF,
|
||||
USELESS_TRANSMUTE,
|
||||
WRONG_TRANSMUTE,
|
||||
TRANSMUTE_INT_TO_CHAR,
|
||||
TRANSMUTE_INT_TO_BOOL,
|
||||
TRANSMUTE_INT_TO_FLOAT
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,6 +241,50 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||
db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string());
|
||||
},
|
||||
),
|
||||
(&ty::TyInt(ast::IntTy::I32), &ty::TyChar) |
|
||||
(&ty::TyUint(ast::UintTy::U32), &ty::TyChar) => span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_INT_TO_CHAR,
|
||||
e.span,
|
||||
&format!("transmute from a `{}` to a `char`", from_ty),
|
||||
|db| {
|
||||
let arg = sugg::Sugg::hir(cx, &args[0], "..");
|
||||
let arg = if let ty::TyInt(_) = from_ty.sty {
|
||||
arg.as_ty(ty::TyUint(ast::UintTy::U32))
|
||||
} else {
|
||||
arg
|
||||
};
|
||||
db.span_suggestion(e.span, "consider using", format!("std::char::from_u32({})", arg.to_string()));
|
||||
}
|
||||
),
|
||||
(&ty::TyInt(ast::IntTy::I8), &ty::TyBool) |
|
||||
(&ty::TyUint(ast::UintTy::U8), &ty::TyBool) => span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_INT_TO_BOOL,
|
||||
e.span,
|
||||
&format!("transmute from a `{}` to a `bool`", from_ty),
|
||||
|db| {
|
||||
let arg = sugg::Sugg::hir(cx, &args[0], "..");
|
||||
let zero = sugg::Sugg::NonParen(Cow::from("0"));
|
||||
db.span_suggestion(e.span, "consider using", sugg::make_binop(ast::BinOpKind::Ne, &arg, &zero).to_string());
|
||||
}
|
||||
),
|
||||
(&ty::TyInt(_), &ty::TyFloat(_)) |
|
||||
(&ty::TyUint(_), &ty::TyFloat(_)) => span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_INT_TO_FLOAT,
|
||||
e.span,
|
||||
&format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
|
||||
|db| {
|
||||
let arg = sugg::Sugg::hir(cx, &args[0], "..");
|
||||
let arg = if let ty::TyInt(int_ty) = from_ty.sty {
|
||||
arg.as_ty(format!("u{}", int_ty.bit_width().map_or_else(|| "size".to_string(), |v| v.to_string())))
|
||||
} else {
|
||||
arg
|
||||
};
|
||||
db.span_suggestion(e.span, "consider using", format!("{}::from_bits({})", to_ty, arg.to_string()));
|
||||
}
|
||||
),
|
||||
_ => return,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -118,4 +118,21 @@ fn crosspointer() {
|
|||
}
|
||||
}
|
||||
|
||||
#[warn(transmute_int_to_char)]
|
||||
fn int_to_char() {
|
||||
let _: char = unsafe { std::mem::transmute(0_u32) };
|
||||
let _: char = unsafe { std::mem::transmute(0_i32) };
|
||||
}
|
||||
|
||||
#[warn(transmute_int_to_bool)]
|
||||
fn int_to_bool() {
|
||||
let _: bool = unsafe { std::mem::transmute(0_u8) };
|
||||
}
|
||||
|
||||
#[warn(transmute_int_to_float)]
|
||||
fn int_to_float() {
|
||||
let _: f32 = unsafe { std::mem::transmute(0_u32) };
|
||||
let _: f32 = unsafe { std::mem::transmute(0_i32) };
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -154,3 +154,39 @@ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`)
|
|||
117 | let _: *mut Usize = core::intrinsics::transmute(my_int());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: transmute from a `u32` to a `char`
|
||||
--> $DIR/transmute.rs:123:28
|
||||
|
|
||||
123 | let _: char = unsafe { std::mem::transmute(0_u32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32)`
|
||||
|
|
||||
= note: `-D transmute-int-to-char` implied by `-D warnings`
|
||||
|
||||
error: transmute from a `i32` to a `char`
|
||||
--> $DIR/transmute.rs:124:28
|
||||
|
|
||||
124 | let _: char = unsafe { std::mem::transmute(0_i32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32)`
|
||||
|
||||
error: transmute from a `u8` to a `bool`
|
||||
--> $DIR/transmute.rs:129:28
|
||||
|
|
||||
129 | let _: bool = unsafe { std::mem::transmute(0_u8) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0`
|
||||
|
|
||||
= note: `-D transmute-int-to-bool` implied by `-D warnings`
|
||||
|
||||
error: transmute from a `u32` to a `f32`
|
||||
--> $DIR/transmute.rs:134:27
|
||||
|
|
||||
134 | let _: f32 = unsafe { std::mem::transmute(0_u32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
|
||||
|
|
||||
= note: `-D transmute-int-to-float` implied by `-D warnings`
|
||||
|
||||
error: transmute from a `i32` to a `f32`
|
||||
--> $DIR/transmute.rs:135:27
|
||||
|
|
||||
135 | let _: f32 = unsafe { std::mem::transmute(0_i32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)`
|
||||
|
||||
|
|
Loading…
Reference in a new issue