]> git.lizzy.rs Git - rust.git/blobdiff - clippy_utils/src/sugg.rs
fix `box-default` linting `no_std` non-boxes
[rust.git] / clippy_utils / src / sugg.rs
index 081c98e2f3ce726ccf9019a46fc4631eefde9a29..f25bced0c2b3dd15ccfb3d6508fd1759002c6006 100644 (file)
@@ -1,7 +1,9 @@
 //! Contains utility functions to generate suggestions.
 #![deny(clippy::missing_docs_in_private_items)]
 
-use crate::source::{snippet, snippet_opt, snippet_with_applicability, snippet_with_macro_callsite};
+use crate::source::{
+    snippet, snippet_opt, snippet_with_applicability, snippet_with_context, snippet_with_macro_callsite,
+};
 use crate::ty::expr_sig;
 use crate::{get_parent_expr_for_hir, higher};
 use rustc_ast::util::parser::AssocOp;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind};
+use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{EarlyContext, LateContext, LintContext};
 use rustc_middle::hir::place::ProjectionKind;
 use rustc_middle::mir::{FakeReadCause, Mutability};
 use rustc_middle::ty;
 use rustc_span::source_map::{BytePos, CharPos, Pos, Span, SyntaxContext};
-use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use std::borrow::Cow;
 use std::fmt::{Display, Write as _};
 use std::ops::{Add, Neg, Not, Sub};
 
 /// A helper type to build suggestion correctly handling parentheses.
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum Sugg<'a> {
     /// An expression that never needs parentheses such as `1337` or `[0; 42]`.
     NonParen(Cow<'a, str>),
@@ -110,7 +112,7 @@ pub fn hir_with_context(
         if expr.span.ctxt() == ctxt {
             Self::hir_from_snippet(expr, |span| snippet(cx, span, default))
         } else {
-            let snip = snippet_with_applicability(cx, expr.span, default, applicability);
+            let (snip, _) = snippet_with_context(cx, expr.span, ctxt, default, applicability);
             Sugg::NonParen(snip)
         }
     }
@@ -155,8 +157,8 @@ fn hir_from_snippet(expr: &hir::Expr<'_>, get_snippet: impl Fn(Span) -> Cow<'a,
             | hir::ExprKind::Ret(..)
             | hir::ExprKind::Struct(..)
             | hir::ExprKind::Tup(..)
-            | hir::ExprKind::DropTemps(_)
             | hir::ExprKind::Err => Sugg::NonParen(get_snippet(expr.span)),
+            hir::ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
             hir::ExprKind::Assign(lhs, rhs, _) => {
                 Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
             },
@@ -177,11 +179,11 @@ fn hir_from_snippet(expr: &hir::Expr<'_>, get_snippet: impl Fn(Span) -> Cow<'a,
     pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self {
         use rustc_ast::ast::RangeLimits;
 
-        let get_whole_snippet = || {
-            if expr.span.from_expansion() {
-                snippet_with_macro_callsite(cx, expr.span, default)
+        let snippet_without_expansion = |cx, span: Span, default| {
+            if span.from_expansion() {
+                snippet_with_macro_callsite(cx, span, default)
             } else {
-                snippet(cx, expr.span, default)
+                snippet(cx, span, default)
             }
         };
 
@@ -192,7 +194,7 @@ pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self {
             | ast::ExprKind::If(..)
             | ast::ExprKind::Let(..)
             | ast::ExprKind::Unary(..)
-            | ast::ExprKind::Match(..) => Sugg::MaybeParen(get_whole_snippet()),
+            | ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet_without_expansion(cx, expr.span, default)),
             ast::ExprKind::Async(..)
             | ast::ExprKind::Block(..)
             | ast::ExprKind::Break(..)
@@ -221,41 +223,45 @@ pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self {
             | ast::ExprKind::Array(..)
             | ast::ExprKind::While(..)
             | ast::ExprKind::Await(..)
-            | ast::ExprKind::Err => Sugg::NonParen(get_whole_snippet()),
+            | ast::ExprKind::Err => Sugg::NonParen(snippet_without_expansion(cx, expr.span, default)),
             ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
                 AssocOp::DotDot,
-                lhs.as_ref().map_or("".into(), |lhs| snippet(cx, lhs.span, default)),
-                rhs.as_ref().map_or("".into(), |rhs| snippet(cx, rhs.span, default)),
+                lhs.as_ref()
+                    .map_or("".into(), |lhs| snippet_without_expansion(cx, lhs.span, default)),
+                rhs.as_ref()
+                    .map_or("".into(), |rhs| snippet_without_expansion(cx, rhs.span, default)),
             ),
             ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp(
                 AssocOp::DotDotEq,
-                lhs.as_ref().map_or("".into(), |lhs| snippet(cx, lhs.span, default)),
-                rhs.as_ref().map_or("".into(), |rhs| snippet(cx, rhs.span, default)),
+                lhs.as_ref()
+                    .map_or("".into(), |lhs| snippet_without_expansion(cx, lhs.span, default)),
+                rhs.as_ref()
+                    .map_or("".into(), |rhs| snippet_without_expansion(cx, rhs.span, default)),
             ),
             ast::ExprKind::Assign(ref lhs, ref rhs, _) => Sugg::BinOp(
                 AssocOp::Assign,
-                snippet(cx, lhs.span, default),
-                snippet(cx, rhs.span, default),
+                snippet_without_expansion(cx, lhs.span, default),
+                snippet_without_expansion(cx, rhs.span, default),
             ),
             ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
                 astbinop2assignop(op),
-                snippet(cx, lhs.span, default),
-                snippet(cx, rhs.span, default),
+                snippet_without_expansion(cx, lhs.span, default),
+                snippet_without_expansion(cx, rhs.span, default),
             ),
             ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
                 AssocOp::from_ast_binop(op.node),
-                snippet(cx, lhs.span, default),
-                snippet(cx, rhs.span, default),
+                snippet_without_expansion(cx, lhs.span, default),
+                snippet_without_expansion(cx, rhs.span, default),
             ),
             ast::ExprKind::Cast(ref lhs, ref ty) => Sugg::BinOp(
                 AssocOp::As,
-                snippet(cx, lhs.span, default),
-                snippet(cx, ty.span, default),
+                snippet_without_expansion(cx, lhs.span, default),
+                snippet_without_expansion(cx, ty.span, default),
             ),
             ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
                 AssocOp::Colon,
-                snippet(cx, lhs.span, default),
-                snippet(cx, ty.span, default),
+                snippet_without_expansion(cx, lhs.span, default),
+                snippet_without_expansion(cx, ty.span, default),
             ),
         }
     }
@@ -306,19 +312,19 @@ pub fn mut_addr_deref(self) -> Sugg<'static> {
 
     /// Convenience method to transform suggestion into a return call
     pub fn make_return(self) -> Sugg<'static> {
-        Sugg::NonParen(Cow::Owned(format!("return {}", self)))
+        Sugg::NonParen(Cow::Owned(format!("return {self}")))
     }
 
     /// Convenience method to transform suggestion into a block
     /// where the suggestion is a trailing expression
     pub fn blockify(self) -> Sugg<'static> {
-        Sugg::NonParen(Cow::Owned(format!("{{ {} }}", self)))
+        Sugg::NonParen(Cow::Owned(format!("{{ {self} }}")))
     }
 
     /// Convenience method to prefix the expression with the `async` keyword.
     /// Can be used after `blockify` to create an async block.
     pub fn asyncify(self) -> Sugg<'static> {
-        Sugg::NonParen(Cow::Owned(format!("async {}", self)))
+        Sugg::NonParen(Cow::Owned(format!("async {self}")))
     }
 
     /// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>`
@@ -342,12 +348,12 @@ pub fn maybe_par(self) -> Self {
                 if has_enclosing_paren(&sugg) {
                     Sugg::MaybeParen(sugg)
                 } else {
-                    Sugg::NonParen(format!("({})", sugg).into())
+                    Sugg::NonParen(format!("({sugg})").into())
                 }
             },
             Sugg::BinOp(op, lhs, rhs) => {
                 let sugg = binop_to_string(op, &lhs, &rhs);
-                Sugg::NonParen(format!("({})", sugg).into())
+                Sugg::NonParen(format!("({sugg})").into())
             },
         }
     }
@@ -373,20 +379,20 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
         | AssocOp::LessEqual
         | AssocOp::NotEqual
         | AssocOp::Greater
-        | AssocOp::GreaterEqual => format!(
-            "{} {} {}",
-            lhs,
-            op.to_ast_binop().expect("Those are AST ops").to_string(),
-            rhs
-        ),
-        AssocOp::Assign => format!("{} = {}", lhs, rhs),
+        | AssocOp::GreaterEqual => {
+            format!(
+                "{lhs} {} {rhs}",
+                op.to_ast_binop().expect("Those are AST ops").to_string()
+            )
+        },
+        AssocOp::Assign => format!("{lhs} = {rhs}"),
         AssocOp::AssignOp(op) => {
-            format!("{} {}= {}", lhs, token_kind_to_string(&token::BinOp(op)), rhs)
+            format!("{lhs} {}= {rhs}", token_kind_to_string(&token::BinOp(op)))
         },
-        AssocOp::As => format!("{} as {}", lhs, rhs),
-        AssocOp::DotDot => format!("{}..{}", lhs, rhs),
-        AssocOp::DotDotEq => format!("{}..={}", lhs, rhs),
-        AssocOp::Colon => format!("{}: {}", lhs, rhs),
+        AssocOp::As => format!("{lhs} as {rhs}"),
+        AssocOp::DotDot => format!("{lhs}..{rhs}"),
+        AssocOp::DotDotEq => format!("{lhs}..={rhs}"),
+        AssocOp::Colon => format!("{lhs}: {rhs}"),
     }
 }
 
@@ -517,7 +523,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
 /// operators have the same
 /// precedence.
 pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> {
-    Sugg::MaybeParen(format!("{}{}", op, expr.maybe_par()).into())
+    Sugg::MaybeParen(format!("{op}{}", expr.maybe_par()).into())
 }
 
 /// Builds the string for `<lhs> <op> <rhs>` adding parenthesis when necessary.
@@ -738,7 +744,7 @@ fn suggest_item_with_attr<D: Display + ?Sized>(
         if let Some(indent) = indentation(cx, item) {
             let span = item.with_hi(item.lo());
 
-            self.span_suggestion(span, msg, format!("{}\n{}", attr, indent), applicability);
+            self.span_suggestion(span, msg, format!("{attr}\n{indent}"), applicability);
         }
     }
 
@@ -752,14 +758,14 @@ fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str
                 .map(|l| {
                     if first {
                         first = false;
-                        format!("{}\n", l)
+                        format!("{l}\n")
                     } else {
-                        format!("{}{}\n", indent, l)
+                        format!("{indent}{l}\n")
                     }
                 })
                 .collect::<String>();
 
-            self.span_suggestion(span, msg, format!("{}\n{}", new_item, indent), applicability);
+            self.span_suggestion(span, msg, format!("{new_item}\n{indent}"), applicability);
         }
     }
 
@@ -857,7 +863,7 @@ impl<'tcx> DerefDelegate<'_, 'tcx> {
     pub fn finish(&mut self) -> String {
         let end_span = Span::new(self.next_pos, self.closure_span.hi(), self.closure_span.ctxt(), None);
         let end_snip = snippet_with_applicability(self.cx, end_span, "..", &mut self.applicability);
-        let sugg = format!("{}{}", self.suggestion_start, end_snip);
+        let sugg = format!("{}{end_snip}", self.suggestion_start);
         if self.closure_arg_is_type_annotated_double_ref {
             sugg.replacen('&', "", 1)
         } else {
@@ -868,15 +874,15 @@ pub fn finish(&mut self) -> String {
     /// indicates whether the function from `parent_expr` takes its args by double reference
     fn func_takes_arg_by_double_ref(&self, parent_expr: &'tcx hir::Expr<'_>, cmt_hir_id: HirId) -> bool {
         let ty = match parent_expr.kind {
-            ExprKind::MethodCall(_, call_args, _) => {
+            ExprKind::MethodCall(_, receiver, call_args, _) => {
                 if let Some(sig) = self
                     .cx
                     .typeck_results()
                     .type_dependent_def_id(parent_expr.hir_id)
                     .map(|did| self.cx.tcx.fn_sig(did).skip_binder())
                 {
-                    call_args
-                        .iter()
+                    std::iter::once(receiver)
+                        .chain(call_args.iter())
                         .position(|arg| arg.hir_id == cmt_hir_id)
                         .map(|i| sig.inputs()[i])
                 } else {
@@ -919,7 +925,7 @@ fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
             if cmt.place.projections.is_empty() {
                 // handle item without any projection, that needs an explicit borrowing
                 // i.e.: suggest `&x` instead of `x`
-                let _ = write!(self.suggestion_start, "{}&{}", start_snip, ident_str);
+                let _ = write!(self.suggestion_start, "{start_snip}&{ident_str}");
             } else {
                 // cases where a parent `Call` or `MethodCall` is using the item
                 // i.e.: suggest `.contains(&x)` for `.find(|x| [1, 2, 3].contains(x)).is_none()`
@@ -933,14 +939,14 @@ fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
                     match &parent_expr.kind {
                         // given expression is the self argument and will be handled completely by the compiler
                         // i.e.: `|x| x.is_something()`
-                        ExprKind::MethodCall(_, [self_expr, ..], _) if self_expr.hir_id == cmt.hir_id => {
-                            let _ = write!(self.suggestion_start, "{}{}", start_snip, ident_str_with_proj);
+                        ExprKind::MethodCall(_, self_expr, ..) if self_expr.hir_id == cmt.hir_id => {
+                            let _ = write!(self.suggestion_start, "{start_snip}{ident_str_with_proj}");
                             self.next_pos = span.hi();
                             return;
                         },
                         // item is used in a call
                         // i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)`
-                        ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, [_, call_args @ ..], _) => {
+                        ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, _, [call_args @ ..], _) => {
                             let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id);
                             let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind();
 
@@ -967,9 +973,9 @@ fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
                                     } else {
                                         ident_str
                                     };
-                                    format!("{}{}", start_snip, ident)
+                                    format!("{start_snip}{ident}")
                                 } else {
-                                    format!("{}&{}", start_snip, ident_str)
+                                    format!("{start_snip}&{ident_str}")
                                 };
                                 self.suggestion_start.push_str(&ident_sugg);
                                 self.next_pos = span.hi();
@@ -1036,13 +1042,13 @@ fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
 
                         for item in projections {
                             if item.kind == ProjectionKind::Deref {
-                                replacement_str = format!("*{}", replacement_str);
+                                replacement_str = format!("*{replacement_str}");
                             }
                         }
                     }
                 }
 
-                let _ = write!(self.suggestion_start, "{}{}", start_snip, replacement_str);
+                let _ = write!(self.suggestion_start, "{start_snip}{replacement_str}");
             }
             self.next_pos = span.hi();
         }
@@ -1050,7 +1056,13 @@ fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
 
     fn mutate(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
 
-    fn fake_read(&mut self, _: &rustc_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+    fn fake_read(
+        &mut self,
+        _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>,
+        _: FakeReadCause,
+        _: HirId,
+    ) {
+    }
 }
 
 #[cfg(test)]