diff options
Diffstat (limited to '')
-rw-r--r-- | src/tools/clippy/clippy_utils/src/sugg.rs | 120 |
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)] |