]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/types.rs
Auto merge of #4544 - JoshMcguigan:issue-4542, r=flip1995
[rust.git] / clippy_lints / src / types.rs
index f11bcf25aec4b1f16fad9253ded65bad2ede29a3..5696c2be12a8c6bb801d249f68509d48a3794108 100644 (file)
 use syntax::ast::{FloatTy, IntTy, LitIntType, LitKind, UintTy};
 use syntax::errors::DiagnosticBuilder;
 use syntax::source_map::Span;
-use syntax::symbol::sym;
+use syntax::symbol::{sym, Symbol};
 
 use crate::consts::{constant, Constant};
 use crate::utils::paths;
 use crate::utils::{
     clip, comparisons, differing_macro_contexts, higher, in_constant, int_bits, last_path_segment, match_def_path,
-    match_path, multispan_sugg, same_tys, sext, snippet, snippet_opt, snippet_with_applicability,
+    match_path, multispan_sugg, qpath_res, same_tys, sext, snippet, snippet_opt, snippet_with_applicability,
     snippet_with_macro_callsite, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext,
 };
 
@@ -218,7 +218,7 @@ fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str])
             _ => None,
         });
         if let TyKind::Path(ref qpath) = ty.node;
-        if let Some(did) = cx.tables.qpath_res(qpath, ty.hir_id).opt_def_id();
+        if let Some(did) = qpath_res(cx, qpath, ty.hir_id).opt_def_id();
         if match_def_path(cx, did, path);
         then {
             return true;
@@ -240,7 +240,7 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) {
     match hir_ty.node {
         TyKind::Path(ref qpath) if !is_local => {
             let hir_id = hir_ty.hir_id;
-            let res = cx.tables.qpath_res(qpath, hir_id);
+            let res = qpath_res(cx, qpath, hir_id);
             if let Some(def_id) = res.opt_def_id() {
                 if Some(def_id) == cx.tcx.lang_items().owned_box() {
                     if match_type_parameter(cx, qpath, &paths::VEC) {
@@ -253,7 +253,7 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) {
                         );
                         return; // don't recurse into the type
                     }
-                } else if match_def_path(cx, def_id, &paths::VEC) {
+                } else if cx.tcx.is_diagnostic_item(Symbol::intern("vec_type"), def_id) {
                     if_chain! {
                         // Get the _ part of Vec<_>
                         if let Some(ref last) = last_path_segment(qpath).args;
@@ -263,7 +263,7 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) {
                         });
                         // ty is now _ at this point
                         if let TyKind::Path(ref ty_qpath) = ty.node;
-                        let res = cx.tables.qpath_res(ty_qpath, ty.hir_id);
+                        let res = qpath_res(cx, ty_qpath, ty.hir_id);
                         if let Some(def_id) = res.opt_def_id();
                         if Some(def_id) == cx.tcx.lang_items().owned_box();
                         // At this point, we know ty is Box<T>, now get T
@@ -369,7 +369,7 @@ fn check_ty_rptr(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool, lt:
     match mut_ty.ty.node {
         TyKind::Path(ref qpath) => {
             let hir_id = mut_ty.ty.hir_id;
-            let def = cx.tables.qpath_res(qpath, hir_id);
+            let def = qpath_res(cx, qpath, hir_id);
             if_chain! {
                 if let Some(def_id) = def.opt_def_id();
                 if Some(def_id) == cx.tcx.lang_items().owned_box();
@@ -765,7 +765,7 @@ fn is_unit_literal(expr: &Expr) -> bool {
     /// }
     /// ```
     pub CAST_LOSSLESS,
-    complexity,
+    pedantic,
     "casts using `as` that are known to be lossless, e.g., `x as u64` where `x: u8`"
 }
 
@@ -1158,83 +1158,97 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
                 }
             }
             if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
-                match (cast_from.is_integral(), cast_to.is_integral()) {
-                    (true, false) => {
-                        let from_nbits = int_ty_to_nbits(cast_from, cx.tcx);
-                        let to_nbits = if let ty::Float(FloatTy::F32) = cast_to.sty {
-                            32
-                        } else {
-                            64
-                        };
-                        if is_isize_or_usize(cast_from) || from_nbits >= to_nbits {
-                            span_precision_loss_lint(cx, expr, cast_from, to_nbits == 64);
-                        }
-                        if from_nbits < to_nbits {
-                            span_lossless_lint(cx, expr, ex, cast_from, cast_to);
-                        }
-                    },
-                    (false, true) => {
-                        span_lint(
-                            cx,
-                            CAST_POSSIBLE_TRUNCATION,
-                            expr.span,
-                            &format!("casting {} to {} may truncate the value", cast_from, cast_to),
-                        );
-                        if !cast_to.is_signed() {
-                            span_lint(
-                                cx,
-                                CAST_SIGN_LOSS,
-                                expr.span,
-                                &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to),
-                            );
-                        }
-                    },
-                    (true, true) => {
-                        check_loss_of_sign(cx, expr, ex, cast_from, cast_to);
-                        check_truncation_and_wrapping(cx, expr, cast_from, cast_to);
-                        check_lossless(cx, expr, ex, cast_from, cast_to);
-                    },
-                    (false, false) => {
-                        if let (&ty::Float(FloatTy::F64), &ty::Float(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) {
-                            span_lint(
-                                cx,
-                                CAST_POSSIBLE_TRUNCATION,
-                                expr.span,
-                                "casting f64 to f32 may truncate the value",
-                            );
-                        }
-                        if let (&ty::Float(FloatTy::F32), &ty::Float(FloatTy::F64)) = (&cast_from.sty, &cast_to.sty) {
-                            span_lossless_lint(cx, expr, ex, cast_from, cast_to);
-                        }
-                    },
-                }
+                lint_numeric_casts(cx, expr, ex, cast_from, cast_to);
             }
 
-            if_chain! {
-                if let ty::RawPtr(from_ptr_ty) = &cast_from.sty;
-                if let ty::RawPtr(to_ptr_ty) = &cast_to.sty;
-                if let Ok(from_layout) = cx.layout_of(from_ptr_ty.ty);
-                if let Ok(to_layout) = cx.layout_of(to_ptr_ty.ty);
-                if from_layout.align.abi < to_layout.align.abi;
-                // with c_void, we inherently need to trust the user
-                if !is_c_void(cx, from_ptr_ty.ty);
-                // when casting from a ZST, we don't know enough to properly lint
-                if !from_layout.is_zst();
-                then {
-                    span_lint(
-                        cx,
-                        CAST_PTR_ALIGNMENT,
-                        expr.span,
-                        &format!(
-                            "casting from `{}` to a more-strictly-aligned pointer (`{}`) ({} < {} bytes)",
-                            cast_from,
-                            cast_to,
-                            from_layout.align.abi.bytes(),
-                            to_layout.align.abi.bytes(),
-                        ),
-                    );
-                }
+            lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
+        }
+    }
+}
+
+fn lint_numeric_casts<'tcx>(
+    cx: &LateContext<'_, 'tcx>,
+    expr: &Expr,
+    cast_expr: &Expr,
+    cast_from: Ty<'tcx>,
+    cast_to: Ty<'tcx>,
+) {
+    match (cast_from.is_integral(), cast_to.is_integral()) {
+        (true, false) => {
+            let from_nbits = int_ty_to_nbits(cast_from, cx.tcx);
+            let to_nbits = if let ty::Float(FloatTy::F32) = cast_to.sty {
+                32
+            } else {
+                64
+            };
+            if is_isize_or_usize(cast_from) || from_nbits >= to_nbits {
+                span_precision_loss_lint(cx, expr, cast_from, to_nbits == 64);
+            }
+            if from_nbits < to_nbits {
+                span_lossless_lint(cx, expr, cast_expr, cast_from, cast_to);
+            }
+        },
+        (false, true) => {
+            span_lint(
+                cx,
+                CAST_POSSIBLE_TRUNCATION,
+                expr.span,
+                &format!("casting {} to {} may truncate the value", cast_from, cast_to),
+            );
+            if !cast_to.is_signed() {
+                span_lint(
+                    cx,
+                    CAST_SIGN_LOSS,
+                    expr.span,
+                    &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to),
+                );
+            }
+        },
+        (true, true) => {
+            check_loss_of_sign(cx, expr, cast_expr, cast_from, cast_to);
+            check_truncation_and_wrapping(cx, expr, cast_from, cast_to);
+            check_lossless(cx, expr, cast_expr, cast_from, cast_to);
+        },
+        (false, false) => {
+            if let (&ty::Float(FloatTy::F64), &ty::Float(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) {
+                span_lint(
+                    cx,
+                    CAST_POSSIBLE_TRUNCATION,
+                    expr.span,
+                    "casting f64 to f32 may truncate the value",
+                );
+            }
+            if let (&ty::Float(FloatTy::F32), &ty::Float(FloatTy::F64)) = (&cast_from.sty, &cast_to.sty) {
+                span_lossless_lint(cx, expr, cast_expr, cast_from, cast_to);
             }
+        },
+    }
+}
+
+fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &Expr, cast_from: Ty<'tcx>, cast_to: Ty<'tcx>) {
+    if_chain! {
+        if let ty::RawPtr(from_ptr_ty) = &cast_from.sty;
+        if let ty::RawPtr(to_ptr_ty) = &cast_to.sty;
+        if let Ok(from_layout) = cx.layout_of(from_ptr_ty.ty);
+        if let Ok(to_layout) = cx.layout_of(to_ptr_ty.ty);
+        if from_layout.align.abi < to_layout.align.abi;
+        // with c_void, we inherently need to trust the user
+        if !is_c_void(cx, from_ptr_ty.ty);
+        // when casting from a ZST, we don't know enough to properly lint
+        if !from_layout.is_zst();
+        then {
+            span_lint(
+                cx,
+                CAST_PTR_ALIGNMENT,
+                expr.span,
+                &format!(
+                    "casting from `{}` to a more-strictly-aligned pointer (`{}`) ({} < {} bytes)",
+                    cast_from,
+                    cast_to,
+                    from_layout.align.abi.bytes(),
+                    to_layout.align.abi.bytes(),
+                ),
+            );
         }
     }
 }