]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/misc.rs
Update Clippy for MethodCall changes
[rust.git] / clippy_lints / src / misc.rs
index 58a5a29eb16bc8f70bf793e749e537aaae7a6a52..a0947608e60776dc0db4ab3a43addc0871f72f10 100644 (file)
@@ -9,12 +9,13 @@
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{ExpnKind, Span};
 
 use crate::consts::{constant, Constant};
 use crate::utils::sugg::Sugg;
 use crate::utils::{
-    get_item_name, get_parent_expr, implements_trait, in_constant, is_integer_const, iter_input_pats,
+    get_item_name, get_parent_expr, higher, implements_trait, in_constant, is_integer_const, iter_input_pats,
     last_path_segment, match_qpath, match_trait_method, paths, snippet, snippet_opt, span_lint, span_lint_and_sugg,
     span_lint_and_then, span_lint_hir_and_then, walk_ptrs_ty, SpanlessEq,
 };
     /// dereferences, e.g., changing `*x` to `x` within the function.
     ///
     /// **Example:**
-    /// ```rust
+    /// ```rust,ignore
+    /// // Bad
     /// fn foo(ref x: u8) -> bool {
     ///     true
     /// }
+    ///
+    /// // Good
+    /// fn foo(x: &u8) -> bool {
+    ///     true
+    /// }
     /// ```
     pub TOPLEVEL_REF_ARG,
     style,
     /// ```rust
     /// # let x = 1.0;
     ///
+    /// // Bad
     /// if x == f32::NAN { }
+    ///
+    /// // Good
+    /// if x.is_nan() { }
     /// ```
     pub CMP_NAN,
     correctness,
     /// ```rust
     /// let x = 1.2331f64;
     /// let y = 1.2332f64;
+    ///
+    /// // Bad
     /// if y == 1.23f64 { }
     /// if y != x {} // where both are floats
+    ///
+    /// // Good
+    /// let error = 0.01f64; // Use an epsilon for comparison
+    /// if (y - 1.23f64).abs() < error { }
+    /// if (y - x).abs() > error { }
     /// ```
     pub FLOAT_CMP,
     correctness,
     /// **Example:**
     ///
     /// ```rust
+    /// // Bad
     /// let a = 0 as *const u32;
+    ///
+    /// // Good
+    /// let a = std::ptr::null::<u32>();
     /// ```
     pub ZERO_PTR,
     style,
     /// ```rust
     /// let x: f64 = 1.0;
     /// const ONE: f64 = 1.00;
-    /// x == ONE;  // where both are floats
+    ///
+    /// // Bad
+    /// if x == ONE { }  // where both are floats
+    ///
+    /// // Good
+    /// let error = 0.1f64; // Use an epsilon for comparison
+    /// if (x - ONE).abs() < error { }
     /// ```
     pub FLOAT_CMP_CONST,
     restriction,
@@ -247,17 +275,14 @@ fn check_fn(
             return;
         }
         for arg in iter_input_pats(decl, body) {
-            match arg.pat.kind {
-                PatKind::Binding(BindingAnnotation::Ref, ..) | PatKind::Binding(BindingAnnotation::RefMut, ..) => {
-                    span_lint(
-                        cx,
-                        TOPLEVEL_REF_ARG,
-                        arg.pat.span,
-                        "`ref` directly on a function argument is ignored. Consider using a reference type \
-                         instead.",
-                    );
-                },
-                _ => {},
+            if let PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..) = arg.pat.kind {
+                span_lint(
+                    cx,
+                    TOPLEVEL_REF_ARG,
+                    arg.pat.span,
+                    "`ref` directly on a function argument is ignored. \
+                    Consider using a reference type instead.",
+                );
             }
         }
     }
@@ -267,6 +292,7 @@ fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt<'_>) {
             if let StmtKind::Local(ref local) = stmt.kind;
             if let PatKind::Binding(an, .., name, None) = local.pat.kind;
             if let Some(ref init) = local.init;
+            if !higher::is_from_for_desugar(local);
             then {
                 if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut {
                     let sugg_init = if init.span.from_expansion() {
@@ -290,8 +316,8 @@ fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt<'_>) {
                         init.hir_id,
                         local.pat.span,
                         "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead",
-                        |db| {
-                            db.span_suggestion(
+                        |diag| {
+                            diag.span_suggestion(
                                 stmt.span,
                                 "try",
                                 format!(
@@ -317,9 +343,9 @@ fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt<'_>) {
                     SHORT_CIRCUIT_STATEMENT,
                     stmt.span,
                     "boolean short circuit operator in statement may be clearer using an explicit test",
-                    |db| {
+                    |diag| {
                         let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg };
-                        db.span_suggestion(
+                        diag.span_suggestion(
                             stmt.span,
                             "replace it with",
                             format!(
@@ -374,12 +400,12 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
                         is_named_constant(cx, left) || is_named_constant(cx, right),
                         is_comparing_arrays,
                     );
-                    span_lint_and_then(cx, lint, expr.span, msg, |db| {
+                    span_lint_and_then(cx, lint, expr.span, msg, |diag| {
                         let lhs = Sugg::hir(cx, left, "..");
                         let rhs = Sugg::hir(cx, right, "..");
 
                         if !is_comparing_arrays {
-                            db.span_suggestion(
+                            diag.span_suggestion(
                                 expr.span,
                                 "consider comparing them within some error",
                                 format!(
@@ -390,7 +416,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
                                 Applicability::HasPlaceholders, // snippet
                             );
                         }
-                        db.note("`f32::EPSILON` and `f64::EPSILON` are available for the `error`");
+                        diag.note("`f32::EPSILON` and `f64::EPSILON` are available for the `error`");
                     });
                 } else if op == BinOpKind::Rem && is_integer_const(cx, right, 1) {
                     span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0");
@@ -398,8 +424,8 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
             },
             _ => {},
         }
-        if in_attributes_expansion(expr) {
-            // Don't lint things expanded by #[derive(...)], etc
+        if in_attributes_expansion(expr) || expr.span.is_desugaring(DesugaringKind::Await) {
+            // Don't lint things expanded by #[derive(...)], etc or `await` desugaring
             return;
         }
         let binding = match expr.kind {
@@ -519,7 +545,7 @@ fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
     }
 
     if_chain! {
-        if let ExprKind::MethodCall(ref method_name, _, ref expressions) = expr.kind;
+        if let ExprKind::MethodCall(ref method_name, _, ref expressions, _) = expr.kind;
         if sym!(signum) == method_name.ident.name;
         // Check that the receiver of the signum() is a float (expressions[0] is the receiver of
         // the method call)
@@ -546,7 +572,7 @@ fn is_array(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
 
 fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) {
     let (arg_ty, snip) = match expr.kind {
-        ExprKind::MethodCall(.., ref args) if args.len() == 1 => {
+        ExprKind::MethodCall(.., ref args, _) if args.len() == 1 => {
             if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) {
                 (cx.tables.expr_ty_adjusted(&args[0]), snippet(cx, args[0].span, ".."))
             } else {
@@ -601,10 +627,10 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) {
         CMP_OWNED,
         lint_span,
         "this creates an owned instance just for comparison",
-        |db| {
+        |diag| {
             // This also catches `PartialEq` implementations that call `to_owned`.
             if other_gets_derefed {
-                db.span_label(lint_span, "try implementing the comparison without allocating");
+                diag.span_label(lint_span, "try implementing the comparison without allocating");
                 return;
             }
 
@@ -616,7 +642,7 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) {
                 snip.to_string()
             };
 
-            db.span_suggestion(
+            diag.span_suggestion(
                 lint_span,
                 "try",
                 try_hint,