Skip to content

Commit 8f6e32d

Browse files
authored
Merge pull request #1045 from oli-obk/more_transmutes
lint transmuting references to pointer
2 parents 60cc87b + a469ee1 commit 8f6e32d

File tree

2 files changed

+79
-55
lines changed

2 files changed

+79
-55
lines changed

clippy_lints/src/transmute.rs

Lines changed: 64 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use rustc::lint::*;
22
use rustc::ty::TypeVariants::{TyRawPtr, TyRef};
3-
use rustc::ty;
43
use rustc::hir::*;
54
use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then};
65

@@ -66,66 +65,76 @@ impl LateLintPass for Transmute {
6665
let from_ty = cx.tcx.expr_ty(&args[0]);
6766
let to_ty = cx.tcx.expr_ty(e);
6867

69-
if from_ty == to_ty {
70-
span_lint(cx,
71-
USELESS_TRANSMUTE,
72-
e.span,
73-
&format!("transmute from a type (`{}`) to itself", from_ty));
74-
} else if is_ptr_to(to_ty, from_ty) {
75-
span_lint(cx,
76-
CROSSPOINTER_TRANSMUTE,
77-
e.span,
78-
&format!("transmute from a type (`{}`) to a pointer to that type (`{}`)",
79-
from_ty,
80-
to_ty));
81-
} else if is_ptr_to(from_ty, to_ty) {
82-
span_lint(cx,
83-
CROSSPOINTER_TRANSMUTE,
84-
e.span,
85-
&format!("transmute from a type (`{}`) to the type that it points to (`{}`)",
86-
from_ty,
87-
to_ty));
88-
} else {
89-
check_ptr_to_ref(cx, from_ty, to_ty, e, &args[0]);
90-
}
91-
}
92-
}
93-
}
94-
}
95-
}
68+
match (&from_ty.sty, &to_ty.sty) {
69+
_ if from_ty == to_ty => span_lint(
70+
cx,
71+
USELESS_TRANSMUTE,
72+
e.span,
73+
&format!("transmute from a type (`{}`) to itself", from_ty),
74+
),
75+
(&TyRef(_, rty), &TyRawPtr(ptr_ty)) => span_lint_and_then(
76+
cx,
77+
USELESS_TRANSMUTE,
78+
e.span,
79+
"transmute from a reference to a pointer",
80+
|db| {
81+
if let Some(arg) = snippet_opt(cx, args[0].span) {
82+
let sugg = if ptr_ty == rty {
83+
format!("{} as {}", arg, to_ty)
84+
} else {
85+
format!("{} as {} as {}", arg, cx.tcx.mk_ptr(rty), to_ty)
86+
};
9687

97-
fn is_ptr_to(from: ty::Ty, to: ty::Ty) -> bool {
98-
if let TyRawPtr(from_ptr) = from.sty {
99-
from_ptr.ty == to
100-
} else {
101-
false
102-
}
103-
}
88+
db.span_suggestion(e.span, "try", sugg);
89+
}
90+
},
91+
),
92+
(&TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint(
93+
cx,
94+
CROSSPOINTER_TRANSMUTE,
95+
e.span,
96+
&format!("transmute from a type (`{}`) to the type that it points to (`{}`)",
97+
from_ty,
98+
to_ty),
99+
),
100+
(_, &TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint(
101+
cx,
102+
CROSSPOINTER_TRANSMUTE,
103+
e.span,
104+
&format!("transmute from a type (`{}`) to a pointer to that type (`{}`)",
105+
from_ty,
106+
to_ty),
107+
),
108+
(&TyRawPtr(from_pty), &TyRef(_, to_rty)) => span_lint_and_then(
109+
cx,
110+
TRANSMUTE_PTR_TO_REF,
111+
e.span,
112+
&format!("transmute from a pointer type (`{}`) to a reference type (`{}`)",
113+
from_ty,
114+
to_ty),
115+
|db| {
116+
if let Some(arg) = snippet_opt(cx, args[0].span) {
117+
let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable {
118+
("&mut *", "*mut")
119+
} else {
120+
("&*", "*const")
121+
};
104122

105-
fn check_ptr_to_ref<'tcx>(cx: &LateContext, from_ty: ty::Ty<'tcx>, to_ty: ty::Ty<'tcx>, e: &Expr, arg: &Expr) {
106-
if let TyRawPtr(ref from_pty) = from_ty.sty {
107-
if let TyRef(_, ref to_rty) = to_ty.sty {
108-
let mess = format!("transmute from a pointer type (`{}`) to a reference type (`{}`)",
109-
from_ty,
110-
to_ty);
111-
span_lint_and_then(cx, TRANSMUTE_PTR_TO_REF, e.span, &mess, |db| {
112-
if let Some(arg) = snippet_opt(cx, arg.span) {
113-
let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable {
114-
("&mut *", "*mut")
115-
} else {
116-
("&*", "*const")
117-
};
118123

124+
let sugg = if from_pty.ty == to_rty.ty {
125+
format!("{}{}", deref, arg)
126+
} else {
127+
format!("{}({} as {} {})", deref, arg, cast, to_rty.ty)
128+
};
119129

120-
let sugg = if from_pty.ty == to_rty.ty {
121-
format!("{}{}", deref, arg)
122-
} else {
123-
format!("{}({} as {} {})", deref, arg, cast, to_rty.ty)
130+
db.span_suggestion(e.span, "try", sugg);
131+
}
132+
},
133+
),
134+
_ => return,
124135
};
125-
126-
db.span_suggestion(e.span, "try", sugg);
127136
}
128-
});
137+
}
129138
}
130139
}
131140
}

tests/compile-fail/transmute.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ unsafe fn _generic<'a, T, U: 'a>(t: &'a T) {
2121
//~^ ERROR transmute from a type (`&'a T`) to itself
2222

2323
let _: &'a U = core::intrinsics::transmute(t);
24+
25+
let _: *const T = core::intrinsics::transmute(t);
26+
//~^ ERROR transmute from a reference to a pointer
27+
//~| HELP try
28+
//~| SUGGESTION = t as *const T
29+
30+
let _: *mut T = core::intrinsics::transmute(t);
31+
//~^ ERROR transmute from a reference to a pointer
32+
//~| HELP try
33+
//~| SUGGESTION = t as *const T as *mut T
34+
35+
let _: *const U = core::intrinsics::transmute(t);
36+
//~^ ERROR transmute from a reference to a pointer
37+
//~| HELP try
38+
//~| SUGGESTION = t as *const T as *const U
2439
}
2540

2641
#[deny(transmute_ptr_to_ref)]

0 commit comments

Comments
 (0)