Skip to content

Commit 61a415b

Browse files
committed
Auto merge of #106780 - flip1995:clippyup, r=Manishearth
Update Clippy r? `@Manishearth`
2 parents 1bc3683 + 01c7584 commit 61a415b

File tree

85 files changed

+1879
-850
lines changed

Some content is hidden

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

85 files changed

+1879
-850
lines changed

src/tools/clippy/.github/driver.sh

+7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ test "$sysroot" = $desired_sysroot
1717
sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot)
1818
test "$sysroot" = $desired_sysroot
1919

20+
# Check that the --sysroot argument is only passed once (SYSROOT is ignored)
21+
(
22+
cd rustc_tools_util
23+
touch src/lib.rs
24+
SYSROOT=/tmp RUSTFLAGS="--sysroot=$(rustc --print sysroot)" ../target/debug/cargo-clippy clippy --verbose
25+
)
26+
2027
# Make sure this isn't set - clippy-driver should cope without it
2128
unset CARGO_MANIFEST_DIR
2229

src/tools/clippy/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -4137,6 +4137,7 @@ Released 2018-09-13
41374137
[`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
41384138
[`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord
41394139
[`derive_partial_eq_without_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq
4140+
[`derived_hash_with_manual_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derived_hash_with_manual_eq
41404141
[`disallowed_macros`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros
41414142
[`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method
41424143
[`disallowed_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods

src/tools/clippy/book/src/installation.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Installation
22

3-
If you're using `rustup` to install and manage you're Rust toolchains, Clippy is
3+
If you're using `rustup` to install and manage your Rust toolchains, Clippy is
44
usually **already installed**. In that case you can skip this chapter and go to
55
the [Usage] chapter.
66

src/tools/clippy/clippy_dev/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
// warn on lints, that are included in `rust-lang/rust`s bootstrap
66
#![warn(rust_2018_idioms, unused_lifetimes)]
77

8+
// The `rustc_driver` crate seems to be required in order to use the `rust_lexer` crate.
9+
#[allow(unused_extern_crates)]
10+
extern crate rustc_driver;
811
extern crate rustc_lexer;
912

1013
use std::path::PathBuf;

src/tools/clippy/clippy_lints/src/box_default.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_hir::{
88
Block, Expr, ExprKind, Local, Node, QPath, TyKind,
99
};
1010
use rustc_lint::{LateContext, LateLintPass, LintContext};
11-
use rustc_middle::lint::in_external_macro;
11+
use rustc_middle::{lint::in_external_macro, ty::print::with_forced_trimmed_paths};
1212
use rustc_session::{declare_lint_pass, declare_tool_lint};
1313
use rustc_span::sym;
1414

@@ -59,7 +59,7 @@ impl LateLintPass<'_> for BoxDefault {
5959
if is_plain_default(arg_path) || given_type(cx, expr) {
6060
"Box::default()".into()
6161
} else {
62-
format!("Box::<{arg_ty}>::default()")
62+
with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
6363
},
6464
Applicability::MachineApplicable
6565
);

src/tools/clippy/clippy_lints/src/copies.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,11 @@ fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbo
525525
.iter()
526526
.filter(|&&(_, name)| !name.as_str().starts_with('_'))
527527
.any(|&(_, name)| {
528-
let mut walker = ContainsName { name, result: false };
528+
let mut walker = ContainsName {
529+
name,
530+
result: false,
531+
cx,
532+
};
529533

530534
// Scan block
531535
block

src/tools/clippy/clippy_lints/src/dbg_macro.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ use rustc_span::sym;
1010

1111
declare_clippy_lint! {
1212
/// ### What it does
13-
/// Checks for usage of dbg!() macro.
13+
/// Checks for usage of the [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) macro.
1414
///
1515
/// ### Why is this bad?
16-
/// `dbg!` macro is intended as a debugging tool. It
17-
/// should not be in version control.
16+
/// The `dbg!` macro is intended as a debugging tool. It should not be present in released
17+
/// software or committed to a version control system.
1818
///
1919
/// ### Example
2020
/// ```rust,ignore
@@ -91,8 +91,8 @@ impl LateLintPass<'_> for DbgMacro {
9191
cx,
9292
DBG_MACRO,
9393
macro_call.span,
94-
"`dbg!` macro is intended as a debugging tool",
95-
"ensure to avoid having uses of it in version control",
94+
"the `dbg!` macro is intended as a debugging tool",
95+
"remove the invocation before committing it to a version control system",
9696
suggestion,
9797
applicability,
9898
);

src/tools/clippy/clippy_lints/src/declared_lints.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
111111
crate::dereference::NEEDLESS_BORROW_INFO,
112112
crate::dereference::REF_BINDING_TO_REFERENCE_INFO,
113113
crate::derivable_impls::DERIVABLE_IMPLS_INFO,
114-
crate::derive::DERIVE_HASH_XOR_EQ_INFO,
114+
crate::derive::DERIVED_HASH_WITH_MANUAL_EQ_INFO,
115115
crate::derive::DERIVE_ORD_XOR_PARTIAL_ORD_INFO,
116116
crate::derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ_INFO,
117117
crate::derive::EXPL_IMPL_CLONE_ON_COPY_INFO,

src/tools/clippy/clippy_lints/src/default.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_hir::def::Res;
1111
use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
1212
use rustc_lint::{LateContext, LateLintPass};
1313
use rustc_middle::ty;
14+
use rustc_middle::ty::print::with_forced_trimmed_paths;
1415
use rustc_session::{declare_tool_lint, impl_lint_pass};
1516
use rustc_span::symbol::{Ident, Symbol};
1617
use rustc_span::Span;
@@ -98,9 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
9899
if let ty::Adt(def, ..) = expr_ty.kind();
99100
if !is_from_proc_macro(cx, expr);
100101
then {
101-
// TODO: Work out a way to put "whatever the imported way of referencing
102-
// this type in this file" rather than a fully-qualified type.
103-
let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did()));
102+
let replacement = with_forced_trimmed_paths!(format!("{}::default()", cx.tcx.def_path_str(def.did())));
104103
span_lint_and_sugg(
105104
cx,
106105
DEFAULT_TRAIT_ACCESS,
@@ -170,7 +169,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
170169
// find out if and which field was set by this `consecutive_statement`
171170
if let Some((field_ident, assign_rhs)) = field_reassigned_by_stmt(consecutive_statement, binding_name) {
172171
// interrupt and cancel lint if assign_rhs references the original binding
173-
if contains_name(binding_name, assign_rhs) {
172+
if contains_name(binding_name, assign_rhs, cx) {
174173
cancel_lint = true;
175174
break;
176175
}

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -1282,10 +1282,10 @@ fn referent_used_exactly_once<'tcx>(
12821282
possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir)));
12831283
}
12841284
let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1;
1285-
// If `place.local` were not included here, the `copyable_iterator::warn` test would fail. The
1286-
// reason is that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible
1287-
// borrower of itself. See the comment in that method for an explanation as to why.
1288-
possible_borrower.at_most_borrowers(cx, &[local, place.local], place.local, location)
1285+
// If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is
1286+
// that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of
1287+
// itself. See the comment in that method for an explanation as to why.
1288+
possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location)
12891289
&& used_exactly_once(mir, place.local).unwrap_or(false)
12901290
} else {
12911291
false

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

+117-44
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
2+
use clippy_utils::msrvs::{self, Msrv};
3+
use clippy_utils::source::indent_of;
24
use clippy_utils::{is_default_equivalent, peel_blocks};
35
use rustc_errors::Applicability;
46
use rustc_hir::{
5-
def::{DefKind, Res},
6-
Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind,
7+
def::{CtorKind, CtorOf, DefKind, Res},
8+
Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, Ty, TyKind,
79
};
810
use rustc_lint::{LateContext, LateLintPass};
9-
use rustc_session::{declare_lint_pass, declare_tool_lint};
11+
use rustc_middle::ty::{AdtDef, DefIdTree};
12+
use rustc_session::{declare_tool_lint, impl_lint_pass};
1013
use rustc_span::sym;
1114

1215
declare_clippy_lint! {
@@ -51,7 +54,18 @@ declare_clippy_lint! {
5154
"manual implementation of the `Default` trait which is equal to a derive"
5255
}
5356

54-
declare_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]);
57+
pub struct DerivableImpls {
58+
msrv: Msrv,
59+
}
60+
61+
impl DerivableImpls {
62+
#[must_use]
63+
pub fn new(msrv: Msrv) -> Self {
64+
DerivableImpls { msrv }
65+
}
66+
}
67+
68+
impl_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]);
5569

5670
fn is_path_self(e: &Expr<'_>) -> bool {
5771
if let ExprKind::Path(QPath::Resolved(_, p)) = e.kind {
@@ -61,6 +75,98 @@ fn is_path_self(e: &Expr<'_>) -> bool {
6175
}
6276
}
6377

78+
fn check_struct<'tcx>(
79+
cx: &LateContext<'tcx>,
80+
item: &'tcx Item<'_>,
81+
self_ty: &Ty<'_>,
82+
func_expr: &Expr<'_>,
83+
adt_def: AdtDef<'_>,
84+
) {
85+
if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
86+
if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() {
87+
for arg in a.args {
88+
if !matches!(arg, GenericArg::Lifetime(_)) {
89+
return;
90+
}
91+
}
92+
}
93+
}
94+
let should_emit = match peel_blocks(func_expr).kind {
95+
ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)),
96+
ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)),
97+
ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
98+
_ => false,
99+
};
100+
101+
if should_emit {
102+
let struct_span = cx.tcx.def_span(adt_def.did());
103+
span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| {
104+
diag.span_suggestion_hidden(
105+
item.span,
106+
"remove the manual implementation...",
107+
String::new(),
108+
Applicability::MachineApplicable,
109+
);
110+
diag.span_suggestion(
111+
struct_span.shrink_to_lo(),
112+
"...and instead derive it",
113+
"#[derive(Default)]\n".to_string(),
114+
Applicability::MachineApplicable,
115+
);
116+
});
117+
}
118+
}
119+
120+
fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Expr<'_>, adt_def: AdtDef<'_>) {
121+
if_chain! {
122+
if let ExprKind::Path(QPath::Resolved(None, p)) = &peel_blocks(func_expr).kind;
123+
if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res;
124+
if let variant_id = cx.tcx.parent(id);
125+
if let Some(variant_def) = adt_def.variants().iter().find(|v| v.def_id == variant_id);
126+
if variant_def.fields.is_empty();
127+
if !variant_def.is_field_list_non_exhaustive();
128+
129+
then {
130+
let enum_span = cx.tcx.def_span(adt_def.did());
131+
let indent_enum = indent_of(cx, enum_span).unwrap_or(0);
132+
let variant_span = cx.tcx.def_span(variant_def.def_id);
133+
let indent_variant = indent_of(cx, variant_span).unwrap_or(0);
134+
span_lint_and_then(
135+
cx,
136+
DERIVABLE_IMPLS,
137+
item.span,
138+
"this `impl` can be derived",
139+
|diag| {
140+
diag.span_suggestion_hidden(
141+
item.span,
142+
"remove the manual implementation...",
143+
String::new(),
144+
Applicability::MachineApplicable
145+
);
146+
diag.span_suggestion(
147+
enum_span.shrink_to_lo(),
148+
"...and instead derive it...",
149+
format!(
150+
"#[derive(Default)]\n{indent}",
151+
indent = " ".repeat(indent_enum),
152+
),
153+
Applicability::MachineApplicable
154+
);
155+
diag.span_suggestion(
156+
variant_span.shrink_to_lo(),
157+
"...and mark the default variant",
158+
format!(
159+
"#[default]\n{indent}",
160+
indent = " ".repeat(indent_variant),
161+
),
162+
Applicability::MachineApplicable
163+
);
164+
}
165+
);
166+
}
167+
}
168+
}
169+
64170
impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
65171
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
66172
if_chain! {
@@ -83,49 +189,16 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
83189
if !attrs.iter().any(|attr| attr.doc_str().is_some());
84190
if let child_attrs = cx.tcx.hir().attrs(impl_item_hir);
85191
if !child_attrs.iter().any(|attr| attr.doc_str().is_some());
86-
if adt_def.is_struct();
87-
then {
88-
if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
89-
if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() {
90-
for arg in a.args {
91-
if !matches!(arg, GenericArg::Lifetime(_)) {
92-
return;
93-
}
94-
}
95-
}
96-
}
97-
let should_emit = match peel_blocks(func_expr).kind {
98-
ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)),
99-
ExprKind::Call(callee, args)
100-
if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)),
101-
ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
102-
_ => false,
103-
};
104192

105-
if should_emit {
106-
let struct_span = cx.tcx.def_span(adt_def.did());
107-
span_lint_and_then(
108-
cx,
109-
DERIVABLE_IMPLS,
110-
item.span,
111-
"this `impl` can be derived",
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-
}
126-
);
193+
then {
194+
if adt_def.is_struct() {
195+
check_struct(cx, item, self_ty, func_expr, adt_def);
196+
} else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) {
197+
check_enum(cx, item, func_expr, adt_def);
127198
}
128199
}
129200
}
130201
}
202+
203+
extract_msrv_attr!(LateContext);
131204
}

0 commit comments

Comments
 (0)