|
| 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