Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 18d37a5

Browse files
committed
Merge remote-tracking branch 'upstream/master' into rustup
2 parents 5d585ec + f9b8a59 commit 18d37a5

File tree

61 files changed

+1132
-218
lines changed

Some content is hidden

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

61 files changed

+1132
-218
lines changed

README.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ cargo clippy -- -W clippy::lint_name
182182
```
183183

184184
This also works with lint groups. For example you
185-
can run Clippy with warnings for all lints enabled:
185+
can run Clippy with warnings for all lints enabled:
186186
```terminal
187187
cargo clippy -- -W clippy::pedantic
188188
```
@@ -194,6 +194,33 @@ cargo clippy -- -A clippy::all -W clippy::useless_format -W clippy::...
194194
```
195195
Note that if you've run clippy before, this may only take effect after you've modified a file or ran `cargo clean`.
196196

197+
### Specifying the minimum supported Rust version
198+
199+
Projects that intend to support old versions of Rust can disable lints pertaining to newer features by
200+
specifying the minimum supported Rust version (MSRV) in the clippy configuration file.
201+
202+
```toml
203+
msrv = "1.30.0"
204+
```
205+
206+
The MSRV can also be specified as an inner attribute, like below.
207+
208+
```rust
209+
#![feature(custom_inner_attributes)]
210+
#![clippy::msrv = "1.30.0"]
211+
212+
fn main() {
213+
...
214+
}
215+
```
216+
217+
You can also omit the patch version when specifying the MSRV, so `msrv = 1.30`
218+
is equivalent to `msrv = 1.30.0`.
219+
220+
Note: `custom_inner_attributes` is an unstable feature so it has to be enabled explicitly.
221+
222+
Lints that recognize this configuration option can be found [here](https://rust-lang.github.io/rust-clippy/master/index.html#msrv)
223+
197224
## Contributing
198225

199226
If you want to contribute to Clippy, you can find more information in [CONTRIBUTING.md](https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md).

clippy_lints/src/attrs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use crate::utils::{
55
span_lint_and_sugg, span_lint_and_then, without_block_comments,
66
};
77
use if_chain::if_chain;
8-
use rustc_span::lev_distance::find_best_match_for_name;
98
use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
109
use rustc_errors::Applicability;
1110
use rustc_hir::{
@@ -15,6 +14,7 @@ use rustc_lint::{CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext,
1514
use rustc_middle::lint::in_external_macro;
1615
use rustc_middle::ty;
1716
use rustc_session::{declare_lint_pass, declare_tool_lint};
17+
use rustc_span::lev_distance::find_best_match_for_name;
1818
use rustc_span::source_map::Span;
1919
use rustc_span::sym;
2020
use rustc_span::symbol::{Symbol, SymbolStr};

clippy_lints/src/deprecated_lints.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,26 +51,6 @@ declare_deprecated_lint! {
5151
"`Vec::as_mut_slice` has been stabilized in 1.7"
5252
}
5353

54-
declare_deprecated_lint! {
55-
/// **What it does:** Nothing. This lint has been deprecated.
56-
///
57-
/// **Deprecation reason:** This used to check for `.to_string()` method calls on values
58-
/// of type `&str`. This is not unidiomatic and with specialization coming, `to_string` could be
59-
/// specialized to be as efficient as `to_owned`.
60-
pub STR_TO_STRING,
61-
"using `str::to_string` is common even today and specialization will likely happen soon"
62-
}
63-
64-
declare_deprecated_lint! {
65-
/// **What it does:** Nothing. This lint has been deprecated.
66-
///
67-
/// **Deprecation reason:** This used to check for `.to_string()` method calls on values
68-
/// of type `String`. This is not unidiomatic and with specialization coming, `to_string` could be
69-
/// specialized to be as efficient as `clone`.
70-
pub STRING_TO_STRING,
71-
"using `string::to_string` is common even today and specialization will likely happen soon"
72-
}
73-
7454
declare_deprecated_lint! {
7555
/// **What it does:** Nothing. This lint has been deprecated.
7656
///

clippy_lints/src/future_not_send.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,8 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
9292
|db| {
9393
cx.tcx.infer_ctxt().enter(|infcx| {
9494
for FulfillmentError { obligation, .. } in send_errors {
95-
infcx.maybe_note_obligation_cause_for_async_await(
96-
db,
97-
&obligation,
98-
);
99-
if let Trait(trait_pred, _) =
100-
obligation.predicate.skip_binders()
101-
{
95+
infcx.maybe_note_obligation_cause_for_async_await(db, &obligation);
96+
if let Trait(trait_pred, _) = obligation.predicate.skip_binders() {
10297
db.note(&format!(
10398
"`{}` doesn't implement `{}`",
10499
trait_pred.self_ty(),

clippy_lints/src/lib.rs

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ extern crate rustc_target;
4444
extern crate rustc_trait_selection;
4545
extern crate rustc_typeck;
4646

47+
use crate::utils::parse_msrv;
4748
use rustc_data_structures::fx::FxHashSet;
4849
use rustc_lint::LintId;
4950
use rustc_session::Session;
@@ -440,14 +441,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
440441
"clippy::unstable_as_mut_slice",
441442
"`Vec::as_mut_slice` has been stabilized in 1.7",
442443
);
443-
store.register_removed(
444-
"clippy::str_to_string",
445-
"using `str::to_string` is common even today and specialization will likely happen soon",
446-
);
447-
store.register_removed(
448-
"clippy::string_to_string",
449-
"using `string::to_string` is common even today and specialization will likely happen soon",
450-
);
451444
store.register_removed(
452445
"clippy::misaligned_transmute",
453446
"this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",
@@ -839,6 +832,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
839832
&strings::STRING_ADD_ASSIGN,
840833
&strings::STRING_FROM_UTF8_AS_BYTES,
841834
&strings::STRING_LIT_AS_BYTES,
835+
&strings::STRING_TO_STRING,
836+
&strings::STR_TO_STRING,
842837
&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
843838
&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
844839
&swap::ALMOST_SWAPPED,
@@ -933,7 +928,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
933928
&zero_div_zero::ZERO_DIVIDED_BY_ZERO,
934929
]);
935930
// end register lints, do not remove this comment, it’s used in `update_lints`
936-
937931
store.register_late_pass(|| box await_holding_invalid::AwaitHolding);
938932
store.register_late_pass(|| box serde_api::SerdeAPI);
939933
store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
@@ -969,7 +963,23 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
969963
store.register_late_pass(|| box strings::StringAdd);
970964
store.register_late_pass(|| box implicit_return::ImplicitReturn);
971965
store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub);
972-
store.register_late_pass(|| box methods::Methods);
966+
967+
let parsed_msrv = conf.msrv.as_ref().and_then(|s| {
968+
parse_msrv(s, None, None).or_else(|| {
969+
sess.err(&format!("error reading Clippy's configuration file. `{}` is not a valid Rust version", s));
970+
None
971+
})
972+
});
973+
974+
let msrv = parsed_msrv.clone();
975+
store.register_late_pass(move || box methods::Methods::new(msrv.clone()));
976+
let msrv = parsed_msrv.clone();
977+
store.register_late_pass(move || box matches::Matches::new(msrv.clone()));
978+
let msrv = parsed_msrv.clone();
979+
store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv.clone()));
980+
let msrv = parsed_msrv;
981+
store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv.clone()));
982+
973983
store.register_late_pass(|| box map_clone::MapClone);
974984
store.register_late_pass(|| box map_err_ignore::MapErrIgnore);
975985
store.register_late_pass(|| box shadow::Shadow);
@@ -983,7 +993,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
983993
store.register_late_pass(|| box types::Casts);
984994
let type_complexity_threshold = conf.type_complexity_threshold;
985995
store.register_late_pass(move || box types::TypeComplexity::new(type_complexity_threshold));
986-
store.register_late_pass(|| box matches::Matches::default());
987996
store.register_late_pass(|| box minmax::MinMaxPass);
988997
store.register_late_pass(|| box open_options::OpenOptions);
989998
store.register_late_pass(|| box zero_div_zero::ZeroDiv);
@@ -1144,7 +1153,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11441153
store.register_late_pass(|| box if_let_mutex::IfLetMutex);
11451154
store.register_late_pass(|| box mut_mutex_lock::MutMutexLock);
11461155
store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems);
1147-
store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive);
11481156
store.register_late_pass(|| box manual_async_fn::ManualAsyncFn);
11491157
store.register_early_pass(|| box redundant_field_names::RedundantFieldNames);
11501158
store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero);
@@ -1166,13 +1174,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11661174
store.register_late_pass(|| box manual_ok_or::ManualOkOr);
11671175
store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs);
11681176
store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync);
1169-
store.register_late_pass(|| box manual_strip::ManualStrip);
11701177
store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
11711178
let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>();
11721179
store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
11731180
store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax);
11741181
store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax);
11751182
store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops);
1183+
store.register_late_pass(|| box strings::StrToString);
1184+
store.register_late_pass(|| box strings::StringToString);
11761185

11771186

11781187
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
@@ -1215,6 +1224,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
12151224
LintId::of(&shadow::SHADOW_REUSE),
12161225
LintId::of(&shadow::SHADOW_SAME),
12171226
LintId::of(&strings::STRING_ADD),
1227+
LintId::of(&strings::STRING_TO_STRING),
1228+
LintId::of(&strings::STR_TO_STRING),
12181229
LintId::of(&types::RC_BUFFER),
12191230
LintId::of(&unwrap_in_result::UNWRAP_IN_RESULT),
12201231
LintId::of(&verbose_file_reads::VERBOSE_FILE_READS),
@@ -1930,14 +1941,6 @@ fn register_removed_non_tool_lints(store: &mut rustc_lint::LintStore) {
19301941
"unstable_as_mut_slice",
19311942
"`Vec::as_mut_slice` has been stabilized in 1.7",
19321943
);
1933-
store.register_removed(
1934-
"str_to_string",
1935-
"using `str::to_string` is common even today and specialization will likely happen soon",
1936-
);
1937-
store.register_removed(
1938-
"string_to_string",
1939-
"using `string::to_string` is common even today and specialization will likely happen soon",
1940-
);
19411944
store.register_removed(
19421945
"misaligned_transmute",
19431946
"this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",

clippy_lints/src/loops.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2950,7 +2950,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
29502950
for ref stmt in block.stmts {
29512951
if_chain! {
29522952
if let StmtKind::Local(
2953-
Local { pat: Pat { kind: PatKind::Binding(_, _, ident, .. ), .. },
2953+
Local { pat: Pat { hir_id: pat_id, kind: PatKind::Binding(_, _, ident, .. ), .. },
29542954
init: Some(ref init_expr), .. }
29552955
) = stmt.kind;
29562956
if let ExprKind::MethodCall(ref method_name, _, &[ref iter_source], ..) = init_expr.kind;
@@ -2964,6 +2964,16 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
29642964
if let Some(iter_calls) = detect_iter_and_into_iters(block, *ident);
29652965
if iter_calls.len() == 1;
29662966
then {
2967+
let mut used_count_visitor = UsedCountVisitor {
2968+
cx,
2969+
id: *pat_id,
2970+
count: 0,
2971+
};
2972+
walk_block(&mut used_count_visitor, block);
2973+
if used_count_visitor.count > 1 {
2974+
return;
2975+
}
2976+
29672977
// Suggest replacing iter_call with iter_replacement, and removing stmt
29682978
let iter_call = &iter_calls[0];
29692979
span_lint_and_then(
@@ -3087,6 +3097,28 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor {
30873097
}
30883098
}
30893099

3100+
struct UsedCountVisitor<'a, 'tcx> {
3101+
cx: &'a LateContext<'tcx>,
3102+
id: HirId,
3103+
count: usize,
3104+
}
3105+
3106+
impl<'a, 'tcx> Visitor<'tcx> for UsedCountVisitor<'a, 'tcx> {
3107+
type Map = Map<'tcx>;
3108+
3109+
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
3110+
if same_var(self.cx, expr, self.id) {
3111+
self.count += 1;
3112+
} else {
3113+
walk_expr(self, expr);
3114+
}
3115+
}
3116+
3117+
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
3118+
NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
3119+
}
3120+
}
3121+
30903122
/// Detect the occurrences of calls to `iter` or `into_iter` for the
30913123
/// given identifier
30923124
fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) -> Option<Vec<IterFunction>> {

clippy_lints/src/manual_non_exhaustive.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
1-
use crate::utils::{snippet_opt, span_lint_and_then};
1+
use crate::utils::{meets_msrv, snippet_opt, span_lint_and_then};
22
use if_chain::if_chain;
33
use rustc_ast::ast::{Attribute, Item, ItemKind, StructField, Variant, VariantData, VisibilityKind};
44
use rustc_attr as attr;
55
use rustc_errors::Applicability;
66
use rustc_lint::{EarlyContext, EarlyLintPass};
7-
use rustc_session::{declare_lint_pass, declare_tool_lint};
7+
use rustc_session::{declare_tool_lint, impl_lint_pass};
88
use rustc_span::{sym, Span};
9+
use semver::{Version, VersionReq};
10+
11+
const MANUAL_NON_EXHAUSTIVE_MSRV: Version = Version {
12+
major: 1,
13+
minor: 40,
14+
patch: 0,
15+
pre: Vec::new(),
16+
build: Vec::new(),
17+
};
918

1019
declare_clippy_lint! {
1120
/// **What it does:** Checks for manual implementations of the non-exhaustive pattern.
@@ -55,10 +64,26 @@ declare_clippy_lint! {
5564
"manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]"
5665
}
5766

58-
declare_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
67+
#[derive(Clone)]
68+
pub struct ManualNonExhaustive {
69+
msrv: Option<VersionReq>,
70+
}
71+
72+
impl ManualNonExhaustive {
73+
#[must_use]
74+
pub fn new(msrv: Option<VersionReq>) -> Self {
75+
Self { msrv }
76+
}
77+
}
78+
79+
impl_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
5980

6081
impl EarlyLintPass for ManualNonExhaustive {
6182
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
83+
if !meets_msrv(self.msrv.as_ref(), &MANUAL_NON_EXHAUSTIVE_MSRV) {
84+
return;
85+
}
86+
6287
match &item.kind {
6388
ItemKind::Enum(def, _) => {
6489
check_manual_non_exhaustive_enum(cx, item, &def.variants);
@@ -73,6 +98,8 @@ impl EarlyLintPass for ManualNonExhaustive {
7398
_ => {},
7499
}
75100
}
101+
102+
extract_msrv_attr!(EarlyContext);
76103
}
77104

78105
fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants: &[Variant]) {

0 commit comments

Comments
 (0)