Skip to content

Commit 23646e6

Browse files
committed
Merge remote-tracking branch 'upstream/master' into sync-from-rust
2 parents 4286d9c + b9e35df commit 23646e6

31 files changed

+724
-134
lines changed

CHANGELOG.md

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,113 @@ document.
66

77
## Unreleased / In Rust Nightly
88

9-
[c2c07fa...master](https://github.com/rust-lang/rust-clippy/compare/c2c07fa...master)
9+
[09bd400...master](https://github.com/rust-lang/rust-clippy/compare/09bd400...master)
10+
11+
## Rust 1.47
12+
13+
Current beta, release 2020-10-08
14+
15+
[c2c07fa...09bd400](https://github.com/rust-lang/rust-clippy/compare/c2c07fa...09bd400)
16+
17+
### New lints
18+
19+
* [`derive_ord_xor_partial_ord`] [#5848](https://github.com/rust-lang/rust-clippy/pull/5848)
20+
* [`trait_duplication_in_bounds`] [#5852](https://github.com/rust-lang/rust-clippy/pull/5852)
21+
* [`map_identity`] [#5694](https://github.com/rust-lang/rust-clippy/pull/5694)
22+
* [`unit_return_expecting_ord`] [#5737](https://github.com/rust-lang/rust-clippy/pull/5737)
23+
* [`pattern_type_mismatch`] [#4841](https://github.com/rust-lang/rust-clippy/pull/4841)
24+
* [`repeat_once`] [#5773](https://github.com/rust-lang/rust-clippy/pull/5773)
25+
* [`same_item_push`] [#5825](https://github.com/rust-lang/rust-clippy/pull/5825)
26+
* [`needless_arbitrary_self_type`] [#5869](https://github.com/rust-lang/rust-clippy/pull/5869)
27+
* [`match_like_matches_macro`] [#5769](https://github.com/rust-lang/rust-clippy/pull/5769)
28+
* [`stable_sort_primitive`] [#5809](https://github.com/rust-lang/rust-clippy/pull/5809)
29+
* [`blanket_clippy_restriction_lints`] [#5750](https://github.com/rust-lang/rust-clippy/pull/5750)
30+
* [`option_if_let_else`] [#5301](https://github.com/rust-lang/rust-clippy/pull/5301)
31+
32+
### Moves and Deprecations
33+
34+
* Deprecate [`regex_macro`] lint
35+
[#5760](https://github.com/rust-lang/rust-clippy/pull/5760)
36+
* Move [`range_minus_one`] to `pedantic`
37+
[#5752](https://github.com/rust-lang/rust-clippy/pull/5752)
38+
39+
### Enhancements
40+
41+
* Improve [`needless_collect`] by catching `collect` calls followed by `iter` or `into_iter` calls
42+
[#5837](https://github.com/rust-lang/rust-clippy/pull/5837)
43+
* [`panic`], [`todo`], [`unimplemented`] and [`unreachable`] now detect calls with formatting
44+
[#5811](https://github.com/rust-lang/rust-clippy/pull/5811)
45+
* Detect more cases of [`suboptimal_flops`] and [`imprecise_flops`]
46+
[#5443](https://github.com/rust-lang/rust-clippy/pull/5443)
47+
* Handle asymmetrical implementations of `PartialEq` in [`cmp_owned`]
48+
[#5701](https://github.com/rust-lang/rust-clippy/pull/5701)
49+
* Make it possible to allow [`unsafe_derive_deserialize`]
50+
[#5870](https://github.com/rust-lang/rust-clippy/pull/5870)
51+
* Catch `ord.min(a).max(b)` where a < b in [`min_max`]
52+
[#5871](https://github.com/rust-lang/rust-clippy/pull/5871)
53+
* Make [`clone_on_copy`] suggestion machine applicable
54+
[#5745](https://github.com/rust-lang/rust-clippy/pull/5745)
55+
* Enable [`len_zero`] on ranges now that `is_empty` is stable on them
56+
[#5961](https://github.com/rust-lang/rust-clippy/pull/5961)
57+
58+
### False Positive Fixes
59+
60+
* Avoid triggering [`or_fun_call`] with const fns that take no arguments
61+
[#5889](https://github.com/rust-lang/rust-clippy/pull/5889)
62+
* Fix [`redundant_closure_call`] false positive for closures that have multiple calls
63+
[#5800](https://github.com/rust-lang/rust-clippy/pull/5800)
64+
* Don't lint cases involving `ManuallyDrop` in [`redundant_clone`]
65+
[#5824](https://github.com/rust-lang/rust-clippy/pull/5824)
66+
* Treat a single expression the same as a single statement in the 2nd arm of a match in [`single_match_else`]
67+
[#5771](https://github.com/rust-lang/rust-clippy/pull/5771)
68+
* Don't trigger [`unnested_or_patterns`] if the feature `or_patterns` is not enabled
69+
[#5758](https://github.com/rust-lang/rust-clippy/pull/5758)
70+
* Avoid linting if key borrows in [`unnecessary_sort_by`]
71+
[#5756](https://github.com/rust-lang/rust-clippy/pull/5756)
72+
* Consider `Try` impl for `Poll` when generating suggestions in [`try_err`]
73+
[#5857](https://github.com/rust-lang/rust-clippy/pull/5857)
74+
* Take input lifetimes into account in `manual_async_fn`
75+
[#5859](https://github.com/rust-lang/rust-clippy/pull/5859)
76+
* Fix multiple false positives in [`type_repetition_in_bounds`] and add a configuration option
77+
[#5761](https://github.com/rust-lang/rust-clippy/pull/5761)
78+
* Limit the [`suspicious_arithmetic_impl`] lint to one binary operation
79+
[#5820](https://github.com/rust-lang/rust-clippy/pull/5820)
80+
81+
### Suggestion Fixes/Improvements
82+
83+
* Improve readability of [`shadow_unrelated`] suggestion by truncating the RHS snippet
84+
[#5788](https://github.com/rust-lang/rust-clippy/pull/5788)
85+
* Suggest `filter_map` instead of `flat_map` when mapping to `Option` in [`map_flatten`]
86+
[#5846](https://github.com/rust-lang/rust-clippy/pull/5846)
87+
* Ensure suggestion is shown correctly for long method call chains in [`iter_nth_zero`]
88+
[#5793](https://github.com/rust-lang/rust-clippy/pull/5793)
89+
* Drop borrow operator in suggestions of [`redundant_pattern_matching`]
90+
[#5815](https://github.com/rust-lang/rust-clippy/pull/5815)
91+
* Add suggestion for [`iter_skip_next`]
92+
[#5843](https://github.com/rust-lang/rust-clippy/pull/5843)
93+
* Improve [`collapsible_if`] fix suggestion
94+
[#5732](https://github.com/rust-lang/rust-clippy/pull/5732)
95+
96+
### ICE Fixes
97+
98+
* Fix ICE caused by [`needless_collect`]
99+
[#5877](https://github.com/rust-lang/rust-clippy/pull/5877)
100+
* Fix ICE caused by [`unnested_or_patterns`]
101+
[#5784](https://github.com/rust-lang/rust-clippy/pull/5784)
102+
103+
### Documentation Improvements
104+
105+
* Fix grammar of [`await_holding_lock`] documentation
106+
[#5748](https://github.com/rust-lang/rust-clippy/pull/5748)
107+
108+
### Others
109+
110+
* Make lints adhere to the rustc dev guide
111+
[#5888](https://github.com/rust-lang/rust-clippy/pull/5888)
10112

11113
## Rust 1.46
12114

13-
Current beta, release 2020-08-27
115+
Current stable, released 2020-08-27
14116

15117
[7ea7cd1...c2c07fa](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...c2c07fa)
16118

@@ -72,7 +174,7 @@ Current beta, release 2020-08-27
72174

73175
## Rust 1.45
74176

75-
Current stable, released 2020-07-16
177+
Released 2020-07-16
76178

77179
[891e1a8...7ea7cd1](https://github.com/rust-lang/rust-clippy/compare/891e1a8...7ea7cd1)
78180

@@ -1410,6 +1512,7 @@ Released 2018-09-13
14101512
[`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants
14111513
[`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern
14121514
[`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops
1515+
[`async_yields_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#async_yields_async
14131516
[`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock
14141517
[`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask
14151518
[`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#bind_instead_of_map
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use crate::utils::{implements_trait, snippet, span_lint_and_then};
2+
use rustc_errors::Applicability;
3+
use rustc_hir::{AsyncGeneratorKind, Body, BodyId, ExprKind, GeneratorKind, QPath};
4+
use rustc_lint::{LateContext, LateLintPass};
5+
use rustc_session::{declare_lint_pass, declare_tool_lint};
6+
7+
declare_clippy_lint! {
8+
/// **What it does:** Checks for async blocks that yield values of types
9+
/// that can themselves be awaited.
10+
///
11+
/// **Why is this bad?** An await is likely missing.
12+
///
13+
/// **Known problems:** None.
14+
///
15+
/// **Example:**
16+
///
17+
/// ```rust
18+
/// async fn foo() {}
19+
///
20+
/// fn bar() {
21+
/// let x = async {
22+
/// foo()
23+
/// };
24+
/// }
25+
/// ```
26+
/// Use instead:
27+
/// ```rust
28+
/// async fn foo() {}
29+
///
30+
/// fn bar() {
31+
/// let x = async {
32+
/// foo().await
33+
/// };
34+
/// }
35+
/// ```
36+
pub ASYNC_YIELDS_ASYNC,
37+
correctness,
38+
"async blocks that return a type that can be awaited"
39+
}
40+
41+
declare_lint_pass!(AsyncYieldsAsync => [ASYNC_YIELDS_ASYNC]);
42+
43+
impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync {
44+
fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
45+
use AsyncGeneratorKind::{Block, Closure};
46+
// For functions, with explicitly defined types, don't warn.
47+
// XXXkhuey maybe we should?
48+
if let Some(GeneratorKind::Async(Block | Closure)) = body.generator_kind {
49+
if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() {
50+
let body_id = BodyId {
51+
hir_id: body.value.hir_id,
52+
};
53+
let def_id = cx.tcx.hir().body_owner_def_id(body_id);
54+
let typeck_results = cx.tcx.typeck(def_id);
55+
let expr_ty = typeck_results.expr_ty(&body.value);
56+
57+
if implements_trait(cx, expr_ty, future_trait_def_id, &[]) {
58+
let return_expr_span = match &body.value.kind {
59+
// XXXkhuey there has to be a better way.
60+
ExprKind::Block(block, _) => block.expr.map(|e| e.span),
61+
ExprKind::Path(QPath::Resolved(_, path)) => Some(path.span),
62+
_ => None,
63+
};
64+
if let Some(return_expr_span) = return_expr_span {
65+
span_lint_and_then(
66+
cx,
67+
ASYNC_YIELDS_ASYNC,
68+
return_expr_span,
69+
"an async construct yields a type which is itself awaitable",
70+
|db| {
71+
db.span_label(body.value.span, "outer async construct");
72+
db.span_label(return_expr_span, "awaitable value not awaited");
73+
db.span_suggestion(
74+
return_expr_span,
75+
"consider awaiting this value",
76+
format!("{}.await", snippet(cx, return_expr_span, "..")),
77+
Applicability::MaybeIncorrect,
78+
);
79+
},
80+
);
81+
}
82+
}
83+
}
84+
}
85+
}
86+
}

clippy_lints/src/attrs.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ declare_clippy_lint! {
7171
/// **What it does:** Checks for `extern crate` and `use` items annotated with
7272
/// lint attributes.
7373
///
74-
/// This lint permits `#[allow(unused_imports)]`, `#[allow(deprecated)]` and
75-
/// `#[allow(unreachable_pub)]` on `use` items and `#[allow(unused_imports)]` on
74+
/// This lint permits `#[allow(unused_imports)]`, `#[allow(deprecated)]`,
75+
/// `#[allow(unreachable_pub)]`, `#[allow(clippy::wildcard_imports)]` and
76+
/// `#[allow(clippy::enum_glob_use)]` on `use` items and `#[allow(unused_imports)]` on
7677
/// `extern crate` items with a `#[macro_use]` attribute.
7778
///
7879
/// **Why is this bad?** Lint attributes have no effect on crate imports. Most
@@ -318,7 +319,8 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
318319
if let Some(ident) = attr.ident() {
319320
match &*ident.as_str() {
320321
"allow" | "warn" | "deny" | "forbid" => {
321-
// permit `unused_imports`, `deprecated` and `unreachable_pub` for `use` items
322+
// permit `unused_imports`, `deprecated`, `unreachable_pub`,
323+
// `clippy::wildcard_imports`, and `clippy::enum_glob_use` for `use` items
322324
// and `unused_imports` for `extern crate` items with `macro_use`
323325
for lint in lint_list {
324326
match item.kind {
@@ -327,6 +329,9 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
327329
|| is_word(lint, sym!(deprecated))
328330
|| is_word(lint, sym!(unreachable_pub))
329331
|| is_word(lint, sym!(unused))
332+
|| extract_clippy_lint(lint)
333+
.map_or(false, |s| s == "wildcard_imports")
334+
|| extract_clippy_lint(lint).map_or(false, |s| s == "enum_glob_use")
330335
{
331336
return;
332337
}
@@ -387,24 +392,25 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
387392
}
388393
}
389394

390-
fn check_clippy_lint_names(cx: &LateContext<'_>, ident: &str, items: &[NestedMetaItem]) {
391-
fn extract_name(lint: &NestedMetaItem) -> Option<SymbolStr> {
392-
if_chain! {
393-
if let Some(meta_item) = lint.meta_item();
394-
if meta_item.path.segments.len() > 1;
395-
if let tool_name = meta_item.path.segments[0].ident;
396-
if tool_name.as_str() == "clippy";
397-
let lint_name = meta_item.path.segments.last().unwrap().ident.name;
398-
then {
399-
return Some(lint_name.as_str());
400-
}
395+
/// Returns the lint name if it is clippy lint.
396+
fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<SymbolStr> {
397+
if_chain! {
398+
if let Some(meta_item) = lint.meta_item();
399+
if meta_item.path.segments.len() > 1;
400+
if let tool_name = meta_item.path.segments[0].ident;
401+
if tool_name.as_str() == "clippy";
402+
let lint_name = meta_item.path.segments.last().unwrap().ident.name;
403+
then {
404+
return Some(lint_name.as_str());
401405
}
402-
None
403406
}
407+
None
408+
}
404409

410+
fn check_clippy_lint_names(cx: &LateContext<'_>, ident: &str, items: &[NestedMetaItem]) {
405411
let lint_store = cx.lints();
406412
for lint in items {
407-
if let Some(lint_name) = extract_name(lint) {
413+
if let Some(lint_name) = extract_clippy_lint(lint) {
408414
if let CheckLintNameResult::Tool(Err((None, _))) =
409415
lint_store.check_lint_name(&lint_name, Some(sym!(clippy)))
410416
{

clippy_lints/src/default_trait_access.rs

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -38,37 +38,23 @@ impl<'tcx> LateLintPass<'tcx> for DefaultTraitAccess {
3838
if let ExprKind::Path(ref qpath) = path.kind;
3939
if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
4040
if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
41+
// Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type.
42+
if let QPath::Resolved(None, _path) = qpath;
4143
then {
42-
match qpath {
43-
QPath::Resolved(..) => {
44-
if_chain! {
45-
// Detect and ignore <Foo as Default>::default() because these calls do
46-
// explicitly name the type.
47-
if let ExprKind::Call(ref method, ref _args) = expr.kind;
48-
if let ExprKind::Path(ref p) = method.kind;
49-
if let QPath::Resolved(Some(_ty), _path) = p;
50-
then {
51-
return;
52-
}
53-
}
54-
55-
// TODO: Work out a way to put "whatever the imported way of referencing
56-
// this type in this file" rather than a fully-qualified type.
57-
let expr_ty = cx.typeck_results().expr_ty(expr);
58-
if let ty::Adt(..) = expr_ty.kind() {
59-
let replacement = format!("{}::default()", expr_ty);
60-
span_lint_and_sugg(
61-
cx,
62-
DEFAULT_TRAIT_ACCESS,
63-
expr.span,
64-
&format!("calling `{}` is more clear than this expression", replacement),
65-
"try",
66-
replacement,
67-
Applicability::Unspecified, // First resolve the TODO above
68-
);
69-
}
70-
},
71-
QPath::TypeRelative(..) | QPath::LangItem(..) => {},
44+
let expr_ty = cx.typeck_results().expr_ty(expr);
45+
if let ty::Adt(def, ..) = expr_ty.kind {
46+
// TODO: Work out a way to put "whatever the imported way of referencing
47+
// this type in this file" rather than a fully-qualified type.
48+
let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did));
49+
span_lint_and_sugg(
50+
cx,
51+
DEFAULT_TRAIT_ACCESS,
52+
expr.span,
53+
&format!("calling `{}` is more clear than this expression", replacement),
54+
"try",
55+
replacement,
56+
Applicability::Unspecified, // First resolve the TODO above
57+
);
7258
}
7359
}
7460
}

clippy_lints/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ mod arithmetic;
154154
mod as_conversions;
155155
mod assertions_on_constants;
156156
mod assign_ops;
157+
mod async_yields_async;
157158
mod atomic_ordering;
158159
mod attrs;
159160
mod await_holding_lock;
@@ -483,6 +484,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
483484
&assertions_on_constants::ASSERTIONS_ON_CONSTANTS,
484485
&assign_ops::ASSIGN_OP_PATTERN,
485486
&assign_ops::MISREFACTORED_ASSIGN_OP,
487+
&async_yields_async::ASYNC_YIELDS_ASYNC,
486488
&atomic_ordering::INVALID_ATOMIC_ORDERING,
487489
&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS,
488490
&attrs::DEPRECATED_CFG_ATTR,
@@ -1099,6 +1101,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10991101
store.register_late_pass(|| box unwrap_in_result::UnwrapInResult);
11001102
store.register_late_pass(|| box self_assignment::SelfAssignment);
11011103
store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs);
1104+
store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync);
11021105

11031106
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
11041107
LintId::of(&arithmetic::FLOAT_ARITHMETIC),
@@ -1232,6 +1235,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
12321235
LintId::of(&assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
12331236
LintId::of(&assign_ops::ASSIGN_OP_PATTERN),
12341237
LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP),
1238+
LintId::of(&async_yields_async::ASYNC_YIELDS_ASYNC),
12351239
LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING),
12361240
LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
12371241
LintId::of(&attrs::DEPRECATED_CFG_ATTR),
@@ -1675,6 +1679,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
16751679

16761680
store.register_group(true, "clippy::correctness", Some("clippy_correctness"), vec![
16771681
LintId::of(&approx_const::APPROX_CONSTANT),
1682+
LintId::of(&async_yields_async::ASYNC_YIELDS_ASYNC),
16781683
LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING),
16791684
LintId::of(&attrs::DEPRECATED_SEMVER),
16801685
LintId::of(&attrs::MISMATCHED_TARGET_OS),

0 commit comments

Comments
 (0)