Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7276,6 +7276,7 @@ Released 2018-09-13
[`unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used
[`upper_case_acronyms`]: https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms
[`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug
[`use_destructuring`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_destructuring
[`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self
[`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding
[`used_underscore_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_items
Expand Down Expand Up @@ -7410,6 +7411,8 @@ Released 2018-09-13
[`unnecessary-box-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unnecessary-box-size
[`unreadable-literal-lint-fractions`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unreadable-literal-lint-fractions
[`upper-case-acronyms-aggressive`]: https://doc.rust-lang.org/clippy/lint_configuration.html#upper-case-acronyms-aggressive
[`use-destructuring-min-fields`]: https://doc.rust-lang.org/clippy/lint_configuration.html#use-destructuring-min-fields
[`use-destructuring-scope`]: https://doc.rust-lang.org/clippy/lint_configuration.html#use-destructuring-scope
[`vec-box-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#vec-box-size-threshold
[`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold
[`warn-on-all-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-on-all-wildcard-imports
Expand Down
22 changes: 22 additions & 0 deletions book/src/lint_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,28 @@ Enables verbose mode. Triggers if there is more than one uppercase char next to
* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms)


## `use-destructuring-min-fields`
The minimum number of struct fields for the `use_destructuring` lint to trigger.

**Default Value:** `3`

---
**Affected lints:**
* [`use_destructuring`](https://rust-lang.github.io/rust-clippy/master/index.html#use_destructuring)


## `use-destructuring-scope`
Which struct types the `use_destructuring` lint applies to:
`"self"` (only the `self` parameter), `"Self"` (any variable whose type
is `Self`), `"crate"` (types from the current crate), or `"*"` (all types).

**Default Value:** `"self"`

---
**Affected lints:**
* [`use_destructuring`](https://rust-lang.github.io/rust-clippy/master/index.html#use_destructuring)


## `vec-box-size-threshold`
The size of the boxed type in bytes, where boxing in a `Vec` is allowed

Expand Down
12 changes: 10 additions & 2 deletions clippy_config/src/conf.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::ClippyConfiguration;
use crate::types::{
DisallowedPath, DisallowedPathWithoutReplacement, InherentImplLintScope, MacroMatcher, MatchLintBehaviour,
PubUnderscoreFieldsBehaviour, Rename, SourceItemOrdering, SourceItemOrderingCategory,
DestructuringScope, DisallowedPath, DisallowedPathWithoutReplacement, InherentImplLintScope, MacroMatcher,
MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename, SourceItemOrdering, SourceItemOrderingCategory,
SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind, SourceItemOrderingTraitAssocItemKind,
SourceItemOrderingTraitAssocItemKinds, SourceItemOrderingWithinModuleItemGroupings,
};
Expand Down Expand Up @@ -906,6 +906,14 @@ define_Conf! {
/// Enables verbose mode. Triggers if there is more than one uppercase char next to each other
#[lints(upper_case_acronyms)]
upper_case_acronyms_aggressive: bool = false,
/// The minimum number of struct fields for the `use_destructuring` lint to trigger.
#[lints(use_destructuring)]
use_destructuring_min_fields: u64 = 3,
/// Which struct types the `use_destructuring` lint applies to:
/// `"self"` (only the `self` parameter), `"Self"` (any variable whose type
/// is `Self`), `"crate"` (types from the current crate), or `"*"` (all types).
#[lints(use_destructuring)]
use_destructuring_scope: DestructuringScope = DestructuringScope::SelfBinding,
/// The size of the boxed type in bytes, where boxing in a `Vec` is allowed
#[lints(vec_box)]
vec_box_size_threshold: u64 = 4096,
Expand Down
17 changes: 17 additions & 0 deletions clippy_config/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,23 @@ pub enum PubUnderscoreFieldsBehaviour {
AllPubFields,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum DestructuringScope {
/// Only suggest destructuring for the `self` parameter binding.
#[serde(rename = "self")]
SelfBinding,
/// Suggest destructuring for any variable whose type is the `Self` type
/// of the enclosing impl block.
#[serde(rename = "Self")]
SelfType,
/// Suggest destructuring for types defined in the current crate.
Crate,
/// Suggest destructuring for all types, including external ones.
#[serde(rename = "*")]
All,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum InherentImplLintScope {
Expand Down
27 changes: 14 additions & 13 deletions clippy_dev/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,11 @@ impl<'cx> ParseCxImpl<'cx> {
Bang, OpenParen, CaptureDocLines, CaptureIdent, CaptureOptLifetimeArg, FatArrow, OpenBracket,
];

let Self {
str_buf,
arena,
str_list_buf,
} = self;
let mut cursor = Cursor::new(contents);
let mut captures = [Capture::EMPTY; 3];
while let Some(mac_name) = cursor.find_any_ident() {
Expand All @@ -304,9 +309,9 @@ impl<'cx> ParseCxImpl<'cx> {
assert!(
data.lints
.insert(
self.str_buf.alloc_ascii_lower(self.arena, cursor.get_text(captures[0])),
str_buf.alloc_ascii_lower(arena, cursor.get_text(captures[0])),
Lint::Active(ActiveLint {
group: self.arena.alloc_str(cursor.get_text(captures[1])),
group: arena.alloc_str(cursor.get_text(captures[1])),
module,
path: path.into(),
declaration_range: mac_name.pos..cursor.pos(),
Expand All @@ -323,21 +328,17 @@ impl<'cx> ParseCxImpl<'cx> {
};
let docs = match cursor.get_text(captures[0]) {
"" => "",
x => self.arena.alloc_str(x),
x => arena.alloc_str(x),
};
let name = self.arena.alloc_str(cursor.get_text(captures[1]));
let name = arena.alloc_str(cursor.get_text(captures[1]));
let lt = cursor.get_text(captures[2]);
let lt = if lt.is_empty() {
None
} else {
Some(self.arena.alloc_str(lt))
};
let lt = if lt.is_empty() { None } else { Some(arena.alloc_str(lt)) };

let lints = self.str_list_buf.with(|buf| {
let lints = str_list_buf.with(|buf| {
// Parses a comma separated list of paths and converts each path
// to a string with whitespace removed.
while !cursor.match_pat(CloseBracket) {
buf.push(self.str_buf.with(|buf| {
buf.push(str_buf.with(|buf| {
if cursor.match_pat(DoubleColon) {
buf.push_str("::");
}
Expand All @@ -348,7 +349,7 @@ impl<'cx> ParseCxImpl<'cx> {
let capture = cursor.capture_ident()?;
buf.push_str(cursor.get_text(capture));
}
Some(self.arena.alloc_str(buf))
Some(arena.alloc_str(buf))
})?);

if !cursor.match_pat(Comma) {
Expand All @@ -364,7 +365,7 @@ impl<'cx> ParseCxImpl<'cx> {
&[]
} else {
buf.sort_unstable();
&*self.arena.alloc_slice(buf)
&*arena.alloc_slice(buf)
})
});

Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[
crate::unwrap::UNNECESSARY_UNWRAP_INFO,
crate::unwrap_in_result::UNWRAP_IN_RESULT_INFO,
crate::upper_case_acronyms::UPPER_CASE_ACRONYMS_INFO,
crate::use_destructuring::USE_DESTRUCTURING_INFO,
crate::use_self::USE_SELF_INFO,
crate::useless_concat::USELESS_CONCAT_INFO,
crate::useless_conversion::USELESS_CONVERSION_INFO,
Expand Down
7 changes: 3 additions & 4 deletions clippy_lints/src/excessive_nesting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,9 @@ struct NestingVisitor<'conf, 'cx> {

impl NestingVisitor<'_, '_> {
fn check_indent(&mut self, span: Span, id: NodeId) -> bool {
if self.nest_level > self.conf.excessive_nesting_threshold
&& !span.in_external_macro(self.cx.sess().source_map())
{
self.conf.nodes.insert(id);
let Self { nest_level, conf, cx } = self;
if *nest_level > conf.excessive_nesting_threshold && !span.in_external_macro(cx.sess().source_map()) {
conf.nodes.insert(id);

return true;
}
Expand Down
2 changes: 2 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ mod unused_unit;
mod unwrap;
mod unwrap_in_result;
mod upper_case_acronyms;
mod use_destructuring;
mod use_self;
mod useless_concat;
mod useless_conversion;
Expand Down Expand Up @@ -865,6 +866,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co
Box::new(move |tcx| Box::new(duration_suboptimal_units::DurationSuboptimalUnits::new(tcx, conf))),
Box::new(move |_| Box::new(manual_take::ManualTake::new(conf))),
Box::new(|_| Box::new(manual_checked_ops::ManualCheckedOps)),
Box::new(move |_| Box::new(use_destructuring::UseDestructuring::new(conf))),
Box::new(move |tcx| Box::new(manual_pop_if::ManualPopIf::new(tcx, conf))),
Box::new(move |_| Box::new(manual_noop_waker::ManualNoopWaker::new(conf))),
// add late passes here, used by `cargo dev new_lint`
Expand Down
9 changes: 5 additions & 4 deletions clippy_lints/src/loops/while_immutable_condition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,17 @@ struct VarCollectorVisitor<'a, 'tcx> {

impl<'tcx> VarCollectorVisitor<'_, 'tcx> {
fn insert_def_id(&mut self, ex: &'tcx Expr<'_>) {
let Self { cx, ids, def_ids } = self;
if let ExprKind::Path(ref qpath) = ex.kind
&& let QPath::Resolved(None, _) = *qpath
{
match self.cx.qpath_res(qpath, ex.hir_id) {
match cx.qpath_res(qpath, ex.hir_id) {
Res::Local(hir_id) => {
self.ids.insert(hir_id);
ids.insert(hir_id);
},
Res::Def(DefKind::Static { .. }, def_id) => {
let mutable = self.cx.tcx.is_mutable_static(def_id);
self.def_ids.insert(def_id, mutable);
let mutable = cx.tcx.is_mutable_static(def_id);
def_ids.insert(def_id, mutable);
},
_ => {},
}
Expand Down
7 changes: 4 additions & 3 deletions clippy_lints/src/manual_clamp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,16 +595,17 @@ impl<'tcx> BinaryOp<'tcx> {
}

fn flip(&self) -> Self {
let Self { op, left, right } = self;
Self {
op: match self.op {
op: match *op {
BinOpKind::Le => BinOpKind::Ge,
BinOpKind::Lt => BinOpKind::Gt,
BinOpKind::Ge => BinOpKind::Le,
BinOpKind::Gt => BinOpKind::Lt,
other => other,
},
left: self.right,
right: self.left,
left: *right,
right: *left,
}
}
}
Expand Down
20 changes: 11 additions & 9 deletions clippy_lints/src/matches/match_same_arms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,22 +211,24 @@ struct PatRange {
}
impl PatRange {
fn contains(&self, x: u128) -> bool {
x >= self.start
&& match self.bounds {
RangeEnd::Included => x <= self.end,
RangeEnd::Excluded => x < self.end,
let Self { start, end, bounds } = self;
x >= *start
&& match bounds {
RangeEnd::Included => x <= *end,
RangeEnd::Excluded => x < *end,
}
}

fn overlaps(&self, other: &Self) -> bool {
// Note: Empty ranges are impossible, so this is correct even though it would return true if an
// empty exclusive range were to reside within an inclusive range.
(match self.bounds {
RangeEnd::Included => self.end >= other.start,
RangeEnd::Excluded => self.end > other.start,
let Self { start, end, bounds } = *self;
(match bounds {
RangeEnd::Included => end >= other.start,
RangeEnd::Excluded => end > other.start,
} && match other.bounds {
RangeEnd::Included => self.start <= other.end,
RangeEnd::Excluded => self.start < other.end,
RangeEnd::Included => start <= other.end,
RangeEnd::Excluded => start < other.end,
})
}
}
Expand Down
11 changes: 8 additions & 3 deletions clippy_lints/src/methods/bind_instead_of_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,19 @@ impl BindInsteadOfMap {
}

fn lint_msg(&self, cx: &LateContext<'_>) -> Option<String> {
let variant_id = cx.tcx.lang_items().get(self.variant_lang_item)?;
let Self {
variant_lang_item,
bad_method_name,
good_method_name,
} = self;
let variant_id = cx.tcx.lang_items().get(*variant_lang_item)?;
let item_id = cx.tcx.parent(variant_id);
Some(format!(
"using `{}.{}(|x| {}(y))`, which is more succinctly expressed as `{}(|x| y)`",
cx.tcx.item_name(item_id),
self.bad_method_name,
bad_method_name,
cx.tcx.item_name(variant_id),
self.good_method_name,
good_method_name,
))
}

Expand Down
13 changes: 9 additions & 4 deletions clippy_lints/src/non_std_lazy_statics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,17 @@ impl LazyInfo {
}

fn lint(&self, cx: &LateContext<'_>, sugg_map: &FxIndexMap<DefId, Option<String>>) {
let Self {
ty_span_no_args,
item_hir_id,
calls_span_and_id,
} = self;
// Applicability might get adjusted to `Unspecified` later if any calls
// in `calls_span_and_id` are not replaceable judging by the `sugg_map`.
let mut app = Applicability::MachineApplicable;
let mut suggs = vec![(self.ty_span_no_args, "std::sync::LazyLock".to_string())];
let mut suggs = vec![(*ty_span_no_args, "std::sync::LazyLock".to_string())];

for (span, def_id) in &self.calls_span_and_id {
for (span, def_id) in calls_span_and_id {
let maybe_sugg = sugg_map.get(def_id).cloned().flatten();
if let Some(sugg) = maybe_sugg {
suggs.push((*span, sugg));
Expand All @@ -236,8 +241,8 @@ impl LazyInfo {
span_lint_hir_and_then(
cx,
NON_STD_LAZY_STATICS,
self.item_hir_id,
self.ty_span_no_args,
*item_hir_id,
*ty_span_no_args,
"this type has been superseded by `LazyLock` in the standard library",
|diag| {
diag.multipart_suggestion("use `std::sync::LazyLock` instead", suggs, app);
Expand Down
16 changes: 9 additions & 7 deletions clippy_lints/src/only_used_in_recursion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,11 @@ struct Params {
}
impl Params {
fn insert(&mut self, param: Param, id: HirId) {
let idx = self.params.len();
self.by_id.insert(id, idx);
self.by_fn.insert((param.fn_id, param.idx), idx);
self.params.push(param);
let Self { params, by_id, by_fn } = self;
let idx = params.len();
by_id.insert(id, idx);
by_fn.insert((param.fn_id, param.idx), idx);
params.push(param);
}

fn remove_by_id(&mut self, id: HirId) {
Expand All @@ -252,9 +253,10 @@ impl Params {
}

fn clear(&mut self) {
self.params.clear();
self.by_id.clear();
self.by_fn.clear();
let Self { params, by_id, by_fn } = self;
params.clear();
by_id.clear();
by_fn.clear();
}

/// Sets the `apply_lint` flag on each parameter.
Expand Down
Loading
Loading