|
| 1 | +mod utils; |
| 2 | +use utils::*; |
| 3 | + |
1 | 4 | use crate::utils::{
|
2 |
| - in_constant, is_normalizable, last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_sugg, |
3 |
| - span_lint_and_then, sugg, |
| 5 | + in_constant, match_def_path, paths, snippet, span_lint, span_lint_and_sugg, span_lint_and_then, sugg, |
4 | 6 | };
|
5 | 7 | use if_chain::if_chain;
|
6 | 8 | use rustc_ast as ast;
|
7 | 9 | use rustc_errors::Applicability;
|
8 |
| -use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, TyKind, UnOp}; |
| 10 | +use rustc_hir::{Expr, ExprKind, Mutability, UnOp}; |
9 | 11 | use rustc_lint::{LateContext, LateLintPass};
|
10 |
| -use rustc_middle::ty::{self, cast::CastKind, Ty}; |
| 12 | +use rustc_middle::ty; |
11 | 13 | use rustc_session::{declare_lint_pass, declare_tool_lint};
|
12 |
| -use rustc_span::DUMMY_SP; |
13 |
| -use rustc_typeck::check::{cast::CastCheck, FnCtxt, Inherited}; |
14 | 14 | use std::borrow::Cow;
|
15 | 15 |
|
16 | 16 | declare_clippy_lint! {
|
@@ -326,6 +326,7 @@ static COLLECTIONS: &[&[&str]] = &[
|
326 | 326 | &paths::HASHSET,
|
327 | 327 | &paths::HASHMAP,
|
328 | 328 | ];
|
| 329 | + |
329 | 330 | impl<'tcx> LateLintPass<'tcx> for Transmute {
|
330 | 331 | #[allow(clippy::similar_names, clippy::too_many_lines)]
|
331 | 332 | fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
@@ -664,100 +665,3 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
|
664 | 665 | }
|
665 | 666 | }
|
666 | 667 | }
|
667 |
| - |
668 |
| -/// Gets the snippet of `Bar` in `…::transmute<Foo, &Bar>`. If that snippet is |
669 |
| -/// not available , use |
670 |
| -/// the type's `ToString` implementation. In weird cases it could lead to types |
671 |
| -/// with invalid `'_` |
672 |
| -/// lifetime, but it should be rare. |
673 |
| -fn get_type_snippet(cx: &LateContext<'_>, path: &QPath<'_>, to_ref_ty: Ty<'_>) -> String { |
674 |
| - let seg = last_path_segment(path); |
675 |
| - if_chain! { |
676 |
| - if let Some(ref params) = seg.args; |
677 |
| - if !params.parenthesized; |
678 |
| - if let Some(to_ty) = params.args.iter().filter_map(|arg| match arg { |
679 |
| - GenericArg::Type(ty) => Some(ty), |
680 |
| - _ => None, |
681 |
| - }).nth(1); |
682 |
| - if let TyKind::Rptr(_, ref to_ty) = to_ty.kind; |
683 |
| - then { |
684 |
| - return snippet(cx, to_ty.ty.span, &to_ref_ty.to_string()).to_string(); |
685 |
| - } |
686 |
| - } |
687 |
| - |
688 |
| - to_ref_ty.to_string() |
689 |
| -} |
690 |
| - |
691 |
| -// check if the component types of the transmuted collection and the result have different ABI, |
692 |
| -// size or alignment |
693 |
| -fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool { |
694 |
| - let empty_param_env = ty::ParamEnv::empty(); |
695 |
| - // check if `from` and `to` are normalizable to avoid ICE (#4968) |
696 |
| - if !(is_normalizable(cx, empty_param_env, from) && is_normalizable(cx, empty_param_env, to)) { |
697 |
| - return false; |
698 |
| - } |
699 |
| - let from_ty_layout = cx.tcx.layout_of(empty_param_env.and(from)); |
700 |
| - let to_ty_layout = cx.tcx.layout_of(empty_param_env.and(to)); |
701 |
| - if let (Ok(from_layout), Ok(to_layout)) = (from_ty_layout, to_ty_layout) { |
702 |
| - from_layout.size != to_layout.size || from_layout.align != to_layout.align || from_layout.abi != to_layout.abi |
703 |
| - } else { |
704 |
| - // no idea about layout, so don't lint |
705 |
| - false |
706 |
| - } |
707 |
| -} |
708 |
| - |
709 |
| -/// Check if the type conversion can be expressed as a pointer cast, instead of |
710 |
| -/// a transmute. In certain cases, including some invalid casts from array |
711 |
| -/// references to pointers, this may cause additional errors to be emitted and/or |
712 |
| -/// ICE error messages. This function will panic if that occurs. |
713 |
| -fn can_be_expressed_as_pointer_cast<'tcx>( |
714 |
| - cx: &LateContext<'tcx>, |
715 |
| - e: &'tcx Expr<'_>, |
716 |
| - from_ty: Ty<'tcx>, |
717 |
| - to_ty: Ty<'tcx>, |
718 |
| -) -> bool { |
719 |
| - use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast}; |
720 |
| - matches!( |
721 |
| - check_cast(cx, e, from_ty, to_ty), |
722 |
| - Some(PtrPtrCast | PtrAddrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) |
723 |
| - ) |
724 |
| -} |
725 |
| - |
726 |
| -/// If a cast from `from_ty` to `to_ty` is valid, returns an Ok containing the kind of |
727 |
| -/// the cast. In certain cases, including some invalid casts from array references |
728 |
| -/// to pointers, this may cause additional errors to be emitted and/or ICE error |
729 |
| -/// messages. This function will panic if that occurs. |
730 |
| -fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option<CastKind> { |
731 |
| - let hir_id = e.hir_id; |
732 |
| - let local_def_id = hir_id.owner; |
733 |
| - |
734 |
| - Inherited::build(cx.tcx, local_def_id).enter(|inherited| { |
735 |
| - let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, hir_id); |
736 |
| - |
737 |
| - // If we already have errors, we can't be sure we can pointer cast. |
738 |
| - assert!( |
739 |
| - !fn_ctxt.errors_reported_since_creation(), |
740 |
| - "Newly created FnCtxt contained errors" |
741 |
| - ); |
742 |
| - |
743 |
| - if let Ok(check) = CastCheck::new( |
744 |
| - &fn_ctxt, e, from_ty, to_ty, |
745 |
| - // We won't show any error to the user, so we don't care what the span is here. |
746 |
| - DUMMY_SP, DUMMY_SP, |
747 |
| - ) { |
748 |
| - let res = check.do_check(&fn_ctxt); |
749 |
| - |
750 |
| - // do_check's documentation says that it might return Ok and create |
751 |
| - // errors in the fcx instead of returing Err in some cases. Those cases |
752 |
| - // should be filtered out before getting here. |
753 |
| - assert!( |
754 |
| - !fn_ctxt.errors_reported_since_creation(), |
755 |
| - "`fn_ctxt` contained errors after cast check!" |
756 |
| - ); |
757 |
| - |
758 |
| - res.ok() |
759 |
| - } else { |
760 |
| - None |
761 |
| - } |
762 |
| - }) |
763 |
| -} |
0 commit comments