Skip to content

Commit 4a4fd12

Browse files
committed
Auto merge of rust-lang#102106 - djkoloski:sync-from-clippy, r=Manishearth
Update clippy r? `@Manishearth`
2 parents 9062b78 + 0650c40 commit 4a4fd12

File tree

111 files changed

+1997
-1631
lines changed

Some content is hidden

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

111 files changed

+1997
-1631
lines changed

src/tools/clippy/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3800,6 +3800,7 @@ Released 2018-09-13
38003800
[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
38013801
[`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect
38023802
[`iter_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_count
3803+
[`iter_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map
38033804
[`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop
38043805
[`iter_next_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_slice
38053806
[`iter_not_returning_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_not_returning_iterator

src/tools/clippy/CONTRIBUTING.md

+15-10
Original file line numberDiff line numberDiff line change
@@ -110,23 +110,28 @@ Just make sure to remove the dependencies again before finally making a pull req
110110
[IntelliJ_rust_homepage]: https://intellij-rust.github.io/
111111

112112
### Rust Analyzer
113-
As of [#6869][6869], [`rust-analyzer`][ra_homepage] can understand that Clippy uses compiler-internals
114-
using `extern crate` when `package.metadata.rust-analyzer.rustc_private` is set to `true` in Clippy's `Cargo.toml.`
115-
You will require a `nightly` toolchain with the `rustc-dev` component installed.
116-
Make sure that in the `rust-analyzer` configuration, you set
113+
For [`rust-analyzer`][ra_homepage] to work correctly make sure that in the `rust-analyzer` configuration you set
114+
117115
```json
118116
{ "rust-analyzer.rustc.source": "discover" }
119117
```
120-
and
121-
```json
122-
{ "rust-analyzer.updates.channel": "nightly" }
123-
```
118+
124119
You should be able to see information on things like `Expr` or `EarlyContext` now if you hover them, also
125120
a lot more type hints.
126-
This will work with `rust-analyzer 2021-03-15` shipped in nightly `1.52.0-nightly (107896c32 2021-03-15)` or later.
121+
122+
To have `rust-analyzer` also work in the `clippy_dev` and `lintcheck` crates, add the following configuration
123+
124+
```json
125+
{
126+
"rust-analyzer.linkedProjects": [
127+
"./Cargo.toml",
128+
"clippy_dev/Cargo.toml",
129+
"lintcheck/Cargo.toml",
130+
]
131+
}
132+
```
127133

128134
[ra_homepage]: https://rust-analyzer.github.io/
129-
[6869]: https://github.com/rust-lang/rust-clippy/pull/6869
130135

131136
## How Clippy works
132137

src/tools/clippy/book/src/development/adding_lints.md

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ We start by opening the test file created at `tests/ui/foo_functions.rs`.
9090
Update the file with some examples to get started:
9191

9292
```rust
93+
#![allow(unused)]
9394
#![warn(clippy::foo_functions)]
9495

9596
// Impl methods

src/tools/clippy/book/src/development/common_tools_writing_lints.md

+5-10
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ There are three ways to do this, depending on if the target trait has a
123123
diagnostic item, lang item or neither.
124124

125125
```rust
126-
use clippy_utils::{implements_trait, is_trait_method, match_trait_method, paths};
126+
use clippy_utils::ty::implements_trait;
127+
use clippy_utils::is_trait_method;
127128
use rustc_span::symbol::sym;
128129

129130
impl LateLintPass<'_> for MyStructLint {
@@ -143,13 +144,6 @@ impl LateLintPass<'_> for MyStructLint {
143144
.map_or(false, |id| implements_trait(cx, ty, id, &[])) {
144145
// `expr` implements `Drop` trait
145146
}
146-
147-
// 3. Using the type path with the expression
148-
// we use `match_trait_method` function from Clippy's utils
149-
// (This method should be avoided if possible)
150-
if match_trait_method(cx, expr, &paths::INTO) {
151-
// `expr` implements `Into` trait
152-
}
153147
}
154148
}
155149
```
@@ -233,8 +227,9 @@ functions to deal with macros:
233227
crates
234228

235229
```rust
236-
#[macro_use]
237-
extern crate a_crate_with_macros;
230+
use rustc_middle::lint::in_external_macro;
231+
232+
use a_crate_with_macros::foo;
238233

239234
// `foo` is defined in `a_crate_with_macros`
240235
foo!("bar");

src/tools/clippy/clippy_dev/src/new_lint.rs

+1
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ pub(crate) fn get_stabilization_version() -> String {
188188
fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String {
189189
let mut contents = format!(
190190
indoc! {"
191+
#![allow(unused)]
191192
#![warn(clippy::{})]
192193
193194
fn main() {{

src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use clippy_utils::{meets_msrv, msrvs};
44
use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
55
use rustc_errors::Applicability;
66
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
7+
use rustc_middle::lint::in_external_macro;
78
use rustc_semver::RustcVersion;
89
use rustc_session::{declare_tool_lint, impl_lint_pass};
910
use rustc_span::Span;
@@ -79,6 +80,7 @@ fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg
7980
(LitKind::Byte(b'a') | LitKind::Char('a'), LitKind::Byte(b'z') | LitKind::Char('z'))
8081
| (LitKind::Byte(b'A') | LitKind::Char('A'), LitKind::Byte(b'Z') | LitKind::Char('Z'))
8182
)
83+
&& !in_external_macro(cx.sess(), span)
8284
{
8385
span_lint_and_then(
8486
cx,

src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs

+9-13
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
3-
use clippy_utils::path_res;
43
use clippy_utils::source::snippet_with_context;
5-
use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item};
4+
use clippy_utils::ty::{has_debug_impl, is_copy, is_type_diagnostic_item};
65
use clippy_utils::usage::local_used_after_expr;
6+
use clippy_utils::{is_expr_final_block_expr, path_res};
77
use rustc_errors::Applicability;
88
use rustc_hir::def::Res;
99
use rustc_hir::{Expr, ExprKind};
@@ -58,6 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
5858
return;
5959
}
6060
}
61+
let semicolon = if is_expr_final_block_expr(cx.tcx, e) {";"} else {""};
6162
let mut app = Applicability::MachineApplicable;
6263
match method_segment.ident.as_str() {
6364
"is_ok" if type_suitable_to_unwrap(cx, substs.type_at(1)) => {
@@ -68,8 +69,9 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
6869
"called `assert!` with `Result::is_ok`",
6970
"replace with",
7071
format!(
71-
"{}.unwrap()",
72-
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
72+
"{}.unwrap(){}",
73+
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0,
74+
semicolon
7375
),
7476
app,
7577
);
@@ -82,8 +84,9 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
8284
"called `assert!` with `Result::is_err`",
8385
"replace with",
8486
format!(
85-
"{}.unwrap_err()",
86-
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
87+
"{}.unwrap_err(){}",
88+
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0,
89+
semicolon
8790
),
8891
app,
8992
);
@@ -94,13 +97,6 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
9497
}
9598
}
9699

97-
/// This checks whether a given type is known to implement Debug.
98-
fn has_debug_impl<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
99-
cx.tcx
100-
.get_diagnostic_item(sym::Debug)
101-
.map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
102-
}
103-
104100
fn type_suitable_to_unwrap<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
105101
has_debug_impl(cx, ty) && !ty.is_unit() && !ty.is_never()
106102
}

src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs

+29-18
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use rustc_ast::{ExprPrecedence, LitKind};
1+
use rustc_ast::LitKind;
22
use rustc_hir::{Block, ExprKind};
33
use rustc_lint::{LateContext, LateLintPass};
44
use rustc_session::{declare_lint_pass, declare_tool_lint};
55

6-
use clippy_utils::{diagnostics::span_lint_and_then, is_else_clause, source::snippet_block_with_applicability};
6+
use clippy_utils::{diagnostics::span_lint_and_then, is_else_clause, sugg::Sugg};
77
use rustc_errors::Applicability;
88

99
declare_clippy_lint! {
@@ -55,27 +55,42 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx
5555
if let ExprKind::If(check, then, Some(else_)) = expr.kind
5656
&& let Some(then_lit) = int_literal(then)
5757
&& let Some(else_lit) = int_literal(else_)
58-
&& check_int_literal_equals_val(then_lit, 1)
59-
&& check_int_literal_equals_val(else_lit, 0)
6058
{
59+
let inverted = if
60+
check_int_literal_equals_val(then_lit, 1)
61+
&& check_int_literal_equals_val(else_lit, 0) {
62+
false
63+
} else if
64+
check_int_literal_equals_val(then_lit, 0)
65+
&& check_int_literal_equals_val(else_lit, 1) {
66+
true
67+
} else {
68+
// Expression isn't boolean, exit
69+
return;
70+
};
6171
let mut applicability = Applicability::MachineApplicable;
62-
let snippet = snippet_block_with_applicability(ctx, check.span, "..", None, &mut applicability);
63-
let snippet_with_braces = {
64-
let need_parens = should_have_parentheses(check);
65-
let (left_paren, right_paren) = if need_parens {("(", ")")} else {("", "")};
66-
format!("{left_paren}{snippet}{right_paren}")
72+
let snippet = {
73+
let mut sugg = Sugg::hir_with_applicability(ctx, check, "..", &mut applicability);
74+
if inverted {
75+
sugg = !sugg;
76+
}
77+
sugg
6778
};
6879

6980
let ty = ctx.typeck_results().expr_ty(then_lit); // then and else must be of same type
7081

7182
let suggestion = {
7283
let wrap_in_curly = is_else_clause(ctx.tcx, expr);
73-
let (left_curly, right_curly) = if wrap_in_curly {("{", "}")} else {("", "")};
74-
format!(
75-
"{left_curly}{ty}::from({snippet}){right_curly}"
76-
)
84+
let mut s = Sugg::NonParen(format!("{ty}::from({snippet})").into());
85+
if wrap_in_curly {
86+
s = s.blockify();
87+
}
88+
s
7789
}; // when used in else clause if statement should be wrapped in curly braces
7890

91+
let into_snippet = snippet.clone().maybe_par();
92+
let as_snippet = snippet.as_ty(ty);
93+
7994
span_lint_and_then(ctx,
8095
BOOL_TO_INT_WITH_IF,
8196
expr.span,
@@ -87,7 +102,7 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx
87102
suggestion,
88103
applicability,
89104
);
90-
diag.note(format!("`{snippet_with_braces} as {ty}` or `{snippet_with_braces}.into()` can also be valid options"));
105+
diag.note(format!("`{as_snippet}` or `{into_snippet}.into()` can also be valid options"));
91106
});
92107
};
93108
}
@@ -119,7 +134,3 @@ fn check_int_literal_equals_val<'tcx>(expr: &'tcx rustc_hir::Expr<'tcx>, expecte
119134
false
120135
}
121136
}
122-
123-
fn should_have_parentheses<'tcx>(check: &'tcx rustc_hir::Expr<'tcx>) -> bool {
124-
check.precedence().order() < ExprPrecedence::Cast.order()
125-
}

src/tools/clippy/clippy_lints/src/booleans.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
237237
}
238238
},
239239
&Term(n) => {
240-
let snip = snippet_opt(self.cx, self.terminals[n as usize].span)?;
240+
let snip = snippet_opt(self.cx, self.terminals[n as usize].span.source_callsite())?;
241241
self.output.push_str(&snip);
242242
},
243243
}

src/tools/clippy/clippy_lints/src/dereference.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -297,13 +297,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
297297
if !is_lint_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id)
298298
&& position.lint_explicit_deref() =>
299299
{
300+
let ty_changed_count = usize::from(!deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr)));
300301
self.state = Some((
301302
State::DerefMethod {
302-
ty_changed_count: if deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr)) {
303-
0
304-
} else {
305-
1
306-
},
303+
ty_changed_count,
307304
is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)),
308305
target_mut,
309306
},

src/tools/clippy/clippy_lints/src/derivable_impls.rs

+19-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use clippy_utils::diagnostics::span_lint_and_help;
1+
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::{is_default_equivalent, peel_blocks};
3+
use rustc_errors::Applicability;
34
use rustc_hir::{
45
def::{DefKind, Res},
56
Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind,
@@ -100,15 +101,28 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
100101
ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
101102
_ => false,
102103
};
104+
103105
if should_emit {
104-
let path_string = cx.tcx.def_path_str(adt_def.did());
105-
span_lint_and_help(
106+
let struct_span = cx.tcx.def_span(adt_def.did());
107+
span_lint_and_then(
106108
cx,
107109
DERIVABLE_IMPLS,
108110
item.span,
109111
"this `impl` can be derived",
110-
None,
111-
&format!("try annotating `{}` with `#[derive(Default)]`", path_string),
112+
|diag| {
113+
diag.span_suggestion_hidden(
114+
item.span,
115+
"remove the manual implementation...",
116+
String::new(),
117+
Applicability::MachineApplicable
118+
);
119+
diag.span_suggestion(
120+
struct_span.shrink_to_lo(),
121+
"...and instead derive it",
122+
"#[derive(Default)]\n".to_string(),
123+
Applicability::MachineApplicable
124+
);
125+
}
112126
);
113127
}
114128
}

src/tools/clippy/clippy_lints/src/format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
7171
let value = arg.param.value;
7272
if_chain! {
7373
if format_args.format_string.parts == [kw::Empty];
74+
if arg.format.is_default();
7475
if match cx.typeck_results().expr_ty(value).peel_refs().kind() {
7576
ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(sym::String, adt.did()),
7677
ty::Str => true,
7778
_ => false,
7879
};
79-
if !arg.format.has_string_formatting();
8080
then {
8181
let is_new_string = match value.kind {
8282
ExprKind::Binary(..) => true,

src/tools/clippy/clippy_lints/src/format_args.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs {
7777
if let ExpnKind::Macro(_, name) = outermost_expn_data.kind;
7878
then {
7979
for arg in &format_args.args {
80-
if arg.format.has_string_formatting() {
80+
if !arg.format.is_default() {
8181
continue;
8282
}
8383
if is_aliased(&format_args, arg.param.value.hir_id) {

0 commit comments

Comments
 (0)