Skip to content

Commit ad5f64f

Browse files
committed
Merge branch 'master' of github.com:rust-lang/rust-clippy into option_if_let_else
2 parents eaf25c2 + 557f684 commit ad5f64f

32 files changed

+407
-119
lines changed

.github/deploy.sh

+12-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,17 @@ if git diff --exit-code --quiet; then
3333
exit 0
3434
fi
3535

36-
git add .
37-
git commit -m "Automatic deploy to GitHub Pages: ${SHA}"
36+
if [[ -n $TAG_NAME ]]; then
37+
# Add the new dir
38+
git add $TAG_NAME
39+
# Update the symlink
40+
git add stable
41+
# Update versions file
42+
git add versions.json
43+
git commit -m "Add documentation for ${TAG_NAME} release: ${SHA}"
44+
else
45+
git add .
46+
git commit -m "Automatic deploy to GitHub Pages: ${SHA}"
47+
fi
3848

3949
git push "$SSH_REPO" "$TARGET_BRANCH"

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,7 @@ Released 2018-09-13
12091209
[`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
12101210
[`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
12111211
[`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
1212+
[`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports
12121213
[`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
12131214
[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
12141215
[`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic

CONTRIBUTING.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ High level approach:
2828

2929
1. Find something to fix/improve
3030
2. Change code (likely some file in `clippy_lints/src/`)
31-
3. Run `cargo test` in the root directory and wiggle code until it passes
32-
4. Open a PR (also can be done between 2. and 3. if you run into problems)
31+
3. Follow the instructions in the [docs for writing lints](doc/adding_lints.md) such as running the `setup-toolchain.sh` script
32+
4. Run `cargo test` in the root directory and wiggle code until it passes
33+
5. Open a PR (also can be done after 2. if you run into problems)
3334

3435
### Finding something to fix/improve
3536

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
77

8-
[There are 360 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
8+
[There are 361 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
99

1010
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
1111

clippy_lints/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ edition = "2018"
1919
[dependencies]
2020
cargo_metadata = "0.9.0"
2121
if_chain = "1.0.0"
22-
itertools = "0.8"
22+
itertools = "0.9"
2323
lazy_static = "1.0.2"
2424
matches = "0.1.7"
2525
pulldown-cmark = { version = "0.7", default-features = false }

clippy_lints/README.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
This crate contains Clippy lints. For the main crate, check
2-
[*crates.io*](https://crates.io/crates/clippy) or
3-
[GitHub](https://github.com/rust-lang/rust-clippy).
1+
This crate contains Clippy lints. For the main crate, check [GitHub](https://github.com/rust-lang/rust-clippy).

clippy_lints/src/implicit_return.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::utils::{
2-
match_def_path,
2+
fn_has_unsatisfiable_preds, match_def_path,
33
paths::{BEGIN_PANIC, BEGIN_PANIC_FMT},
44
snippet_opt, span_lint_and_then,
55
};
@@ -133,6 +133,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitReturn {
133133
_: HirId,
134134
) {
135135
let def_id = cx.tcx.hir().body_owner_def_id(body.id());
136+
137+
// Building MIR for `fn`s with unsatisfiable preds results in ICE.
138+
if fn_has_unsatisfiable_preds(cx, def_id) {
139+
return;
140+
}
141+
136142
let mir = cx.tcx.optimized_mir(def_id);
137143

138144
// checking return type through MIR, HIR is not able to determine inferred closure return types

clippy_lints/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ pub mod let_underscore;
234234
pub mod lifetimes;
235235
pub mod literal_representation;
236236
pub mod loops;
237+
pub mod macro_use;
237238
pub mod main_recursion;
238239
pub mod map_clone;
239240
pub mod map_unit_fn;
@@ -600,6 +601,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
600601
&loops::WHILE_IMMUTABLE_CONDITION,
601602
&loops::WHILE_LET_LOOP,
602603
&loops::WHILE_LET_ON_ITERATOR,
604+
&macro_use::MACRO_USE_IMPORTS,
603605
&main_recursion::MAIN_RECURSION,
604606
&map_clone::MAP_CLONE,
605607
&map_unit_fn::OPTION_MAP_UNIT_FN,
@@ -1015,6 +1017,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10151017
store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap);
10161018
store.register_late_pass(|| box wildcard_imports::WildcardImports);
10171019
store.register_late_pass(|| box option_if_let_else::OptionIfLetElse);
1020+
store.register_early_pass(|| box macro_use::MacroUseImports);
10181021

10191022
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
10201023
LintId::of(&arithmetic::FLOAT_ARITHMETIC),
@@ -1082,6 +1085,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10821085
LintId::of(&literal_representation::LARGE_DIGIT_GROUPS),
10831086
LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP),
10841087
LintId::of(&loops::EXPLICIT_ITER_LOOP),
1088+
LintId::of(&macro_use::MACRO_USE_IMPORTS),
10851089
LintId::of(&matches::SINGLE_MATCH_ELSE),
10861090
LintId::of(&methods::FILTER_MAP),
10871091
LintId::of(&methods::FILTER_MAP_NEXT),

clippy_lints/src/macro_use.rs

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use crate::utils::{snippet, span_lint_and_sugg};
2+
use if_chain::if_chain;
3+
use rustc_ast::ast;
4+
use rustc_errors::Applicability;
5+
use rustc_lint::{EarlyContext, EarlyLintPass};
6+
use rustc_session::{declare_lint_pass, declare_tool_lint};
7+
use rustc_span::edition::Edition;
8+
9+
declare_clippy_lint! {
10+
/// **What it does:** Checks for `#[macro_use] use...`.
11+
///
12+
/// **Why is this bad?** Since the Rust 2018 edition you can import
13+
/// macro's directly, this is considered idiomatic.
14+
///
15+
/// **Known problems:** This lint does not generate an auto-applicable suggestion.
16+
///
17+
/// **Example:**
18+
/// ```rust
19+
/// #[macro_use]
20+
/// use lazy_static;
21+
/// ```
22+
pub MACRO_USE_IMPORTS,
23+
pedantic,
24+
"#[macro_use] is no longer needed"
25+
}
26+
27+
declare_lint_pass!(MacroUseImports => [MACRO_USE_IMPORTS]);
28+
29+
impl EarlyLintPass for MacroUseImports {
30+
fn check_item(&mut self, ecx: &EarlyContext<'_>, item: &ast::Item) {
31+
if_chain! {
32+
if ecx.sess.opts.edition == Edition::Edition2018;
33+
if let ast::ItemKind::Use(use_tree) = &item.kind;
34+
if let Some(mac_attr) = item
35+
.attrs
36+
.iter()
37+
.find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string()));
38+
then {
39+
let msg = "`macro_use` attributes are no longer needed in the Rust 2018 edition";
40+
let help = format!("use {}::<macro name>", snippet(ecx, use_tree.span, "_"));
41+
span_lint_and_sugg(
42+
ecx,
43+
MACRO_USE_IMPORTS,
44+
mac_attr.span,
45+
msg,
46+
"remove the attribute and import the macro directly, try",
47+
help,
48+
Applicability::HasPlaceholders,
49+
);
50+
}
51+
}
52+
}
53+
}

clippy_lints/src/map_unit_fn.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -186,19 +186,19 @@ fn unit_closure<'a, 'tcx>(
186186
/// `x.field` => `x_field`
187187
/// `y` => `_y`
188188
///
189-
/// Anything else will return `_`.
189+
/// Anything else will return `a`.
190190
fn let_binding_name(cx: &LateContext<'_, '_>, var_arg: &hir::Expr<'_>) -> String {
191191
match &var_arg.kind {
192192
hir::ExprKind::Field(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"),
193193
hir::ExprKind::Path(_) => format!("_{}", snippet(cx, var_arg.span, "")),
194-
_ => "_".to_string(),
194+
_ => "a".to_string(),
195195
}
196196
}
197197

198198
#[must_use]
199199
fn suggestion_msg(function_type: &str, map_type: &str) -> String {
200200
format!(
201-
"called `map(f)` on an `{0}` value where `f` is a unit {1}",
201+
"called `map(f)` on an `{0}` value where `f` is a {1} that returns the unit type",
202202
map_type, function_type
203203
)
204204
}

clippy_lints/src/matches.rs

+43-11
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use rustc_ast::ast::LitKind;
1414
use rustc_errors::Applicability;
1515
use rustc_hir::def::CtorKind;
1616
use rustc_hir::{
17-
print, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, Pat, PatKind,
18-
QPath, RangeEnd,
17+
print, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, Node, Pat,
18+
PatKind, QPath, RangeEnd,
1919
};
2020
use rustc_lint::{LateContext, LateLintPass, LintContext};
2121
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -882,7 +882,7 @@ fn check_wild_in_or_pats(cx: &LateContext<'_, '_>, arms: &[Arm<'_>]) {
882882
}
883883
}
884884

885-
fn check_match_single_binding(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
885+
fn check_match_single_binding<'a>(cx: &LateContext<'_, 'a>, ex: &Expr<'a>, arms: &[Arm<'_>], expr: &Expr<'_>) {
886886
if in_macro(expr.span) || arms.len() != 1 || is_refutable(cx, arms[0].pat) {
887887
return;
888888
}
@@ -914,19 +914,38 @@ fn check_match_single_binding(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[A
914914
let mut applicability = Applicability::MaybeIncorrect;
915915
match arms[0].pat.kind {
916916
PatKind::Binding(..) | PatKind::Tuple(_, _) | PatKind::Struct(..) => {
917+
// If this match is in a local (`let`) stmt
918+
let (target_span, sugg) = if let Some(parent_let_node) = opt_parent_let(cx, ex) {
919+
(
920+
parent_let_node.span,
921+
format!(
922+
"let {} = {};\n{}let {} = {};",
923+
snippet_with_applicability(cx, bind_names, "..", &mut applicability),
924+
snippet_with_applicability(cx, matched_vars, "..", &mut applicability),
925+
" ".repeat(indent_of(cx, expr.span).unwrap_or(0)),
926+
snippet_with_applicability(cx, parent_let_node.pat.span, "..", &mut applicability),
927+
snippet_body
928+
),
929+
)
930+
} else {
931+
(
932+
expr.span,
933+
format!(
934+
"let {} = {};\n{}{}",
935+
snippet_with_applicability(cx, bind_names, "..", &mut applicability),
936+
snippet_with_applicability(cx, matched_vars, "..", &mut applicability),
937+
" ".repeat(indent_of(cx, expr.span).unwrap_or(0)),
938+
snippet_body
939+
),
940+
)
941+
};
917942
span_lint_and_sugg(
918943
cx,
919944
MATCH_SINGLE_BINDING,
920-
expr.span,
945+
target_span,
921946
"this match could be written as a `let` statement",
922947
"consider using `let` statement",
923-
format!(
924-
"let {} = {};\n{}{}",
925-
snippet_with_applicability(cx, bind_names, "..", &mut applicability),
926-
snippet_with_applicability(cx, matched_vars, "..", &mut applicability),
927-
" ".repeat(indent_of(cx, expr.span).unwrap_or(0)),
928-
snippet_body,
929-
),
948+
sugg,
930949
applicability,
931950
);
932951
},
@@ -945,6 +964,19 @@ fn check_match_single_binding(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[A
945964
}
946965
}
947966

967+
/// Returns true if the `ex` match expression is in a local (`let`) statement
968+
fn opt_parent_let<'a>(cx: &LateContext<'_, 'a>, ex: &Expr<'a>) -> Option<&'a Local<'a>> {
969+
if_chain! {
970+
let map = &cx.tcx.hir();
971+
if let Some(Node::Expr(parent_arm_expr)) = map.find(map.get_parent_node(ex.hir_id));
972+
if let Some(Node::Local(parent_let_expr)) = map.find(map.get_parent_node(parent_arm_expr.hir_id));
973+
then {
974+
return Some(parent_let_expr);
975+
}
976+
}
977+
None
978+
}
979+
948980
/// Gets all arms that are unbounded `PatRange`s.
949981
fn all_ranges<'a, 'tcx>(
950982
cx: &LateContext<'a, 'tcx>,

clippy_lints/src/misc_early.rs

+23-16
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use crate::utils::{
55
use if_chain::if_chain;
66
use rustc::lint::in_external_macro;
77
use rustc_ast::ast::{
8-
Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind,
9-
StmtKind, UnOp,
8+
BindingMode, Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability,
9+
NodeId, Pat, PatKind, StmtKind, UnOp,
1010
};
1111
use rustc_ast::visit::{walk_expr, FnKind, Visitor};
1212
use rustc_data_structures::fx::FxHashMap;
@@ -318,18 +318,6 @@ impl EarlyLintPass for MiscEarlyLints {
318318
return;
319319
}
320320
if wilds > 0 {
321-
let mut normal = vec![];
322-
323-
for field in pfields {
324-
match field.pat.kind {
325-
PatKind::Wild => {},
326-
_ => {
327-
if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) {
328-
normal.push(n);
329-
}
330-
},
331-
}
332-
}
333321
for field in pfields {
334322
if let PatKind::Wild = field.pat.kind {
335323
wilds -= 1;
@@ -341,6 +329,19 @@ impl EarlyLintPass for MiscEarlyLints {
341329
"You matched a field with a wildcard pattern. Consider using `..` instead",
342330
);
343331
} else {
332+
let mut normal = vec![];
333+
334+
for field in pfields {
335+
match field.pat.kind {
336+
PatKind::Wild => {},
337+
_ => {
338+
if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) {
339+
normal.push(n);
340+
}
341+
},
342+
}
343+
}
344+
344345
span_lint_and_help(
345346
cx,
346347
UNNEEDED_FIELD_PATTERN,
@@ -355,7 +356,13 @@ impl EarlyLintPass for MiscEarlyLints {
355356
}
356357
}
357358

358-
if let PatKind::Ident(_, ident, Some(ref right)) = pat.kind {
359+
if let PatKind::Ident(left, ident, Some(ref right)) = pat.kind {
360+
let left_binding = match left {
361+
BindingMode::ByRef(Mutability::Mut) => "ref mut ",
362+
BindingMode::ByRef(Mutability::Not) => "ref ",
363+
_ => "",
364+
};
365+
359366
if let PatKind::Wild = right.kind {
360367
span_lint_and_sugg(
361368
cx,
@@ -366,7 +373,7 @@ impl EarlyLintPass for MiscEarlyLints {
366373
ident.name, ident.name,
367374
),
368375
"try",
369-
format!("{}", ident.name),
376+
format!("{}{}", left_binding, ident.name),
370377
Applicability::MachineApplicable,
371378
);
372379
}

clippy_lints/src/missing_const_for_fn.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::utils::{has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method};
1+
use crate::utils::{fn_has_unsatisfiable_preds, has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method};
22
use rustc::lint::in_external_macro;
33
use rustc_hir as hir;
44
use rustc_hir::intravisit::FnKind;
@@ -88,6 +88,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn {
8888
return;
8989
}
9090

91+
// Building MIR for `fn`s with unsatisfiable preds results in ICE.
92+
if fn_has_unsatisfiable_preds(cx, def_id) {
93+
return;
94+
}
95+
9196
// Perform some preliminary checks that rule out constness on the Clippy side. This way we
9297
// can skip the actual const check and return early.
9398
match kind {

clippy_lints/src/redundant_clone.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::utils::{
2-
has_drop, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_hir, span_lint_hir_and_then,
3-
walk_ptrs_ty_depth,
2+
fn_has_unsatisfiable_preds, has_drop, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_hir,
3+
span_lint_hir_and_then, walk_ptrs_ty_depth,
44
};
55
use if_chain::if_chain;
66
use matches::matches;
@@ -79,6 +79,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
7979
_: HirId,
8080
) {
8181
let def_id = cx.tcx.hir().body_owner_def_id(body.id());
82+
83+
// Building MIR for `fn`s with unsatisfiable preds results in ICE.
84+
if fn_has_unsatisfiable_preds(cx, def_id) {
85+
return;
86+
}
87+
8288
let mir = cx.tcx.optimized_mir(def_id);
8389
let mir_read_only = mir.unwrap_read_only();
8490

0 commit comments

Comments
 (0)