Skip to content

Commit f74dcaa

Browse files
committed
Fix wrong suggestion in TRANSMUTE_PTR_TO_REF with lts
1 parent 5f1120b commit f74dcaa

File tree

2 files changed

+47
-8
lines changed

2 files changed

+47
-8
lines changed

clippy_lints/src/transmute.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc::lint::*;
22
use rustc::ty::TypeVariants::{TyRawPtr, TyRef};
33
use rustc::ty;
44
use rustc::hir::*;
5-
use utils::{match_def_path, paths, span_lint, span_lint_and_then};
5+
use utils::{match_def_path, paths, span_lint, span_lint_and_then, snippet};
66
use utils::sugg;
77

88
/// **What it does:** Checks for transmutes that can't ever be correct on any
@@ -87,7 +87,7 @@ impl LintPass for Transmute {
8787
impl LateLintPass for Transmute {
8888
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
8989
if let ExprCall(ref path_expr, ref args) = e.node {
90-
if let ExprPath(None, _) = path_expr.node {
90+
if let ExprPath(None, ref path) = path_expr.node {
9191
let def_id = cx.tcx.expect_def(path_expr.id).def_id();
9292

9393
if match_def_path(cx, def_id, &paths::TRANSMUTE) {
@@ -170,11 +170,10 @@ impl LateLintPass for Transmute {
170170
("&*", "*const")
171171
};
172172

173-
174173
let arg = if from_pty.ty == to_rty.ty {
175174
arg
176175
} else {
177-
arg.as_ty(&format!("{} {}", cast, to_rty.ty))
176+
arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, path, to_rty.ty)))
178177
};
179178

180179
db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string());
@@ -187,3 +186,19 @@ impl LateLintPass for Transmute {
187186
}
188187
}
189188
}
189+
190+
/// Get the snippet of `Bar` in `…::transmute<Foo, &Bar>`. If that snippet is not available , use
191+
/// the type's `ToString` implementation. In weird cases it could lead to types with invalid `'_`
192+
/// lifetime, but it should be rare.
193+
fn get_type_snippet(cx: &LateContext, path: &Path, to_rty: ty::Ty) -> String {
194+
if_let_chain!{[
195+
let Some(seg) = path.segments.last(),
196+
let PathParameters::AngleBracketedParameters(ref ang) = seg.parameters,
197+
let Some(to_ty) = ang.types.get(1),
198+
let TyRptr(_, ref to_ty) = to_ty.node,
199+
], {
200+
return snippet(cx, to_ty.ty.span, &to_rty.to_string()).to_string();
201+
}}
202+
203+
to_rty.to_string()
204+
}

tests/compile-fail/transmute.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#![feature(plugin)]
22
#![plugin(clippy)]
33

4+
#![allow(dead_code)]
5+
46
extern crate core;
57

68
use std::mem::transmute as my_transmute;
@@ -83,6 +85,31 @@ unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) {
8385
let _: &T = &*(om as *const T);
8486
}
8587

88+
#[deny(transmute_ptr_to_ref)]
89+
fn issue1231() {
90+
struct Foo<'a, T: 'a> {
91+
bar: &'a T,
92+
}
93+
94+
let raw = 0 as *const i32;
95+
let _: &Foo<u8> = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) };
96+
//~^ ERROR transmute from a pointer type
97+
//~| HELP try
98+
//~| SUGGESTION unsafe { &*(raw as *const Foo<_>) };
99+
100+
let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) };
101+
//~^ ERROR transmute from a pointer type
102+
//~| HELP try
103+
//~| SUGGESTION unsafe { &*(raw as *const Foo<&_>) };
104+
105+
type Bar<'a> = &'a u8;
106+
let raw = 0 as *const i32;
107+
unsafe { std::mem::transmute::<_, Bar>(raw) };
108+
//~^ ERROR transmute from a pointer type
109+
//~| HELP try
110+
//~| SUGGESTION unsafe { &*(raw as *const u8) };
111+
}
112+
86113
#[deny(useless_transmute)]
87114
fn useless() {
88115
unsafe {
@@ -144,7 +171,4 @@ fn crosspointer() {
144171
}
145172
}
146173

147-
fn main() {
148-
useless();
149-
crosspointer();
150-
}
174+
fn main() { }

0 commit comments

Comments
 (0)