summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
blob: 831b0d450d20a7f933a6bd380dc370db37710a9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
use super::utils::is_layout_incompatible;
use super::UNSOUND_COLLECTION_TRANSMUTE;
use clippy_utils::diagnostics::span_lint;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::sym;

/// 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() {
                return false;
            }
            if !matches!(
                cx.tcx.get_diagnostic_name(to_adt.did()),
                Some(
                    sym::BTreeMap
                        | sym::BTreeSet
                        | sym::BinaryHeap
                        | sym::HashMap
                        | sym::HashSet
                        | sym::Vec
                        | sym::VecDeque
                )
            ) {
                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,
    }
}