Merge pull request #1419 from Manishearth/rustup

Rust upgrade to rustc 1.16.0-nightly (468227129 2017-01-03)
This commit is contained in:
Manish Goregaokar 2017-01-04 16:00:28 -08:00 committed by GitHub
commit 3baa435b70
33 changed files with 264 additions and 172 deletions

View File

@ -1,6 +1,12 @@
# Change Log
All notable changes to this project will be documented in this file.
## 0.0.105 — 2016-12-15
* Update to *rustc 1.15.0-nightly (8f02c429a 2016-12-15)*
* New lints: [`deref_addrof`], [`double_parens`], [`pub_enum_variant_names`]
* Fix suggestion in [`new_without_default`]
* FP fix in [`absurd_extreme_comparisons`]
## 0.0.104 — 2016-12-15
* Update to *rustc 1.15.0-nightly (8f02c429a 2016-12-15)*

View File

@ -1,6 +1,6 @@
[package]
name = "clippy"
version = "0.0.104"
version = "0.0.105"
authors = [
"Manish Goregaokar <manishsmail@gmail.com>",
"Andre Bogus <bogusandre@gmail.com>",
@ -25,7 +25,7 @@ test = false
[dependencies]
# begin automatic update
clippy_lints = { version = "0.0.104", path = "clippy_lints" }
clippy_lints = { version = "0.0.105", path = "clippy_lints" }
# end automatic update
[dev-dependencies]

View File

@ -1,7 +1,7 @@
[package]
name = "clippy_lints"
# begin automatic update
version = "0.0.104"
version = "0.0.105"
# end automatic update
authors = [
"Manish Goregaokar <manishsmail@gmail.com>",

View File

@ -61,7 +61,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing {
// Array with known size can be checked statically
let ty = cx.tcx.tables().expr_ty(array);
if let ty::TyArray(_, size) = ty.sty {
let size = ConstInt::Infer(size as u64);
let size = ConstInt::Infer(size as u128);
// Index is a constant uint
let const_index = eval_const_expr_partial(cx.tcx, index, ExprTypeChecked, None);

View File

@ -157,7 +157,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
fn is_relevant_item(cx: &LateContext, item: &Item) -> bool {
if let ItemFn(_, _, _, _, _, eid) = item.node {
is_relevant_expr(cx, cx.tcx.map.expr(eid))
is_relevant_expr(cx, &cx.tcx.map.body(eid).value)
} else {
false
}
@ -165,15 +165,15 @@ fn is_relevant_item(cx: &LateContext, item: &Item) -> bool {
fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool {
match item.node {
ImplItemKind::Method(_, eid) => is_relevant_expr(cx, cx.tcx.map.expr(eid)),
ImplItemKind::Method(_, eid) => is_relevant_expr(cx, &cx.tcx.map.body(eid).value),
_ => false,
}
}
fn is_relevant_trait(cx: &LateContext, item: &TraitItem) -> bool {
match item.node {
MethodTraitItem(_, None) => true,
MethodTraitItem(_, Some(eid)) => is_relevant_expr(cx, cx.tcx.map.expr(eid)),
TraitItemKind::Method(_, TraitMethod::Required(_)) => true,
TraitItemKind::Method(_, TraitMethod::Provided(eid)) => is_relevant_expr(cx, &cx.tcx.map.body(eid).value),
_ => false,
}
}

View File

@ -106,7 +106,7 @@ fn invert_cmp(cmp: BinOp_) -> BinOp_ {
}
fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) {
fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u128, span: &Span) {
if let ExprBinary(ref op, ref left, ref right) = bit_op.node {
if op.node != BiBitAnd && op.node != BiBitOr {
return;
@ -117,7 +117,7 @@ fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64
}
}
fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, cmp_value: u64, span: &Span) {
fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u128, cmp_value: u128, span: &Span) {
match cmp_op {
BiEq | BiNe => {
match bit_op {
@ -212,7 +212,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value:
}
}
fn check_ineffective_lt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) {
fn check_ineffective_lt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str) {
if c.is_power_of_two() && m < c {
span_lint(cx,
INEFFECTIVE_BIT_MASK,
@ -224,7 +224,7 @@ fn check_ineffective_lt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str)
}
}
fn check_ineffective_gt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) {
fn check_ineffective_gt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str) {
if (c + 1).is_power_of_two() && m <= c {
span_lint(cx,
INEFFECTIVE_BIT_MASK,
@ -236,7 +236,7 @@ fn check_ineffective_gt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str)
}
}
fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> {
fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u128> {
match lit.node {
ExprLit(ref lit_ptr) => {
if let LitKind::Int(value, _) = lit_ptr.node {

View File

@ -57,9 +57,10 @@ struct ExVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx: 'a> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr) {
if let ExprClosure(_, _, eid, _) = expr.node {
let expr = self.cx.tcx.map.expr(eid);
if matches!(expr.node, ExprBlock(_)) {
self.found_block = Some(expr);
let body = self.cx.tcx.map.body(eid);
let ex = &body.value;
if matches!(ex.node, ExprBlock(_)) {
self.found_block = Some(ex);
return;
}
}

View File

@ -74,7 +74,7 @@ impl PartialEq for Constant {
(&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r,
(&Constant::Char(l), &Constant::Char(r)) => l == r,
(&Constant::Int(l), &Constant::Int(r)) => {
l.is_negative() == r.is_negative() && l.to_u64_unchecked() == r.to_u64_unchecked()
l.is_negative() == r.is_negative() && l.to_u128_unchecked() == r.to_u128_unchecked()
},
(&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => {
// we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have
@ -110,7 +110,7 @@ impl Hash for Constant {
c.hash(state);
},
Constant::Int(i) => {
i.to_u64_unchecked().hash(state);
i.to_u128_unchecked().hash(state);
i.is_negative().hash(state);
},
Constant::Float(ref f, _) => {
@ -185,6 +185,7 @@ pub fn lit_to_constant(lit: &LitKind) -> Constant {
LitKind::Int(value, LitIntType::Unsigned(UintTy::U16)) => Constant::Int(ConstInt::U16(value as u16)),
LitKind::Int(value, LitIntType::Unsigned(UintTy::U32)) => Constant::Int(ConstInt::U32(value as u32)),
LitKind::Int(value, LitIntType::Unsigned(UintTy::U64)) => Constant::Int(ConstInt::U64(value as u64)),
LitKind::Int(value, LitIntType::Unsigned(UintTy::U128)) => Constant::Int(ConstInt::U128(value as u128)),
LitKind::Int(value, LitIntType::Unsigned(UintTy::Us)) => {
Constant::Int(ConstInt::Usize(ConstUsize::Us32(value as u32)))
},
@ -192,6 +193,7 @@ pub fn lit_to_constant(lit: &LitKind) -> Constant {
LitKind::Int(value, LitIntType::Signed(IntTy::I16)) => Constant::Int(ConstInt::I16(value as i16)),
LitKind::Int(value, LitIntType::Signed(IntTy::I32)) => Constant::Int(ConstInt::I32(value as i32)),
LitKind::Int(value, LitIntType::Signed(IntTy::I64)) => Constant::Int(ConstInt::I64(value as i64)),
LitKind::Int(value, LitIntType::Signed(IntTy::I128)) => Constant::Int(ConstInt::I128(value as i128)),
LitKind::Int(value, LitIntType::Signed(IntTy::Is)) => {
Constant::Int(ConstInt::Isize(ConstIsize::Is32(value as i32)))
},
@ -258,8 +260,14 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
ExprLit(ref lit) => Some(lit_to_constant(&lit.node)),
ExprArray(ref vec) => self.multi(vec).map(Constant::Vec),
ExprTup(ref tup) => self.multi(tup).map(Constant::Tuple),
ExprRepeat(ref value, ref number) => {
self.binop_apply(value, number, |v, n| Some(Constant::Repeat(Box::new(v), n.as_u64() as usize)))
ExprRepeat(ref value, number_id) => {
if let Some(lcx) = self.lcx {
self.binop_apply(value,
&lcx.tcx.map.body(number_id).value,
|v, n| Some(Constant::Repeat(Box::new(v), n.as_u64() as usize)))
} else {
None
}
},
ExprUnary(op, ref operand) => {
self.expr(operand).and_then(|o| {

View File

@ -94,20 +94,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CyclomaticComplexity {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemFn(_, _, _, _, _, eid) = item.node {
if !attr::contains_name(&item.attrs, "test") {
self.check(cx, cx.tcx.map.expr(eid), item.span);
self.check(cx, &cx.tcx.map.body(eid).value, item.span);
}
}
}
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
if let ImplItemKind::Method(_, eid) = item.node {
self.check(cx, cx.tcx.map.expr(eid), item.span);
self.check(cx, &cx.tcx.map.body(eid).value, item.span);
}
}
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
if let MethodTraitItem(_, Some(eid)) = item.node {
self.check(cx, cx.tcx.map.expr(eid), item.span);
if let TraitItemKind::Method(_, TraitMethod::Provided(eid)) = item.node {
self.check(cx, &cx.tcx.map.body(eid).value, item.span);
}
}

View File

@ -42,9 +42,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant {
if let ItemEnum(ref def, _) = item.node {
for var in &def.variants {
let variant = &var.node;
if let Some(ref disr) = variant.disr_expr {
if let Some(body_id) = variant.disr_expr {
use rustc_const_eval::*;
let bad = match eval_const_expr_partial(cx.tcx, &**disr, EvalHint::ExprTypeChecked, None) {
let bad = match eval_const_expr_partial(cx.tcx,
&cx.tcx.map.body(body_id).value,
EvalHint::ExprTypeChecked,
None) {
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

@ -64,8 +64,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
&mut self,
cx: &LateContext<'a, 'tcx>,
_: visit::FnKind<'tcx>,
decl: &'tcx FnDecl,
body: &'tcx Expr,
_: &'tcx FnDecl,
body: &'tcx Body,
_: Span,
id: NodeId
) {
@ -82,7 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
let infcx = cx.tcx.borrowck_fake_infer_ctxt(param_env);
{
let mut vis = ExprUseVisitor::new(&mut v, &infcx);
vis.walk_fn(decl, body);
vis.consume_body(body);
}
for node in v.set {

View File

@ -1,7 +1,7 @@
use rustc::lint::*;
use rustc::ty;
use rustc::hir::*;
use utils::{snippet_opt, span_lint_and_then, is_adjusted};
use utils::{snippet_opt, span_lint_and_then, is_adjusted, iter_input_pats};
#[allow(missing_copy_implementations)]
pub struct EtaPass;
@ -49,7 +49,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass {
fn check_closure(cx: &LateContext, expr: &Expr) {
if let ExprClosure(_, ref decl, eid, _) = expr.node {
let ex = cx.tcx.map.expr(eid);
let body = cx.tcx.map.body(eid);
let ex = &body.value;
if let ExprCall(ref caller, ref args) = ex.node {
if args.len() != decl.inputs.len() {
// Not the same number of arguments, there
@ -71,7 +72,7 @@ fn check_closure(cx: &LateContext, expr: &Expr) {
},
_ => (),
}
for (a1, a2) in decl.inputs.iter().zip(args) {
for (a1, a2) in iter_input_pats(decl, body).zip(args) {
if let PatKind::Binding(_, _, ident, _) = a1.pat.node {
// XXXManishearth Should I be checking the binding mode here?
if let ExprPath(QPath::Resolved(None, ref p)) = a2.node {

View File

@ -81,7 +81,7 @@ pub fn get_argument_fmtstr_parts<'a, 'b>(cx: &LateContext<'a, 'b>, expr: &'a Exp
let Some(NodeItem(decl)) = cx.tcx.map.find(decl.id),
&*decl.name.as_str() == "__STATIC_FMTSTR",
let ItemStatic(_, _, ref expr) = decl.node,
let ExprAddrOf(_, ref expr) = expr.node, // &["…", "…", …]
let ExprAddrOf(_, ref expr) = cx.tcx.map.body(*expr).value.node, // &["…", "…", …]
let ExprArray(ref exprs) = expr.node,
], {
let mut result = Vec::new();

View File

@ -6,7 +6,7 @@ use std::collections::HashSet;
use syntax::ast;
use syntax::abi::Abi;
use syntax::codemap::Span;
use utils::{span_lint, type_is_unsafe_function};
use utils::{span_lint, type_is_unsafe_function, iter_input_pats};
/// **What it does:** Checks for functions with too many parameters.
///
@ -74,7 +74,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
cx: &LateContext<'a, 'tcx>,
kind: intravisit::FnKind<'tcx>,
decl: &'tcx hir::FnDecl,
expr: &'tcx hir::Expr,
body: &'tcx hir::Body,
span: Span,
nodeid: ast::NodeId
) {
@ -102,19 +102,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
}
}
self.check_raw_ptr(cx, unsafety, decl, expr, nodeid);
self.check_raw_ptr(cx, unsafety, decl, body, nodeid);
}
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) {
if let hir::MethodTraitItem(ref sig, eid) = item.node {
if let hir::TraitItemKind::Method(ref sig, ref eid) = item.node {
// don't lint extern functions decls, it's not their fault
if sig.abi == Abi::Rust {
self.check_arg_number(cx, &sig.decl, item.span);
}
if let Some(eid) = eid {
let expr = cx.tcx.map.expr(eid);
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, expr, item.id);
if let hir::TraitMethod::Provided(eid) = *eid {
let body = cx.tcx.map.body(eid);
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, body, item.id);
}
}
}
@ -136,11 +136,15 @@ impl<'a, 'tcx> Functions {
cx: &LateContext<'a, 'tcx>,
unsafety: hir::Unsafety,
decl: &'tcx hir::FnDecl,
expr: &'tcx hir::Expr,
body: &'tcx hir::Body,
nodeid: ast::NodeId
) {
let expr = &body.value;
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(nodeid) {
let raw_ptrs = decl.inputs.iter().filter_map(|arg| raw_ptr_arg(cx, arg)).collect::<HashSet<_>>();
let raw_ptrs = iter_input_pats(decl, body)
.zip(decl.inputs.iter())
.filter_map(|(arg, ty)| raw_ptr_arg(arg, ty))
.collect::<HashSet<_>>();
if !raw_ptrs.is_empty() {
let mut v = DerefVisitor {
@ -154,8 +158,8 @@ impl<'a, 'tcx> Functions {
}
}
fn raw_ptr_arg(_cx: &LateContext, arg: &hir::Arg) -> Option<hir::def_id::DefId> {
if let (&hir::PatKind::Binding(_, def_id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &arg.ty.node) {
fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option<hir::def_id::DefId> {
if let (&hir::PatKind::Binding(_, def_id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &ty.node) {
Some(def_id)
} else {
None

View File

@ -87,23 +87,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero {
}
}
fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItem]) {
fn is_named_self(item: &TraitItem, name: &str) -> bool {
fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItemRef]) {
fn is_named_self(cx: &LateContext, item: &TraitItemRef, name: &str) -> bool {
&*item.name.as_str() == name &&
if let MethodTraitItem(ref sig, _) = item.node {
if sig.decl.has_self() {
sig.decl.inputs.len() == 1
} else {
false
if let AssociatedItemKind::Method { has_self } = item.kind {
has_self &&
{
let did = cx.tcx.map.local_def_id(item.id.node_id);
let impl_ty = cx.tcx.item_type(did);
impl_ty.fn_args().skip_binder().len() == 1
}
} else {
false
}
}
if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) {
if let Some(i) = trait_items.iter().find(|i| is_named_self(i, "len")) {
if cx.access_levels.is_exported(i.id) {
if !trait_items.iter().any(|i| is_named_self(cx, i, "is_empty")) {
if let Some(i) = trait_items.iter().find(|i| is_named_self(cx, i, "len")) {
if cx.access_levels.is_exported(i.id.node_id) {
span_lint(cx,
LEN_WITHOUT_IS_EMPTY,
i.span,

View File

@ -3,10 +3,12 @@
#![feature(box_syntax)]
#![feature(collections)]
#![feature(custom_attribute)]
#![feature(i128_type)]
#![feature(rustc_private)]
#![feature(slice_patterns)]
#![feature(stmt_expr_attributes)]
#![feature(repeat_str)]
#![feature(conservative_impl_trait)]
#![allow(indexing_slicing, shadow_reuse, unknown_lints, missing_docs_in_private_items)]
#![allow(needless_lifetimes)]

View File

@ -70,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass {
}
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
if let MethodTraitItem(ref sig, _) = item.node {
if let TraitItemKind::Method(ref sig, _) = item.node {
check_fn_inner(cx, &sig.decl, &sig.generics, item.span);
}
}
@ -137,7 +137,7 @@ fn could_use_elision<'a, 'tcx: 'a, T: Iterator<Item = &'tcx Lifetime>>(
// extract lifetimes in input argument types
for arg in &func.inputs {
input_visitor.visit_ty(&arg.ty);
input_visitor.visit_ty(arg);
}
// extract lifetimes in output type
if let Return(ref ty) = func.output {

View File

@ -2,7 +2,7 @@ use rustc::lint::*;
use rustc::hir::*;
use syntax::ast;
use utils::{is_adjusted, match_path, match_trait_method, match_type, remove_blocks, paths, snippet,
span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};
span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, iter_input_pats};
/// **What it does:** Checks for mapping `clone()` over an iterator.
///
@ -31,18 +31,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
if &*name.node.as_str() == "map" && args.len() == 2 {
match args[1].node {
ExprClosure(_, ref decl, closure_eid, _) => {
let closure_expr = remove_blocks(cx.tcx.map.expr(closure_eid));
let body = cx.tcx.map.body(closure_eid);
let closure_expr = remove_blocks(&body.value);
if_let_chain! {[
// nothing special in the argument, besides reference bindings
// (e.g. .map(|&x| x) )
let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat),
let Some(first_arg) = iter_input_pats(decl, body).next(),
let Some(arg_ident) = get_arg_name(&first_arg.pat),
// the method is being called on a known type (option or iterator)
let Some(type_name) = get_type_name(cx, expr, &args[0])
], {
// look for derefs, for .map(|x| *x)
if only_derefs(cx, &*closure_expr, arg_ident) &&
// .cloned() only removes one level of indirection, don't lint on more
walk_ptrs_ty_depth(cx.tcx.tables().pat_ty(&*decl.inputs[0].pat)).1 == 1
walk_ptrs_ty_depth(cx.tcx.tables().pat_ty(&first_arg.pat)).1 == 1
{
span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
"you seem to be using .map() to clone the contents of an {}, consider \
@ -90,7 +92,7 @@ fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool {
name: id,
parameters: PathParameters::none(),
}];
!path.global && path.segments[..] == arg_segment
!path.is_global() && path.segments[..] == arg_segment
},
_ => false,
}

View File

@ -219,10 +219,10 @@ fn check_single_match_opt_like(
if inner.iter().any(|pat| pat.node != PatKind::Wild) {
return;
}
path.to_string()
print::to_string(print::NO_ANN, |s| s.print_qpath(path, false))
},
PatKind::Binding(BindByValue(MutImmutable), _, ident, None) => ident.node.to_string(),
PatKind::Path(ref path) => path.to_string(),
PatKind::Path(ref path) => print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)),
_ => return,
};

View File

@ -1,7 +1,6 @@
use rustc::hir;
use rustc::lint::*;
use rustc::middle::const_val::ConstVal;
use rustc::middle::const_qualif::ConstQualif;
use rustc::ty;
use rustc::hir::def::Def;
use rustc_const_eval::EvalHint::ExprTypeChecked;
@ -12,7 +11,7 @@ use syntax::codemap::Span;
use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, match_path, match_trait_method,
match_type, method_chain_args, return_ty, same_tys, snippet, span_lint, span_lint_and_then,
span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, last_path_segment, single_segment_path,
match_def_path};
match_def_path, is_self, is_self_ty, iter_input_pats};
use utils::paths;
use utils::sugg;
@ -637,16 +636,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
let parent = cx.tcx.map.get_parent(implitem.id);
let item = cx.tcx.map.expect_item(parent);
if_let_chain! {[
let hir::ImplItemKind::Method(ref sig, _) = implitem.node,
let Some(explicit_self) = sig.decl.inputs.get(0).and_then(hir::Arg::to_self),
let hir::ItemImpl(_, _, _, None, _, _) = item.node,
let hir::ImplItemKind::Method(ref sig, id) = implitem.node,
let Some(first_arg_ty) = sig.decl.inputs.get(0),
let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.map.body(id)).next(),
let hir::ItemImpl(_, _, _, None, ref self_ty, _) = item.node,
], {
// check missing trait implementations
for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS {
if &*name.as_str() == method_name &&
sig.decl.inputs.len() == n_args &&
out_type.matches(&sig.decl.output) &&
self_kind.matches(&explicit_self, false) {
self_kind.matches(&first_arg_ty, &first_arg, &self_ty, false) {
span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!(
"defining a method called `{}` on this type; consider implementing \
the `{}` trait or choosing a less ambiguous name", name, trait_name));
@ -659,8 +659,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
for &(ref conv, self_kinds) in &CONVENTIONS {
if_let_chain! {[
conv.check(&name.as_str()),
let Some(explicit_self) = sig.decl.inputs.get(0).and_then(hir::Arg::to_self),
!self_kinds.iter().any(|k| k.matches(&explicit_self, is_copy)),
!self_kinds.iter().any(|k| k.matches(&first_arg_ty, &first_arg, &self_ty, is_copy)),
], {
let lint = if item.vis == hir::Visibility::Public {
WRONG_PUB_SELF_CONVENTION
@ -669,7 +668,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
};
span_lint(cx,
lint,
explicit_self.span,
first_arg.pat.span,
&format!("methods called `{}` usually take {}; consider choosing a less \
ambiguous name",
conv,
@ -685,7 +684,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
!ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem.id)) {
span_lint(cx,
NEW_RET_NO_SELF,
explicit_self.span,
implitem.span,
"methods called `new` usually return `Self`");
}
}}
@ -752,11 +751,16 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir:
) {
// don't lint for constant values
// FIXME: can we `expect` here instead of match?
if let Some(qualif) = cx.tcx.const_qualif_map.borrow().get(&arg.id) {
if !qualif.contains(ConstQualif::NOT_CONST) {
return;
}
let promotable = cx.tcx
.rvalue_promotable_to_static
.borrow()
.get(&arg.id)
.cloned()
.unwrap_or(true);
if promotable {
return;
}
// (path, fn_has_argument, methods, suffix)
let know_types: &[(&[_], _, &[_], _)] =
&[(&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"),
@ -1338,7 +1342,7 @@ const PATTERN_METHODS: [(&'static str, usize); 17] = [
];
#[derive(Clone, Copy)]
#[derive(Clone, Copy, PartialEq)]
enum SelfKind {
Value,
Ref,
@ -1347,27 +1351,36 @@ enum SelfKind {
}
impl SelfKind {
fn matches(self, slf: &hir::ExplicitSelf, allow_value_for_ref: bool) -> bool {
match (self, &slf.node) {
(SelfKind::Value, &hir::SelfKind::Value(_)) |
(SelfKind::Ref, &hir::SelfKind::Region(_, hir::Mutability::MutImmutable)) |
(SelfKind::RefMut, &hir::SelfKind::Region(_, hir::Mutability::MutMutable)) => true,
(SelfKind::Ref, &hir::SelfKind::Value(_)) |
(SelfKind::RefMut, &hir::SelfKind::Value(_)) => allow_value_for_ref,
(_, &hir::SelfKind::Explicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref),
fn matches(self, ty: &hir::Ty, arg: &hir::Arg, self_ty: &hir::Ty, allow_value_for_ref: bool) -> bool {
// Self types in the HIR are desugared to explicit self types. So it will always be `self:
// SomeType`,
// where SomeType can be `Self` or an explicit impl self type (e.g. `Foo` if the impl is on `Foo`)
// Thus, we only need to test equality against the impl self type or if it is an explicit
// `Self`. Furthermore, the only possible types for `self: ` are `&Self`, `Self`, `&mut Self`,
// and `Box<Self>`, including the equivalent types with `Foo`.
let is_actually_self = |ty| is_self_ty(ty) || ty == self_ty;
if is_self(arg) {
match self {
SelfKind::Value => is_actually_self(ty),
SelfKind::Ref | SelfKind::RefMut if allow_value_for_ref => is_actually_self(ty),
SelfKind::Ref | SelfKind::RefMut => {
match ty.node {
hir::TyRptr(_, ref mt_ty) => {
let mutability_match = if self == SelfKind::Ref {
mt_ty.mutbl == hir::MutImmutable
} else {
mt_ty.mutbl == hir::MutMutable
};
is_actually_self(&mt_ty.ty) && mutability_match
_ => false,
}
}
fn matches_explicit_type(self, ty: &hir::Ty, allow_value_for_ref: bool) -> bool {
match (self, &ty.node) {
(SelfKind::Value, &hir::TyPath(..)) |
(SelfKind::Ref, &hir::TyRptr(_, hir::MutTy { mutbl: hir::Mutability::MutImmutable, .. })) |
(SelfKind::RefMut, &hir::TyRptr(_, hir::MutTy { mutbl: hir::Mutability::MutMutable, .. })) => true,
(SelfKind::Ref, &hir::TyPath(..)) |
(SelfKind::RefMut, &hir::TyPath(..)) => allow_value_for_ref,
_ => false,
},
_ => false,
}
},
_ => false,
}
} else {
self == SelfKind::No
}
}

View File

@ -9,7 +9,7 @@ use rustc_const_eval::eval_const_expr_partial;
use rustc_const_math::ConstFloat;
use syntax::codemap::{Span, Spanned, ExpnFormat};
use utils::{get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_path, snippet,
span_lint, span_lint_and_then, walk_ptrs_ty, last_path_segment};
span_lint, span_lint_and_then, walk_ptrs_ty, last_path_segment, iter_input_pats};
use utils::sugg::Sugg;
/// **What it does:** Checks for function arguments and let bindings denoted as `ref`.
@ -175,7 +175,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
cx: &LateContext<'a, 'tcx>,
k: FnKind<'tcx>,
decl: &'tcx FnDecl,
_: &'tcx Expr,
body: &'tcx Body,
_: Span,
_: NodeId
) {
@ -183,7 +183,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
// Does not apply to closures
return;
}
for arg in &decl.inputs {
for arg in iter_input_pats(decl, body) {
if let PatKind::Binding(BindByRef(_), _, _, _) = arg.pat.node {
span_lint(cx,
TOPLEVEL_REF_ARG,

View File

@ -136,9 +136,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx hir::TraitItem) {
let desc = match trait_item.node {
hir::ConstTraitItem(..) => "an associated constant",
hir::MethodTraitItem(..) => "a trait method",
hir::TypeTraitItem(..) => "an associated type",
hir::TraitItemKind::Const(..) => "an associated constant",
hir::TraitItemKind::Method(..) => "a trait method",
hir::TraitItemKind::Type(..) => "an associated type",
};
self.check_missing_docs_attrs(cx, &trait_item.attrs, trait_item.span, desc);

View File

@ -42,7 +42,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed {
.expect("A function with an unknown type is called. If this happened, the compiler would have \
aborted the compilation long ago");
if let ExprPath(ref path) = fn_expr.node {
check_arguments(cx, arguments, function_type, &path.to_string());
check_arguments(cx,
arguments,
function_type,
&print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)));
}
},
ExprMethodCall(ref name, _, ref arguments) => {

View File

@ -95,7 +95,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
cx: &LateContext<'a, 'tcx>,
kind: FnKind<'tcx>,
decl: &'tcx hir::FnDecl,
_: &'tcx hir::Expr,
_: &'tcx hir::Body,
span: Span,
id: ast::NodeId
) {

View File

@ -52,7 +52,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
], {
let is_result_type = match_type(cx, cx.tcx.tables().expr_ty(&result_types[0]), &paths::RESULT);
let some_expr_string = snippet(cx, y[0].span, "");
if print::path_to_string(x) == "Some" && is_result_type {
if print::to_string(print::NO_ANN, |s| s.print_path(x, false)) == "Some" && is_result_type {
span_help_and_lint(cx, IF_LET_SOME_RESULT, expr.span,
"Matching on `Some` with `ok()` is redundant",
&format!("Consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string));

View File

@ -73,7 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass {
}
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
if let MethodTraitItem(ref sig, _) = item.node {
if let TraitItemKind::Method(ref sig, _) = item.node {
check_fn(cx, &sig.decl, item.id);
}
}
@ -99,13 +99,13 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) {
if match_type(cx, ty, &paths::VEC) {
span_lint(cx,
PTR_ARG,
arg.ty.span,
arg.span,
"writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \
with non-Vec-based slices. Consider changing the type to `&[...]`");
} else if match_type(cx, ty, &paths::STRING) {
span_lint(cx,
PTR_ARG,
arg.ty.span,
arg.span,
"writing `&String` instead of `&str` involves a new object where a slice will do. \
Consider changing the type to `&str`");
}

View File

@ -4,7 +4,7 @@ use rustc::hir::*;
use rustc::hir::intravisit::{Visitor, FnKind, NestedVisitorMap};
use rustc::ty;
use syntax::codemap::Span;
use utils::{higher, in_external_macro, snippet, span_lint_and_then};
use utils::{higher, in_external_macro, snippet, span_lint_and_then, iter_input_pats};
/// **What it does:** Checks for bindings that shadow other bindings already in
/// scope, while just changing reference level or mutability.
@ -85,25 +85,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
cx: &LateContext<'a, 'tcx>,
_: FnKind<'tcx>,
decl: &'tcx FnDecl,
expr: &'tcx Expr,
body: &'tcx Body,
_: Span,
_: NodeId
) {
if in_external_macro(cx, expr.span) {
if in_external_macro(cx, body.value.span) {
return;
}
check_fn(cx, decl, expr);
check_fn(cx, decl, body);
}
}
fn check_fn<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, expr: &'tcx Expr) {
fn check_fn<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, body: &'tcx Body) {
let mut bindings = Vec::new();
for arg in &decl.inputs {
for arg in iter_input_pats(decl, body) {
if let PatKind::Binding(_, _, ident, _) = arg.pat.node {
bindings.push((ident.node, ident.span))
}
}
check_expr(cx, expr, &mut bindings);
check_expr(cx, &body.value, &mut bindings);
}
fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, bindings: &mut Vec<(Name, Span)>) {
@ -341,9 +341,9 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V
match ty.node {
TyObjectSum(ref sty, _) |
TySlice(ref sty) => check_ty(cx, sty, bindings),
TyArray(ref fty, ref expr) => {
TyArray(ref fty, body_id) => {
check_ty(cx, fty, bindings);
check_expr(cx, expr, bindings);
check_expr(cx, &cx.tcx.map.body(body_id).value, bindings);
},
TyPtr(MutTy { ty: ref mty, .. }) |
TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings),
@ -352,7 +352,7 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V
check_ty(cx, t, bindings)
}
},
TyTypeof(ref expr) => check_expr(cx, expr, bindings),
TyTypeof(body_id) => check_expr(cx, &cx.tcx.map.body(body_id).value, bindings),
_ => (),
}
}
@ -371,7 +371,7 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool {
}
fn path_eq_name(name: Name, path: &Path) -> bool {
!path.global && path.segments.len() == 1 && path.segments[0].name.as_str() == name.as_str()
!path.is_global() && path.segments.len() == 1 && path.segments[0].name.as_str() == name.as_str()
}
struct ContainsSelf<'a, 'tcx: 'a> {

View File

@ -70,7 +70,7 @@ impl LintPass for TypePass {
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass {
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Expr, _: Span, id: NodeId) {
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Body, _: Span, id: NodeId) {
// skip trait implementations, see #605
if let Some(map::NodeItem(item)) = cx.tcx.map.find(cx.tcx.map.get_parent(id)) {
if let ItemImpl(_, _, _, Some(..), _, _) = item.node {
@ -87,9 +87,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass {
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
match item.node {
ConstTraitItem(ref ty, _) |
TypeTraitItem(_, Some(ref ty)) => check_ty(cx, ty),
MethodTraitItem(ref sig, _) => check_fn_decl(cx, &sig.decl),
TraitItemKind::Const(ref ty, _) |
TraitItemKind::Type(_, Some(ref ty)) => check_ty(cx, ty),
TraitItemKind::Method(ref sig, _) => check_fn_decl(cx, &sig.decl),
_ => (),
}
}
@ -97,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass {
fn check_fn_decl(cx: &LateContext, decl: &FnDecl) {
for input in &decl.inputs {
check_ty(cx, &input.ty);
check_ty(cx, input);
}
if let FunctionRetTy::Return(ref ty) = decl.output {
@ -326,7 +326,7 @@ declare_lint! {
/// **Example:**
/// ```rust
/// let y: i8 = -1;
/// y as u64 // will return 18446744073709551615
/// y as u128 // will return 18446744073709551615
/// ```
declare_lint! {
pub CAST_SIGN_LOSS,
@ -601,7 +601,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass {
cx: &LateContext<'a, 'tcx>,
_: FnKind<'tcx>,
decl: &'tcx FnDecl,
_: &'tcx Expr,
_: &'tcx Body,
_: Span,
_: NodeId
) {
@ -624,9 +624,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass {
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
match item.node {
ConstTraitItem(ref ty, _) |
TypeTraitItem(_, Some(ref ty)) => self.check_type(cx, ty),
MethodTraitItem(MethodSig { ref decl, .. }, None) => self.check_fndecl(cx, decl),
TraitItemKind::Const(ref ty, _) |
TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty),
TraitItemKind::Method(MethodSig { ref decl, .. }, TraitMethod::Required(_)) => self.check_fndecl(cx, decl),
// methods with default impl are covered by check_fn
_ => (),
}
@ -651,7 +651,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass {
impl<'a, 'tcx> TypeComplexityPass {
fn check_fndecl(&self, cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl) {
for arg in &decl.inputs {
self.check_type(cx, &arg.ty);
self.check_type(cx, arg);
}
if let Return(ref ty) = decl.output {
self.check_type(cx, ty);
@ -889,12 +889,14 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
(&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) |
(&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MIN))) |
(&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MIN))) |
(&ty::TyInt(IntTy::I128), Integral(I128(::std::i128::MIN))) |
(&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MIN)))) |
(&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MIN)))) |
(&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) |
(&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MIN))) |
(&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MIN))) |
(&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MIN))) => Minimum,
(&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MIN))) |
(&ty::TyUint(UintTy::U128), Integral(U128(::std::u128::MIN))) => Minimum,
(&ty::TyBool, Bool(true)) |
(&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MAX)))) |
@ -903,12 +905,14 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
(&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) |
(&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MAX))) |
(&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MAX))) |
(&ty::TyInt(IntTy::I128), Integral(I128(::std::i128::MAX))) |
(&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MAX)))) |
(&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MAX)))) |
(&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) |
(&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MAX))) |
(&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MAX))) |
(&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MAX))) => Maximum,
(&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MAX))) |
(&ty::TyUint(UintTy::U128), Integral(U128(::std::u128::MAX))) => Maximum,
_ => return None,
};
@ -985,19 +989,19 @@ impl LintPass for InvalidUpcastComparisons {
#[derive(Copy, Clone, Debug, Eq)]
enum FullInt {
S(i64),
U(u64),
S(i128),
U(u128),
}
impl FullInt {
#[allow(cast_sign_loss)]
fn cmp_s_u(s: i64, u: u64) -> Ordering {
fn cmp_s_u(s: i128, u: u128) -> Ordering {
if s < 0 {
Ordering::Less
} else if u > (i64::max_value() as u64) {
} else if u > (i128::max_value() as u128) {
Ordering::Greater
} else {
(s as u64).cmp(&u)
(s as u128).cmp(&u)
}
}
}
@ -1034,20 +1038,22 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(
match cx.tcx.tables().expr_ty(cast_exp).sty {
TyInt(int_ty) => {
Some(match int_ty {
IntTy::I8 => (FullInt::S(i8::min_value() as i64), FullInt::S(i8::max_value() as i64)),
IntTy::I16 => (FullInt::S(i16::min_value() as i64), FullInt::S(i16::max_value() as i64)),
IntTy::I32 => (FullInt::S(i32::min_value() as i64), FullInt::S(i32::max_value() as i64)),
IntTy::I64 => (FullInt::S(i64::min_value() as i64), FullInt::S(i64::max_value() as i64)),
IntTy::Is => (FullInt::S(isize::min_value() as i64), FullInt::S(isize::max_value() as i64)),
IntTy::I8 => (FullInt::S(i8::min_value() as i128), FullInt::S(i8::max_value() as i128)),
IntTy::I16 => (FullInt::S(i16::min_value() as i128), FullInt::S(i16::max_value() as i128)),
IntTy::I32 => (FullInt::S(i32::min_value() as i128), FullInt::S(i32::max_value() as i128)),
IntTy::I64 => (FullInt::S(i64::min_value() as i128), FullInt::S(i64::max_value() as i128)),
IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)),
IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)),
})
},
TyUint(uint_ty) => {
Some(match uint_ty {
UintTy::U8 => (FullInt::U(u8::min_value() as u64), FullInt::U(u8::max_value() as u64)),
UintTy::U16 => (FullInt::U(u16::min_value() as u64), FullInt::U(u16::max_value() as u64)),
UintTy::U32 => (FullInt::U(u32::min_value() as u64), FullInt::U(u32::max_value() as u64)),
UintTy::U64 => (FullInt::U(u64::min_value() as u64), FullInt::U(u64::max_value() as u64)),
UintTy::Us => (FullInt::U(usize::min_value() as u64), FullInt::U(usize::max_value() as u64)),
UintTy::U8 => (FullInt::U(u8::min_value() as u128), FullInt::U(u8::max_value() as u128)),
UintTy::U16 => (FullInt::U(u16::min_value() as u128), FullInt::U(u16::max_value() as u128)),
UintTy::U32 => (FullInt::U(u32::min_value() as u128), FullInt::U(u32::max_value() as u128)),
UintTy::U64 => (FullInt::U(u64::min_value() as u128), FullInt::U(u64::max_value() as u128)),
UintTy::U128 => (FullInt::U(u128::min_value() as u128), FullInt::U(u128::max_value() as u128)),
UintTy::Us => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)),
})
},
_ => None,
@ -1067,8 +1073,8 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> {
Ok(val) => {
if let Integral(const_int) = val {
Some(match const_int.erase_type() {
ConstInt::InferSigned(x) => FullInt::S(x as i64),
ConstInt::Infer(x) => FullInt::U(x as u64),
ConstInt::InferSigned(x) => FullInt::S(x as i128),
ConstInt::Infer(x) => FullInt::U(x as u128),
_ => unreachable!(),
})
} else {

View File

@ -46,7 +46,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel {
cx: &LateContext<'a, 'tcx>,
kind: FnKind<'tcx>,
decl: &'tcx hir::FnDecl,
body: &'tcx hir::Expr,
body: &'tcx hir::Body,
span: Span,
fn_id: ast::NodeId
) {
@ -58,7 +58,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel {
cx: cx,
labels: HashMap::new(),
};
walk_fn(&mut v, kind, decl, body.expr_id(), span, fn_id);
walk_fn(&mut v, kind, decl, body.id(), span, fn_id);
for (label, span) in v.labels {
span_lint(cx, UNUSED_LABEL, span, &format!("unused label `{}`", label));

View File

@ -112,7 +112,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
!self.ignore_fn && l_name.node == r_name.node && over(l_tys, r_tys, |l, r| self.eq_ty(l, r)) &&
self.eq_exprs(l_args, r_args)
},
(&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => self.eq_expr(le, re) && self.eq_expr(ll, rl),
(&ExprRepeat(ref le, ll_id), &ExprRepeat(ref re, rl_id)) => {
self.eq_expr(le, re) &&
self.eq_expr(&self.cx.tcx.map.body(ll_id).value, &self.cx.tcx.map.body(rl_id).value)
},
(&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)),
(&ExprPath(ref l), &ExprPath(ref r)) => self.eq_qpath(l, r),
(&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => {
@ -183,7 +186,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
}
fn eq_path(&self, left: &Path, right: &Path) -> bool {
left.global == right.global && over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r))
left.is_global() == right.is_global() &&
over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r))
}
fn eq_path_parameters(&self, left: &PathParameters, right: &PathParameters) -> bool {
@ -211,7 +215,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
fn eq_ty(&self, left: &Ty, right: &Ty) -> bool {
match (&left.node, &right.node) {
(&TySlice(ref l_vec), &TySlice(ref r_vec)) => self.eq_ty(l_vec, r_vec),
(&TyArray(ref lt, ref ll), &TyArray(ref rt, ref rl)) => self.eq_ty(lt, rt) && self.eq_expr(ll, rl),
(&TyArray(ref lt, ll_id), &TyArray(ref rt, rl_id)) => {
self.eq_ty(lt, rt) &&
self.eq_expr(&self.cx.tcx.map.body(ll_id).value, &self.cx.tcx.map.body(rl_id).value)
},
(&TyPtr(ref l_mut), &TyPtr(ref r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty),
(&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => {
l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty)
@ -363,7 +370,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
let c: fn(_, _, _, _) -> _ = ExprClosure;
c.hash(&mut self.s);
cap.hash(&mut self.s);
self.hash_expr(self.cx.tcx.map.expr(eid));
self.hash_expr(&self.cx.tcx.map.body(eid).value);
},
ExprField(ref e, ref f) => {
let c: fn(_, _) -> _ = ExprField;
@ -424,11 +431,11 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
self.hash_name(&name.node);
self.hash_exprs(args);
},
ExprRepeat(ref e, ref l) => {
ExprRepeat(ref e, l_id) => {
let c: fn(_, _) -> _ = ExprRepeat;
c.hash(&mut self.s);
self.hash_expr(e);
self.hash_expr(l);
self.hash_expr(&self.cx.tcx.map.body(l_id).value);
},
ExprRet(ref e) => {
let c: fn(_) -> _ = ExprRet;
@ -524,7 +531,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
}
pub fn hash_path(&mut self, p: &Path) {
p.global.hash(&mut self.s);
p.is_global().hash(&mut self.s);
for p in &p.segments {
self.hash_name(&p.name);
}

View File

@ -4,6 +4,7 @@
use rustc::lint::*;
use rustc::hir;
use rustc::hir::print;
use syntax::ast::Attribute;
use syntax::attr;
@ -52,16 +53,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
match item.vis {
hir::Visibility::Public => println!("public"),
hir::Visibility::Crate => println!("visible crate wide"),
hir::Visibility::Restricted { ref path, .. } => println!("visible in module `{}`", path),
hir::Visibility::Restricted { ref path, .. } => {
println!("visible in module `{}`",
print::to_string(print::NO_ANN, |s| s.print_path(path, false)))
},
hir::Visibility::Inherited => println!("visibility inherited from outer item"),
}
if item.defaultness.is_default() {
println!("default");
}
match item.node {
hir::ImplItemKind::Const(_, ref e) => {
hir::ImplItemKind::Const(_, body_id) => {
println!("associated constant");
print_expr(cx, e, 1);
print_expr(cx, &cx.tcx.map.body(body_id).value, 1);
},
hir::ImplItemKind::Method(..) => println!("method"),
hir::ImplItemKind::Type(_) => println!("associated type"),
@ -323,12 +327,12 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) {
print_expr(cx, base, indent + 1);
}
},
hir::ExprRepeat(ref val, ref n) => {
hir::ExprRepeat(ref val, body_id) => {
println!("{}Repeat, {}", ind, ty);
println!("{}value:", ind);
print_expr(cx, val, indent + 1);
println!("{}repeat count:", ind);
print_expr(cx, n, indent + 1);
print_expr(cx, &cx.tcx.map.body(body_id).value, indent + 1);
},
}
}
@ -339,7 +343,10 @@ fn print_item(cx: &LateContext, item: &hir::Item) {
match item.vis {
hir::Visibility::Public => println!("public"),
hir::Visibility::Crate => println!("visible crate wide"),
hir::Visibility::Restricted { ref path, .. } => println!("visible in module `{}`", path),
hir::Visibility::Restricted { ref path, .. } => {
println!("visible in module `{}`",
print::to_string(print::NO_ANN, |s| s.print_path(path, false)))
},
hir::Visibility::Inherited => println!("visibility inherited from outer item"),
}
match item.node {
@ -413,7 +420,9 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) {
},
hir::PatKind::Struct(ref path, ref fields, ignore) => {
println!("{}Struct", ind);
println!("{}name: {}", ind, path);
println!("{}name: {}",
ind,
print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)));
println!("{}ignore leftover fields: {}", ind, ignore);
println!("{}fields:", ind);
for field in fields {
@ -426,7 +435,9 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) {
},
hir::PatKind::TupleStruct(ref path, ref fields, opt_dots_position) => {
println!("{}TupleStruct", ind);
println!("{}path: {}", ind, path);
println!("{}path: {}",
ind,
print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)));
if let Some(dot_position) = opt_dots_position {
println!("{}dot position: {}", ind, dot_position);
}

View File

@ -106,7 +106,7 @@ impl LintPass for LintWithoutLintPass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemStatic(ref ty, MutImmutable, ref expr) = item.node {
if let ItemStatic(ref ty, MutImmutable, body_id) = item.node {
if is_lint_ref_type(ty) {
self.declared_lints.insert(item.name, item.span);
} else if is_lint_array_type(ty) && item.vis == Visibility::Inherited && item.name == "ARRAY" {
@ -114,7 +114,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass {
output: &mut self.registered_lints,
cx: cx,
};
collector.visit_expr(expr);
collector.visit_expr(&cx.tcx.map.body(body_id).value);
}
}
}

View File

@ -19,6 +19,7 @@ use syntax::attr;
use syntax::codemap::{ExpnFormat, ExpnInfo, MultiSpan, Span, DUMMY_SP};
use syntax::errors::DiagnosticBuilder;
use syntax::ptr::P;
use syntax::symbol::keywords;
pub mod cargo;
pub mod comparisons;
@ -487,7 +488,7 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI
match node {
Node::NodeBlock(block) => Some(block),
Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, eid), .. }) => {
match cx.tcx.map.expr(eid).node {
match cx.tcx.map.body(eid).value.node {
ExprBlock(ref block) => Some(block),
_ => None,
}
@ -610,7 +611,7 @@ pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) {
}
/// Check whether the given expression is a constant literal of the given value.
pub fn is_integer_literal(expr: &Expr, value: u64) -> bool {
pub fn is_integer_literal(expr: &Expr, value: u128) -> bool {
// FIXME: use constant folding
if let ExprLit(ref spanned) = expr.node {
if let LitKind::Int(v, _) = spanned.node {
@ -896,3 +897,26 @@ pub fn opt_def_id(def: Def) -> Option<DefId> {
Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None,
}
}
pub fn is_self(slf: &Arg) -> bool {
if let PatKind::Binding(_, _, name, _) = slf.pat.node {
name.node == keywords::SelfValue.name()
} else {
false
}
}
pub fn is_self_ty(slf: &Ty) -> bool {
if_let_chain! {[
let TyPath(ref qp) = slf.node,
let QPath::Resolved(None, ref path) = *qp,
let Def::SelfTy(..) = path.def,
], {
return true
}}
false
}
pub fn iter_input_pats<'tcx>(decl: &FnDecl, body: &'tcx Body) -> impl Iterator<Item = &'tcx Arg> {
(0..decl.inputs.len()).map(move |i| &body.arguments[i])
}