Skip to content

Commit 479ddc0

Browse files
authored
Merge branch 'master' into repeatn
2 parents 0667d78 + 034f3d2 commit 479ddc0

File tree

157 files changed

+2742
-753
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

157 files changed

+2742
-753
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6215,6 +6215,7 @@ Released 2018-09-13
62156215
[`allow-comparison-to-zero`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-comparison-to-zero
62166216
[`allow-dbg-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-dbg-in-tests
62176217
[`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests
6218+
[`allow-indexing-slicing-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-indexing-slicing-in-tests
62186219
[`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args
62196220
[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings
62206221
[`allow-panic-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-panic-in-tests
@@ -6252,6 +6253,7 @@ Released 2018-09-13
62526253
[`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold
62536254
[`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability
62546255
[`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold
6256+
[`lint-inconsistent-struct-field-initializers`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-inconsistent-struct-field-initializers
62556257
[`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold
62566258
[`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else
62576259
[`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools

book/src/development/common_tools_writing_lints.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl LateLintPass<'_> for MyStructLint {
3737
// Get type of `expr`
3838
let ty = cx.typeck_results().expr_ty(expr);
3939
// Match its kind to enter its type
40-
match ty.kind {
40+
match ty.kind() {
4141
ty::Adt(adt_def, _) if adt_def.is_struct() => println!("Our `expr` is a struct!"),
4242
_ => ()
4343
}

book/src/development/method_checking.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use clippy_utils::is_trait_method;
2121
impl<'tcx> LateLintPass<'tcx> for OurFancyMethodLint {
2222
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
2323
// Check our expr is calling a method with pattern matching
24-
if let hir::ExprKind::MethodCall(path, _, [self_arg, ..]) = &expr.kind
24+
if let hir::ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind
2525
// Check if the name of this method is `our_fancy_method`
2626
&& path.ident.name.as_str() == "our_fancy_method"
2727
// We can check the type of the self argument whenever necessary.

book/src/development/the_team.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ you to the alumni group. You're always welcome to come back.
7272

7373
## The Clippy Team
7474

75-
[The Clippy team](https://www.rust-lang.org/governance/teams/dev-tools#Clippy%20team)
75+
[The Clippy team](https://www.rust-lang.org/governance/teams/dev-tools#team-clippy)
7676
is responsible for maintaining Clippy.
7777

7878
### Duties

book/src/development/type_checking.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ impl LateLintPass<'_> for MyStructLint {
9494
// Get type of `expr`
9595
let ty = cx.typeck_results().expr_ty(expr);
9696
// Match its kind to enter the type
97-
match ty.kind {
97+
match ty.kind() {
9898
ty::Adt(adt_def, _) if adt_def.is_struct() => println!("Our `expr` is a struct!"),
9999
_ => ()
100100
}

book/src/lint_configuration.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ Whether `expect` should be allowed in test functions or `#[cfg(test)]`
8181
* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used)
8282

8383

84+
## `allow-indexing-slicing-in-tests`
85+
Whether `indexing_slicing` should be allowed in test functions or `#[cfg(test)]`
86+
87+
**Default Value:** `false`
88+
89+
---
90+
**Affected lints:**
91+
* [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing)
92+
93+
8494
## `allow-mixed-uninlined-format-args`
8595
Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
8696

@@ -572,6 +582,33 @@ The maximum size of the `Err`-variant in a `Result` returned from a function
572582
* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err)
573583

574584

585+
## `lint-inconsistent-struct-field-initializers`
586+
Whether to suggest reordering constructor fields when initializers are present.
587+
588+
Warnings produced by this configuration aren't necessarily fixed by just reordering the fields. Even if the
589+
suggested code would compile, it can change semantics if the initializer expressions have side effects. The
590+
following example [from rust-clippy#11846] shows how the suggestion can run into borrow check errors:
591+
592+
```rust
593+
struct MyStruct {
594+
vector: Vec<u32>,
595+
length: usize
596+
}
597+
fn main() {
598+
let vector = vec![1,2,3];
599+
MyStruct { length: vector.len(), vector};
600+
}
601+
```
602+
603+
[from rust-clippy#11846]: https://github.com/rust-lang/rust-clippy/issues/11846#issuecomment-1820747924
604+
605+
**Default Value:** `false`
606+
607+
---
608+
**Affected lints:**
609+
* [`inconsistent_struct_constructor`](https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor)
610+
611+
575612
## `literal-representation-threshold`
576613
The lower bound for linting decimal literals
577614

clippy.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
avoid-breaking-exported-api = false
22

3+
lint-inconsistent-struct-field-initializers = true
4+
35
[[disallowed-methods]]
46
path = "rustc_lint::context::LintContext::lint"
57
reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead"

clippy_config/src/conf.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,9 @@ define_Conf! {
291291
/// Whether `expect` should be allowed in test functions or `#[cfg(test)]`
292292
#[lints(expect_used)]
293293
allow_expect_in_tests: bool = false,
294+
/// Whether `indexing_slicing` should be allowed in test functions or `#[cfg(test)]`
295+
#[lints(indexing_slicing)]
296+
allow_indexing_slicing_in_tests: bool = false,
294297
/// Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
295298
#[lints(uninlined_format_args)]
296299
allow_mixed_uninlined_format_args: bool = true,
@@ -529,6 +532,26 @@ define_Conf! {
529532
/// The maximum size of the `Err`-variant in a `Result` returned from a function
530533
#[lints(result_large_err)]
531534
large_error_threshold: u64 = 128,
535+
/// Whether to suggest reordering constructor fields when initializers are present.
536+
///
537+
/// Warnings produced by this configuration aren't necessarily fixed by just reordering the fields. Even if the
538+
/// suggested code would compile, it can change semantics if the initializer expressions have side effects. The
539+
/// following example [from rust-clippy#11846] shows how the suggestion can run into borrow check errors:
540+
///
541+
/// ```rust
542+
/// struct MyStruct {
543+
/// vector: Vec<u32>,
544+
/// length: usize
545+
/// }
546+
/// fn main() {
547+
/// let vector = vec![1,2,3];
548+
/// MyStruct { length: vector.len(), vector};
549+
/// }
550+
/// ```
551+
///
552+
/// [from rust-clippy#11846]: https://github.com/rust-lang/rust-clippy/issues/11846#issuecomment-1820747924
553+
#[lints(inconsistent_struct_constructor)]
554+
lint_inconsistent_struct_field_initializers: bool = false,
532555
/// The lower bound for linting decimal literals
533556
#[lints(decimal_literal_representation)]
534557
literal_representation_threshold: u64 = 16384,

clippy_dev/src/fmt.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ fn fmt_conf(check: bool) -> Result<(), Error> {
179179
#[expect(clippy::drain_collect)]
180180
fields.push(ClippyConf {
181181
name,
182-
lints: lints.drain(..).collect(),
183182
attrs: &conf[attrs_start..attrs_end],
183+
lints: lints.drain(..).collect(),
184184
field: conf[field_start..i].trim_end(),
185185
});
186186
attrs_start = i;
@@ -191,8 +191,8 @@ fn fmt_conf(check: bool) -> Result<(), Error> {
191191
#[expect(clippy::drain_collect)]
192192
fields.push(ClippyConf {
193193
name,
194-
lints: lints.drain(..).collect(),
195194
attrs: &conf[attrs_start..attrs_end],
195+
lints: lints.drain(..).collect(),
196196
field: conf[field_start..i].trim_end(),
197197
});
198198
attrs_start = i;
@@ -220,8 +220,8 @@ fn fmt_conf(check: bool) -> Result<(), Error> {
220220
}
221221
fields.push(ClippyConf {
222222
name,
223-
lints,
224223
attrs: &conf[attrs_start..attrs_end],
224+
lints,
225225
field: conf[field_start..].trim_end(),
226226
});
227227

clippy_lints/src/approx_const.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use clippy_config::Conf;
22
use clippy_utils::diagnostics::span_lint_and_help;
33
use clippy_utils::msrvs::{self, Msrv};
44
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
5+
use rustc_attr_parsing::RustcVersion;
56
use rustc_hir::{Expr, ExprKind};
67
use rustc_lint::{LateContext, LateLintPass};
7-
use rustc_session::{RustcVersion, impl_lint_pass};
8+
use rustc_session::impl_lint_pass;
89
use rustc_span::symbol;
910
use std::f64::consts as f64;
1011

clippy_lints/src/arbitrary_source_item_ordering.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,8 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
428428

429429
// Makes a note of the current item for comparison with the next.
430430
cur_t = Some(CurItem {
431-
order: module_level_order,
432431
item,
432+
order: module_level_order,
433433
name: get_item_name(item),
434434
});
435435
}

clippy_lints/src/attrs/inline_always.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::INLINE_ALWAYS;
22
use super::utils::is_word;
33
use clippy_utils::diagnostics::span_lint;
4-
use rustc_ast::Attribute;
4+
use rustc_hir::Attribute;
55
use rustc_lint::LateContext;
66
use rustc_span::symbol::Symbol;
77
use rustc_span::{Span, sym};

clippy_lints/src/attrs/repr_attributes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_ast::Attribute;
1+
use rustc_hir::Attribute;
22
use rustc_lint::LateContext;
33
use rustc_span::{Span, sym};
44

clippy_lints/src/attrs/should_panic_without_expect.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,20 @@ use super::{Attribute, SHOULD_PANIC_WITHOUT_EXPECT};
22
use clippy_utils::diagnostics::span_lint_and_sugg;
33
use rustc_ast::token::{Token, TokenKind};
44
use rustc_ast::tokenstream::TokenTree;
5-
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind};
5+
use rustc_ast::{AttrArgs, AttrKind};
66
use rustc_errors::Applicability;
77
use rustc_lint::EarlyContext;
88
use rustc_span::sym;
99

1010
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
1111
if let AttrKind::Normal(normal_attr) = &attr.kind {
12-
if let AttrArgs::Eq {
13-
value: AttrArgsEq::Ast(_),
14-
..
15-
} = &normal_attr.item.args
16-
{
12+
if let AttrArgs::Eq { .. } = &normal_attr.item.args {
1713
// `#[should_panic = ".."]` found, good
1814
return;
1915
}
2016

2117
if let AttrArgs::Delimited(args) = &normal_attr.item.args
22-
&& let mut tt_iter = args.tokens.trees()
18+
&& let mut tt_iter = args.tokens.iter()
2319
&& let Some(TokenTree::Token(
2420
Token {
2521
kind: TokenKind::Ident(sym::expected, _),

clippy_lints/src/attrs/useless_attribute.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use super::USELESS_ATTRIBUTE;
2-
use super::utils::{extract_clippy_lint, is_lint_level, is_word};
2+
use super::utils::{is_lint_level, is_word, namespace_and_lint};
33
use clippy_utils::diagnostics::span_lint_and_then;
44
use clippy_utils::source::{SpanRangeExt, first_line_of_span};
5-
use rustc_ast::{Attribute, Item, ItemKind, MetaItemInner};
5+
use rustc_ast::{Attribute, Item, ItemKind};
66
use rustc_errors::Applicability;
77
use rustc_lint::{EarlyContext, LintContext};
88
use rustc_middle::lint::in_external_macro;
@@ -20,11 +20,13 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
2020
for lint in lint_list {
2121
match item.kind {
2222
ItemKind::Use(..) => {
23-
if let MetaItemInner::MetaItem(meta_item) = lint
24-
&& meta_item.is_word()
25-
&& let Some(ident) = meta_item.ident()
23+
let (namespace @ (Some(sym::clippy) | None), Some(name)) = namespace_and_lint(lint) else {
24+
return;
25+
};
26+
27+
if namespace.is_none()
2628
&& matches!(
27-
ident.name.as_str(),
29+
name.as_str(),
2830
"ambiguous_glob_reexports"
2931
| "dead_code"
3032
| "deprecated"
@@ -39,9 +41,9 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
3941
return;
4042
}
4143

42-
if extract_clippy_lint(lint).is_some_and(|symbol| {
43-
matches!(
44-
symbol.as_str(),
44+
if namespace == Some(sym::clippy)
45+
&& matches!(
46+
name.as_str(),
4547
"wildcard_imports"
4648
| "enum_glob_use"
4749
| "redundant_pub_crate"
@@ -52,7 +54,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
5254
| "disallowed_types"
5355
| "unused_trait_names"
5456
)
55-
}) {
57+
{
5658
return;
5759
}
5860
},

clippy_lints/src/attrs/utils.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,18 @@ fn is_relevant_expr(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>
7575

7676
/// Returns the lint name if it is clippy lint.
7777
pub(super) fn extract_clippy_lint(lint: &MetaItemInner) -> Option<Symbol> {
78-
if let Some(meta_item) = lint.meta_item()
79-
&& meta_item.path.segments.len() > 1
80-
&& let tool_name = meta_item.path.segments[0].ident
81-
&& tool_name.name == sym::clippy
82-
{
83-
let lint_name = meta_item.path.segments.last().unwrap().ident.name;
84-
return Some(lint_name);
78+
match namespace_and_lint(lint) {
79+
(Some(sym::clippy), name) => name,
80+
_ => None,
81+
}
82+
}
83+
84+
/// Returns the lint namespace, if any, as well as the lint name. (`None`, `None`) means
85+
/// the lint had less than 1 or more than 2 segments.
86+
pub(super) fn namespace_and_lint(lint: &MetaItemInner) -> (Option<Symbol>, Option<Symbol>) {
87+
match lint.meta_item().map(|m| m.path.segments.as_slice()).unwrap_or_default() {
88+
[name] => (None, Some(name.ident.name)),
89+
[namespace, name] => (Some(namespace.ident.name), Some(name.ident.name)),
90+
_ => (None, None),
8591
}
86-
None
8792
}

clippy_lints/src/booleans.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ use clippy_utils::msrvs::{self, Msrv};
55
use clippy_utils::source::SpanRangeExt;
66
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
77
use rustc_ast::ast::LitKind;
8+
use rustc_attr_parsing::RustcVersion;
89
use rustc_errors::Applicability;
910
use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
1011
use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp};
1112
use rustc_lint::{LateContext, LateLintPass, Level};
12-
use rustc_session::{RustcVersion, impl_lint_pass};
13+
use rustc_session::impl_lint_pass;
1314
use rustc_span::def_id::LocalDefId;
1415
use rustc_span::{Span, sym};
1516

clippy_lints/src/casts/borrow_as_ptr.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::msrvs::Msrv;
3-
use clippy_utils::source::snippet_with_context;
3+
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
4+
use clippy_utils::sugg::has_enclosing_paren;
45
use clippy_utils::{is_lint_allowed, msrvs, std_or_core};
56
use rustc_errors::Applicability;
67
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind};
78
use rustc_lint::LateContext;
89
use rustc_middle::ty::adjustment::Adjust;
10+
use rustc_span::BytePos;
911

1012
use super::BORROW_AS_PTR;
1113

@@ -32,12 +34,21 @@ pub(super) fn check<'tcx>(
3234
return false;
3335
}
3436

35-
let suggestion = if msrv.meets(msrvs::RAW_REF_OP) {
37+
let (suggestion, span) = if msrv.meets(msrvs::RAW_REF_OP) {
3638
let operator_kind = match mutability {
3739
Mutability::Not => "const",
3840
Mutability::Mut => "mut",
3941
};
40-
format!("&raw {operator_kind} {snip}")
42+
// Make sure that the span to be replaced doesn't include parentheses, that could break the
43+
// suggestion.
44+
let span = if has_enclosing_paren(snippet_with_applicability(cx, expr.span, "", &mut app)) {
45+
expr.span
46+
.with_lo(expr.span.lo() + BytePos(1))
47+
.with_hi(expr.span.hi() - BytePos(1))
48+
} else {
49+
expr.span
50+
};
51+
(format!("&raw {operator_kind} {snip}"), span)
4152
} else {
4253
let Some(std_or_core) = std_or_core(cx) else {
4354
return false;
@@ -46,18 +57,10 @@ pub(super) fn check<'tcx>(
4657
Mutability::Not => "addr_of",
4758
Mutability::Mut => "addr_of_mut",
4859
};
49-
format!("{std_or_core}::ptr::{macro_name}!({snip})")
60+
(format!("{std_or_core}::ptr::{macro_name}!({snip})"), expr.span)
5061
};
5162

52-
span_lint_and_sugg(
53-
cx,
54-
BORROW_AS_PTR,
55-
expr.span,
56-
"borrow as raw pointer",
57-
"try",
58-
suggestion,
59-
Applicability::MachineApplicable,
60-
);
63+
span_lint_and_sugg(cx, BORROW_AS_PTR, span, "borrow as raw pointer", "try", suggestion, app);
6164
return true;
6265
}
6366
false

0 commit comments

Comments
 (0)