From f74dcaac0cf3e5b7375af943adb562e9629e233a Mon Sep 17 00:00:00 2001 From: mcarton Date: Mon, 19 Sep 2016 17:59:12 +0200 Subject: [PATCH] Fix wrong suggestion in `TRANSMUTE_PTR_TO_REF` with lts --- clippy_lints/src/transmute.rs | 23 +++++++++++++++++++---- tests/compile-fail/transmute.rs | 32 ++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index e042cb678..5e9931c3b 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::ty::TypeVariants::{TyRawPtr, TyRef}; use rustc::ty; use rustc::hir::*; -use utils::{match_def_path, paths, span_lint, span_lint_and_then}; +use utils::{match_def_path, paths, span_lint, span_lint_and_then, snippet}; use utils::sugg; /// **What it does:** Checks for transmutes that can't ever be correct on any @@ -87,7 +87,7 @@ impl LintPass for Transmute { impl LateLintPass for Transmute { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprCall(ref path_expr, ref args) = e.node { - if let ExprPath(None, _) = path_expr.node { + if let ExprPath(None, ref path) = path_expr.node { let def_id = cx.tcx.expect_def(path_expr.id).def_id(); if match_def_path(cx, def_id, &paths::TRANSMUTE) { @@ -170,11 +170,10 @@ impl LateLintPass for Transmute { ("&*", "*const") }; - let arg = if from_pty.ty == to_rty.ty { arg } else { - arg.as_ty(&format!("{} {}", cast, to_rty.ty)) + arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, path, to_rty.ty))) }; db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); @@ -187,3 +186,19 @@ impl LateLintPass for Transmute { } } } + +/// Get the snippet of `Bar` in `…::transmute`. If that snippet is not available , use +/// the type's `ToString` implementation. In weird cases it could lead to types with invalid `'_` +/// lifetime, but it should be rare. +fn get_type_snippet(cx: &LateContext, path: &Path, to_rty: ty::Ty) -> String { + if_let_chain!{[ + let Some(seg) = path.segments.last(), + let PathParameters::AngleBracketedParameters(ref ang) = seg.parameters, + let Some(to_ty) = ang.types.get(1), + let TyRptr(_, ref to_ty) = to_ty.node, + ], { + return snippet(cx, to_ty.ty.span, &to_rty.to_string()).to_string(); + }} + + to_rty.to_string() +} diff --git a/tests/compile-fail/transmute.rs b/tests/compile-fail/transmute.rs index 134485899..c5ab854b0 100644 --- a/tests/compile-fail/transmute.rs +++ b/tests/compile-fail/transmute.rs @@ -1,6 +1,8 @@ #![feature(plugin)] #![plugin(clippy)] +#![allow(dead_code)] + extern crate core; use std::mem::transmute as my_transmute; @@ -83,6 +85,31 @@ unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = &*(om as *const T); } +#[deny(transmute_ptr_to_ref)] +fn issue1231() { + struct Foo<'a, T: 'a> { + bar: &'a T, + } + + let raw = 0 as *const i32; + let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; + //~^ ERROR transmute from a pointer type + //~| HELP try + //~| SUGGESTION unsafe { &*(raw as *const Foo<_>) }; + + let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; + //~^ ERROR transmute from a pointer type + //~| HELP try + //~| SUGGESTION unsafe { &*(raw as *const Foo<&_>) }; + + type Bar<'a> = &'a u8; + let raw = 0 as *const i32; + unsafe { std::mem::transmute::<_, Bar>(raw) }; + //~^ ERROR transmute from a pointer type + //~| HELP try + //~| SUGGESTION unsafe { &*(raw as *const u8) }; +} + #[deny(useless_transmute)] fn useless() { unsafe { @@ -144,7 +171,4 @@ fn crosspointer() { } } -fn main() { - useless(); - crosspointer(); -} +fn main() { }