Merge remote-tracking branch 'upstream/master' into luckily_literals_love_lints

This commit is contained in:
Jay Hardee 2017-07-31 19:17:42 -04:00
commit 500857c944
23 changed files with 162 additions and 74 deletions

View file

@ -34,6 +34,12 @@ script:
- cp clippy_tests/target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy
- PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy
- cd clippy_lints && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ..
- cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ..
- cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../..
- cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../..
- cd clippy_workspace_tests/subcrate/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../../..
- PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=clippy_workspace_tests/Cargo.toml -- -D clippy
- cd clippy_workspace_tests/subcrate && PATH=$PATH:~/rust/cargo/bin cargo clippy --manifest-path=../Cargo.toml -- -D clippy && cd ../..
- set +e
after_success: |

View file

@ -1,6 +1,14 @@
# Change Log
All notable changes to this project will be documented in this file.
## 0.0.147
* Update to *rustc 1.21.0-nightly (aac223f4f 2017-07-30)*
## 0.0.146
* Update to *rustc 1.21.0-nightly (52a330969 2017-07-27)*
* Fixes false positives in `inline_always`
* Fixes false negatives in `panic_params`
## 0.0.145
* Update to *rustc 1.20.0-nightly (afe145d22 2017-07-23)*

View file

@ -1,6 +1,6 @@
[package]
name = "clippy"
version = "0.0.145"
version = "0.0.147"
authors = [
"Manish Goregaokar <manishsmail@gmail.com>",
"Andre Bogus <bogusandre@gmail.com>",
@ -32,7 +32,7 @@ path = "src/main.rs"
[dependencies]
# begin automatic update
clippy_lints = { version = "0.0.145", path = "clippy_lints" }
clippy_lints = { version = "0.0.147", path = "clippy_lints" }
# end automatic update
cargo_metadata = "0.2"

View file

@ -1,7 +1,7 @@
[package]
name = "clippy_lints"
# begin automatic update
version = "0.0.145"
version = "0.0.147"
# end automatic update
authors = [
"Manish Goregaokar <manishsmail@gmail.com>",
@ -27,6 +27,7 @@ serde = "1.0"
serde_derive = "1.0"
toml = "0.4"
unicode-normalization = "0.1"
pulldown-cmark = "0.0.15"
[features]
debugging = []

View file

@ -1,6 +1,7 @@
use rustc::lint::*;
use rustc::middle::const_val::ConstVal;
use rustc::ty;
use rustc::ty::subst::Substs;
use rustc_const_eval::ConstContext;
use rustc_const_math::{ConstUsize, ConstIsize, ConstInt};
use rustc::hir;
@ -62,7 +63,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing {
if let ty::TyArray(_, size) = ty.sty {
let size = ConstInt::Usize(ConstUsize::new(size as u64, cx.sess().target.uint_type)
.expect("array size is invalid"));
let constcx = ConstContext::with_tables(cx.tcx, cx.tables);
let parent_item = cx.tcx.hir.get_parent(e.id);
let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
let constcx = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables);
// Index is a constant uint
let const_index = constcx.eval(index);

View file

@ -249,7 +249,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u128> {
ExprPath(ref qpath) => {
let def = cx.tables.qpath_def(qpath, lit.id);
if let Def::Const(def_id) = def {
lookup_const_by_id(cx.tcx, def_id, Substs::empty()).and_then(|(l, _ty)| {
lookup_const_by_id(cx.tcx, cx.param_env.and((def_id, Substs::empty()))).and_then(|(l, _ty)| {
let body = if let Some(id) = cx.tcx.hir.as_local_node_id(l) {
cx.tcx.mir_const_qualif(def_id);
cx.tcx.hir.body(cx.tcx.hir.body_owned_by(id))

View file

@ -225,6 +225,7 @@ pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> {
let mut cx = ConstEvalLateContext {
tcx: lcx.tcx,
tables: lcx.tables,
param_env: lcx.param_env,
needed_resolution: false,
substs: lcx.tcx.intern_substs(&[]),
};
@ -238,6 +239,7 @@ pub fn constant_simple(lcx: &LateContext, e: &Expr) -> Option<Constant> {
struct ConstEvalLateContext<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
param_env: ty::ParamEnv<'tcx>,
needed_resolution: bool,
substs: &'tcx Substs<'tcx>,
}
@ -292,12 +294,14 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
} else {
substs.subst(self.tcx, self.substs)
};
if let Some((def_id, substs)) = lookup_const_by_id(self.tcx, def_id, substs) {
let param_env = self.param_env.and((def_id, substs));
if let Some((def_id, substs)) = lookup_const_by_id(self.tcx, param_env) {
let mut cx = ConstEvalLateContext {
tcx: self.tcx,
tables: self.tcx.typeck_tables_of(def_id),
needed_resolution: false,
substs: substs,
param_env: param_env.param_env,
};
let body = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
self.tcx.mir_const_qualif(def_id);

View file

@ -4,6 +4,9 @@ use rustc::lint::*;
use rustc::middle::const_val::ConstVal;
use rustc_const_math::*;
use rustc::hir::*;
use rustc::ty;
use rustc::traits::Reveal;
use rustc::ty::subst::Substs;
use utils::span_lint;
/// **What it does:** Checks for C-like enumerations that are
@ -43,9 +46,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant {
for var in &def.variants {
let variant = &var.node;
if let Some(body_id) = variant.disr_expr {
use rustc_const_eval::*;
let constcx = ConstContext::with_tables(cx.tcx, cx.tcx.body_tables(body_id));
let bad = match constcx.eval(&cx.tcx.hir.body(body_id).value) {
let expr = &cx.tcx.hir.body(body_id).value;
let did = cx.tcx.hir.body_owner_def_id(body_id);
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
let substs = Substs::identity_for_item(cx.tcx.global_tcx(), did);
let bad = match cx.tcx.at(expr.span).const_eval(param_env.and((did, substs))) {
Ok(ConstVal::Integral(Usize(Us64(i)))) => i as u32 as u64 != i,
Ok(ConstVal::Integral(Isize(Is64(i)))) => i as i32 as i64 != i,
_ => false,

View file

@ -8,7 +8,7 @@ use rustc::lint::*;
use rustc::middle::const_val::ConstVal;
use rustc::middle::region::CodeExtent;
use rustc::ty::{self, Ty};
use rustc::ty::subst::Subst;
use rustc::ty::subst::{Subst, Substs};
use rustc_const_eval::ConstContext;
use std::collections::{HashMap, HashSet};
use syntax::ast;
@ -685,7 +685,10 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) {
// if this for loop is iterating over a two-sided range...
if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(arg) {
// ...and both sides are compile-time constant integers...
let constcx = ConstContext::with_tables(cx.tcx, cx.tables);
let parent_item = cx.tcx.hir.get_parent(arg.id);
let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
let constcx = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables);
if let Ok(start_idx) = constcx.eval(start) {
if let Ok(end_idx) = constcx.eval(end) {
// ...and the start index is greater than the end index,

View file

@ -2,11 +2,13 @@ use rustc::hir::*;
use rustc::lint::*;
use rustc::middle::const_val::ConstVal;
use rustc::ty::{self, Ty};
use rustc::ty::subst::Substs;
use rustc_const_eval::ConstContext;
use rustc_const_math::ConstInt;
use std::cmp::Ordering;
use std::collections::Bound;
use syntax::ast::LitKind;
use syntax::ast::NodeId;
use syntax::codemap::Span;
use utils::paths;
use utils::{match_type, snippet, span_note_and_lint, span_lint_and_then, span_lint_and_sugg, in_external_macro,
@ -307,7 +309,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) {
if arms.len() >= 2 && cx.tables.expr_ty(ex).is_integral() {
let ranges = all_ranges(cx, arms);
let ranges = all_ranges(cx, arms, ex.id);
let type_ranges = type_ranges(&ranges);
if !type_ranges.is_empty() {
if let Some((start, end)) = overlapping(&type_ranges) {
@ -390,8 +392,11 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match
}
/// Get all arms that are unbounded `PatRange`s.
fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &[Arm]) -> Vec<SpannedRange<ConstVal<'tcx>>> {
let constcx = ConstContext::with_tables(cx.tcx, cx.tables);
fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &[Arm], id: NodeId) -> Vec<SpannedRange<ConstVal<'tcx>>> {
let parent_item = cx.tcx.hir.get_parent(id);
let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
let constcx = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables);
arms.iter()
.flat_map(|arm| {
if let Arm { ref pats, guard: None, .. } = *arm {

View file

@ -3,6 +3,7 @@ use rustc::lint::*;
use rustc::middle::const_val::ConstVal;
use rustc::ty::{self, Ty};
use rustc::hir::def::Def;
use rustc::ty::subst::Substs;
use rustc_const_eval::ConstContext;
use std::borrow::Cow;
use std::fmt;
@ -1226,7 +1227,10 @@ fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other:
/// lint for length-1 `str`s for methods in `PATTERN_METHODS`
fn lint_single_char_pattern(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) {
if let Ok(ConstVal::Str(r)) = ConstContext::with_tables(cx.tcx, cx.tables).eval(arg) {
let parent_item = cx.tcx.hir.get_parent(arg.id);
let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
if let Ok(ConstVal::Str(r)) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg) {
if r.len() == 1 {
let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r));
span_lint_and_then(cx,

View file

@ -4,6 +4,7 @@ use rustc::hir::intravisit::FnKind;
use rustc::lint::*;
use rustc::middle::const_val::ConstVal;
use rustc::ty;
use rustc::ty::subst::Substs;
use rustc_const_eval::ConstContext;
use rustc_const_math::ConstFloat;
use syntax::codemap::{Span, ExpnFormat};
@ -389,7 +390,10 @@ fn check_nan(cx: &LateContext, path: &Path, expr: &Expr) {
}
fn is_allowed(cx: &LateContext, expr: &Expr) -> bool {
let res = ConstContext::with_tables(cx.tcx, cx.tables).eval(expr);
let parent_item = cx.tcx.hir.get_parent(expr.id);
let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
let res = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr);
if let Ok(ConstVal::Float(val)) = res {
use std::cmp::Ordering;
match val {

View file

@ -3,6 +3,7 @@ use rustc::hir::*;
use rustc::lint::*;
use rustc::middle::const_val::ConstVal;
use rustc_const_eval::ConstContext;
use rustc::ty::subst::Substs;
use std::collections::HashSet;
use std::error::Error;
use syntax::ast::{LitKind, NodeId};
@ -150,7 +151,10 @@ fn str_span(base: Span, s: &str, c: usize) -> Span {
}
fn const_str(cx: &LateContext, e: &Expr) -> Option<InternedString> {
match ConstContext::with_tables(cx.tcx, cx.tables).eval(e) {
let parent_item = cx.tcx.hir.get_parent(e.id);
let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(e) {
Ok(ConstVal::Str(r)) => Some(r),
_ => None,
}

View file

@ -4,6 +4,7 @@ use rustc::hir::*;
use rustc::hir::intravisit::{FnKind, Visitor, walk_ty, NestedVisitorMap};
use rustc::lint::*;
use rustc::ty::{self, Ty};
use rustc::ty::subst::Substs;
use std::cmp::Ordering;
use syntax::ast::{IntTy, UintTy, FloatTy};
use syntax::attr::IntType;
@ -977,7 +978,10 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
_ => return None,
};
let cv = match ConstContext::with_tables(cx.tcx, cx.tables).eval(expr) {
let parent_item = cx.tcx.hir.get_parent(expr.id);
let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
let cv = match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr) {
Ok(val) => val,
Err(_) => return None,
};
@ -1174,7 +1178,10 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> {
use rustc::middle::const_val::ConstVal::*;
use rustc_const_eval::ConstContext;
match ConstContext::with_tables(cx.tcx, cx.tables).eval(expr) {
let parent_item = cx.tcx.hir.get_parent(expr.id);
let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr) {
Ok(val) => {
if let Integral(const_int) = val {
match const_int.int_type() {

View file

@ -1,6 +1,7 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::ty::{self, Ty};
use rustc::ty::subst::Substs;
use rustc_const_eval::ConstContext;
use syntax::codemap::Span;
use utils::{higher, is_copy, snippet, span_lint_and_sugg};
@ -59,7 +60,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) {
let snippet = match *vec_args {
higher::VecArgs::Repeat(elem, len) => {
if ConstContext::with_tables(cx.tcx, cx.tables).eval(len).is_ok() {
let parent_item = cx.tcx.hir.get_parent(len.id);
let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
if ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(len).is_ok() {
format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into()
} else {
return;

View file

@ -6,24 +6,6 @@ error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usuall
|
= note: `-D inline-always` implied by `-D warnings`
error: you have declared `#[inline(always)]` on `false_positive_expr`. This is usually a bad idea
--> attrs.rs:11:1
|
11 | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
error: you have declared `#[inline(always)]` on `false_positive_stmt`. This is usually a bad idea
--> attrs.rs:16:1
|
16 | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
error: you have declared `#[inline(always)]` on `empty_and_false_positive_stmt`. This is usually a bad idea
--> attrs.rs:21:1
|
21 | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
error: the since field must contain a semver-compliant version
--> attrs.rs:27:14
|
@ -38,7 +20,7 @@ error: the since field must contain a semver-compliant version
30 | #[deprecated(since = "1")]
| ^^^^^^^^^^^
error: aborting due to 6 previous errors
error: aborting due to 3 previous errors
To learn more, run the command again with --verbose.

View file

@ -0,0 +1,32 @@
error: you probably are missing some parameter in your format string
--> panic.rs:8:16
|
8 | panic!("{}");
| ^^^^
|
= note: `-D panic-params` implied by `-D warnings`
error: you probably are missing some parameter in your format string
--> panic.rs:10:16
|
10 | panic!("{:?}");
| ^^^^^^
error: you probably are missing some parameter in your format string
--> panic.rs:12:23
|
12 | assert!(true, "here be missing values: {}");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: you probably are missing some parameter in your format string
--> panic.rs:22:5
|
22 | assert!("foo bar".contains(&format!("foo {}", "bar")));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate
error: aborting due to 4 previous errors
To learn more, run the command again with --verbose.

View file

@ -0,0 +1,6 @@
[package]
name = "clippy_workspace_tests"
version = "0.1.0"
[workspace]
members = ["subcrate"]

View file

@ -0,0 +1,2 @@
fn main() {
}

View file

@ -0,0 +1,3 @@
[package]
name = "subcrate"
version = "0.1.0"

View file

@ -15,6 +15,7 @@ extern crate syntax;
use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation};
use rustc::session::{config, Session, CompileIncomplete};
use rustc::session::config::{Input, ErrorOutputType};
use std::collections::HashMap;
use std::path::PathBuf;
use std::process::{self, Command};
use syntax::ast;
@ -158,12 +159,6 @@ fn show_version() {
println!("{}", env!("CARGO_PKG_VERSION"));
}
// FIXME: false positive for needless_lifetimes
#[allow(needless_lifetimes)]
fn has_prefix<'a, T: PartialEq, I: Iterator<Item = &'a T>>(v: &'a [T], itr: I) -> bool {
v.iter().zip(itr).all(|(a, b)| a == b)
}
pub fn main() {
use std::env;
@ -196,46 +191,52 @@ pub fn main() {
process::exit(101);
};
let manifest_path = manifest_path_arg.map(|arg| PathBuf::from(Path::new(&arg["--manifest-path=".len()..])));
let manifest_path = manifest_path_arg.map(|arg| Path::new(&arg["--manifest-path=".len()..])
.canonicalize().expect("manifest path could not be canonicalized"));
let package_index = {
let mut iterator = metadata.packages.iter();
if let Some(ref manifest_path) = manifest_path {
iterator.position(|package| {
let package_manifest_path = Path::new(&package.manifest_path);
if let Some(manifest_path) = manifest_path {
metadata.packages.iter().position(|package| {
let package_manifest_path = Path::new(&package.manifest_path)
.canonicalize().expect("package manifest path could not be canonicalized");
package_manifest_path == manifest_path
})
} else {
let current_dir = std::env::current_dir()
.expect("could not read current directory")
.canonicalize()
.expect("current directory cannot be canonicalized");
let current_dir_components = current_dir.components().collect::<Vec<_>>();
// This gets the most-recent parent (the one that takes the fewest `cd ..`s to
// reach).
iterator
let package_manifest_paths: HashMap<_, _> =
metadata.packages.iter()
.enumerate()
.filter_map(|(i, package)| {
let package_manifest_path = Path::new(&package.manifest_path);
let canonical_path = package_manifest_path
.map(|(i, package)| {
let package_manifest_path = Path::new(&package.manifest_path)
.parent()
.expect("could not find parent directory of package manifest")
.canonicalize()
.expect("package directory cannot be canonicalized");
// TODO: We can do this in `O(1)` by combining the `len` and the
// iteration.
let components = canonical_path.components().collect::<Vec<_>>();
if has_prefix(&current_dir_components, components.iter()) {
Some((i, components.len()))
} else {
None
}
(package_manifest_path, i)
})
.max_by_key(|&(_, length)| length)
.map(|(i, _)| i)
.collect();
let current_dir = std::env::current_dir()
.expect("could not read current directory")
.canonicalize()
.expect("current directory cannot be canonicalized");
let mut current_path: &Path = &current_dir;
// This gets the most-recent parent (the one that takes the fewest `cd ..`s to
// reach).
loop {
if let Some(&package_index) = package_manifest_paths.get(current_path) {
break Some(package_index);
}
else {
// We'll never reach the filesystem root, because to get to this point in the code
// the call to `cargo_metadata::metadata` must have succeeded. So it's okay to
// unwrap the current path's parent.
current_path = current_path
.parent()
.unwrap_or_else(|| panic!("could not find parent of path {}", current_path.display()));
}
}
}
}
.expect("could not find matching package");

View file

@ -1,3 +1,6 @@
// FIXME: rustc doesn't generate expansion info for `cfg!` anymore
#![allow(logic_bug)]
#[macro_use]
extern crate duct;