summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_utils/src/sugg.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs120
1 files changed, 61 insertions, 59 deletions
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index cca71bbf7..aad7da61a 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -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;
@@ -10,19 +12,19 @@ use rustc_ast_pretty::pprust::token_kind_to_string;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind};
+use rustc_hir_typeck::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 @@ impl<'a> Sugg<'a> {
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 @@ impl<'a> Sugg<'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 @@ impl<'a> Sugg<'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 @@ impl<'a> Sugg<'a> {
| 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 @@ impl<'a> Sugg<'a> {
| 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 @@ impl<'a> Sugg<'a> {
/// 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 @@ impl<'a> Sugg<'a> {
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())
},
}
}
@@ -375,20 +381,18 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
| AssocOp::Greater
| AssocOp::GreaterEqual => {
format!(
- "{} {} {}",
- lhs,
- op.to_ast_binop().expect("Those are AST ops").to_string(),
- rhs
+ "{lhs} {} {rhs}",
+ op.to_ast_binop().expect("Those are AST ops").to_string()
)
},
- AssocOp::Assign => format!("{} = {}", lhs, rhs),
+ 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}"),
}
}
@@ -519,7 +523,7 @@ impl<T: Display> Display for ParenHelper<T> {
/// 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.
@@ -740,7 +744,7 @@ impl<T: LintContext> DiagnosticExt<T> for rustc_errors::Diagnostic {
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);
}
}
@@ -754,21 +758,20 @@ impl<T: LintContext> DiagnosticExt<T> for rustc_errors::Diagnostic {
.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);
}
}
fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability) {
let mut remove_span = item;
- let hi = cx.sess().source_map().next_point(remove_span).hi();
- let fmpos = cx.sess().source_map().lookup_byte_offset(hi);
+ let fmpos = cx.sess().source_map().lookup_byte_offset(remove_span.hi());
if let Some(ref src) = fmpos.sf.src {
let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n');
@@ -819,10 +822,9 @@ pub fn deref_closure_args<'tcx>(cx: &LateContext<'_>, closure: &'tcx hir::Expr<'
};
let fn_def_id = cx.tcx.hir().local_def_id(closure.hir_id);
- cx.tcx.infer_ctxt().enter(|infcx| {
- ExprUseVisitor::new(&mut visitor, &infcx, fn_def_id, cx.param_env, cx.typeck_results())
- .consume_body(closure_body);
- });
+ let infcx = cx.tcx.infer_ctxt().build();
+ ExprUseVisitor::new(&mut visitor, &infcx, fn_def_id, cx.param_env, cx.typeck_results())
+ .consume_body(closure_body);
if !visitor.suggestion_start.is_empty() {
return Some(DerefClosure {
@@ -859,7 +861,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 {
@@ -921,7 +923,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
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()`
@@ -936,7 +938,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
// 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);
+ let _ = write!(self.suggestion_start, "{start_snip}{ident_str_with_proj}");
self.next_pos = span.hi();
return;
},
@@ -969,9 +971,9 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
} 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();
@@ -1038,13 +1040,13 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
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();
}
@@ -1052,7 +1054,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
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, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
}
#[cfg(test)]