mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-15 09:27:25 +00:00
Merge remote-tracking branch 'upstream/master' into luckily_literals_love_lints
This commit is contained in:
commit
500857c944
23 changed files with 162 additions and 74 deletions
|
@ -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: |
|
||||
|
|
|
@ -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)*
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
6
clippy_workspace_tests/Cargo.toml
Normal file
6
clippy_workspace_tests/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "clippy_workspace_tests"
|
||||
version = "0.1.0"
|
||||
|
||||
[workspace]
|
||||
members = ["subcrate"]
|
2
clippy_workspace_tests/src/main.rs
Normal file
2
clippy_workspace_tests/src/main.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
fn main() {
|
||||
}
|
3
clippy_workspace_tests/subcrate/Cargo.toml
Normal file
3
clippy_workspace_tests/subcrate/Cargo.toml
Normal file
|
@ -0,0 +1,3 @@
|
|||
[package]
|
||||
name = "subcrate"
|
||||
version = "0.1.0"
|
0
clippy_workspace_tests/subcrate/src/lib.rs
Normal file
0
clippy_workspace_tests/subcrate/src/lib.rs
Normal file
71
src/main.rs
71
src/main.rs
|
@ -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(¤t_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 = ¤t_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");
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// FIXME: rustc doesn't generate expansion info for `cfg!` anymore
|
||||
#![allow(logic_bug)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate duct;
|
||||
|
||||
|
|
Loading…
Reference in a new issue