Skip to content

Commit 378fc6e

Browse files
committed
Update clippy
1 parent eec4421 commit 378fc6e

File tree

88 files changed

+1517
-487
lines changed

Some content is hidden

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

88 files changed

+1517
-487
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,12 +1050,14 @@ Released 2018-09-13
10501050
[`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum
10511051
[`mem_forget`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_forget
10521052
[`mem_replace_option_with_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_none
1053+
[`mem_replace_with_uninit`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_uninit
10531054
[`min_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_max
10541055
[`misaligned_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#misaligned_transmute
10551056
[`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op
10561057
[`missing_const_for_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn
10571058
[`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items
10581059
[`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items
1060+
[`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc
10591061
[`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes
10601062
[`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals
10611063
[`module_inception`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_inception

README.md

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

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

9-
[There are 313 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
9+
[There are 315 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
1010

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

clippy_lints/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ semver = "0.9.0"
2727
serde = { version = "1.0", features = ["derive"] }
2828
toml = "0.5.3"
2929
unicode-normalization = "0.1"
30-
pulldown-cmark = "0.5.3"
30+
pulldown-cmark = "0.6.0"
3131
url = { version = "2.1.0", features = ["serde"] } # cargo requires serde feat in its url dep
3232
# see https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864
3333
if_chain = "1.0.0"

clippy_lints/src/assign_ops.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,13 @@ fn lint_misrefactored_assign_op(
216216
long
217217
),
218218
format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
219-
Applicability::MachineApplicable,
219+
Applicability::MaybeIncorrect,
220220
);
221221
db.span_suggestion(
222222
expr.span,
223223
"or",
224224
long,
225-
Applicability::MachineApplicable, // snippet
225+
Applicability::MaybeIncorrect, // snippet
226226
);
227227
}
228228
},

clippy_lints/src/block_in_if_condition.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::utils::*;
22
use matches::matches;
33
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
44
use rustc::hir::*;
5-
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
5+
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
66
use rustc::{declare_lint_pass, declare_tool_lint};
77

88
declare_clippy_lint! {
@@ -72,6 +72,9 @@ const COMPLEX_BLOCK_MESSAGE: &str = "in an 'if' condition, avoid complex blocks
7272

7373
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition {
7474
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
75+
if in_external_macro(cx.sess(), expr.span) {
76+
return;
77+
}
7578
if let Some((check, then, _)) = higher::if_block(&expr) {
7679
if let ExprKind::Block(block, _) = &check.node {
7780
if block.rules == DefaultBlock {

clippy_lints/src/cargo_common_metadata.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! lint on missing cargo common metadata
22
3+
use std::path::PathBuf;
4+
35
use crate::utils::span_lint;
46
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
57
use rustc::{declare_lint_pass, declare_tool_lint};
@@ -47,6 +49,10 @@ fn is_empty_str(value: &Option<String>) -> bool {
4749
value.as_ref().map_or(true, String::is_empty)
4850
}
4951

52+
fn is_empty_path(value: &Option<PathBuf>) -> bool {
53+
value.as_ref().and_then(|x| x.to_str()).map_or(true, str::is_empty)
54+
}
55+
5056
fn is_empty_vec(value: &[String]) -> bool {
5157
// This works because empty iterators return true
5258
value.iter().all(std::string::String::is_empty)
@@ -72,8 +78,8 @@ impl EarlyLintPass for CargoCommonMetadata {
7278
missing_warning(cx, &package, "package.description");
7379
}
7480

75-
if is_empty_str(&package.license) {
76-
missing_warning(cx, &package, "package.license");
81+
if is_empty_str(&package.license) && is_empty_path(&package.license_file) {
82+
missing_warning(cx, &package, "either package.license or package.license_file");
7783
}
7884

7985
if is_empty_str(&package.repository) {

clippy_lints/src/doc.rs

Lines changed: 83 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,40 @@ declare_clippy_lint! {
3434
"presence of `_`, `::` or camel-case outside backticks in documentation"
3535
}
3636

37+
declare_clippy_lint! {
38+
/// **What it does:** Checks for the doc comments of publicly visible
39+
/// unsafe functions and warns if there is no `# Safety` section.
40+
///
41+
/// **Why is this bad?** Unsafe functions should document their safety
42+
/// preconditions, so that users can be sure they are using them safely.
43+
///
44+
/// **Known problems:** None.
45+
///
46+
/// **Examples**:
47+
/// ```rust
48+
///# type Universe = ();
49+
/// /// This function should really be documented
50+
/// pub unsafe fn start_apocalypse(u: &mut Universe) {
51+
/// unimplemented!();
52+
/// }
53+
/// ```
54+
///
55+
/// At least write a line about safety:
56+
///
57+
/// ```rust
58+
///# type Universe = ();
59+
/// /// # Safety
60+
/// ///
61+
/// /// This function should not be called before the horsemen are ready.
62+
/// pub unsafe fn start_apocalypse(u: &mut Universe) {
63+
/// unimplemented!();
64+
/// }
65+
/// ```
66+
pub MISSING_SAFETY_DOC,
67+
style,
68+
"`pub unsafe fn` without `# Safety` docs"
69+
}
70+
3771
#[allow(clippy::module_name_repetitions)]
3872
#[derive(Clone)]
3973
pub struct DocMarkdown {
@@ -46,15 +80,28 @@ impl DocMarkdown {
4680
}
4781
}
4882

49-
impl_lint_pass!(DocMarkdown => [DOC_MARKDOWN]);
83+
impl_lint_pass!(DocMarkdown => [DOC_MARKDOWN, MISSING_SAFETY_DOC]);
5084

5185
impl EarlyLintPass for DocMarkdown {
5286
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
5387
check_attrs(cx, &self.valid_idents, &krate.attrs);
5488
}
5589

5690
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
57-
check_attrs(cx, &self.valid_idents, &item.attrs);
91+
if check_attrs(cx, &self.valid_idents, &item.attrs) {
92+
return;
93+
}
94+
// no safety header
95+
if let ast::ItemKind::Fn(_, ref header, ..) = item.node {
96+
if item.vis.node.is_pub() && header.unsafety == ast::Unsafety::Unsafe {
97+
span_lint(
98+
cx,
99+
MISSING_SAFETY_DOC,
100+
item.span,
101+
"unsafe function's docs miss `# Safety` section",
102+
);
103+
}
104+
}
58105
}
59106
}
60107

@@ -115,7 +162,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<(
115162
panic!("not a doc-comment: {}", comment);
116163
}
117164

118-
pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &FxHashSet<String>, attrs: &'a [ast::Attribute]) {
165+
pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &FxHashSet<String>, attrs: &'a [ast::Attribute]) -> bool {
119166
let mut doc = String::new();
120167
let mut spans = vec![];
121168

@@ -129,7 +176,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &FxHashSet<String>,
129176
}
130177
} else if attr.check_name(sym!(doc)) {
131178
// ignore mix of sugared and non-sugared doc
132-
return;
179+
return true; // don't trigger the safety check
133180
}
134181
}
135182

@@ -140,57 +187,64 @@ pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &FxHashSet<String>,
140187
current += offset_copy;
141188
}
142189

143-
if !doc.is_empty() {
144-
let parser = pulldown_cmark::Parser::new(&doc).into_offset_iter();
145-
// Iterate over all `Events` and combine consecutive events into one
146-
let events = parser.coalesce(|previous, current| {
147-
use pulldown_cmark::Event::*;
148-
149-
let previous_range = previous.1;
150-
let current_range = current.1;
151-
152-
match (previous.0, current.0) {
153-
(Text(previous), Text(current)) => {
154-
let mut previous = previous.to_string();
155-
previous.push_str(&current);
156-
Ok((Text(previous.into()), previous_range))
157-
},
158-
(previous, current) => Err(((previous, previous_range), (current, current_range))),
159-
}
160-
});
161-
check_doc(cx, valid_idents, events, &spans);
190+
if doc.is_empty() {
191+
return false;
162192
}
193+
194+
let parser = pulldown_cmark::Parser::new(&doc).into_offset_iter();
195+
// Iterate over all `Events` and combine consecutive events into one
196+
let events = parser.coalesce(|previous, current| {
197+
use pulldown_cmark::Event::*;
198+
199+
let previous_range = previous.1;
200+
let current_range = current.1;
201+
202+
match (previous.0, current.0) {
203+
(Text(previous), Text(current)) => {
204+
let mut previous = previous.to_string();
205+
previous.push_str(&current);
206+
Ok((Text(previous.into()), previous_range))
207+
},
208+
(previous, current) => Err(((previous, previous_range), (current, current_range))),
209+
}
210+
});
211+
check_doc(cx, valid_idents, events, &spans)
163212
}
164213

165214
fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize>)>>(
166215
cx: &EarlyContext<'_>,
167216
valid_idents: &FxHashSet<String>,
168217
events: Events,
169218
spans: &[(usize, Span)],
170-
) {
219+
) -> bool {
220+
// true if a safety header was found
171221
use pulldown_cmark::Event::*;
172222
use pulldown_cmark::Tag::*;
173223

224+
let mut safety_header = false;
174225
let mut in_code = false;
175226
let mut in_link = None;
227+
let mut in_heading = false;
176228

177229
for (event, range) in events {
178230
match event {
179231
Start(CodeBlock(_)) => in_code = true,
180232
End(CodeBlock(_)) => in_code = false,
181233
Start(Link(_, url, _)) => in_link = Some(url),
182234
End(Link(..)) => in_link = None,
183-
Start(_tag) | End(_tag) => (), // We don't care about other tags
184-
Html(_html) | InlineHtml(_html) => (), // HTML is weird, just ignore it
185-
SoftBreak | HardBreak | TaskListMarker(_) | Code(_) => (),
235+
Start(Heading(_)) => in_heading = true,
236+
End(Heading(_)) => in_heading = false,
237+
Start(_tag) | End(_tag) => (), // We don't care about other tags
238+
Html(_html) => (), // HTML is weird, just ignore it
239+
SoftBreak | HardBreak | TaskListMarker(_) | Code(_) | Rule => (),
186240
FootnoteReference(text) | Text(text) => {
187241
if Some(&text) == in_link.as_ref() {
188242
// Probably a link of the form `<http://example.com>`
189243
// Which are represented as a link to "http://example.com" with
190244
// text "http://example.com" by pulldown-cmark
191245
continue;
192246
}
193-
247+
safety_header |= in_heading && text.trim() == "Safety";
194248
if !in_code {
195249
let index = match spans.binary_search_by(|c| c.0.cmp(&range.start)) {
196250
Ok(o) => o,
@@ -207,6 +261,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
207261
},
208262
}
209263
}
264+
safety_header
210265
}
211266

212267
fn check_text(cx: &EarlyContext<'_>, valid_idents: &FxHashSet<String>, text: &str, span: Span) {

clippy_lints/src/drop_forget_ref.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::utils::{is_copy, match_def_path, paths, span_note_and_lint};
1+
use crate::utils::{is_copy, match_def_path, paths, qpath_res, span_note_and_lint};
22
use if_chain::if_chain;
33
use rustc::hir::*;
44
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@@ -114,7 +114,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DropForgetRef {
114114
if let ExprKind::Call(ref path, ref args) = expr.node;
115115
if let ExprKind::Path(ref qpath) = path.node;
116116
if args.len() == 1;
117-
if let Some(def_id) = cx.tables.qpath_res(qpath, path.hir_id).opt_def_id();
117+
if let Some(def_id) = qpath_res(cx, qpath, path.hir_id).opt_def_id();
118118
then {
119119
let lint;
120120
let msg;

clippy_lints/src/explicit_write.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ fn write_output_string(write_args: &HirVec<Expr>) -> Option<String> {
140140
if output_args.len() > 0;
141141
if let ExprKind::AddrOf(_, ref output_string_expr) = output_args[0].node;
142142
if let ExprKind::Array(ref string_exprs) = output_string_expr.node;
143-
if string_exprs.len() > 0;
143+
// we only want to provide an automatic suggestion for simple (non-format) strings
144+
if string_exprs.len() == 1;
144145
if let ExprKind::Lit(ref lit) = string_exprs[0].node;
145146
if let LitKind::Str(ref write_output, _) = lit.node;
146147
then {

clippy_lints/src/functions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::convert::TryFrom;
22

3-
use crate::utils::{iter_input_pats, snippet, snippet_opt, span_lint, type_is_unsafe_function};
3+
use crate::utils::{iter_input_pats, qpath_res, snippet, snippet_opt, span_lint, type_is_unsafe_function};
44
use matches::matches;
55
use rustc::hir;
66
use rustc::hir::def::Res;
@@ -318,7 +318,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
318318
impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
319319
fn check_arg(&self, ptr: &hir::Expr) {
320320
if let hir::ExprKind::Path(ref qpath) = ptr.node {
321-
if let Res::Local(id) = self.cx.tables.qpath_res(qpath, ptr.hir_id) {
321+
if let Res::Local(id) = qpath_res(self.cx, qpath, ptr.hir_id) {
322322
if self.ptrs.contains(&id) {
323323
span_lint(
324324
self.cx,

0 commit comments

Comments
 (0)