]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | use crate::utils::{match_def_path, match_qpath, paths, span_lint}; |
2 | use if_chain::if_chain; | |
3 | use rustc_hir as hir; | |
4 | use rustc_lint::LateContext; | |
5 | use rustc_middle::ty::{self, Ty}; | |
6 | ||
7 | use super::UNINIT_ASSUMED_INIT; | |
8 | ||
9 | /// lint for `MaybeUninit::uninit().assume_init()` (we already have the latter) | |
10 | pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, outer: &hir::Expr<'_>) { | |
11 | if_chain! { | |
12 | if let hir::ExprKind::Call(ref callee, ref args) = expr.kind; | |
13 | if args.is_empty(); | |
14 | if let hir::ExprKind::Path(ref path) = callee.kind; | |
15 | if match_qpath(path, &paths::MEM_MAYBEUNINIT_UNINIT); | |
16 | if !is_maybe_uninit_ty_valid(cx, cx.typeck_results().expr_ty_adjusted(outer)); | |
17 | then { | |
18 | span_lint( | |
19 | cx, | |
20 | UNINIT_ASSUMED_INIT, | |
21 | outer.span, | |
22 | "this call for this type may be undefined behavior" | |
23 | ); | |
24 | } | |
25 | } | |
26 | } | |
27 | ||
28 | fn is_maybe_uninit_ty_valid(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { | |
29 | match ty.kind() { | |
30 | ty::Array(ref component, _) => is_maybe_uninit_ty_valid(cx, component), | |
31 | ty::Tuple(ref types) => types.types().all(|ty| is_maybe_uninit_ty_valid(cx, ty)), | |
32 | ty::Adt(ref adt, _) => match_def_path(cx, adt.did, &paths::MEM_MAYBEUNINIT), | |
33 | _ => false, | |
34 | } | |
35 | } |