summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/utils')
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs57
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints.rs61
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs10
4 files changed, 94 insertions, 61 deletions
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index c0726868f..4003fff27 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -6,7 +6,9 @@ use rustc_ast::ast::{LitFloatType, LitKind};
use rustc_ast::LitIntType;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
-use rustc_hir::{ArrayLen, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind};
+use rustc_hir::{
+ ArrayLen, BindingAnnotation, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
+};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::{Ident, Symbol};
@@ -140,7 +142,7 @@ fn check_item(cx: &LateContext<'_>, hir_id: HirId) {
let hir = cx.tcx.hir();
if let Some(body_id) = hir.maybe_body_owned_by(hir_id.expect_owner()) {
check_node(cx, hir_id, |v| {
- v.expr(&v.bind("expr", &hir.body(body_id).value));
+ v.expr(&v.bind("expr", hir.body(body_id).value));
});
}
}
@@ -276,7 +278,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
match lit.value.node {
LitKind::Bool(val) => kind!("Bool({val:?})"),
LitKind::Char(c) => kind!("Char({c:?})"),
- LitKind::Err(val) => kind!("Err({val})"),
+ LitKind::Err => kind!("Err"),
LitKind::Byte(b) => kind!("Byte({b})"),
LitKind::Int(i, suffix) => {
let int_ty = match suffix {
@@ -402,10 +404,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
self.expr(func);
self.slice(args, |e| self.expr(e));
},
- ExprKind::MethodCall(method_name, args, _) => {
- bind!(self, method_name, args);
- kind!("MethodCall({method_name}, {args}, _)");
+ ExprKind::MethodCall(method_name, receiver, args, _) => {
+ bind!(self, method_name, receiver, args);
+ kind!("MethodCall({method_name}, {receiver}, {args}, _)");
self.ident(field!(method_name.ident));
+ self.expr(receiver);
self.slice(args, |e| self.expr(e));
},
ExprKind::Tup(elements) => {
@@ -595,7 +598,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
}
fn body(&self, body_id: &Binding<hir::BodyId>) {
- let expr = &self.cx.tcx.hir().body(body_id.value).value;
+ let expr = self.cx.tcx.hir().body(body_id.value).value;
bind!(self, expr);
out!("let {expr} = &cx.tcx.hir().body({body_id}).value;");
self.expr(expr);
@@ -609,10 +612,16 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
match pat.value.kind {
PatKind::Wild => kind!("Wild"),
- PatKind::Binding(anno, .., name, sub) => {
+ PatKind::Binding(ann, _, name, sub) => {
bind!(self, name);
opt_bind!(self, sub);
- kind!("Binding(BindingAnnotation::{anno:?}, _, {name}, {sub})");
+ let ann = match ann {
+ BindingAnnotation::NONE => "NONE",
+ BindingAnnotation::REF => "REF",
+ BindingAnnotation::MUT => "MUT",
+ BindingAnnotation::REF_MUT => "REF_MUT",
+ };
+ kind!("Binding(BindingAnnotation::{ann}, _, {name}, {sub})");
self.ident(name);
sub.if_some(|p| self.pat(p));
},
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 6e033b3be..a8500beb2 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -30,7 +30,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[
"MinGW",
"CamelCase",
];
-const DEFAULT_BLACKLISTED_NAMES: &[&str] = &["foo", "baz", "quux"];
+const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"];
/// Holds information used by `MISSING_ENFORCED_IMPORT_RENAMES` lint.
#[derive(Clone, Debug, Deserialize)]
@@ -68,6 +68,7 @@ pub enum DisallowedType {
pub struct TryConf {
pub conf: Conf,
pub errors: Vec<Box<dyn Error>>,
+ pub warnings: Vec<Box<dyn Error>>,
}
impl TryConf {
@@ -75,6 +76,7 @@ impl TryConf {
Self {
conf: Conf::default(),
errors: vec![Box::new(error)],
+ warnings: vec![],
}
}
}
@@ -90,14 +92,14 @@ impl fmt::Display for ConfError {
impl Error for ConfError {}
-fn conf_error(s: String) -> Box<dyn Error> {
- Box::new(ConfError(s))
+fn conf_error(s: impl Into<String>) -> Box<dyn Error> {
+ Box::new(ConfError(s.into()))
}
macro_rules! define_Conf {
($(
$(#[doc = $doc:literal])+
- $(#[conf_deprecated($dep:literal)])?
+ $(#[conf_deprecated($dep:literal, $new_conf:ident)])?
($name:ident: $ty:ty = $default:expr),
)*) => {
/// Clippy lint configuration
@@ -137,17 +139,29 @@ macro_rules! define_Conf {
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error> where V: MapAccess<'de> {
let mut errors = Vec::new();
+ let mut warnings = Vec::new();
$(let mut $name = None;)*
// could get `Field` here directly, but get `str` first for diagnostics
while let Some(name) = map.next_key::<&str>()? {
match Field::deserialize(name.into_deserializer())? {
$(Field::$name => {
- $(errors.push(conf_error(format!("deprecated field `{}`. {}", name, $dep)));)?
+ $(warnings.push(conf_error(format!("deprecated field `{}`. {}", name, $dep)));)?
match map.next_value() {
Err(e) => errors.push(conf_error(e.to_string())),
Ok(value) => match $name {
Some(_) => errors.push(conf_error(format!("duplicate field `{}`", name))),
- None => $name = Some(value),
+ None => {
+ $name = Some(value);
+ // $new_conf is the same as one of the defined `$name`s, so
+ // this variable is defined in line 2 of this function.
+ $(match $new_conf {
+ Some(_) => errors.push(conf_error(concat!(
+ "duplicate field `", stringify!($new_conf),
+ "` (provided as `", stringify!($name), "`)"
+ ))),
+ None => $new_conf = $name.clone(),
+ })?
+ },
}
}
})*
@@ -156,7 +170,7 @@ macro_rules! define_Conf {
}
}
let conf = Conf { $($name: $name.unwrap_or_else(defaults::$name),)* };
- Ok(TryConf { conf, errors })
+ Ok(TryConf { conf, errors, warnings })
}
}
@@ -194,7 +208,7 @@ define_Conf! {
/// Lint: Arithmetic.
///
/// Suppress checking of the passed type names.
- (arithmetic_allowed: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
+ (arithmetic_side_effects_allowed: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
/// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX.
///
/// Suppress lints whenever the suggested change would cause breakage for other crates.
@@ -203,12 +217,11 @@ define_Conf! {
///
/// The minimum rust version that the project supports
(msrv: Option<String> = None),
- /// Lint: BLACKLISTED_NAME.
+ /// DEPRECATED LINT: BLACKLISTED_NAME.
///
- /// The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses. The value
- /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the
- /// default configuration of Clippy. By default any configuraction will replace the default value.
- (blacklisted_names: Vec<String> = super::DEFAULT_BLACKLISTED_NAMES.iter().map(ToString::to_string).collect()),
+ /// Use the Disallowed Names lint instead
+ #[conf_deprecated("Please use `disallowed-names` instead", disallowed_names)]
+ (blacklisted_names: Vec<String> = Vec::new()),
/// Lint: COGNITIVE_COMPLEXITY.
///
/// The maximum cognitive complexity a function can have
@@ -216,8 +229,14 @@ define_Conf! {
/// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY.
///
/// Use the Cognitive Complexity lint instead.
- #[conf_deprecated("Please use `cognitive-complexity-threshold` instead")]
- (cyclomatic_complexity_threshold: Option<u64> = None),
+ #[conf_deprecated("Please use `cognitive-complexity-threshold` instead", cognitive_complexity_threshold)]
+ (cyclomatic_complexity_threshold: u64 = 25),
+ /// Lint: DISALLOWED_NAMES.
+ ///
+ /// The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
+ /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the
+ /// default configuration of Clippy. By default any configuration will replace the default value.
+ (disallowed_names: Vec<String> = super::DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect()),
/// Lint: DOC_MARKDOWN.
///
/// The list of words this lint should not consider as identifiers needing ticks. The value
@@ -331,7 +350,7 @@ define_Conf! {
/// Lint: DISALLOWED_SCRIPT_IDENTS.
///
/// The list of unicode scripts allowed to be used in the scope.
- (allowed_scripts: Vec<String> = ["Latin"].iter().map(ToString::to_string).collect()),
+ (allowed_scripts: Vec<String> = vec!["Latin".to_string()]),
/// Lint: NON_SEND_FIELDS_IN_SEND_TY.
///
/// Whether to apply the raw pointer heuristic to determine if a type is `Send`.
@@ -360,6 +379,10 @@ define_Conf! {
///
/// Whether `dbg!` should be allowed in test functions
(allow_dbg_in_tests: bool = false),
+ /// Lint: RESULT_LARGE_ERR
+ ///
+ /// The maximum size of the `Err`-variant in a `Result` returned from a function
+ (large_error_threshold: u64 = 128),
}
/// Search for the configuration file.
@@ -420,7 +443,7 @@ pub fn read(path: &Path) -> TryConf {
match toml::from_str::<TryConf>(&content) {
Ok(mut conf) => {
extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS);
- extend_vec_if_indicator_present(&mut conf.conf.blacklisted_names, DEFAULT_BLACKLISTED_NAMES);
+ extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES);
conf
},
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
index b30965329..17d9a0418 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
@@ -496,14 +496,16 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
cx,
};
let body_id = cx.tcx.hir().body_owned_by(
- impl_item_refs
- .iter()
- .find(|iiref| iiref.ident.as_str() == "get_lints")
- .expect("LintPass needs to implement get_lints")
- .id
- .hir_id(),
+ cx.tcx.hir().local_def_id(
+ impl_item_refs
+ .iter()
+ .find(|iiref| iiref.ident.as_str() == "get_lints")
+ .expect("LintPass needs to implement get_lints")
+ .id
+ .hir_id(),
+ ),
);
- collector.visit_expr(&cx.tcx.hir().body(body_id).value);
+ collector.visit_expr(cx.tcx.hir().body(body_id).value);
}
}
}
@@ -569,7 +571,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'
item.span,
"this item has an invalid `clippy::version` attribute",
None,
- "please use a valid sematic version, see `doc/adding_lints.md`",
+ "please use a valid semantic version, see `doc/adding_lints.md`",
);
}
} else {
@@ -591,8 +593,8 @@ fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Opt
attrs.iter().find_map(|attr| {
if_chain! {
// Identify attribute
- if let ast::AttrKind::Normal(ref attr_kind, _) = &attr.kind;
- if let [tool_name, attr_name] = &attr_kind.path.segments[..];
+ if let ast::AttrKind::Normal(ref attr_kind) = &attr.kind;
+ if let [tool_name, attr_name] = &attr_kind.item.path.segments[..];
if tool_name.ident.name == sym::clippy;
if attr_name.ident.name == sym::version;
if let Some(version) = attr.value_str();
@@ -651,7 +653,7 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
}
if_chain! {
- if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
+ if let ExprKind::MethodCall(path, self_arg, _, _) = &expr.kind;
let fn_name = path.ident;
if let Some(sugg) = self.map.get(fn_name.as_str());
let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
@@ -683,9 +685,8 @@ impl<'tcx> LateLintPass<'tcx> for OuterExpnDataPass {
let method_names: Vec<&str> = method_names.iter().map(Symbol::as_str).collect();
if_chain! {
if let ["expn_data", "outer_expn"] = method_names.as_slice();
- let args = arg_lists[1];
- if args.len() == 1;
- let self_arg = &args[0];
+ let (self_arg, args)= arg_lists[1];
+ if args.is_empty();
let self_ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
if match_type(cx, self_ty, &paths::SYNTAX_CONTEXT);
then {
@@ -732,30 +733,30 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
if and_then_args.len() == 5;
if let ExprKind::Closure(&Closure { body, .. }) = &and_then_args[4].kind;
let body = cx.tcx.hir().body(body);
- let only_expr = peel_blocks_with_stmt(&body.value);
- if let ExprKind::MethodCall(ps, span_call_args, _) = &only_expr.kind;
- if let ExprKind::Path(..) = span_call_args[0].kind;
+ let only_expr = peel_blocks_with_stmt(body.value);
+ if let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind;
+ if let ExprKind::Path(..) = recv.kind;
then {
let and_then_snippets = get_and_then_snippets(cx, and_then_args);
let mut sle = SpanlessEq::new(cx).deny_side_effects();
match ps.ident.as_str() {
- "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => {
+ "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
suggest_suggestion(cx, expr, &and_then_snippets, &span_suggestion_snippets(cx, span_call_args));
},
- "span_help" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => {
- let help_snippet = snippet(cx, span_call_args[2].span, r#""...""#);
+ "span_help" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
+ let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true);
},
- "span_note" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => {
- let note_snippet = snippet(cx, span_call_args[2].span, r#""...""#);
+ "span_note" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
+ let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true);
},
"help" => {
- let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
+ let help_snippet = snippet(cx, span_call_args[0].span, r#""...""#);
suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false);
}
"note" => {
- let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
+ let note_snippet = snippet(cx, span_call_args[0].span, r#""...""#);
suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false);
}
_ => (),
@@ -796,9 +797,9 @@ fn span_suggestion_snippets<'a, 'hir>(
cx: &LateContext<'_>,
span_call_args: &'hir [Expr<'hir>],
) -> SpanSuggestionSnippets<'a> {
- let help_snippet = snippet(cx, span_call_args[2].span, r#""...""#);
- let sugg_snippet = snippet(cx, span_call_args[3].span, "..");
- let applicability_snippet = snippet(cx, span_call_args[4].span, "Applicability::MachineApplicable");
+ let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
+ let sugg_snippet = snippet(cx, span_call_args[2].span, "..");
+ let applicability_snippet = snippet(cx, span_call_args[3].span, "Applicability::MachineApplicable");
SpanSuggestionSnippets {
help: help_snippet,
@@ -952,7 +953,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Ve
if let Some(Node::Item(item)) = cx.tcx.hir().get_if_local(def_id) {
if let ItemKind::Const(.., body_id) | ItemKind::Static(.., body_id) = item.kind {
let body = cx.tcx.hir().body(body_id);
- return path_to_matched_type(cx, &body.value);
+ return path_to_matched_type(cx, body.value);
}
}
},
@@ -1044,7 +1045,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
if el_ty.is_str();
let body = cx.tcx.hir().body(body_id);
let typeck_results = cx.tcx.typeck_body(body_id);
- if let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, &body.value);
+ if let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, body.value);
let path: Vec<&str> = path.iter().map(|x| {
if let Constant::Str(s) = x {
s.as_str()
@@ -1175,7 +1176,7 @@ impl InterningDefinedSymbol {
};
if_chain! {
// is a method call
- if let ExprKind::MethodCall(_, [item], _) = call.kind;
+ if let ExprKind::MethodCall(_, item, [], _) = call.kind;
if let Some(did) = cx.typeck_results().type_dependent_def_id(call.hir_id);
let ty = cx.typeck_results().expr_ty(item);
// ...on either an Ident or a Symbol
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 92934c16d..342f627e3 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -619,7 +619,7 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
if_chain! {
// item validation
if is_lint_ref_type(cx, ty);
- // blacklist check
+ // disallow check
let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase();
if !BLACK_LISTED_LINTS.contains(&lint_name.as_str());
// metadata extraction
@@ -644,7 +644,7 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
if_chain! {
if is_deprecated_lint(cx, ty);
- // blacklist check
+ // disallow check
let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase();
if !BLACK_LISTED_LINTS.contains(&lint_name.as_str());
// Metadata the little we can get from a deprecated lint
@@ -797,7 +797,7 @@ fn get_lint_group_and_level_or_lint(
let result = cx.lint_store.check_lint_name(
lint_name,
Some(sym::clippy),
- &[Ident::with_dummy_span(sym::clippy)].into_iter().collect(),
+ &std::iter::once(Ident::with_dummy_span(sym::clippy)).collect(),
);
if let CheckLintNameResult::Tool(Ok(lint_lst)) = result {
if let Some(group) = get_lint_group(cx, lint_lst[0]) {
@@ -1145,8 +1145,8 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> {
self.add_single_span_suggestion();
}
},
- ExprKind::MethodCall(path, arg, _arg_span) => {
- let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(&arg[0]));
+ ExprKind::MethodCall(path, recv, _, _arg_span) => {
+ let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(recv));
if match_type(self.cx, self_ty, &paths::DIAGNOSTIC_BUILDER) {
let called_method = path.ident.name.as_str().to_string();
for (method_name, is_multi_part) in &SUGGESTION_DIAGNOSTIC_BUILDER_METHODS {