Lint transmute::<&[u8], &str>

This commit is contained in:
sinkuu 2017-10-29 10:27:45 +09:00
parent fcebd5ce0c
commit 7fa27d9387
3 changed files with 74 additions and 4 deletions

View File

@ -88,7 +88,7 @@ declare_lint! {
/// ```rust
/// let _: char = std::mem::transmute(x); // where x: u32
/// // should be:
/// let _: Option<char> = std::char::from_u32(x);
/// let _ = std::char::from_u32(x).unwrap();
/// ```
declare_lint! {
pub TRANSMUTE_INT_TO_CHAR,
@ -96,6 +96,24 @@ declare_lint! {
"transmutes from an integer to a `char`"
}
/// **What it does:** Checks for transmutes from a `&[u8] to a `&str`.
///
/// **Why is this bad?** Not every byte slice is a valid UTF-8 string.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let _: &str = std::mem::transmute(b); // where b: &[u8]
/// // should be:
/// let _ = std::str::from_utf8(b).unwrap();
/// ```
declare_lint! {
pub TRANSMUTE_BYTES_TO_STR,
Warn,
"transmutes from a `&[u8]` to a `&str`"
}
/// **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`.
@ -142,6 +160,7 @@ impl LintPass for Transmute {
USELESS_TRANSMUTE,
WRONG_TRANSMUTE,
TRANSMUTE_INT_TO_CHAR,
TRANSMUTE_BYTES_TO_STR,
TRANSMUTE_INT_TO_BOOL,
TRANSMUTE_INT_TO_FLOAT
)
@ -254,9 +273,41 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
} else {
arg
};
db.span_suggestion(e.span, "consider using", format!("std::char::from_u32({})", arg.to_string()));
db.span_suggestion(e.span, "consider using", format!("std::char::from_u32({}).unwrap()", arg.to_string()));
}
),
(&ty::TyRef(_, ref ref_from), &ty::TyRef(_, ref ref_to)) => {
if_chain! {
if let (&ty::TySlice(slice_ty), &ty::TyStr) = (&ref_from.ty.sty, &ref_to.ty.sty);
if let ty::TyUint(ast::UintTy::U8) = slice_ty.sty;
if ref_from.mutbl == ref_to.mutbl;
then {
let postfix = if ref_from.mutbl == Mutability::MutMutable {
"_mut"
} else {
""
};
span_lint_and_then(
cx,
TRANSMUTE_BYTES_TO_STR,
e.span,
&format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
|db| {
db.span_suggestion(
e.span,
"consider using",
format!(
"std::str::from_utf8{}({}).unwrap()",
postfix,
snippet(cx, args[0].span, ".."),
),
);
}
)
}
}
},
(&ty::TyInt(ast::IntTy::I8), &ty::TyBool) |
(&ty::TyUint(ast::UintTy::U8), &ty::TyBool) => span_lint_and_then(
cx,

View File

@ -135,4 +135,9 @@ fn int_to_float() {
let _: f32 = unsafe { std::mem::transmute(0_i32) };
}
fn bytes_to_str(b: &[u8], mb: &mut [u8]) {
let _: &str = unsafe { std::mem::transmute(b) };
let _: &mut str = unsafe { std::mem::transmute(mb) };
}
fn main() { }

View File

@ -158,7 +158,7 @@ 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)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()`
|
= note: `-D transmute-int-to-char` implied by `-D warnings`
@ -166,7 +166,7 @@ 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)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()`
error: transmute from a `u8` to a `bool`
--> $DIR/transmute.rs:129:28
@ -190,3 +190,17 @@ error: transmute from a `i32` to a `f32`
135 | 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:139:28
|
139 | let _: &str = unsafe { std::mem::transmute(b) };
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()`
|
= note: `-D transmute-bytes-to-str` implied by `-D warnings`
error: transmute from a `&mut [u8]` to a `&mut str`
--> $DIR/transmute.rs:140:32
|
140 | let _: &mut str = unsafe { std::mem::transmute(mb) };
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`