Skip to content

Commit fcdce8f

Browse files
committed
Merge branch 'master' into no_effect_with_drop
2 parents 9a0a8a0 + 12a7d14 commit fcdce8f

File tree

348 files changed

+2205
-1459
lines changed

Some content is hidden

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

348 files changed

+2205
-1459
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ script:
2828
- cargo test --features debugging
2929
- mkdir -p ~/rust/cargo/bin
3030
- cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy
31+
- cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver
3132
- PATH=$PATH:~/rust/cargo/bin cargo clippy --all -- -D clippy
3233
- cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ..
3334
- cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../..

CHANGELOG.md

+19
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
# Change Log
22
All notable changes to this project will be documented in this file.
33

4+
## 0.0.165
5+
* Rust upgrade to rustc 1.22.0-nightly (0e6f4cf51 2017-09-27)
6+
* New lint: [`mut_range_bound`]
7+
8+
## 0.0.164
9+
* Update to *rustc 1.22.0-nightly (6c476ce46 2017-09-25)*
10+
* New lint: [`int_plus_one`]
11+
12+
## 0.0.163
13+
* Update to *rustc 1.22.0-nightly (14039a42a 2017-09-22)*
14+
15+
## 0.0.162
16+
* Update to *rustc 1.22.0-nightly (0701b37d9 2017-09-18)*
17+
* New lint: [`chars_last_cmp`]
18+
* Improved suggestions for [`needless_borrow`], [`ptr_arg`],
19+
420
## 0.0.161
521
* Update to *rustc 1.22.0-nightly (539f2083d 2017-09-13)*
622

@@ -457,6 +473,7 @@ All notable changes to this project will be documented in this file.
457473
[`cast_precision_loss`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_precision_loss
458474
[`cast_sign_loss`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cast_sign_loss
459475
[`char_lit_as_u8`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#char_lit_as_u8
476+
[`chars_last_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#chars_last_cmp
460477
[`chars_next_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#chars_next_cmp
461478
[`clone_double_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#clone_double_ref
462479
[`clone_on_copy`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#clone_on_copy
@@ -510,6 +527,7 @@ All notable changes to this project will be documented in this file.
510527
[`ineffective_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ineffective_bit_mask
511528
[`infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#infinite_iter
512529
[`inline_always`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_always
530+
[`int_plus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#int_plus_one
513531
[`integer_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#integer_arithmetic
514532
[`invalid_regex`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_regex
515533
[`invalid_upcast_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons
@@ -547,6 +565,7 @@ All notable changes to this project will be documented in this file.
547565
[`modulo_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#modulo_one
548566
[`mut_from_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_from_ref
549567
[`mut_mut`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_mut
568+
[`mut_range_bound`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mut_range_bound
550569
[`mutex_atomic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mutex_atomic
551570
[`mutex_integer`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mutex_integer
552571
[`naive_bytecount`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#naive_bytecount

Cargo.lock

+72-34
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "clippy"
3-
version = "0.0.161"
3+
version = "0.0.165"
44
authors = [
55
"Manish Goregaokar <[email protected]>",
66
"Andre Bogus <[email protected]>",
@@ -14,6 +14,7 @@ readme = "README.md"
1414
license = "MPL-2.0"
1515
keywords = ["clippy", "lint", "plugin"]
1616
categories = ["development-tools", "development-tools::cargo-plugins"]
17+
build = "build.rs"
1718

1819
[badges]
1920
travis-ci = { repository = "rust-lang-nursery/rust-clippy" }
@@ -29,9 +30,14 @@ name = "cargo-clippy"
2930
test = false
3031
path = "src/main.rs"
3132

33+
[[bin]]
34+
name = "clippy-driver"
35+
test = false
36+
path = "src/driver.rs"
37+
3238
[dependencies]
3339
# begin automatic update
34-
clippy_lints = { version = "0.0.161", path = "clippy_lints" }
40+
clippy_lints = { version = "0.0.165", path = "clippy_lints" }
3541
# end automatic update
3642
cargo_metadata = "0.2"
3743

PUBLISH.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Steps to publish a new clippy version
77
- `git push`
88
- Wait for Travis's approval.
99
- Merge.
10-
- `cargo publish` in `./clippy_clints`.
10+
- `cargo publish` in `./clippy_lints`.
1111
- `cargo publish` in the root directory.
1212
- `git pull`.
1313
- `git tag -s v0.0.X -m "v0.0.X"`.

build.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use std::env;
2+
3+
fn main() {
4+
// Forward the profile to the main compilation
5+
println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap());
6+
// Don't rebuild even if nothing changed
7+
println!("cargo:rerun-if-changed=build.rs");
8+
}

clippy_lints/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "clippy_lints"
33
# begin automatic update
4-
version = "0.0.161"
4+
version = "0.0.165"
55
# end automatic update
66
authors = [
77
"Manish Goregaokar <[email protected]>",
@@ -28,6 +28,7 @@ serde_derive = "1.0"
2828
toml = "0.4"
2929
unicode-normalization = "0.1"
3030
pulldown-cmark = "0.0.15"
31+
url = "1.5.0"
3132

3233
[features]
3334
debugging = []

clippy_lints/src/bit_mask.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,17 @@ declare_lint! {
9090
}
9191

9292
#[derive(Copy, Clone)]
93-
pub struct BitMask;
93+
pub struct BitMask {
94+
verbose_bit_mask_threshold: u64,
95+
}
96+
97+
impl BitMask {
98+
pub fn new(verbose_bit_mask_threshold: u64) -> Self {
99+
Self {
100+
verbose_bit_mask_threshold: verbose_bit_mask_threshold,
101+
}
102+
}
103+
}
94104

95105
impl LintPass for BitMask {
96106
fn get_lints(&self) -> LintArray {
@@ -119,6 +129,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask {
119129
let Expr_::ExprLit(ref lit1) = right.node,
120130
let LitKind::Int(0, _) = lit1.node,
121131
n.leading_zeros() == n.count_zeros(),
132+
n > u128::from(self.verbose_bit_mask_threshold),
122133
], {
123134
span_lint_and_then(cx,
124135
VERBOSE_BIT_MASK,
@@ -307,7 +318,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u128> {
307318
cx.tcx.mir_const_qualif(def_id);
308319
cx.tcx.hir.body(cx.tcx.hir.body_owned_by(id))
309320
} else {
310-
cx.tcx.extern_const_body(def_id)
321+
cx.tcx.extern_const_body(def_id).body
311322
};
312323
fetch_int_literal(cx, &body.value)
313324
})

clippy_lints/src/consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
298298
self.tcx.mir_const_qualif(def_id);
299299
self.tcx.hir.body(self.tcx.hir.body_owned_by(id))
300300
} else {
301-
self.tcx.extern_const_body(def_id)
301+
self.tcx.extern_const_body(def_id).body
302302
};
303303
let ret = cx.expr(&body.value);
304304
if ret.is_some() {

clippy_lints/src/doc.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use syntax::ast;
55
use syntax::codemap::{BytePos, Span};
66
use syntax_pos::Pos;
77
use utils::span_lint;
8+
use url::Url;
89

910
/// **What it does:** Checks for the presence of `_`, `::` or camel-case words
1011
/// outside ticks in documentation.
@@ -195,16 +196,26 @@ fn check_doc<'a, Events: Iterator<Item = (usize, pulldown_cmark::Event<'a>)>>(
195196
use pulldown_cmark::Tag::*;
196197

197198
let mut in_code = false;
199+
let mut in_link = None;
198200

199201
for (offset, event) in docs {
200202
match event {
201203
Start(CodeBlock(_)) | Start(Code) => in_code = true,
202204
End(CodeBlock(_)) | End(Code) => in_code = false,
203-
Start(_tag) | End(_tag) => (), // We don't care about other tags
205+
Start(Link(link, _)) => in_link = Some(link),
206+
End(Link(_, _)) => in_link = None,
207+
Start(_tag) | End(_tag) => (), // We don't care about other tags
204208
Html(_html) | InlineHtml(_html) => (), // HTML is weird, just ignore it
205209
SoftBreak => (),
206210
HardBreak => (),
207211
FootnoteReference(text) | Text(text) => {
212+
if Some(&text) == in_link.as_ref() {
213+
// Probably a link of the form `<http://example.com>`
214+
// Which are represented as a link to "http://example.com" with
215+
// text "http://example.com" by pulldown-cmark
216+
continue;
217+
}
218+
208219
if !in_code {
209220
let index = match spans.binary_search_by(|c| c.0.cmp(&offset)) {
210221
Ok(o) => o,
@@ -270,6 +281,18 @@ fn check_word(cx: &EarlyContext, word: &str, span: Span) {
270281
s != "_" && !s.contains("\\_") && s.contains('_')
271282
}
272283

284+
if let Ok(url) = Url::parse(word) {
285+
// try to get around the fact that `foo::bar` parses as a valid URL
286+
if !url.cannot_be_a_base() {
287+
span_lint(cx,
288+
DOC_MARKDOWN,
289+
span,
290+
"you should put bare URLs between `<`/`>` or make a proper Markdown link");
291+
292+
return;
293+
}
294+
}
295+
273296
if has_underscore(word) || word.contains("::") || is_camel_case(word) {
274297
span_lint(
275298
cx,

clippy_lints/src/format.rs

+11-37
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
use rustc::hir::*;
2-
use rustc::hir::map::Node::NodeItem;
32
use rustc::lint::*;
43
use rustc::ty;
54
use syntax::ast::LitKind;
6-
use syntax::symbol::InternedString;
75
use utils::paths;
86
use utils::{is_expn_of, match_def_path, match_type, resolve_node, span_lint, walk_ptrs_ty, opt_def_id};
97

@@ -50,8 +48,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
5048
let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)),
5149
match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1),
5250
// ensure the format string is `"{..}"` with only one argument and no text
53-
check_static_str(cx, &args[0]),
51+
check_static_str(&args[0]),
5452
// ensure the format argument is `{}` ie. Display with no fancy option
53+
// and that the argument is a string
5554
check_arg_is_display(cx, &args[1])
5655
], {
5756
span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`");
@@ -69,44 +68,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
6968
}
7069
}
7170

72-
/// Returns the slice of format string parts in an `Arguments::new_v1` call.
73-
/// Public because it's shared with a lint in print.rs.
74-
pub fn get_argument_fmtstr_parts<'a, 'b>(cx: &LateContext<'a, 'b>, expr: &'a Expr) -> Option<Vec<InternedString>> {
71+
/// Checks if the expressions matches `&[""]`
72+
fn check_static_str(expr: &Expr) -> bool {
7573
if_let_chain! {[
76-
let ExprBlock(ref block) = expr.node,
77-
block.stmts.len() == 1,
78-
let StmtDecl(ref decl, _) = block.stmts[0].node,
79-
let DeclItem(ref decl) = decl.node,
80-
let Some(NodeItem(decl)) = cx.tcx.hir.find(decl.id),
81-
decl.name == "__STATIC_FMTSTR",
82-
let ItemStatic(_, _, ref expr) = decl.node,
83-
let ExprAddrOf(_, ref expr) = cx.tcx.hir.body(*expr).value.node, // &["…", "…", …]
84-
let ExprArray(ref exprs) = expr.node,
74+
let ExprAddrOf(_, ref expr) = expr.node, // &[""]
75+
let ExprArray(ref exprs) = expr.node, // [""]
76+
exprs.len() == 1,
77+
let ExprLit(ref lit) = exprs[0].node,
78+
let LitKind::Str(ref lit, _) = lit.node,
8579
], {
86-
let mut result = Vec::new();
87-
for expr in exprs {
88-
if let ExprLit(ref lit) = expr.node {
89-
if let LitKind::Str(ref lit, _) = lit.node {
90-
result.push(lit.as_str());
91-
}
92-
}
93-
}
94-
return Some(result);
80+
return lit.as_str().is_empty();
9581
}}
96-
None
97-
}
9882

99-
/// Checks if the expressions matches
100-
/// ```rust, ignore
101-
/// { static __STATIC_FMTSTR: &'static[&'static str] = &["a", "b", c];
102-
/// __STATIC_FMTSTR }
103-
/// ```
104-
fn check_static_str(cx: &LateContext, expr: &Expr) -> bool {
105-
if let Some(expr) = get_argument_fmtstr_parts(cx, expr) {
106-
expr.len() == 1 && expr[0].is_empty()
107-
} else {
108-
false
109-
}
83+
false
11084
}
11185

11286
/// Checks if the expressions matches
+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use rustc::lint::*;
2+
use rustc::hir::*;
3+
use syntax::ast::NodeId;
4+
use utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, span_lint_and_then};
5+
use utils::{opt_def_id, paths, resolve_node};
6+
7+
/// **What it does:** Checks for always-identical `Into`/`From` conversions.
8+
///
9+
/// **Why is this bad?** Redundant code.
10+
///
11+
/// **Known problems:** None.
12+
///
13+
/// **Example:**
14+
/// ```rust
15+
/// // format!() returns a `String`
16+
/// let s: String = format!("hello").into();
17+
/// ```
18+
declare_lint! {
19+
pub IDENTITY_CONVERSION,
20+
Warn,
21+
"using always-identical `Into`/`From` conversions"
22+
}
23+
24+
#[derive(Default)]
25+
pub struct IdentityConversion {
26+
try_desugar_arm: Vec<NodeId>,
27+
}
28+
29+
impl LintPass for IdentityConversion {
30+
fn get_lints(&self) -> LintArray {
31+
lint_array!(IDENTITY_CONVERSION)
32+
}
33+
}
34+
35+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion {
36+
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
37+
if in_macro(e.span) {
38+
return;
39+
}
40+
41+
if Some(&e.id) == self.try_desugar_arm.last() {
42+
return;
43+
}
44+
45+
match e.node {
46+
ExprMatch(_, ref arms, MatchSource::TryDesugar) => {
47+
let e = match arms[0].body.node {
48+
ExprRet(Some(ref e)) | ExprBreak(_, Some(ref e)) => e,
49+
_ => return,
50+
};
51+
if let ExprCall(_, ref args) = e.node {
52+
self.try_desugar_arm.push(args[0].id);
53+
} else {
54+
return;
55+
}
56+
},
57+
58+
ExprMethodCall(ref name, .., ref args) => {
59+
if match_trait_method(cx, e, &paths::INTO[..]) && &*name.name.as_str() == "into" {
60+
let a = cx.tables.expr_ty(e);
61+
let b = cx.tables.expr_ty(&args[0]);
62+
if same_tys(cx, a, b) {
63+
let sugg = snippet(cx, args[0].span, "<expr>").into_owned();
64+
span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| {
65+
db.span_suggestion(e.span, "consider removing `.into()`", sugg);
66+
});
67+
}
68+
}
69+
},
70+
71+
ExprCall(ref path, ref args) => if let ExprPath(ref qpath) = path.node {
72+
if let Some(def_id) = opt_def_id(resolve_node(cx, qpath, path.hir_id)) {
73+
if match_def_path(cx.tcx, def_id, &paths::FROM_FROM[..]) {
74+
let a = cx.tables.expr_ty(e);
75+
let b = cx.tables.expr_ty(&args[0]);
76+
if same_tys(cx, a, b) {
77+
let sugg = snippet(cx, args[0].span, "<expr>").into_owned();
78+
let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from"));
79+
span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| {
80+
db.span_suggestion(e.span, &sugg_msg, sugg);
81+
});
82+
}
83+
}
84+
}
85+
},
86+
87+
_ => {},
88+
}
89+
}
90+
91+
fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
92+
if Some(&e.id) == self.try_desugar_arm.last() {
93+
self.try_desugar_arm.pop();
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)