From 306545ff9653a8e1d00c4f381c8e609d3ad49adb Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Wed, 10 Feb 2021 22:59:08 +0900 Subject: [PATCH 01/17] Create transmute directory --- clippy_lints/src/{transmute.rs => transmute/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename clippy_lints/src/{transmute.rs => transmute/mod.rs} (100%) diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute/mod.rs similarity index 100% rename from clippy_lints/src/transmute.rs rename to clippy_lints/src/transmute/mod.rs From 4ac438bfed36c1de307cac0f86d8d4938157ac50 Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Wed, 10 Feb 2021 23:15:06 +0900 Subject: [PATCH 02/17] Add transmute/utils.rs --- clippy_lints/src/transmute/mod.rs | 110 ++-------------------------- clippy_lints/src/transmute/utils.rs | 109 +++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 103 deletions(-) create mode 100644 clippy_lints/src/transmute/utils.rs diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index dc938ed02383..0258244a07ba 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -1,16 +1,16 @@ +mod utils; +use utils::*; + use crate::utils::{ - in_constant, is_normalizable, last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_sugg, - span_lint_and_then, sugg, + in_constant, match_def_path, paths, snippet, span_lint, span_lint_and_sugg, span_lint_and_then, sugg, }; use if_chain::if_chain; use rustc_ast as ast; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, TyKind, UnOp}; +use rustc_hir::{Expr, ExprKind, Mutability, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, cast::CastKind, Ty}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::DUMMY_SP; -use rustc_typeck::check::{cast::CastCheck, FnCtxt, Inherited}; use std::borrow::Cow; declare_clippy_lint! { @@ -326,6 +326,7 @@ static COLLECTIONS: &[&[&str]] = &[ &paths::HASHSET, &paths::HASHMAP, ]; + impl<'tcx> LateLintPass<'tcx> for Transmute { #[allow(clippy::similar_names, clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { @@ -664,100 +665,3 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { } } } - -/// Gets 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: &QPath<'_>, to_ref_ty: Ty<'_>) -> String { - let seg = last_path_segment(path); - if_chain! { - if let Some(ref params) = seg.args; - if !params.parenthesized; - if let Some(to_ty) = params.args.iter().filter_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty), - _ => None, - }).nth(1); - if let TyKind::Rptr(_, ref to_ty) = to_ty.kind; - then { - return snippet(cx, to_ty.ty.span, &to_ref_ty.to_string()).to_string(); - } - } - - to_ref_ty.to_string() -} - -// check if the component types of the transmuted collection and the result have different ABI, -// size or alignment -fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool { - let empty_param_env = ty::ParamEnv::empty(); - // check if `from` and `to` are normalizable to avoid ICE (#4968) - if !(is_normalizable(cx, empty_param_env, from) && is_normalizable(cx, empty_param_env, to)) { - return false; - } - let from_ty_layout = cx.tcx.layout_of(empty_param_env.and(from)); - let to_ty_layout = cx.tcx.layout_of(empty_param_env.and(to)); - if let (Ok(from_layout), Ok(to_layout)) = (from_ty_layout, to_ty_layout) { - from_layout.size != to_layout.size || from_layout.align != to_layout.align || from_layout.abi != to_layout.abi - } else { - // no idea about layout, so don't lint - false - } -} - -/// Check if the type conversion can be expressed as a pointer cast, instead of -/// a transmute. In certain cases, including some invalid casts from array -/// references to pointers, this may cause additional errors to be emitted and/or -/// ICE error messages. This function will panic if that occurs. -fn can_be_expressed_as_pointer_cast<'tcx>( - cx: &LateContext<'tcx>, - e: &'tcx Expr<'_>, - from_ty: Ty<'tcx>, - to_ty: Ty<'tcx>, -) -> bool { - use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast}; - matches!( - check_cast(cx, e, from_ty, to_ty), - Some(PtrPtrCast | PtrAddrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) - ) -} - -/// If a cast from `from_ty` to `to_ty` is valid, returns an Ok containing the kind of -/// the cast. In certain cases, including some invalid casts from array references -/// to pointers, this may cause additional errors to be emitted and/or ICE error -/// messages. This function will panic if that occurs. -fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option { - let hir_id = e.hir_id; - let local_def_id = hir_id.owner; - - Inherited::build(cx.tcx, local_def_id).enter(|inherited| { - let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, hir_id); - - // If we already have errors, we can't be sure we can pointer cast. - assert!( - !fn_ctxt.errors_reported_since_creation(), - "Newly created FnCtxt contained errors" - ); - - if let Ok(check) = CastCheck::new( - &fn_ctxt, e, from_ty, to_ty, - // We won't show any error to the user, so we don't care what the span is here. - DUMMY_SP, DUMMY_SP, - ) { - let res = check.do_check(&fn_ctxt); - - // do_check's documentation says that it might return Ok and create - // errors in the fcx instead of returing Err in some cases. Those cases - // should be filtered out before getting here. - assert!( - !fn_ctxt.errors_reported_since_creation(), - "`fn_ctxt` contained errors after cast check!" - ); - - res.ok() - } else { - None - } - }) -} diff --git a/clippy_lints/src/transmute/utils.rs b/clippy_lints/src/transmute/utils.rs new file mode 100644 index 000000000000..734a92d50d2a --- /dev/null +++ b/clippy_lints/src/transmute/utils.rs @@ -0,0 +1,109 @@ +use crate::utils::{is_normalizable, last_path_segment, snippet}; +use if_chain::if_chain; +use rustc_hir::{Expr, GenericArg, QPath, TyKind}; +use rustc_lint::LateContext; +use rustc_middle::ty::{self, cast::CastKind, Ty}; +use rustc_span::DUMMY_SP; +use rustc_typeck::check::{cast::CastCheck, FnCtxt, Inherited}; + +/// Gets 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. +pub(super) fn get_type_snippet(cx: &LateContext<'_>, path: &QPath<'_>, to_ref_ty: Ty<'_>) -> String { + let seg = last_path_segment(path); + if_chain! { + if let Some(ref params) = seg.args; + if !params.parenthesized; + if let Some(to_ty) = params.args.iter().filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + _ => None, + }).nth(1); + if let TyKind::Rptr(_, ref to_ty) = to_ty.kind; + then { + return snippet(cx, to_ty.ty.span, &to_ref_ty.to_string()).to_string(); + } + } + + to_ref_ty.to_string() +} + +// check if the component types of the transmuted collection and the result have different ABI, +// size or alignment +pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool { + let empty_param_env = ty::ParamEnv::empty(); + // check if `from` and `to` are normalizable to avoid ICE (#4968) + if !(is_normalizable(cx, empty_param_env, from) && is_normalizable(cx, empty_param_env, to)) { + return false; + } + let from_ty_layout = cx.tcx.layout_of(empty_param_env.and(from)); + let to_ty_layout = cx.tcx.layout_of(empty_param_env.and(to)); + if let (Ok(from_layout), Ok(to_layout)) = (from_ty_layout, to_ty_layout) { + from_layout.size != to_layout.size || from_layout.align != to_layout.align || from_layout.abi != to_layout.abi + } else { + // no idea about layout, so don't lint + false + } +} + +/// Check if the type conversion can be expressed as a pointer cast, instead of +/// a transmute. In certain cases, including some invalid casts from array +/// references to pointers, this may cause additional errors to be emitted and/or +/// ICE error messages. This function will panic if that occurs. +pub(super) fn can_be_expressed_as_pointer_cast<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, +) -> bool { + use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast}; + matches!( + check_cast(cx, e, from_ty, to_ty), + Some(PtrPtrCast | PtrAddrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) + ) +} + +/// If a cast from `from_ty` to `to_ty` is valid, returns an Ok containing the kind of +/// the cast. In certain cases, including some invalid casts from array references +/// to pointers, this may cause additional errors to be emitted and/or ICE error +/// messages. This function will panic if that occurs. +pub(super) fn check_cast<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, +) -> Option { + let hir_id = e.hir_id; + let local_def_id = hir_id.owner; + + Inherited::build(cx.tcx, local_def_id).enter(|inherited| { + let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, hir_id); + + // If we already have errors, we can't be sure we can pointer cast. + assert!( + !fn_ctxt.errors_reported_since_creation(), + "Newly created FnCtxt contained errors" + ); + + if let Ok(check) = CastCheck::new( + &fn_ctxt, e, from_ty, to_ty, + // We won't show any error to the user, so we don't care what the span is here. + DUMMY_SP, DUMMY_SP, + ) { + let res = check.do_check(&fn_ctxt); + + // do_check's documentation says that it might return Ok and create + // errors in the fcx instead of returing Err in some cases. Those cases + // should be filtered out before getting here. + assert!( + !fn_ctxt.errors_reported_since_creation(), + "`fn_ctxt` contained errors after cast check!" + ); + + res.ok() + } else { + None + } + }) +} From 0d7dd00860e5a2b8b7c7a34daaa5553ff2e542f3 Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Wed, 10 Feb 2021 23:54:11 +0900 Subject: [PATCH 03/17] Move useless_transmute to its own module --- clippy_lints/src/transmute/mod.rs | 51 ++----------- .../src/transmute/useless_transmute.rs | 74 +++++++++++++++++++ 2 files changed, 81 insertions(+), 44 deletions(-) create mode 100644 clippy_lints/src/transmute/useless_transmute.rs diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 0258244a07ba..4897934376f1 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -1,4 +1,6 @@ +mod useless_transmute; mod utils; + use utils::*; use crate::utils::{ @@ -344,51 +346,12 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { let from_ty = cx.typeck_results().expr_ty(&args[0]); let to_ty = cx.typeck_results().expr_ty(e); - match (&from_ty.kind(), &to_ty.kind()) { - _ if from_ty == to_ty => span_lint( - cx, - USELESS_TRANSMUTE, - e.span, - &format!("transmute from a type (`{}`) to itself", from_ty), - ), - (ty::Ref(_, rty, rty_mutbl), ty::RawPtr(ptr_ty)) => span_lint_and_then( - cx, - USELESS_TRANSMUTE, - e.span, - "transmute from a reference to a pointer", - |diag| { - if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let rty_and_mut = ty::TypeAndMut { - ty: rty, - mutbl: *rty_mutbl, - }; - - let sugg = if *ptr_ty == rty_and_mut { - arg.as_ty(to_ty) - } else { - arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty) - }; + let triggered = useless_transmute::check(cx, e, from_ty, to_ty, args); + if triggered { + return; + } - diag.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified); - } - }, - ), - (ty::Int(_) | ty::Uint(_), ty::RawPtr(_)) => span_lint_and_then( - cx, - USELESS_TRANSMUTE, - e.span, - "transmute from an integer to a pointer", - |diag| { - if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - diag.span_suggestion( - e.span, - "try", - arg.as_ty(&to_ty.to_string()).to_string(), - Applicability::Unspecified, - ); - } - }, - ), + match (&from_ty.kind(), &to_ty.kind()) { (ty::Float(_) | ty::Char, ty::Ref(..) | ty::RawPtr(_)) => span_lint( cx, WRONG_TRANSMUTE, diff --git a/clippy_lints/src/transmute/useless_transmute.rs b/clippy_lints/src/transmute/useless_transmute.rs new file mode 100644 index 000000000000..86d75fd2ee0b --- /dev/null +++ b/clippy_lints/src/transmute/useless_transmute.rs @@ -0,0 +1,74 @@ +use super::USELESS_TRANSMUTE; +use crate::utils::{span_lint, span_lint_and_then, sugg}; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; + +/// Checks for `useless_transmute` lint. +/// Returns `true` if it's triggered, otherwise returns `false`. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + args: &'tcx [Expr<'_>], +) -> bool { + match (&from_ty.kind(), &to_ty.kind()) { + _ if from_ty == to_ty => { + span_lint( + cx, + USELESS_TRANSMUTE, + e.span, + &format!("transmute from a type (`{}`) to itself", from_ty), + ); + true + }, + (ty::Ref(_, rty, rty_mutbl), ty::RawPtr(ptr_ty)) => { + span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from a reference to a pointer", + |diag| { + if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let rty_and_mut = ty::TypeAndMut { + ty: rty, + mutbl: *rty_mutbl, + }; + + let sugg = if *ptr_ty == rty_and_mut { + arg.as_ty(to_ty) + } else { + arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty) + }; + + diag.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified); + } + }, + ); + true + }, + (ty::Int(_) | ty::Uint(_), ty::RawPtr(_)) => { + span_lint_and_then( + cx, + USELESS_TRANSMUTE, + e.span, + "transmute from an integer to a pointer", + |diag| { + if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + diag.span_suggestion( + e.span, + "try", + arg.as_ty(&to_ty.to_string()).to_string(), + Applicability::Unspecified, + ); + } + }, + ); + true + }, + _ => false, + } +} From ef97764dcc45493eebe0332acf4b2410583af5e4 Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Wed, 10 Feb 2021 23:57:56 +0900 Subject: [PATCH 04/17] Move wrong_transmute to its own module --- clippy_lints/src/transmute/mod.rs | 11 ++++----- clippy_lints/src/transmute/wrong_transmute.rs | 23 +++++++++++++++++++ 2 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 clippy_lints/src/transmute/wrong_transmute.rs diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 4897934376f1..09e0fe257a5e 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -1,5 +1,6 @@ mod useless_transmute; mod utils; +mod wrong_transmute; use utils::*; @@ -350,14 +351,12 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if triggered { return; } + let triggered = wrong_transmute::check(cx, e, from_ty, to_ty); + if triggered { + return; + } match (&from_ty.kind(), &to_ty.kind()) { - (ty::Float(_) | ty::Char, ty::Ref(..) | ty::RawPtr(_)) => span_lint( - cx, - WRONG_TRANSMUTE, - e.span, - &format!("transmute from a `{}` to a pointer", from_ty), - ), (ty::RawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( cx, CROSSPOINTER_TRANSMUTE, diff --git a/clippy_lints/src/transmute/wrong_transmute.rs b/clippy_lints/src/transmute/wrong_transmute.rs new file mode 100644 index 000000000000..d2d3f0a9c890 --- /dev/null +++ b/clippy_lints/src/transmute/wrong_transmute.rs @@ -0,0 +1,23 @@ +use super::WRONG_TRANSMUTE; +use crate::utils::span_lint; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; + +/// Checks for `wrong_transmute` lint. +/// Returns `true` if it's triggered, otherwise returns `false`. +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool { + match (&from_ty.kind(), &to_ty.kind()) { + (ty::Float(_) | ty::Char, ty::Ref(..) | ty::RawPtr(_)) => { + span_lint( + cx, + WRONG_TRANSMUTE, + e.span, + &format!("transmute from a `{}` to a pointer", from_ty), + ); + true + }, + _ => false, + } +} From afc9275928905d2142da027815aac67b81d0a89b Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 00:02:21 +0900 Subject: [PATCH 05/17] Move crosspointer_transmute to its own module --- .../src/transmute/crosspointer_transmute.rs | 38 +++++++++++++++++++ clippy_lints/src/transmute/mod.rs | 23 +++-------- 2 files changed, 43 insertions(+), 18 deletions(-) create mode 100644 clippy_lints/src/transmute/crosspointer_transmute.rs diff --git a/clippy_lints/src/transmute/crosspointer_transmute.rs b/clippy_lints/src/transmute/crosspointer_transmute.rs new file mode 100644 index 000000000000..b570bb3a396e --- /dev/null +++ b/clippy_lints/src/transmute/crosspointer_transmute.rs @@ -0,0 +1,38 @@ +use super::CROSSPOINTER_TRANSMUTE; +use crate::utils::span_lint; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; + +/// Checks for `crosspointer_transmute` lint. +/// Returns `true` if it's triggered, otherwise returns `false`. +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool { + match (&from_ty.kind(), &to_ty.kind()) { + (ty::RawPtr(from_ptr), _) if from_ptr.ty == to_ty => { + span_lint( + cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!( + "transmute from a type (`{}`) to the type that it points to (`{}`)", + from_ty, to_ty + ), + ); + true + }, + (_, ty::RawPtr(to_ptr)) if to_ptr.ty == from_ty => { + span_lint( + cx, + CROSSPOINTER_TRANSMUTE, + e.span, + &format!( + "transmute from a type (`{}`) to a pointer to that type (`{}`)", + from_ty, to_ty + ), + ); + true + }, + _ => false, + } +} diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 09e0fe257a5e..7e05771c8851 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -1,3 +1,4 @@ +mod crosspointer_transmute; mod useless_transmute; mod utils; mod wrong_transmute; @@ -355,26 +356,12 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if triggered { return; } + let triggered = crosspointer_transmute::check(cx, e, from_ty, to_ty); + if triggered { + return; + } match (&from_ty.kind(), &to_ty.kind()) { - (ty::RawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint( - cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!( - "transmute from a type (`{}`) to the type that it points to (`{}`)", - from_ty, to_ty - ), - ), - (_, ty::RawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( - cx, - CROSSPOINTER_TRANSMUTE, - e.span, - &format!( - "transmute from a type (`{}`) to a pointer to that type (`{}`)", - from_ty, to_ty - ), - ), (ty::RawPtr(from_pty), ty::Ref(_, to_ref_ty, mutbl)) => span_lint_and_then( cx, TRANSMUTE_PTR_TO_REF, From 6442d45d3a55cee14ccee14c004ea344072d54cd Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 00:10:19 +0900 Subject: [PATCH 06/17] Move transmute_ptr_to_ref to its own module --- clippy_lints/src/transmute/mod.rs | 36 ++---------- .../src/transmute/transmute_ptr_to_ref.rs | 56 +++++++++++++++++++ 2 files changed, 61 insertions(+), 31 deletions(-) create mode 100644 clippy_lints/src/transmute/transmute_ptr_to_ref.rs diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 7e05771c8851..f00cb9b935c2 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -1,4 +1,5 @@ mod crosspointer_transmute; +mod transmute_ptr_to_ref; mod useless_transmute; mod utils; mod wrong_transmute; @@ -360,39 +361,12 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if triggered { return; } + let triggered = transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, args, qpath); + if triggered { + return; + } match (&from_ty.kind(), &to_ty.kind()) { - (ty::RawPtr(from_pty), ty::Ref(_, to_ref_ty, mutbl)) => span_lint_and_then( - cx, - TRANSMUTE_PTR_TO_REF, - e.span, - &format!( - "transmute from a pointer type (`{}`) to a reference type \ - (`{}`)", - from_ty, to_ty - ), - |diag| { - let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let (deref, cast) = if *mutbl == Mutability::Mut { - ("&mut *", "*mut") - } else { - ("&*", "*const") - }; - - let arg = if from_pty.ty == *to_ref_ty { - arg - } else { - arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_ref_ty))) - }; - - diag.span_suggestion( - e.span, - "try", - sugg::make_unop(deref, arg).to_string(), - Applicability::Unspecified, - ); - }, - ), (ty::Int(ty::IntTy::I32) | ty::Uint(ty::UintTy::U32), &ty::Char) => { span_lint_and_then( cx, diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs new file mode 100644 index 000000000000..7be47da35dac --- /dev/null +++ b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -0,0 +1,56 @@ +use super::utils::get_type_snippet; +use super::TRANSMUTE_PTR_TO_REF; +use crate::utils::{span_lint_and_then, sugg}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, Mutability, QPath}; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; + +/// Checks for `transmute_ptr_to_ref` lint. +/// Returns `true` if it's triggered, otherwise returns `false`. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + args: &'tcx [Expr<'_>], + qpath: &'tcx QPath<'_>, +) -> bool { + match (&from_ty.kind(), &to_ty.kind()) { + (ty::RawPtr(from_pty), ty::Ref(_, to_ref_ty, mutbl)) => { + span_lint_and_then( + cx, + TRANSMUTE_PTR_TO_REF, + e.span, + &format!( + "transmute from a pointer type (`{}`) to a reference type (`{}`)", + from_ty, to_ty + ), + |diag| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let (deref, cast) = if *mutbl == Mutability::Mut { + ("&mut *", "*mut") + } else { + ("&*", "*const") + }; + + let arg = if from_pty.ty == *to_ref_ty { + arg + } else { + arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_ref_ty))) + }; + + diag.span_suggestion( + e.span, + "try", + sugg::make_unop(deref, arg).to_string(), + Applicability::Unspecified, + ); + }, + ); + true + }, + _ => false, + } +} From 4c6522118802b5fd98337eeb57d3d81268069385 Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 00:18:45 +0900 Subject: [PATCH 07/17] Move transmute_int_to_char to its own module --- clippy_lints/src/transmute/mod.rs | 27 ++--------- .../src/transmute/transmute_int_to_char.rs | 47 +++++++++++++++++++ 2 files changed, 52 insertions(+), 22 deletions(-) create mode 100644 clippy_lints/src/transmute/transmute_int_to_char.rs diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index f00cb9b935c2..376f9bd78c0d 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -1,4 +1,5 @@ mod crosspointer_transmute; +mod transmute_int_to_char; mod transmute_ptr_to_ref; mod useless_transmute; mod utils; @@ -365,30 +366,12 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if triggered { return; } + let triggered = transmute_int_to_char::check(cx, e, from_ty, to_ty, args); + if triggered { + return; + } match (&from_ty.kind(), &to_ty.kind()) { - (ty::Int(ty::IntTy::I32) | ty::Uint(ty::UintTy::U32), &ty::Char) => { - span_lint_and_then( - cx, - TRANSMUTE_INT_TO_CHAR, - e.span, - &format!("transmute from a `{}` to a `char`", from_ty), - |diag| { - let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let arg = if let ty::Int(_) = from_ty.kind() { - arg.as_ty(ast::UintTy::U32.name_str()) - } else { - arg - }; - diag.span_suggestion( - e.span, - "consider using", - format!("std::char::from_u32({}).unwrap()", arg.to_string()), - Applicability::Unspecified, - ); - }, - ) - }, (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) => { if_chain! { if let (&ty::Slice(slice_ty), &ty::Str) = (&ty_from.kind(), &ty_to.kind()); diff --git a/clippy_lints/src/transmute/transmute_int_to_char.rs b/clippy_lints/src/transmute/transmute_int_to_char.rs new file mode 100644 index 000000000000..179627d9964b --- /dev/null +++ b/clippy_lints/src/transmute/transmute_int_to_char.rs @@ -0,0 +1,47 @@ +use super::TRANSMUTE_INT_TO_CHAR; +use crate::utils::{span_lint_and_then, sugg}; +use rustc_ast as ast; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; + +/// Checks for `transmute_int_to_char` lint. +/// Returns `true` if it's triggered, otherwise returns `false`. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + args: &'tcx [Expr<'_>], +) -> bool { + match (&from_ty.kind(), &to_ty.kind()) { + (ty::Int(ty::IntTy::I32) | ty::Uint(ty::UintTy::U32), &ty::Char) => { + { + span_lint_and_then( + cx, + TRANSMUTE_INT_TO_CHAR, + e.span, + &format!("transmute from a `{}` to a `char`", from_ty), + |diag| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let arg = if let ty::Int(_) = from_ty.kind() { + arg.as_ty(ast::UintTy::U32.name_str()) + } else { + arg + }; + diag.span_suggestion( + e.span, + "consider using", + format!("std::char::from_u32({}).unwrap()", arg.to_string()), + Applicability::Unspecified, + ); + }, + ) + }; + true + }, + _ => false, + } +} From 7af3458b5458ad99dc900b9fe744f39b9dae449e Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 00:40:57 +0900 Subject: [PATCH 08/17] Move transmute_bytes_to_str and transmute_ptr_to_ptr to transmute_ref_to_ref module --- clippy_lints/src/transmute/mod.rs | 64 ++----------- .../src/transmute/transmute_ref_to_ref.rs | 89 +++++++++++++++++++ 2 files changed, 94 insertions(+), 59 deletions(-) create mode 100644 clippy_lints/src/transmute/transmute_ref_to_ref.rs diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 376f9bd78c0d..8a0c83789d54 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -1,6 +1,7 @@ mod crosspointer_transmute; mod transmute_int_to_char; mod transmute_ptr_to_ref; +mod transmute_ref_to_ref; mod useless_transmute; mod utils; mod wrong_transmute; @@ -370,67 +371,12 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if triggered { return; } + let triggered = transmute_ref_to_ref::check(cx, e, from_ty, to_ty, args, const_context); + if triggered { + return; + } match (&from_ty.kind(), &to_ty.kind()) { - (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) => { - if_chain! { - if let (&ty::Slice(slice_ty), &ty::Str) = (&ty_from.kind(), &ty_to.kind()); - if let ty::Uint(ty::UintTy::U8) = slice_ty.kind(); - if from_mutbl == to_mutbl; - then { - let postfix = if *from_mutbl == Mutability::Mut { - "_mut" - } else { - "" - }; - - span_lint_and_sugg( - cx, - TRANSMUTE_BYTES_TO_STR, - e.span, - &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), - "consider using", - format!( - "std::str::from_utf8{}({}).unwrap()", - postfix, - snippet(cx, args[0].span, ".."), - ), - Applicability::Unspecified, - ); - } else { - if (cx.tcx.erase_regions(from_ty) != cx.tcx.erase_regions(to_ty)) - && !const_context { - span_lint_and_then( - cx, - TRANSMUTE_PTR_TO_PTR, - e.span, - "transmute from a reference to a reference", - |diag| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let ty_from_and_mut = ty::TypeAndMut { - ty: ty_from, - mutbl: *from_mutbl - }; - let ty_to_and_mut = ty::TypeAndMut { ty: ty_to, mutbl: *to_mutbl }; - let sugg_paren = arg - .as_ty(cx.tcx.mk_ptr(ty_from_and_mut)) - .as_ty(cx.tcx.mk_ptr(ty_to_and_mut)); - let sugg = if *to_mutbl == Mutability::Mut { - sugg_paren.mut_addr_deref() - } else { - sugg_paren.addr_deref() - }; - diag.span_suggestion( - e.span, - "try", - sugg.to_string(), - Applicability::Unspecified, - ); - }, - ) - } - } - } - }, (ty::RawPtr(_), ty::RawPtr(to_ty)) => span_lint_and_then( cx, TRANSMUTE_PTR_TO_PTR, diff --git a/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/clippy_lints/src/transmute/transmute_ref_to_ref.rs new file mode 100644 index 000000000000..a9e3385664bd --- /dev/null +++ b/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -0,0 +1,89 @@ +use super::{TRANSMUTE_BYTES_TO_STR, TRANSMUTE_PTR_TO_PTR}; +use crate::utils::{snippet, span_lint_and_sugg, span_lint_and_then, sugg}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{Expr, Mutability}; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; + +/// Checks for `transmute_bytes_to_str` and `transmute_ptr_to_ptr` lints. +/// Returns `true` if either one triggered, otherwise returns `false`. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + args: &'tcx [Expr<'_>], + const_context: bool, +) -> bool { + let mut triggered = false; + + match (&from_ty.kind(), &to_ty.kind()) { + (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) => { + if_chain! { + if let (&ty::Slice(slice_ty), &ty::Str) = (&ty_from.kind(), &ty_to.kind()); + if let ty::Uint(ty::UintTy::U8) = slice_ty.kind(); + if from_mutbl == to_mutbl; + then { + let postfix = if *from_mutbl == Mutability::Mut { + "_mut" + } else { + "" + }; + + span_lint_and_sugg( + cx, + TRANSMUTE_BYTES_TO_STR, + e.span, + &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), + "consider using", + format!( + "std::str::from_utf8{}({}).unwrap()", + postfix, + snippet(cx, args[0].span, ".."), + ), + Applicability::Unspecified, + ); + triggered = true; + } else { + if (cx.tcx.erase_regions(from_ty) != cx.tcx.erase_regions(to_ty)) + && !const_context { + span_lint_and_then( + cx, + TRANSMUTE_PTR_TO_PTR, + e.span, + "transmute from a reference to a reference", + |diag| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let ty_from_and_mut = ty::TypeAndMut { + ty: ty_from, + mutbl: *from_mutbl + }; + let ty_to_and_mut = ty::TypeAndMut { ty: ty_to, mutbl: *to_mutbl }; + let sugg_paren = arg + .as_ty(cx.tcx.mk_ptr(ty_from_and_mut)) + .as_ty(cx.tcx.mk_ptr(ty_to_and_mut)); + let sugg = if *to_mutbl == Mutability::Mut { + sugg_paren.mut_addr_deref() + } else { + sugg_paren.addr_deref() + }; + diag.span_suggestion( + e.span, + "try", + sugg.to_string(), + Applicability::Unspecified, + ); + }, + ); + + triggered = true; + } + } + } + }, + _ => {}, + } + + triggered +} From f8bc0e249c532ceacc9897ea08f7b97ecba5408e Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 00:50:09 +0900 Subject: [PATCH 09/17] Move transmute_ptr_to_ptr to its own module --- clippy_lints/src/transmute/mod.rs | 17 +++------ .../src/transmute/transmute_ptr_to_ptr.rs | 36 +++++++++++++++++++ 2 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 clippy_lints/src/transmute/transmute_ptr_to_ptr.rs diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 8a0c83789d54..e144c96498bd 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -1,5 +1,6 @@ mod crosspointer_transmute; mod transmute_int_to_char; +mod transmute_ptr_to_ptr; mod transmute_ptr_to_ref; mod transmute_ref_to_ref; mod useless_transmute; @@ -375,20 +376,12 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if triggered { return; } + let triggered = transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, args); + if triggered { + return; + } match (&from_ty.kind(), &to_ty.kind()) { - (ty::RawPtr(_), ty::RawPtr(to_ty)) => span_lint_and_then( - cx, - TRANSMUTE_PTR_TO_PTR, - e.span, - "transmute from a pointer to a pointer", - |diag| { - if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let sugg = arg.as_ty(cx.tcx.mk_ptr(*to_ty)); - diag.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified); - } - }, - ), (ty::Int(ty::IntTy::I8) | ty::Uint(ty::UintTy::U8), ty::Bool) => { span_lint_and_then( cx, diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs new file mode 100644 index 000000000000..68668ec30db0 --- /dev/null +++ b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -0,0 +1,36 @@ +use super::TRANSMUTE_PTR_TO_PTR; +use crate::utils::{span_lint_and_then, sugg}; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; + +/// Checks for `transmute_ptr_to_ptr` lint. +/// Returns `true` if it's triggered, otherwise returns `false`. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + args: &'tcx [Expr<'_>], +) -> bool { + match (&from_ty.kind(), &to_ty.kind()) { + (ty::RawPtr(_), ty::RawPtr(to_ty)) => { + span_lint_and_then( + cx, + TRANSMUTE_PTR_TO_PTR, + e.span, + "transmute from a pointer to a pointer", + |diag| { + if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let sugg = arg.as_ty(cx.tcx.mk_ptr(*to_ty)); + diag.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified); + } + }, + ); + true + }, + _ => false, + } +} From d04ea41d1fbf8c60115bf0746fd9756ff17183c2 Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 00:55:32 +0900 Subject: [PATCH 10/17] Move transmute_int_to_bool to its own module --- clippy_lints/src/transmute/mod.rs | 23 +++------- .../src/transmute/transmute_int_to_bool.rs | 42 +++++++++++++++++++ 2 files changed, 47 insertions(+), 18 deletions(-) create mode 100644 clippy_lints/src/transmute/transmute_int_to_bool.rs diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index e144c96498bd..fa9edc9ae2cb 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -1,4 +1,5 @@ mod crosspointer_transmute; +mod transmute_int_to_bool; mod transmute_int_to_char; mod transmute_ptr_to_ptr; mod transmute_ptr_to_ref; @@ -380,26 +381,12 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if triggered { return; } + let triggered = transmute_int_to_bool::check(cx, e, from_ty, to_ty, args); + if triggered { + return; + } match (&from_ty.kind(), &to_ty.kind()) { - (ty::Int(ty::IntTy::I8) | ty::Uint(ty::UintTy::U8), ty::Bool) => { - span_lint_and_then( - cx, - TRANSMUTE_INT_TO_BOOL, - e.span, - &format!("transmute from a `{}` to a `bool`", from_ty), - |diag| { - let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let zero = sugg::Sugg::NonParen(Cow::from("0")); - diag.span_suggestion( - e.span, - "consider using", - sugg::make_binop(ast::BinOpKind::Ne, &arg, &zero).to_string(), - Applicability::Unspecified, - ); - }, - ) - }, (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context => span_lint_and_then( cx, TRANSMUTE_INT_TO_FLOAT, diff --git a/clippy_lints/src/transmute/transmute_int_to_bool.rs b/clippy_lints/src/transmute/transmute_int_to_bool.rs new file mode 100644 index 000000000000..c66c7bff2325 --- /dev/null +++ b/clippy_lints/src/transmute/transmute_int_to_bool.rs @@ -0,0 +1,42 @@ +use super::TRANSMUTE_INT_TO_BOOL; +use crate::utils::{span_lint_and_then, sugg}; +use rustc_ast as ast; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; +use std::borrow::Cow; + +/// Checks for `transmute_int_to_bool` lint. +/// Returns `true` if it's triggered, otherwise returns `false`. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + args: &'tcx [Expr<'_>], +) -> bool { + match (&from_ty.kind(), &to_ty.kind()) { + (ty::Int(ty::IntTy::I8) | ty::Uint(ty::UintTy::U8), ty::Bool) => { + span_lint_and_then( + cx, + TRANSMUTE_INT_TO_BOOL, + e.span, + &format!("transmute from a `{}` to a `bool`", from_ty), + |diag| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let zero = sugg::Sugg::NonParen(Cow::from("0")); + diag.span_suggestion( + e.span, + "consider using", + sugg::make_binop(ast::BinOpKind::Ne, &arg, &zero).to_string(), + Applicability::Unspecified, + ); + }, + ); + true + }, + _ => false, + } +} From acedc7b8f261e97ea544b7d43a053312e55e6ebf Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 01:03:08 +0900 Subject: [PATCH 11/17] Move transmute_int_to_float to its own module --- clippy_lints/src/transmute/mod.rs | 28 ++--------- .../src/transmute/transmute_int_to_float.rs | 48 +++++++++++++++++++ 2 files changed, 53 insertions(+), 23 deletions(-) create mode 100644 clippy_lints/src/transmute/transmute_int_to_float.rs diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index fa9edc9ae2cb..6e1207abd524 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -1,6 +1,7 @@ mod crosspointer_transmute; mod transmute_int_to_bool; mod transmute_int_to_char; +mod transmute_int_to_float; mod transmute_ptr_to_ptr; mod transmute_ptr_to_ref; mod transmute_ref_to_ref; @@ -385,31 +386,12 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if triggered { return; } + let triggered = transmute_int_to_float::check(cx, e, from_ty, to_ty, args, const_context); + if triggered { + return; + } match (&from_ty.kind(), &to_ty.kind()) { - (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context => span_lint_and_then( - cx, - TRANSMUTE_INT_TO_FLOAT, - e.span, - &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), - |diag| { - let arg = sugg::Sugg::hir(cx, &args[0], ".."); - let arg = if let ty::Int(int_ty) = from_ty.kind() { - arg.as_ty(format!( - "u{}", - int_ty.bit_width().map_or_else(|| "size".to_string(), |v| v.to_string()) - )) - } else { - arg - }; - diag.span_suggestion( - e.span, - "consider using", - format!("{}::from_bits({})", to_ty, arg.to_string()), - Applicability::Unspecified, - ); - }, - ), (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) if !const_context => span_lint_and_then( cx, TRANSMUTE_FLOAT_TO_INT, diff --git a/clippy_lints/src/transmute/transmute_int_to_float.rs b/clippy_lints/src/transmute/transmute_int_to_float.rs new file mode 100644 index 000000000000..564a27df562d --- /dev/null +++ b/clippy_lints/src/transmute/transmute_int_to_float.rs @@ -0,0 +1,48 @@ +use super::TRANSMUTE_INT_TO_FLOAT; +use crate::utils::{span_lint_and_then, sugg}; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; + +/// Checks for `transmute_int_to_float` lint. +/// Returns `true` if it's triggered, otherwise returns `false`. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + args: &'tcx [Expr<'_>], + const_context: bool, +) -> bool { + match (&from_ty.kind(), &to_ty.kind()) { + (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context => { + span_lint_and_then( + cx, + TRANSMUTE_INT_TO_FLOAT, + e.span, + &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), + |diag| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + let arg = if let ty::Int(int_ty) = from_ty.kind() { + arg.as_ty(format!( + "u{}", + int_ty.bit_width().map_or_else(|| "size".to_string(), |v| v.to_string()) + )) + } else { + arg + }; + diag.span_suggestion( + e.span, + "consider using", + format!("{}::from_bits({})", to_ty, arg.to_string()), + Applicability::Unspecified, + ); + }, + ); + true + }, + _ => false, + } +} From e7d2393d0182f9837897723e1541c0404bdcd55b Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 01:08:48 +0900 Subject: [PATCH 12/17] Move transmute_float_to_int to its own module --- clippy_lints/src/transmute/mod.rs | 49 ++------------ .../src/transmute/transmute_float_to_int.rs | 66 +++++++++++++++++++ 2 files changed, 71 insertions(+), 44 deletions(-) create mode 100644 clippy_lints/src/transmute/transmute_float_to_int.rs diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 6e1207abd524..3ba0872393d0 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -1,4 +1,5 @@ mod crosspointer_transmute; +mod transmute_float_to_int; mod transmute_int_to_bool; mod transmute_int_to_char; mod transmute_int_to_float; @@ -390,52 +391,12 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if triggered { return; } + let triggered = transmute_float_to_int::check(cx, e, from_ty, to_ty, args, const_context); + if triggered { + return; + } match (&from_ty.kind(), &to_ty.kind()) { - (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) if !const_context => span_lint_and_then( - cx, - TRANSMUTE_FLOAT_TO_INT, - e.span, - &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), - |diag| { - let mut expr = &args[0]; - let mut arg = sugg::Sugg::hir(cx, expr, ".."); - - if let ExprKind::Unary(UnOp::Neg, inner_expr) = &expr.kind { - expr = &inner_expr; - } - - if_chain! { - // if the expression is a float literal and it is unsuffixed then - // add a suffix so the suggestion is valid and unambiguous - let op = format!("{}{}", arg, float_ty.name_str()).into(); - if let ExprKind::Lit(lit) = &expr.kind; - if let ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) = lit.node; - then { - match arg { - sugg::Sugg::MaybeParen(_) => arg = sugg::Sugg::MaybeParen(op), - _ => arg = sugg::Sugg::NonParen(op) - } - } - } - - arg = sugg::Sugg::NonParen(format!("{}.to_bits()", arg.maybe_par()).into()); - - // cast the result of `to_bits` if `to_ty` is signed - arg = if let ty::Int(int_ty) = to_ty.kind() { - arg.as_ty(int_ty.name_str().to_string()) - } else { - arg - }; - - diag.span_suggestion( - e.span, - "consider using", - arg.to_string(), - Applicability::Unspecified, - ); - }, - ), (ty::Adt(from_adt, from_substs), ty::Adt(to_adt, to_substs)) => { if from_adt.did != to_adt.did || !COLLECTIONS.iter().any(|path| match_def_path(cx, to_adt.did, path)) { diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs new file mode 100644 index 000000000000..58cd0e217925 --- /dev/null +++ b/clippy_lints/src/transmute/transmute_float_to_int.rs @@ -0,0 +1,66 @@ +use super::TRANSMUTE_FLOAT_TO_INT; +use crate::utils::{span_lint_and_then, sugg}; +use if_chain::if_chain; +use rustc_ast as ast; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, UnOp}; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; + +/// Checks for `transmute_float_to_int` lint. +/// Returns `true` if it's triggered, otherwise returns `false`. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + args: &'tcx [Expr<'_>], + const_context: bool, +) -> bool { + match (&from_ty.kind(), &to_ty.kind()) { + (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) if !const_context => { + span_lint_and_then( + cx, + TRANSMUTE_FLOAT_TO_INT, + e.span, + &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), + |diag| { + let mut expr = &args[0]; + let mut arg = sugg::Sugg::hir(cx, expr, ".."); + + if let ExprKind::Unary(UnOp::Neg, inner_expr) = &expr.kind { + expr = &inner_expr; + } + + if_chain! { + // if the expression is a float literal and it is unsuffixed then + // add a suffix so the suggestion is valid and unambiguous + let op = format!("{}{}", arg, float_ty.name_str()).into(); + if let ExprKind::Lit(lit) = &expr.kind; + if let ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) = lit.node; + then { + match arg { + sugg::Sugg::MaybeParen(_) => arg = sugg::Sugg::MaybeParen(op), + _ => arg = sugg::Sugg::NonParen(op) + } + } + } + + arg = sugg::Sugg::NonParen(format!("{}.to_bits()", arg.maybe_par()).into()); + + // cast the result of `to_bits` if `to_ty` is signed + arg = if let ty::Int(int_ty) = to_ty.kind() { + arg.as_ty(int_ty.name_str().to_string()) + } else { + arg + }; + + diag.span_suggestion(e.span, "consider using", arg.to_string(), Applicability::Unspecified); + }, + ); + true + }, + _ => false, + } +} From c57a8260f22d4968f8c802ce92593a32e1e27f4c Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 01:21:38 +0900 Subject: [PATCH 13/17] Move unsound_collection_transmute to its own module --- clippy_lints/src/transmute/mod.rs | 35 ++----------- .../transmute/unsound_collection_transmute.rs | 49 +++++++++++++++++++ 2 files changed, 54 insertions(+), 30 deletions(-) create mode 100644 clippy_lints/src/transmute/unsound_collection_transmute.rs diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 3ba0872393d0..8cb4f6500574 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -6,6 +6,7 @@ mod transmute_int_to_float; mod transmute_ptr_to_ptr; mod transmute_ptr_to_ref; mod transmute_ref_to_ref; +mod unsound_collection_transmute; mod useless_transmute; mod utils; mod wrong_transmute; @@ -327,17 +328,6 @@ declare_lint_pass!(Transmute => [ TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, ]); -// used to check for UNSOUND_COLLECTION_TRANSMUTE -static COLLECTIONS: &[&[&str]] = &[ - &paths::VEC, - &paths::VEC_DEQUE, - &paths::BINARY_HEAP, - &paths::BTREESET, - &paths::BTREEMAP, - &paths::HASHSET, - &paths::HASHMAP, -]; - impl<'tcx> LateLintPass<'tcx> for Transmute { #[allow(clippy::similar_names, clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { @@ -395,27 +385,12 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if triggered { return; } + let triggered = unsound_collection_transmute::check(cx, e, from_ty, to_ty); + if triggered { + return; + } match (&from_ty.kind(), &to_ty.kind()) { - (ty::Adt(from_adt, from_substs), ty::Adt(to_adt, to_substs)) => { - if from_adt.did != to_adt.did || - !COLLECTIONS.iter().any(|path| match_def_path(cx, to_adt.did, path)) { - return; - } - if from_substs.types().zip(to_substs.types()) - .any(|(from_ty, to_ty)| is_layout_incompatible(cx, from_ty, to_ty)) { - span_lint( - cx, - UNSOUND_COLLECTION_TRANSMUTE, - e.span, - &format!( - "transmute from `{}` to `{}` with mismatched layout is unsound", - from_ty, - to_ty - ) - ); - } - }, (_, _) if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) => span_lint_and_then( cx, TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, diff --git a/clippy_lints/src/transmute/unsound_collection_transmute.rs b/clippy_lints/src/transmute/unsound_collection_transmute.rs new file mode 100644 index 000000000000..3ce6bcd3ea03 --- /dev/null +++ b/clippy_lints/src/transmute/unsound_collection_transmute.rs @@ -0,0 +1,49 @@ +use super::utils::is_layout_incompatible; +use super::UNSOUND_COLLECTION_TRANSMUTE; +use crate::utils::{match_def_path, paths, span_lint}; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; + +// used to check for UNSOUND_COLLECTION_TRANSMUTE +static COLLECTIONS: &[&[&str]] = &[ + &paths::VEC, + &paths::VEC_DEQUE, + &paths::BINARY_HEAP, + &paths::BTREESET, + &paths::BTREEMAP, + &paths::HASHSET, + &paths::HASHMAP, +]; + +/// Checks for `unsound_collection_transmute` lint. +/// Returns `true` if it's triggered, otherwise returns `false`. +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool { + match (&from_ty.kind(), &to_ty.kind()) { + (ty::Adt(from_adt, from_substs), ty::Adt(to_adt, to_substs)) => { + if from_adt.did != to_adt.did || !COLLECTIONS.iter().any(|path| match_def_path(cx, to_adt.did, path)) { + return false; + } + if from_substs + .types() + .zip(to_substs.types()) + .any(|(from_ty, to_ty)| is_layout_incompatible(cx, from_ty, to_ty)) + { + span_lint( + cx, + UNSOUND_COLLECTION_TRANSMUTE, + e.span, + &format!( + "transmute from `{}` to `{}` with mismatched layout is unsound", + from_ty, to_ty + ), + ); + true + } else { + false + } + }, + _ => false, + } +} From 25c221ec92bdf7be29335f4ea830edb9509a8ce9 Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 01:27:44 +0900 Subject: [PATCH 14/17] Move transmutes_expressible_as_ptr_casts to its own module --- clippy_lints/src/transmute/mod.rs | 25 ++---------- .../transmutes_expressible_as_ptr_casts.rs | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+), 21 deletions(-) create mode 100644 clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 8cb4f6500574..3b010f39c8ab 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -6,6 +6,7 @@ mod transmute_int_to_float; mod transmute_ptr_to_ptr; mod transmute_ptr_to_ref; mod transmute_ref_to_ref; +mod transmutes_expressible_as_ptr_casts; mod unsound_collection_transmute; mod useless_transmute; mod utils; @@ -389,27 +390,9 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if triggered { return; } - - match (&from_ty.kind(), &to_ty.kind()) { - (_, _) if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) => span_lint_and_then( - cx, - TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, - e.span, - &format!( - "transmute from `{}` to `{}` which could be expressed as a pointer cast instead", - from_ty, - to_ty - ), - |diag| { - if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let sugg = arg.as_ty(&to_ty.to_string()).to_string(); - diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable); - } - } - ), - _ => { - return; - }, + let triggered = transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, to_ty, args); + if triggered { + return; } } } diff --git a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs new file mode 100644 index 000000000000..dea896622f11 --- /dev/null +++ b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -0,0 +1,38 @@ +use super::utils::can_be_expressed_as_pointer_cast; +use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS; +use crate::utils::{span_lint_and_then, sugg}; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::ty::Ty; + +/// Checks for `transmutes_expressible_as_ptr_casts` lint. +/// Returns `true` if it's triggered, otherwise returns `false`. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + args: &'tcx [Expr<'_>], +) -> bool { + if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) { + span_lint_and_then( + cx, + TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, + e.span, + &format!( + "transmute from `{}` to `{}` which could be expressed as a pointer cast instead", + from_ty, to_ty + ), + |diag| { + if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let sugg = arg.as_ty(&to_ty.to_string()).to_string(); + diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable); + } + }, + ); + true + } else { + false + } +} From 89ef26a68131d846b07e339e277232ff8737be3e Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 01:29:45 +0900 Subject: [PATCH 15/17] Cleanup imports --- clippy_lints/src/transmute/crosspointer_transmute.rs | 3 +-- clippy_lints/src/transmute/mod.rs | 12 ++---------- clippy_lints/src/transmute/transmute_float_to_int.rs | 3 +-- clippy_lints/src/transmute/transmute_int_to_bool.rs | 3 +-- clippy_lints/src/transmute/transmute_int_to_char.rs | 3 +-- clippy_lints/src/transmute/transmute_int_to_float.rs | 3 +-- clippy_lints/src/transmute/transmute_ptr_to_ptr.rs | 3 +-- clippy_lints/src/transmute/transmute_ptr_to_ref.rs | 3 +-- clippy_lints/src/transmute/transmute_ref_to_ref.rs | 3 +-- .../src/transmute/unsound_collection_transmute.rs | 3 +-- clippy_lints/src/transmute/useless_transmute.rs | 3 +-- clippy_lints/src/transmute/wrong_transmute.rs | 3 +-- 12 files changed, 13 insertions(+), 32 deletions(-) diff --git a/clippy_lints/src/transmute/crosspointer_transmute.rs b/clippy_lints/src/transmute/crosspointer_transmute.rs index b570bb3a396e..ce87defaa940 100644 --- a/clippy_lints/src/transmute/crosspointer_transmute.rs +++ b/clippy_lints/src/transmute/crosspointer_transmute.rs @@ -2,8 +2,7 @@ use super::CROSSPOINTER_TRANSMUTE; use crate::utils::span_lint; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; /// Checks for `crosspointer_transmute` lint. /// Returns `true` if it's triggered, otherwise returns `false`. diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 3b010f39c8ab..e16dfa872299 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -12,19 +12,11 @@ mod useless_transmute; mod utils; mod wrong_transmute; -use utils::*; - -use crate::utils::{ - in_constant, match_def_path, paths, snippet, span_lint, span_lint_and_sugg, span_lint_and_then, sugg, -}; +use crate::utils::{in_constant, match_def_path, paths}; use if_chain::if_chain; -use rustc_ast as ast; -use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, Mutability, UnOp}; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use std::borrow::Cow; declare_clippy_lint! { /// **What it does:** Checks for transmutes that can't ever be correct on any diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs index 58cd0e217925..562d880e39af 100644 --- a/clippy_lints/src/transmute/transmute_float_to_int.rs +++ b/clippy_lints/src/transmute/transmute_float_to_int.rs @@ -5,8 +5,7 @@ use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, UnOp}; use rustc_lint::LateContext; -use rustc_middle::ty; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; /// Checks for `transmute_float_to_int` lint. /// Returns `true` if it's triggered, otherwise returns `false`. diff --git a/clippy_lints/src/transmute/transmute_int_to_bool.rs b/clippy_lints/src/transmute/transmute_int_to_bool.rs index c66c7bff2325..5b609f906a3d 100644 --- a/clippy_lints/src/transmute/transmute_int_to_bool.rs +++ b/clippy_lints/src/transmute/transmute_int_to_bool.rs @@ -4,8 +4,7 @@ use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; use std::borrow::Cow; /// Checks for `transmute_int_to_bool` lint. diff --git a/clippy_lints/src/transmute/transmute_int_to_char.rs b/clippy_lints/src/transmute/transmute_int_to_char.rs index 179627d9964b..48473e0d799d 100644 --- a/clippy_lints/src/transmute/transmute_int_to_char.rs +++ b/clippy_lints/src/transmute/transmute_int_to_char.rs @@ -4,8 +4,7 @@ use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; /// Checks for `transmute_int_to_char` lint. /// Returns `true` if it's triggered, otherwise returns `false`. diff --git a/clippy_lints/src/transmute/transmute_int_to_float.rs b/clippy_lints/src/transmute/transmute_int_to_float.rs index 564a27df562d..f83fba8966a1 100644 --- a/clippy_lints/src/transmute/transmute_int_to_float.rs +++ b/clippy_lints/src/transmute/transmute_int_to_float.rs @@ -3,8 +3,7 @@ use crate::utils::{span_lint_and_then, sugg}; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; /// Checks for `transmute_int_to_float` lint. /// Returns `true` if it's triggered, otherwise returns `false`. diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index 68668ec30db0..f4e60a3020cf 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -3,8 +3,7 @@ use crate::utils::{span_lint_and_then, sugg}; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; /// Checks for `transmute_ptr_to_ptr` lint. /// Returns `true` if it's triggered, otherwise returns `false`. diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index 7be47da35dac..a6719b68098a 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -4,8 +4,7 @@ use crate::utils::{span_lint_and_then, sugg}; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability, QPath}; use rustc_lint::LateContext; -use rustc_middle::ty; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; /// Checks for `transmute_ptr_to_ref` lint. /// Returns `true` if it's triggered, otherwise returns `false`. diff --git a/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/clippy_lints/src/transmute/transmute_ref_to_ref.rs index a9e3385664bd..ccfcb03e87ac 100644 --- a/clippy_lints/src/transmute/transmute_ref_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -4,8 +4,7 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; -use rustc_middle::ty; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; /// Checks for `transmute_bytes_to_str` and `transmute_ptr_to_ptr` lints. /// Returns `true` if either one triggered, otherwise returns `false`. diff --git a/clippy_lints/src/transmute/unsound_collection_transmute.rs b/clippy_lints/src/transmute/unsound_collection_transmute.rs index 3ce6bcd3ea03..503c5e0ff382 100644 --- a/clippy_lints/src/transmute/unsound_collection_transmute.rs +++ b/clippy_lints/src/transmute/unsound_collection_transmute.rs @@ -3,8 +3,7 @@ use super::UNSOUND_COLLECTION_TRANSMUTE; use crate::utils::{match_def_path, paths, span_lint}; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; // used to check for UNSOUND_COLLECTION_TRANSMUTE static COLLECTIONS: &[&[&str]] = &[ diff --git a/clippy_lints/src/transmute/useless_transmute.rs b/clippy_lints/src/transmute/useless_transmute.rs index 86d75fd2ee0b..83441514af05 100644 --- a/clippy_lints/src/transmute/useless_transmute.rs +++ b/clippy_lints/src/transmute/useless_transmute.rs @@ -3,8 +3,7 @@ use crate::utils::{span_lint, span_lint_and_then, sugg}; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; /// Checks for `useless_transmute` lint. /// Returns `true` if it's triggered, otherwise returns `false`. diff --git a/clippy_lints/src/transmute/wrong_transmute.rs b/clippy_lints/src/transmute/wrong_transmute.rs index d2d3f0a9c890..d6d77f2c8345 100644 --- a/clippy_lints/src/transmute/wrong_transmute.rs +++ b/clippy_lints/src/transmute/wrong_transmute.rs @@ -2,8 +2,7 @@ use super::WRONG_TRANSMUTE; use crate::utils::span_lint; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; /// Checks for `wrong_transmute` lint. /// Returns `true` if it's triggered, otherwise returns `false`. From 8a8f7b4cf5c7642e72b0c0e40586a9310b1ca48b Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 01:41:52 +0900 Subject: [PATCH 16/17] Refactor calls to lint check functions --- clippy_lints/src/transmute/mod.rs | 61 ++++++++----------------------- 1 file changed, 16 insertions(+), 45 deletions(-) diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index e16dfa872299..c1870f5208b4 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -338,53 +338,24 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { let from_ty = cx.typeck_results().expr_ty(&args[0]); let to_ty = cx.typeck_results().expr_ty(e); - let triggered = useless_transmute::check(cx, e, from_ty, to_ty, args); - if triggered { + // If useless_transmute is triggered, the other lints can be skipped. + if useless_transmute::check(cx, e, from_ty, to_ty, args) { return; } - let triggered = wrong_transmute::check(cx, e, from_ty, to_ty); - if triggered { - return; - } - let triggered = crosspointer_transmute::check(cx, e, from_ty, to_ty); - if triggered { - return; - } - let triggered = transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, args, qpath); - if triggered { - return; - } - let triggered = transmute_int_to_char::check(cx, e, from_ty, to_ty, args); - if triggered { - return; - } - let triggered = transmute_ref_to_ref::check(cx, e, from_ty, to_ty, args, const_context); - if triggered { - return; - } - let triggered = transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, args); - if triggered { - return; - } - let triggered = transmute_int_to_bool::check(cx, e, from_ty, to_ty, args); - if triggered { - return; - } - let triggered = transmute_int_to_float::check(cx, e, from_ty, to_ty, args, const_context); - if triggered { - return; - } - let triggered = transmute_float_to_int::check(cx, e, from_ty, to_ty, args, const_context); - if triggered { - return; - } - let triggered = unsound_collection_transmute::check(cx, e, from_ty, to_ty); - if triggered { - return; - } - let triggered = transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, to_ty, args); - if triggered { - return; + + let mut linted = wrong_transmute::check(cx, e, from_ty, to_ty); + linted |= crosspointer_transmute::check(cx, e, from_ty, to_ty); + linted |= transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, args, qpath); + linted |= transmute_int_to_char::check(cx, e, from_ty, to_ty, args); + linted |= transmute_ref_to_ref::check(cx, e, from_ty, to_ty, args, const_context); + linted |= transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, args); + linted |= transmute_int_to_bool::check(cx, e, from_ty, to_ty, args); + linted |= transmute_int_to_float::check(cx, e, from_ty, to_ty, args, const_context); + linted |= transmute_float_to_int::check(cx, e, from_ty, to_ty, args, const_context); + linted |= unsound_collection_transmute::check(cx, e, from_ty, to_ty); + + if !linted { + transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, to_ty, args); } } } From bf000985f50af1e506709ea5d735a35fac13925c Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Thu, 11 Feb 2021 01:42:12 +0900 Subject: [PATCH 17/17] Make check_cast private --- clippy_lints/src/transmute/utils.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/clippy_lints/src/transmute/utils.rs b/clippy_lints/src/transmute/utils.rs index 734a92d50d2a..55008d8ec3f1 100644 --- a/clippy_lints/src/transmute/utils.rs +++ b/clippy_lints/src/transmute/utils.rs @@ -68,12 +68,7 @@ pub(super) fn can_be_expressed_as_pointer_cast<'tcx>( /// the cast. In certain cases, including some invalid casts from array references /// to pointers, this may cause additional errors to be emitted and/or ICE error /// messages. This function will panic if that occurs. -pub(super) fn check_cast<'tcx>( - cx: &LateContext<'tcx>, - e: &'tcx Expr<'_>, - from_ty: Ty<'tcx>, - to_ty: Ty<'tcx>, -) -> Option { +fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option { let hir_id = e.hir_id; let local_def_id = hir_id.owner;