Skip to content

Commit 9d15aaf

Browse files
committed
submodules: update clippy from b7a431e to a416c5e
Changes: ```` rustup rust-lang/rust#52994 Fix test Line length fix Remove references to sized for end users Remove DUMMY_SP Add suggestion for replacement Update lint definitions Lint for Vec<Box<T: Sized>> - Closes rust-lang#3530 Fix doc_markdown mixed case false positive question_mark: Suggest Some(opt?) for if-else redundant_field_names: Do not trigger on path with type params question_mark: Lint only early returns question_mark: Fix applicability Remove obsolete comment new_without_default, partialeq_ne_impl: Use span_lint_node Update .stderr after rebase cargo fmt and remove stabilized feature Make suggestion Applicability::MachineApplicable Address review feedback Extract method Check array lengths to prevent OOB access Add suggestion for explicit_write lint Fix write_with_newline escaping false positive ````
1 parent 7a19419 commit 9d15aaf

29 files changed

+396
-85
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,7 @@ All notable changes to this project will be documented in this file.
899899
[`useless_let_if_seq`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_let_if_seq
900900
[`useless_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_transmute
901901
[`useless_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec
902+
[`vec_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_box
902903
[`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask
903904
[`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition
904905
[`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

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

10-
[There are 290 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
10+
[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
1111

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

clippy_lints/src/collapsible_if.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) {
116116
fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool {
117117
// We trim all opening braces and whitespaces and then check if the next string is a comment.
118118
let trimmed_block_text = snippet_block(cx, expr.span, "..")
119-
.trim_left_matches(|c: char| c.is_whitespace() || c == '{')
119+
.trim_start_matches(|c: char| c.is_whitespace() || c == '{')
120120
.to_owned();
121121
trimmed_block_text.starts_with("//") || trimmed_block_text.starts_with("/*")
122122
}

clippy_lints/src/doc.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<(
116116
for line in doc.lines() {
117117
let offset = line.as_ptr() as usize - comment.as_ptr() as usize;
118118
debug_assert_eq!(offset as u32 as usize, offset);
119-
contains_initial_stars |= line.trim_left().starts_with('*');
119+
contains_initial_stars |= line.trim_start().starts_with('*');
120120
// +1 for the newline
121121
sizes.push((line.len() + 1, span.with_lo(span.lo() + BytePos(offset as u32))));
122122
}
@@ -281,6 +281,10 @@ fn check_word(cx: &EarlyContext<'_>, word: &str, span: Span) {
281281
s != "_" && !s.contains("\\_") && s.contains('_')
282282
}
283283

284+
fn has_hyphen(s: &str) -> bool {
285+
s != "-" && s.contains('-')
286+
}
287+
284288
if let Ok(url) = Url::parse(word) {
285289
// try to get around the fact that `foo::bar` parses as a valid URL
286290
if !url.cannot_be_a_base() {
@@ -295,6 +299,11 @@ fn check_word(cx: &EarlyContext<'_>, word: &str, span: Span) {
295299
}
296300
}
297301

302+
// We assume that mixed-case words are not meant to be put inside bacticks. (Issue #2343)
303+
if has_underscore(word) && has_hyphen(word) {
304+
return;
305+
}
306+
298307
if has_underscore(word) || word.contains("::") || is_camel_case(word) {
299308
span_lint(
300309
cx,

clippy_lints/src/explicit_write.rs

Lines changed: 79 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
use crate::rustc::hir::*;
1111
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
1212
use crate::rustc::{declare_tool_lint, lint_array};
13-
use crate::utils::opt_def_id;
14-
use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint};
13+
use crate::rustc_errors::Applicability;
14+
use crate::syntax::ast::LitKind;
15+
use crate::utils::{is_expn_of, match_def_path, opt_def_id, resolve_node, span_lint, span_lint_and_sugg};
1516
use if_chain::if_chain;
1617

1718
/// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be
@@ -81,32 +82,85 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
8182
} else {
8283
""
8384
};
84-
if let Some(macro_name) = calling_macro {
85-
span_lint(
86-
cx,
87-
EXPLICIT_WRITE,
88-
expr.span,
89-
&format!(
90-
"use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead",
91-
macro_name,
92-
dest_name,
93-
prefix,
94-
macro_name.replace("write", "print")
95-
)
96-
);
85+
86+
// We need to remove the last trailing newline from the string because the
87+
// underlying `fmt::write` function doesn't know whether `println!` or `print!` was
88+
// used.
89+
if let Some(mut write_output) = write_output_string(write_args) {
90+
if write_output.ends_with('\n') {
91+
write_output.pop();
92+
}
93+
94+
if let Some(macro_name) = calling_macro {
95+
span_lint_and_sugg(
96+
cx,
97+
EXPLICIT_WRITE,
98+
expr.span,
99+
&format!(
100+
"use of `{}!({}(), ...).unwrap()`",
101+
macro_name,
102+
dest_name
103+
),
104+
"try this",
105+
format!("{}{}!(\"{}\")", prefix, macro_name.replace("write", "print"), write_output.escape_default()),
106+
Applicability::MachineApplicable
107+
);
108+
} else {
109+
span_lint_and_sugg(
110+
cx,
111+
EXPLICIT_WRITE,
112+
expr.span,
113+
&format!("use of `{}().write_fmt(...).unwrap()`", dest_name),
114+
"try this",
115+
format!("{}print!(\"{}\")", prefix, write_output.escape_default()),
116+
Applicability::MachineApplicable
117+
);
118+
}
97119
} else {
98-
span_lint(
99-
cx,
100-
EXPLICIT_WRITE,
101-
expr.span,
102-
&format!(
103-
"use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead",
104-
dest_name,
105-
prefix,
106-
)
107-
);
120+
// We don't have a proper suggestion
121+
if let Some(macro_name) = calling_macro {
122+
span_lint(
123+
cx,
124+
EXPLICIT_WRITE,
125+
expr.span,
126+
&format!(
127+
"use of `{}!({}(), ...).unwrap()`. Consider using `{}{}!` instead",
128+
macro_name,
129+
dest_name,
130+
prefix,
131+
macro_name.replace("write", "print")
132+
)
133+
);
134+
} else {
135+
span_lint(
136+
cx,
137+
EXPLICIT_WRITE,
138+
expr.span,
139+
&format!("use of `{}().write_fmt(...).unwrap()`. Consider using `{}print!` instead", dest_name, prefix),
140+
);
141+
}
108142
}
143+
109144
}
110145
}
111146
}
112147
}
148+
149+
// Extract the output string from the given `write_args`.
150+
fn write_output_string(write_args: &HirVec<Expr>) -> Option<String> {
151+
if_chain! {
152+
// Obtain the string that should be printed
153+
if write_args.len() > 1;
154+
if let ExprKind::Call(_, ref output_args) = write_args[1].node;
155+
if output_args.len() > 0;
156+
if let ExprKind::AddrOf(_, ref output_string_expr) = output_args[0].node;
157+
if let ExprKind::Array(ref string_exprs) = output_string_expr.node;
158+
if string_exprs.len() > 0;
159+
if let ExprKind::Lit(ref lit) = string_exprs[0].node;
160+
if let LitKind::Str(ref write_output, _) = lit.node;
161+
then {
162+
return Some(write_output.to_string())
163+
}
164+
}
165+
None
166+
}

clippy_lints/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#![feature(slice_patterns)]
1515
#![feature(stmt_expr_attributes)]
1616
#![feature(range_contains)]
17+
#![feature(str_escape)]
1718
#![allow(clippy::missing_docs_in_private_items)]
1819
#![recursion_limit = "256"]
1920
#![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)]
@@ -765,6 +766,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
765766
types::UNIT_ARG,
766767
types::UNIT_CMP,
767768
types::UNNECESSARY_CAST,
769+
types::VEC_BOX,
768770
unicode::ZERO_WIDTH_SPACE,
769771
unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
770772
unused_io_amount::UNUSED_IO_AMOUNT,
@@ -930,6 +932,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
930932
types::TYPE_COMPLEXITY,
931933
types::UNIT_ARG,
932934
types::UNNECESSARY_CAST,
935+
types::VEC_BOX,
933936
unused_label::UNUSED_LABEL,
934937
zero_div_zero::ZERO_DIVIDED_BY_ZERO,
935938
]);

clippy_lints/src/methods/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2350,8 +2350,8 @@ const PATTERN_METHODS: [(&str, usize); 17] = [
23502350
("rmatches", 1),
23512351
("match_indices", 1),
23522352
("rmatch_indices", 1),
2353-
("trim_left_matches", 1),
2354-
("trim_right_matches", 1),
2353+
("trim_start_matches", 1),
2354+
("trim_end_matches", 1),
23552355
];
23562356

23572357
#[derive(Clone, Copy, PartialEq, Debug)]

clippy_lints/src/misc_early.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,13 +446,13 @@ impl MiscEarly {
446446
db.span_suggestion_with_applicability(
447447
lit.span,
448448
"if you mean to use a decimal constant, remove the `0` to remove confusion",
449-
src.trim_left_matches(|c| c == '_' || c == '0').to_string(),
449+
src.trim_start_matches(|c| c == '_' || c == '0').to_string(),
450450
Applicability::MaybeIncorrect,
451451
);
452452
db.span_suggestion_with_applicability(
453453
lit.span,
454454
"if you mean to use an octal constant, use `0o`",
455-
format!("0o{}", src.trim_left_matches(|c| c == '_' || c == '0')),
455+
format!("0o{}", src.trim_start_matches(|c| c == '_' || c == '0')),
456456
Applicability::MaybeIncorrect,
457457
);
458458
});

clippy_lints/src/new_without_default.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::rustc_errors::Applicability;
1717
use crate::syntax::source_map::Span;
1818
use crate::utils::paths;
1919
use crate::utils::sugg::DiagnosticBuilderExt;
20-
use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_and_then};
20+
use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_node_and_then};
2121
use if_chain::if_chain;
2222

2323
/// **What it does:** Checks for types with a `fn new() -> Self` method and no
@@ -165,9 +165,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
165165
}
166166

167167
if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
168-
span_lint_and_then(
168+
span_lint_node_and_then(
169169
cx,
170170
NEW_WITHOUT_DEFAULT_DERIVE,
171+
id,
171172
impl_item.span,
172173
&format!(
173174
"you should consider deriving a `Default` implementation for `{}`",
@@ -183,9 +184,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
183184
);
184185
});
185186
} else {
186-
span_lint_and_then(
187+
span_lint_node_and_then(
187188
cx,
188189
NEW_WITHOUT_DEFAULT,
190+
id,
189191
impl_item.span,
190192
&format!(
191193
"you should consider adding a `Default` implementation for `{}`",

clippy_lints/src/partialeq_ne_impl.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use crate::rustc::hir::*;
1111
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
1212
use crate::rustc::{declare_tool_lint, lint_array};
13-
use crate::utils::{is_automatically_derived, span_lint};
13+
use crate::utils::{is_automatically_derived, span_lint_node};
1414
use if_chain::if_chain;
1515

1616
/// **What it does:** Checks for manual re-implementations of `PartialEq::ne`.
@@ -56,10 +56,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
5656
then {
5757
for impl_item in impl_items {
5858
if impl_item.ident.name == "ne" {
59-
span_lint(cx,
60-
PARTIALEQ_NE_IMPL,
61-
impl_item.span,
62-
"re-implementing `PartialEq::ne` is unnecessary")
59+
span_lint_node(
60+
cx,
61+
PARTIALEQ_NE_IMPL,
62+
impl_item.id.node_id,
63+
impl_item.span,
64+
"re-implementing `PartialEq::ne` is unnecessary",
65+
);
6366
}
6467
}
6568
}

clippy_lints/src/question_mark.rs

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use if_chain::if_chain;
1717

1818
use crate::rustc_errors::Applicability;
1919
use crate::utils::paths::*;
20-
use crate::utils::{match_def_path, match_type, span_lint_and_then};
20+
use crate::utils::{match_def_path, match_type, span_lint_and_then, SpanlessEq};
2121

2222
/// **What it does:** Checks for expressions that could be replaced by the question mark operator
2323
///
@@ -64,14 +64,40 @@ impl Pass {
6464
/// If it matches, it will suggest to use the question mark operator instead
6565
fn check_is_none_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr) {
6666
if_chain! {
67-
if let ExprKind::If(ref if_expr, ref body, _) = expr.node;
68-
if let ExprKind::MethodCall(ref segment, _, ref args) = if_expr.node;
67+
if let ExprKind::If(if_expr, body, else_) = &expr.node;
68+
if let ExprKind::MethodCall(segment, _, args) = &if_expr.node;
6969
if segment.ident.name == "is_none";
7070
if Self::expression_returns_none(cx, body);
7171
if let Some(subject) = args.get(0);
7272
if Self::is_option(cx, subject);
7373

7474
then {
75+
if let Some(else_) = else_ {
76+
if_chain! {
77+
if let ExprKind::Block(block, None) = &else_.node;
78+
if block.stmts.len() == 0;
79+
if let Some(block_expr) = &block.expr;
80+
if SpanlessEq::new(cx).ignore_fn().eq_expr(subject, block_expr);
81+
then {
82+
span_lint_and_then(
83+
cx,
84+
QUESTION_MARK,
85+
expr.span,
86+
"this block may be rewritten with the `?` operator",
87+
|db| {
88+
db.span_suggestion_with_applicability(
89+
expr.span,
90+
"replace_it_with",
91+
format!("Some({}?)", Sugg::hir(cx, subject, "..")),
92+
Applicability::MaybeIncorrect, // snippet
93+
);
94+
}
95+
)
96+
}
97+
}
98+
return;
99+
}
100+
75101
span_lint_and_then(
76102
cx,
77103
QUESTION_MARK,
@@ -84,7 +110,7 @@ impl Pass {
84110
expr.span,
85111
"replace_it_with",
86112
format!("{}?;", receiver_str),
87-
Applicability::MachineApplicable, // snippet
113+
Applicability::MaybeIncorrect, // snippet
88114
);
89115
}
90116
)
@@ -133,9 +159,13 @@ impl Pass {
133159
}
134160
}
135161

136-
// Check if the block has an implicit return expression
137-
if let Some(ref ret_expr) = block.expr {
138-
return Some(ret_expr.clone());
162+
// Check for `return` without a semicolon.
163+
if_chain! {
164+
if block.stmts.len() == 0;
165+
if let Some(ExprKind::Ret(Some(ret_expr))) = block.expr.as_ref().map(|e| &e.node);
166+
then {
167+
return Some(ret_expr.clone());
168+
}
139169
}
140170

141171
None

clippy_lints/src/redundant_field_names.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ impl EarlyLintPass for RedundantFieldNames {
5757
continue;
5858
}
5959
if let ExprKind::Path(None, path) = &field.expr.node {
60-
if path.segments.len() == 1 && path.segments[0].ident == field.ident {
60+
if path.segments.len() == 1
61+
&& path.segments[0].ident == field.ident
62+
&& path.segments[0].args.is_none()
63+
{
6164
span_lint_and_sugg(
6265
cx,
6366
REDUNDANT_FIELD_NAMES,

0 commit comments

Comments
 (0)