Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into sync-from-rust
Browse files Browse the repository at this point in the history
  • Loading branch information
giraffate committed Nov 27, 2020
2 parents f303168 + 403816f commit 0924d62
Show file tree
Hide file tree
Showing 60 changed files with 1,129 additions and 216 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,32 @@ cargo clippy -- -A clippy::all -W clippy::useless_format -W clippy::...
```
Note that if you've run clippy before, this may only take effect after you've modified a file or ran `cargo clean`.

### Specifying the minimum supported Rust version

Projects that intend to support old versions of Rust can disable lints pertaining to newer features by
specifying the minimum supported Rust version (MSRV) in the clippy configuration file.

```toml
msrv = "1.30.0"
```

The MSRV can also be specified as an inner attribute, like below.

```rust
#![feature(custom_inner_attributes)]
#![clippy::msrv = "1.30.0"]

fn main() {
...
}
```

Tilde/Caret version requirements (like `^1.0` or `~1.2`) can be specified as well.

Note: `custom_inner_attributes` is an unstable feature so it has to be enabled explicitly.

Lints that recognize this configuration option can be found [here](https://rust-lang.github.io/rust-clippy/master/index.html#msrv)

## Contributing

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).
Expand Down
20 changes: 0 additions & 20 deletions clippy_lints/src/deprecated_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,26 +51,6 @@ declare_deprecated_lint! {
"`Vec::as_mut_slice` has been stabilized in 1.7"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `.to_string()` method calls on values
/// of type `&str`. This is not unidiomatic and with specialization coming, `to_string` could be
/// specialized to be as efficient as `to_owned`.
pub STR_TO_STRING,
"using `str::to_string` is common even today and specialization will likely happen soon"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `.to_string()` method calls on values
/// of type `String`. This is not unidiomatic and with specialization coming, `to_string` could be
/// specialized to be as efficient as `clone`.
pub STRING_TO_STRING,
"using `string::to_string` is common even today and specialization will likely happen soon"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
Expand Down
9 changes: 2 additions & 7 deletions clippy_lints/src/future_not_send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,8 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
|db| {
cx.tcx.infer_ctxt().enter(|infcx| {
for FulfillmentError { obligation, .. } in send_errors {
infcx.maybe_note_obligation_cause_for_async_await(
db,
&obligation,
);
if let Trait(trait_pred, _) =
obligation.predicate.skip_binders()
{
infcx.maybe_note_obligation_cause_for_async_await(db, &obligation);
if let Trait(trait_pred, _) = obligation.predicate.skip_binders() {
db.note(&format!(
"`{}` doesn't implement `{}`",
trait_pred.self_ty(),
Expand Down
45 changes: 24 additions & 21 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ extern crate rustc_target;
extern crate rustc_trait_selection;
extern crate rustc_typeck;

use crate::utils::parse_msrv;
use rustc_data_structures::fx::FxHashSet;
use rustc_lint::LintId;
use rustc_session::Session;
Expand Down Expand Up @@ -440,14 +441,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
"clippy::unstable_as_mut_slice",
"`Vec::as_mut_slice` has been stabilized in 1.7",
);
store.register_removed(
"clippy::str_to_string",
"using `str::to_string` is common even today and specialization will likely happen soon",
);
store.register_removed(
"clippy::string_to_string",
"using `string::to_string` is common even today and specialization will likely happen soon",
);
store.register_removed(
"clippy::misaligned_transmute",
"this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",
Expand Down Expand Up @@ -839,6 +832,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&strings::STRING_ADD_ASSIGN,
&strings::STRING_FROM_UTF8_AS_BYTES,
&strings::STRING_LIT_AS_BYTES,
&strings::STRING_TO_STRING,
&strings::STR_TO_STRING,
&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
&swap::ALMOST_SWAPPED,
Expand Down Expand Up @@ -933,7 +928,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&zero_div_zero::ZERO_DIVIDED_BY_ZERO,
]);
// end register lints, do not remove this comment, it’s used in `update_lints`

store.register_late_pass(|| box await_holding_invalid::AwaitHolding);
store.register_late_pass(|| box serde_api::SerdeAPI);
store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
Expand Down Expand Up @@ -969,7 +963,23 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box strings::StringAdd);
store.register_late_pass(|| box implicit_return::ImplicitReturn);
store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub);
store.register_late_pass(|| box methods::Methods);

let parsed_msrv = conf.msrv.as_ref().and_then(|s| {
parse_msrv(s, None, None).or_else(|| {
sess.err(&format!("error reading Clippy's configuration file. `{}` is not a valid Rust version", s));
None
})
});

let msrv = parsed_msrv.clone();
store.register_late_pass(move || box methods::Methods::new(msrv.clone()));
let msrv = parsed_msrv.clone();
store.register_late_pass(move || box matches::Matches::new(msrv.clone()));
let msrv = parsed_msrv.clone();
store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv.clone()));
let msrv = parsed_msrv;
store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv.clone()));

store.register_late_pass(|| box map_clone::MapClone);
store.register_late_pass(|| box map_err_ignore::MapErrIgnore);
store.register_late_pass(|| box shadow::Shadow);
Expand All @@ -983,7 +993,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box types::Casts);
let type_complexity_threshold = conf.type_complexity_threshold;
store.register_late_pass(move || box types::TypeComplexity::new(type_complexity_threshold));
store.register_late_pass(|| box matches::Matches::default());
store.register_late_pass(|| box minmax::MinMaxPass);
store.register_late_pass(|| box open_options::OpenOptions);
store.register_late_pass(|| box zero_div_zero::ZeroDiv);
Expand Down Expand Up @@ -1144,7 +1153,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box if_let_mutex::IfLetMutex);
store.register_late_pass(|| box mut_mutex_lock::MutMutexLock);
store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems);
store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive);
store.register_late_pass(|| box manual_async_fn::ManualAsyncFn);
store.register_early_pass(|| box redundant_field_names::RedundantFieldNames);
store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero);
Expand All @@ -1166,13 +1174,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box manual_ok_or::ManualOkOr);
store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs);
store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync);
store.register_late_pass(|| box manual_strip::ManualStrip);
store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>();
store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax);
store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax);
store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops);
store.register_late_pass(|| box strings::StrToString);
store.register_late_pass(|| box strings::StringToString);


store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
Expand Down Expand Up @@ -1215,6 +1224,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&shadow::SHADOW_REUSE),
LintId::of(&shadow::SHADOW_SAME),
LintId::of(&strings::STRING_ADD),
LintId::of(&strings::STRING_TO_STRING),
LintId::of(&strings::STR_TO_STRING),
LintId::of(&types::RC_BUFFER),
LintId::of(&unwrap_in_result::UNWRAP_IN_RESULT),
LintId::of(&verbose_file_reads::VERBOSE_FILE_READS),
Expand Down Expand Up @@ -1930,14 +1941,6 @@ fn register_removed_non_tool_lints(store: &mut rustc_lint::LintStore) {
"unstable_as_mut_slice",
"`Vec::as_mut_slice` has been stabilized in 1.7",
);
store.register_removed(
"str_to_string",
"using `str::to_string` is common even today and specialization will likely happen soon",
);
store.register_removed(
"string_to_string",
"using `string::to_string` is common even today and specialization will likely happen soon",
);
store.register_removed(
"misaligned_transmute",
"this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",
Expand Down
34 changes: 33 additions & 1 deletion clippy_lints/src/loops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2950,7 +2950,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
for ref stmt in block.stmts {
if_chain! {
if let StmtKind::Local(
Local { pat: Pat { kind: PatKind::Binding(_, _, ident, .. ), .. },
Local { pat: Pat { hir_id: pat_id, kind: PatKind::Binding(_, _, ident, .. ), .. },
init: Some(ref init_expr), .. }
) = stmt.kind;
if let ExprKind::MethodCall(ref method_name, _, &[ref iter_source], ..) = init_expr.kind;
Expand All @@ -2964,6 +2964,16 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
if let Some(iter_calls) = detect_iter_and_into_iters(block, *ident);
if iter_calls.len() == 1;
then {
let mut used_count_visitor = UsedCountVisitor {
cx,
id: *pat_id,
count: 0,
};
walk_block(&mut used_count_visitor, block);
if used_count_visitor.count > 1 {
return;
}

// Suggest replacing iter_call with iter_replacement, and removing stmt
let iter_call = &iter_calls[0];
span_lint_and_then(
Expand Down Expand Up @@ -3087,6 +3097,28 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor {
}
}

struct UsedCountVisitor<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
id: HirId,
count: usize,
}

impl<'a, 'tcx> Visitor<'tcx> for UsedCountVisitor<'a, 'tcx> {
type Map = Map<'tcx>;

fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if same_var(self.cx, expr, self.id) {
self.count += 1;
} else {
walk_expr(self, expr);
}
}

fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
}
}

/// Detect the occurrences of calls to `iter` or `into_iter` for the
/// given identifier
fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) -> Option<Vec<IterFunction>> {
Expand Down
33 changes: 30 additions & 3 deletions clippy_lints/src/manual_non_exhaustive.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
use crate::utils::{snippet_opt, span_lint_and_then};
use crate::utils::{meets_msrv, snippet_opt, span_lint_and_then};
use if_chain::if_chain;
use rustc_ast::ast::{Attribute, Item, ItemKind, StructField, Variant, VariantData, VisibilityKind};
use rustc_attr as attr;
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{sym, Span};
use semver::{Version, VersionReq};

const MANUAL_NON_EXHAUSTIVE_MSRV: Version = Version {
major: 1,
minor: 40,
patch: 0,
pre: Vec::new(),
build: Vec::new(),
};

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

declare_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
#[derive(Clone)]
pub struct ManualNonExhaustive {
msrv: Option<VersionReq>,
}

impl ManualNonExhaustive {
#[must_use]
pub fn new(msrv: Option<VersionReq>) -> Self {
Self { msrv }
}
}

impl_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);

impl EarlyLintPass for ManualNonExhaustive {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
if !meets_msrv(self.msrv.as_ref(), &MANUAL_NON_EXHAUSTIVE_MSRV) {
return;
}

match &item.kind {
ItemKind::Enum(def, _) => {
check_manual_non_exhaustive_enum(cx, item, &def.variants);
Expand All @@ -73,6 +98,8 @@ impl EarlyLintPass for ManualNonExhaustive {
_ => {},
}
}

extract_msrv_attr!(EarlyContext);
}

fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants: &[Variant]) {
Expand Down
34 changes: 30 additions & 4 deletions clippy_lints/src/manual_strip.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::consts::{constant, Constant};
use crate::utils::usage::mutated_variables;
use crate::utils::{
eq_expr_value, higher, match_def_path, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then,
eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then,
};

use if_chain::if_chain;
Expand All @@ -10,12 +10,21 @@ use rustc_hir::def::Res;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc_hir::BinOpKind;
use rustc_hir::{BorrowKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Spanned;
use rustc_span::Span;
use semver::{Version, VersionReq};

const MANUAL_STRIP_MSRV: Version = Version {
major: 1,
minor: 45,
patch: 0,
pre: Vec::new(),
build: Vec::new(),
};

declare_clippy_lint! {
/// **What it does:**
Expand Down Expand Up @@ -51,7 +60,18 @@ declare_clippy_lint! {
"suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing"
}

declare_lint_pass!(ManualStrip => [MANUAL_STRIP]);
pub struct ManualStrip {
msrv: Option<VersionReq>,
}

impl ManualStrip {
#[must_use]
pub fn new(msrv: Option<VersionReq>) -> Self {
Self { msrv }
}
}

impl_lint_pass!(ManualStrip => [MANUAL_STRIP]);

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum StripKind {
Expand All @@ -61,6 +81,10 @@ enum StripKind {

impl<'tcx> LateLintPass<'tcx> for ManualStrip {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if !meets_msrv(self.msrv.as_ref(), &MANUAL_STRIP_MSRV) {
return;
}

if_chain! {
if let Some((cond, then, _)) = higher::if_block(&expr);
if let ExprKind::MethodCall(_, _, [target_arg, pattern], _) = cond.kind;
Expand Down Expand Up @@ -114,6 +138,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
}
}
}

extract_msrv_attr!(LateContext);
}

// Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise.
Expand Down
Loading

0 comments on commit 0924d62

Please sign in to comment.