mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-23 21:23:20 +00:00
Merge pull request #1823 from eddyb/nightly-magic
Update for rustc 1.19.0-nightly (4bf5c99af
2017-06-10) and some cleanups.
This commit is contained in:
commit
7535afc0fa
@ -82,14 +82,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
|
|||||||
if let hir::ExprBinary(binop, ref l, ref r) = rhs.node {
|
if let hir::ExprBinary(binop, ref l, ref r) = rhs.node {
|
||||||
if op.node == binop.node {
|
if op.node == binop.node {
|
||||||
let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
|
let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
|
||||||
let ty = cx.tables.expr_ty(assignee);
|
|
||||||
if ty.walk_shallow().next().is_some() {
|
|
||||||
return; // implements_trait does not work with generics
|
|
||||||
}
|
|
||||||
let rty = cx.tables.expr_ty(rhs);
|
|
||||||
if rty.walk_shallow().next().is_some() {
|
|
||||||
return; // implements_trait does not work with generics
|
|
||||||
}
|
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
MISREFACTORED_ASSIGN_OP,
|
MISREFACTORED_ASSIGN_OP,
|
||||||
expr.span,
|
expr.span,
|
||||||
@ -120,13 +112,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
|
|||||||
#[allow(cyclomatic_complexity)]
|
#[allow(cyclomatic_complexity)]
|
||||||
let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
|
let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
|
||||||
let ty = cx.tables.expr_ty(assignee);
|
let ty = cx.tables.expr_ty(assignee);
|
||||||
if ty.walk_shallow().next().is_some() {
|
|
||||||
return; // implements_trait does not work with generics
|
|
||||||
}
|
|
||||||
let rty = cx.tables.expr_ty(rhs);
|
let rty = cx.tables.expr_ty(rhs);
|
||||||
if rty.walk_shallow().next().is_some() {
|
|
||||||
return; // implements_trait does not work with generics
|
|
||||||
}
|
|
||||||
macro_rules! ops {
|
macro_rules! ops {
|
||||||
($op:expr,
|
($op:expr,
|
||||||
$cx:expr,
|
$cx:expr,
|
||||||
@ -152,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
|
|||||||
let hir::Item_::ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = item.node,
|
let hir::Item_::ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = item.node,
|
||||||
trait_ref.path.def.def_id() == trait_id
|
trait_ref.path.def.def_id() == trait_id
|
||||||
], { return; }}
|
], { return; }}
|
||||||
implements_trait($cx, $ty, trait_id, &[$rty], None)
|
implements_trait($cx, $ty, trait_id, &[$rty])
|
||||||
},)*
|
},)*
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use reexport::*;
|
use reexport::*;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::ty;
|
use rustc::ty::{self, TyCtxt};
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
|
use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
@ -158,7 +158,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_relevant_item(tcx: ty::TyCtxt, item: &Item) -> bool {
|
fn is_relevant_item(tcx: TyCtxt, item: &Item) -> bool {
|
||||||
if let ItemFn(_, _, _, _, _, eid) = item.node {
|
if let ItemFn(_, _, _, _, _, eid) = item.node {
|
||||||
is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value)
|
is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value)
|
||||||
} else {
|
} else {
|
||||||
@ -166,14 +166,14 @@ fn is_relevant_item(tcx: ty::TyCtxt, item: &Item) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_relevant_impl(tcx: ty::TyCtxt, item: &ImplItem) -> bool {
|
fn is_relevant_impl(tcx: TyCtxt, item: &ImplItem) -> bool {
|
||||||
match item.node {
|
match item.node {
|
||||||
ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value),
|
ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_relevant_trait(tcx: ty::TyCtxt, item: &TraitItem) -> bool {
|
fn is_relevant_trait(tcx: TyCtxt, item: &TraitItem) -> bool {
|
||||||
match item.node {
|
match item.node {
|
||||||
TraitItemKind::Method(_, TraitMethod::Required(_)) => true,
|
TraitItemKind::Method(_, TraitMethod::Required(_)) => true,
|
||||||
TraitItemKind::Method(_, TraitMethod::Provided(eid)) => {
|
TraitItemKind::Method(_, TraitMethod::Provided(eid)) => {
|
||||||
@ -183,7 +183,7 @@ fn is_relevant_trait(tcx: ty::TyCtxt, item: &TraitItem) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_relevant_block(tcx: ty::TyCtxt, tables: &ty::TypeckTables, block: &Block) -> bool {
|
fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> bool {
|
||||||
for stmt in &block.stmts {
|
for stmt in &block.stmts {
|
||||||
match stmt.node {
|
match stmt.node {
|
||||||
StmtDecl(_, _) => return true,
|
StmtDecl(_, _) => return true,
|
||||||
@ -196,7 +196,7 @@ fn is_relevant_block(tcx: ty::TyCtxt, tables: &ty::TypeckTables, block: &Block)
|
|||||||
block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e))
|
block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_relevant_expr(tcx: ty::TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool {
|
fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExprBlock(ref block) => is_relevant_block(tcx, tables, block),
|
ExprBlock(ref block) => is_relevant_block(tcx, tables, block),
|
||||||
ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e),
|
ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e),
|
||||||
|
@ -5,7 +5,7 @@ use rustc::hir::def::Def;
|
|||||||
use rustc_const_eval::lookup_const_by_id;
|
use rustc_const_eval::lookup_const_by_id;
|
||||||
use rustc_const_math::ConstInt;
|
use rustc_const_math::ConstInt;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt, Ty};
|
||||||
use rustc::ty::subst::{Substs, Subst};
|
use rustc::ty::subst::{Substs, Subst};
|
||||||
use std::cmp::Ordering::{self, Equal};
|
use std::cmp::Ordering::{self, Equal};
|
||||||
use std::cmp::PartialOrd;
|
use std::cmp::PartialOrd;
|
||||||
@ -161,7 +161,7 @@ impl PartialOrd for Constant {
|
|||||||
|
|
||||||
/// parse a `LitKind` to a `Constant`
|
/// parse a `LitKind` to a `Constant`
|
||||||
#[allow(cast_possible_wrap)]
|
#[allow(cast_possible_wrap)]
|
||||||
pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut ty: ty::Ty<'tcx>) -> Constant {
|
pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut ty: Ty<'tcx>) -> Constant {
|
||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
use syntax::ast::LitIntType::*;
|
use syntax::ast::LitIntType::*;
|
||||||
use rustc::ty::util::IntTypeExt;
|
use rustc::ty::util::IntTypeExt;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::ty;
|
use rustc::ty::Ty;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
@ -251,11 +251,11 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the list of bindings in a pattern.
|
/// Return the list of bindings in a pattern.
|
||||||
fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, ty::Ty<'tcx>> {
|
fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, Ty<'tcx>> {
|
||||||
fn bindings_impl<'a, 'tcx>(
|
fn bindings_impl<'a, 'tcx>(
|
||||||
cx: &LateContext<'a, 'tcx>,
|
cx: &LateContext<'a, 'tcx>,
|
||||||
pat: &Pat,
|
pat: &Pat,
|
||||||
map: &mut HashMap<InternedString, ty::Ty<'tcx>>
|
map: &mut HashMap<InternedString, Ty<'tcx>>
|
||||||
) {
|
) {
|
||||||
match pat.node {
|
match pat.node {
|
||||||
PatKind::Box(ref pat) |
|
PatKind::Box(ref pat) |
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::ty::TypeVariants;
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty;
|
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::paths;
|
use utils::paths;
|
||||||
@ -89,7 +88,7 @@ fn check_hash_peq<'a, 'tcx>(
|
|||||||
cx: &LateContext<'a, 'tcx>,
|
cx: &LateContext<'a, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
trait_ref: &TraitRef,
|
trait_ref: &TraitRef,
|
||||||
ty: ty::Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
hash_is_automatically_derived: bool
|
hash_is_automatically_derived: bool
|
||||||
) {
|
) {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
@ -134,28 +133,27 @@ fn check_hash_peq<'a, 'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
|
/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
|
||||||
fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) {
|
fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: Ty<'tcx>) {
|
||||||
if match_path_old(&trait_ref.path, &paths::CLONE_TRAIT) {
|
if match_path_old(&trait_ref.path, &paths::CLONE_TRAIT) {
|
||||||
let def_id = cx.tcx.hir.local_def_id(item.id);
|
if !is_copy(cx, ty) {
|
||||||
if !is_copy(cx, ty, def_id) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
TypeVariants::TyAdt(def, _) if def.is_union() => return,
|
ty::TyAdt(def, _) if def.is_union() => return,
|
||||||
|
|
||||||
// Some types are not Clone by default but could be cloned “by hand” if necessary
|
// Some types are not Clone by default but could be cloned “by hand” if necessary
|
||||||
TypeVariants::TyAdt(def, substs) => {
|
ty::TyAdt(def, substs) => {
|
||||||
for variant in &def.variants {
|
for variant in &def.variants {
|
||||||
for field in &variant.fields {
|
for field in &variant.fields {
|
||||||
match field.ty(cx.tcx, substs).sty {
|
match field.ty(cx.tcx, substs).sty {
|
||||||
TypeVariants::TyArray(_, size) if size > 32 => {
|
ty::TyArray(_, size) if size > 32 => {
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
TypeVariants::TyFnPtr(..) => {
|
ty::TyFnPtr(..) => {
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
TypeVariants::TyTuple(tys, _) if tys.len() > 12 => {
|
ty::TyTuple(tys, _) if tys.len() > 12 => {
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -135,8 +135,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||||||
expr.span,
|
expr.span,
|
||||||
&msg,
|
&msg,
|
||||||
arg.span,
|
arg.span,
|
||||||
&format!("argument has type {}", arg_ty.sty));
|
&format!("argument has type {}", arg_ty));
|
||||||
} else if is_copy(cx, arg_ty, cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(arg.id))) {
|
} else if is_copy(cx, arg_ty) {
|
||||||
if match_def_path(cx.tcx, def_id, &paths::DROP) {
|
if match_def_path(cx.tcx, def_id, &paths::DROP) {
|
||||||
lint = DROP_COPY;
|
lint = DROP_COPY;
|
||||||
msg = DROP_COPY_SUMMARY.to_string();
|
msg = DROP_COPY_SUMMARY.to_string();
|
||||||
@ -151,7 +151,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||||||
expr.span,
|
expr.span,
|
||||||
&msg,
|
&msg,
|
||||||
arg.span,
|
arg.span,
|
||||||
&format!("argument has type {}", arg_ty.sty));
|
&format!("argument has type {}", arg_ty));
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse {
|
|||||||
fn check_mod(&mut self, cx: &LateContext<'a, 'tcx>, m: &'tcx Mod, _: Span, _: NodeId) {
|
fn check_mod(&mut self, cx: &LateContext<'a, 'tcx>, m: &'tcx Mod, _: Span, _: NodeId) {
|
||||||
// only check top level `use` statements
|
// only check top level `use` statements
|
||||||
for item in &m.item_ids {
|
for item in &m.item_ids {
|
||||||
self.lint_item(cx, cx.krate.item(item.id));
|
self.lint_item(cx, cx.tcx.hir.expect_item(item.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,8 +75,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
|
|||||||
BiNe | BiEq => (cx.tcx.lang_items.eq_trait(), true),
|
BiNe | BiEq => (cx.tcx.lang_items.eq_trait(), true),
|
||||||
BiLt | BiLe | BiGe | BiGt => (cx.tcx.lang_items.ord_trait(), true),
|
BiLt | BiLe | BiGe | BiGt => (cx.tcx.lang_items.ord_trait(), true),
|
||||||
};
|
};
|
||||||
let parent = cx.tcx.hir.get_parent(e.id);
|
|
||||||
let parent = cx.tcx.hir.local_def_id(parent);
|
|
||||||
if let Some(trait_id) = trait_id {
|
if let Some(trait_id) = trait_id {
|
||||||
#[allow(match_same_arms)]
|
#[allow(match_same_arms)]
|
||||||
match (&left.node, &right.node) {
|
match (&left.node, &right.node) {
|
||||||
@ -87,10 +85,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
|
|||||||
(&ExprAddrOf(_, ref l), &ExprAddrOf(_, ref r)) => {
|
(&ExprAddrOf(_, ref l), &ExprAddrOf(_, ref r)) => {
|
||||||
let lty = cx.tables.expr_ty(l);
|
let lty = cx.tables.expr_ty(l);
|
||||||
let rty = cx.tables.expr_ty(r);
|
let rty = cx.tables.expr_ty(r);
|
||||||
let lcpy = is_copy(cx, lty, parent);
|
let lcpy = is_copy(cx, lty);
|
||||||
let rcpy = is_copy(cx, rty, parent);
|
let rcpy = is_copy(cx, rty);
|
||||||
// either operator autorefs or both args are copyable
|
// either operator autorefs or both args are copyable
|
||||||
if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty], None) {
|
if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty]) {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
OP_REF,
|
OP_REF,
|
||||||
e.span,
|
e.span,
|
||||||
@ -104,13 +102,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
|
|||||||
(right.span, rsnip)]);
|
(right.span, rsnip)]);
|
||||||
})
|
})
|
||||||
} else if lcpy && !rcpy &&
|
} else if lcpy && !rcpy &&
|
||||||
implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)], None) {
|
implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)]) {
|
||||||
span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
|
span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
|
||||||
let lsnip = snippet(cx, l.span, "...").to_string();
|
let lsnip = snippet(cx, l.span, "...").to_string();
|
||||||
db.span_suggestion(left.span, "use the left value directly", lsnip);
|
db.span_suggestion(left.span, "use the left value directly", lsnip);
|
||||||
})
|
})
|
||||||
} else if !lcpy && rcpy &&
|
} else if !lcpy && rcpy &&
|
||||||
implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty], None) {
|
implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty]) {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
OP_REF,
|
OP_REF,
|
||||||
e.span,
|
e.span,
|
||||||
@ -124,9 +122,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
|
|||||||
// &foo == bar
|
// &foo == bar
|
||||||
(&ExprAddrOf(_, ref l), _) => {
|
(&ExprAddrOf(_, ref l), _) => {
|
||||||
let lty = cx.tables.expr_ty(l);
|
let lty = cx.tables.expr_ty(l);
|
||||||
let lcpy = is_copy(cx, lty, parent);
|
let lcpy = is_copy(cx, lty);
|
||||||
if (requires_ref || lcpy) &&
|
if (requires_ref || lcpy) &&
|
||||||
implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)], None) {
|
implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)]) {
|
||||||
span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
|
span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
|
||||||
let lsnip = snippet(cx, l.span, "...").to_string();
|
let lsnip = snippet(cx, l.span, "...").to_string();
|
||||||
db.span_suggestion(left.span, "use the left value directly", lsnip);
|
db.span_suggestion(left.span, "use the left value directly", lsnip);
|
||||||
@ -136,9 +134,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
|
|||||||
// foo == &bar
|
// foo == &bar
|
||||||
(_, &ExprAddrOf(_, ref r)) => {
|
(_, &ExprAddrOf(_, ref r)) => {
|
||||||
let rty = cx.tables.expr_ty(r);
|
let rty = cx.tables.expr_ty(r);
|
||||||
let rcpy = is_copy(cx, rty, parent);
|
let rcpy = is_copy(cx, rty);
|
||||||
if (requires_ref || rcpy) &&
|
if (requires_ref || rcpy) &&
|
||||||
implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty], None) {
|
implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty]) {
|
||||||
span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| {
|
span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| {
|
||||||
let rsnip = snippet(cx, r.span, "...").to_string();
|
let rsnip = snippet(cx, r.span, "...").to_string();
|
||||||
db.span_suggestion(right.span, "use the right value directly", rsnip);
|
db.span_suggestion(right.span, "use the right value directly", rsnip);
|
||||||
|
@ -4,11 +4,11 @@ use rustc::hir::map::Node::{NodeExpr, NodeStmt};
|
|||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::middle::expr_use_visitor::*;
|
use rustc::middle::expr_use_visitor::*;
|
||||||
use rustc::middle::mem_categorization::{cmt, Categorization};
|
use rustc::middle::mem_categorization::{cmt, Categorization};
|
||||||
use rustc::ty;
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::util::nodemap::NodeSet;
|
use rustc::util::nodemap::NodeSet;
|
||||||
use syntax::ast::NodeId;
|
use syntax::ast::NodeId;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::span_lint;
|
use utils::{span_lint, type_size};
|
||||||
|
|
||||||
pub struct Pass {
|
pub struct Pass {
|
||||||
pub too_large_for_stack: u64,
|
pub too_large_for_stack: u64,
|
||||||
@ -37,14 +37,13 @@ declare_lint! {
|
|||||||
"using `Box<T>` where unnecessary"
|
"using `Box<T>` where unnecessary"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_non_trait_box(ty: ty::Ty) -> bool {
|
fn is_non_trait_box(ty: Ty) -> bool {
|
||||||
ty.is_box() && !ty.boxed_ty().is_trait()
|
ty.is_box() && !ty.boxed_ty().is_trait()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EscapeDelegate<'a, 'tcx: 'a> {
|
struct EscapeDelegate<'a, 'tcx: 'a> {
|
||||||
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
set: NodeSet,
|
set: NodeSet,
|
||||||
tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
too_large_for_stack: u64,
|
too_large_for_stack: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,19 +64,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||||||
node_id: NodeId
|
node_id: NodeId
|
||||||
) {
|
) {
|
||||||
let fn_def_id = cx.tcx.hir.local_def_id(node_id);
|
let fn_def_id = cx.tcx.hir.local_def_id(node_id);
|
||||||
let param_env = cx.tcx.param_env(fn_def_id).reveal_all();
|
|
||||||
let mut v = EscapeDelegate {
|
let mut v = EscapeDelegate {
|
||||||
|
cx: cx,
|
||||||
set: NodeSet(),
|
set: NodeSet(),
|
||||||
tcx: cx.tcx,
|
|
||||||
param_env: param_env,
|
|
||||||
too_large_for_stack: self.too_large_for_stack,
|
too_large_for_stack: self.too_large_for_stack,
|
||||||
};
|
};
|
||||||
|
|
||||||
cx.tcx.infer_ctxt(body.id()).enter(|infcx| {
|
let region_maps = &cx.tcx.region_maps(fn_def_id);
|
||||||
let region_maps = &cx.tcx.region_maps(fn_def_id);
|
ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_maps, cx.tables)
|
||||||
let mut vis = ExprUseVisitor::new(&mut v, region_maps, &infcx, param_env);
|
.consume_body(body);
|
||||||
vis.consume_body(body);
|
|
||||||
});
|
|
||||||
|
|
||||||
for node in v.set {
|
for node in v.set {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
@ -88,7 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx: 'tcx, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'gcx> {
|
impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
|
||||||
fn consume(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, mode: ConsumeMode) {
|
fn consume(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, mode: ConsumeMode) {
|
||||||
if let Categorization::Local(lid) = cmt.cat {
|
if let Categorization::Local(lid) = cmt.cat {
|
||||||
if let Move(DirectRefMove) = mode {
|
if let Move(DirectRefMove) = mode {
|
||||||
@ -99,7 +94,7 @@ impl<'a, 'gcx: 'tcx, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'gcx> {
|
|||||||
}
|
}
|
||||||
fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {}
|
fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {}
|
||||||
fn consume_pat(&mut self, consume_pat: &Pat, cmt: cmt<'tcx>, _: ConsumeMode) {
|
fn consume_pat(&mut self, consume_pat: &Pat, cmt: cmt<'tcx>, _: ConsumeMode) {
|
||||||
let map = &self.tcx.hir;
|
let map = &self.cx.tcx.hir;
|
||||||
if map.is_argument(consume_pat.id) {
|
if map.is_argument(consume_pat.id) {
|
||||||
// Skip closure arguments
|
// Skip closure arguments
|
||||||
if let Some(NodeExpr(..)) = map.find(map.get_parent_node(consume_pat.id)) {
|
if let Some(NodeExpr(..)) = map.find(map.get_parent_node(consume_pat.id)) {
|
||||||
@ -172,18 +167,14 @@ impl<'a, 'gcx: 'tcx, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'gcx> {
|
|||||||
fn mutate(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: MutateMode) {}
|
fn mutate(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: MutateMode) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx: 'a> EscapeDelegate<'a, 'tcx> {
|
impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
|
||||||
fn is_large_box(&self, ty: ty::Ty) -> bool {
|
fn is_large_box(&self, ty: Ty<'tcx>) -> bool {
|
||||||
// Large types need to be boxed to avoid stack
|
// Large types need to be boxed to avoid stack
|
||||||
// overflows.
|
// overflows.
|
||||||
if ty.is_box() {
|
if ty.is_box() {
|
||||||
if let Some(inner) = self.tcx.lift(&ty.boxed_ty()) {
|
type_size(self.cx, ty.boxed_ty()).unwrap_or(0) > self.too_large_for_stack
|
||||||
if let Ok(layout) = inner.layout(self.tcx, self.param_env) {
|
} else {
|
||||||
return layout.size(self.tcx).bytes() > self.too_large_for_stack;
|
false
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::map::Node::NodeItem;
|
use rustc::hir::map::Node::NodeItem;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::ty::TypeVariants;
|
use rustc::ty;
|
||||||
use syntax::ast::LitKind;
|
use syntax::ast::LitKind;
|
||||||
use syntax::symbol::InternedString;
|
use syntax::symbol::InternedString;
|
||||||
use utils::paths;
|
use utils::paths;
|
||||||
@ -132,7 +132,7 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool {
|
|||||||
], {
|
], {
|
||||||
let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0]));
|
let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0]));
|
||||||
|
|
||||||
return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &paths::STRING);
|
return ty.sty == ty::TyStr || match_type(cx, ty, &paths::STRING);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
false
|
false
|
||||||
|
@ -7,7 +7,7 @@ use rustc::hir::map::Node::NodeBlock;
|
|||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::middle::const_val::ConstVal;
|
use rustc::middle::const_val::ConstVal;
|
||||||
use rustc::middle::region::CodeExtent;
|
use rustc::middle::region::CodeExtent;
|
||||||
use rustc::ty;
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty::subst::Subst;
|
use rustc::ty::subst::Subst;
|
||||||
use rustc_const_eval::ConstContext;
|
use rustc_const_eval::ConstContext;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -985,7 +985,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool {
|
|||||||
match_type(cx, ty, &paths::BTREESET)
|
match_type(cx, ty, &paths::BTREESET)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_iterable_array(ty: ty::Ty) -> bool {
|
fn is_iterable_array(ty: Ty) -> bool {
|
||||||
// IntoIterator is currently only implemented for array sizes <= 32 in rustc
|
// IntoIterator is currently only implemented for array sizes <= 32 in rustc
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyArray(_, 0...32) => true,
|
ty::TyArray(_, 0...32) => true,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::middle::const_val::ConstVal;
|
use rustc::middle::const_val::ConstVal;
|
||||||
use rustc::ty;
|
use rustc::ty::{self, Ty};
|
||||||
use rustc_const_eval::ConstContext;
|
use rustc_const_eval::ConstContext;
|
||||||
use rustc_const_math::ConstInt;
|
use rustc_const_math::ConstInt;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@ -231,7 +231,7 @@ fn check_single_match_opt_like(
|
|||||||
ex: &Expr,
|
ex: &Expr,
|
||||||
arms: &[Arm],
|
arms: &[Arm],
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
ty: ty::Ty,
|
ty: Ty,
|
||||||
els: Option<&Expr>
|
els: Option<&Expr>
|
||||||
) {
|
) {
|
||||||
// list of candidate Enums we know will never get any more members
|
// list of candidate Enums we know will never get any more members
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::middle::const_val::ConstVal;
|
use rustc::middle::const_val::ConstVal;
|
||||||
use rustc::ty;
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::hir::def::Def;
|
use rustc::hir::def::Def;
|
||||||
use rustc_const_eval::ConstContext;
|
use rustc_const_eval::ConstContext;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
@ -659,7 +659,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||||||
// check conventions w.r.t. conversion method names and predicates
|
// check conventions w.r.t. conversion method names and predicates
|
||||||
let def_id = cx.tcx.hir.local_def_id(item.id);
|
let def_id = cx.tcx.hir.local_def_id(item.id);
|
||||||
let ty = cx.tcx.type_of(def_id);
|
let ty = cx.tcx.type_of(def_id);
|
||||||
let is_copy = is_copy(cx, ty, def_id);
|
let is_copy = is_copy(cx, ty);
|
||||||
for &(ref conv, self_kinds) in &CONVENTIONS {
|
for &(ref conv, self_kinds) in &CONVENTIONS {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
conv.check(&name.as_str()),
|
conv.check(&name.as_str()),
|
||||||
@ -684,9 +684,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let ret_ty = return_ty(cx, implitem.id);
|
let ret_ty = return_ty(cx, implitem.id);
|
||||||
let implitem_defid = cx.tcx.hir.local_def_id(implitem.id);
|
|
||||||
if name == "new" &&
|
if name == "new" &&
|
||||||
!ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem_defid)) {
|
!ret_ty.walk().any(|t| same_tys(cx, t, ty)) {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
NEW_RET_NO_SELF,
|
NEW_RET_NO_SELF,
|
||||||
implitem.span,
|
implitem.span,
|
||||||
@ -725,7 +724,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir:
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if implements_trait(cx, arg_ty, default_trait_id, &[], None) {
|
if implements_trait(cx, arg_ty, default_trait_id, &[]) {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
OR_FUN_CALL,
|
OR_FUN_CALL,
|
||||||
span,
|
span,
|
||||||
@ -820,9 +819,8 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Checks for the `CLONE_ON_COPY` lint.
|
/// Checks for the `CLONE_ON_COPY` lint.
|
||||||
fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_ty: ty::Ty) {
|
fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_ty: Ty) {
|
||||||
let ty = cx.tables.expr_ty(expr);
|
let ty = cx.tables.expr_ty(expr);
|
||||||
let parent = cx.tcx.hir.get_parent(expr.id);
|
|
||||||
if let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = arg_ty.sty {
|
if let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = arg_ty.sty {
|
||||||
if let ty::TyRef(..) = inner.sty {
|
if let ty::TyRef(..) = inner.sty {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
@ -839,7 +837,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_copy(cx, ty, cx.tcx.hir.local_def_id(parent)) {
|
if is_copy(cx, ty) {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
CLONE_ON_COPY,
|
CLONE_ON_COPY,
|
||||||
expr.span,
|
expr.span,
|
||||||
@ -979,8 +977,8 @@ fn lint_iter_skip_next(cx: &LateContext, expr: &hir::Expr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: ty::Ty) -> Option<sugg::Sugg<'static>> {
|
fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option<sugg::Sugg<'static>> {
|
||||||
fn may_slice(cx: &LateContext, ty: ty::Ty) -> bool {
|
fn may_slice(cx: &LateContext, ty: Ty) -> bool {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TySlice(_) => true,
|
ty::TySlice(_) => true,
|
||||||
ty::TyAdt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
|
ty::TyAdt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
|
||||||
@ -1253,7 +1251,7 @@ fn lint_single_char_pattern(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Given a `Result<T, E>` type, return its error type (`E`).
|
/// Given a `Result<T, E>` type, return its error type (`E`).
|
||||||
fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> {
|
fn get_error_type<'a>(cx: &LateContext, ty: Ty<'a>) -> Option<Ty<'a>> {
|
||||||
if let ty::TyAdt(_, substs) = ty.sty {
|
if let ty::TyAdt(_, substs) = ty.sty {
|
||||||
if match_type(cx, ty, &paths::RESULT) {
|
if match_type(cx, ty, &paths::RESULT) {
|
||||||
substs.types().nth(1)
|
substs.types().nth(1)
|
||||||
@ -1266,9 +1264,9 @@ fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option<ty::Ty<'a>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This checks whether a given type is known to implement Debug.
|
/// This checks whether a given type is known to implement Debug.
|
||||||
fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool {
|
fn has_debug_impl<'a, 'b>(ty: Ty<'a>, cx: &LateContext<'b, 'a>) -> bool {
|
||||||
match cx.tcx.lang_items.debug_trait() {
|
match cx.tcx.lang_items.debug_trait() {
|
||||||
Some(debug) => implements_trait(cx, ty, debug, &[], None),
|
Some(debug) => implements_trait(cx, ty, debug, &[]),
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -455,13 +455,13 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) {
|
|||||||
// *arg impls PartialEq<other>
|
// *arg impls PartialEq<other>
|
||||||
if !arg_ty
|
if !arg_ty
|
||||||
.builtin_deref(true, ty::LvaluePreference::NoPreference)
|
.builtin_deref(true, ty::LvaluePreference::NoPreference)
|
||||||
.map_or(false, |tam| implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty], None))
|
.map_or(false, |tam| implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty]))
|
||||||
// arg impls PartialEq<*other>
|
// arg impls PartialEq<*other>
|
||||||
&& !other_ty
|
&& !other_ty
|
||||||
.builtin_deref(true, ty::LvaluePreference::NoPreference)
|
.builtin_deref(true, ty::LvaluePreference::NoPreference)
|
||||||
.map_or(false, |tam| implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty], None))
|
.map_or(false, |tam| implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty]))
|
||||||
// arg impls PartialEq<other>
|
// arg impls PartialEq<other>
|
||||||
&& !implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty], None) {
|
&& !implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,13 +514,11 @@ fn in_attributes_expansion(expr: &Expr) -> bool {
|
|||||||
/// Test whether `def` is a variable defined outside a macro.
|
/// Test whether `def` is a variable defined outside a macro.
|
||||||
fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool {
|
fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool {
|
||||||
match *def {
|
match *def {
|
||||||
def::Def::Local(id) |
|
def::Def::Local(def_id) |
|
||||||
def::Def::Upvar(id, _, _) => {
|
def::Def::Upvar(def_id, _, _) => {
|
||||||
if let Some(span) = cx.tcx.hir.span_if_local(id) {
|
let id = cx.tcx.hir.as_local_node_id(def_id)
|
||||||
!in_macro(span)
|
.expect("local variables should be found in the same crate");
|
||||||
} else {
|
!in_macro(cx.tcx.hir.span(id))
|
||||||
true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::intravisit;
|
use rustc::hir::intravisit;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::ty::{TypeAndMut, TyRef};
|
use rustc::ty;
|
||||||
use utils::{higher, in_external_macro, span_lint};
|
use utils::{higher, in_external_macro, span_lint};
|
||||||
|
|
||||||
/// **What it does:** Checks for instances of `mut mut` references.
|
/// **What it does:** Checks for instances of `mut mut` references.
|
||||||
@ -68,7 +68,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
|
|||||||
MUT_MUT,
|
MUT_MUT,
|
||||||
expr.span,
|
expr.span,
|
||||||
"generally you want to avoid `&mut &mut _` if possible");
|
"generally you want to avoid `&mut &mut _` if possible");
|
||||||
} else if let TyRef(_, TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tables.expr_ty(e).sty {
|
} else if let ty::TyRef(_, ty::TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tables.expr_ty(e).sty {
|
||||||
span_lint(self.cx,
|
span_lint(self.cx,
|
||||||
MUT_MUT,
|
MUT_MUT,
|
||||||
expr.span,
|
expr.span,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::ty::{TypeAndMut, TypeVariants, TyS};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty::subst::Subst;
|
use rustc::ty::subst::Subst;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use utils::span_lint;
|
use utils::span_lint;
|
||||||
@ -55,15 +55,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_arguments(cx: &LateContext, arguments: &[Expr], type_definition: &TyS, name: &str) {
|
fn check_arguments(cx: &LateContext, arguments: &[Expr], type_definition: Ty, name: &str) {
|
||||||
match type_definition.sty {
|
match type_definition.sty {
|
||||||
TypeVariants::TyFnDef(_, _, fn_type) |
|
ty::TyFnDef(_, _, fn_type) |
|
||||||
TypeVariants::TyFnPtr(fn_type) => {
|
ty::TyFnPtr(fn_type) => {
|
||||||
let parameters = fn_type.skip_binder().inputs();
|
let parameters = fn_type.skip_binder().inputs();
|
||||||
for (argument, parameter) in arguments.iter().zip(parameters.iter()) {
|
for (argument, parameter) in arguments.iter().zip(parameters.iter()) {
|
||||||
match parameter.sty {
|
match parameter.sty {
|
||||||
TypeVariants::TyRef(_, TypeAndMut { mutbl: MutImmutable, .. }) |
|
ty::TyRef(_, ty::TypeAndMut { mutbl: MutImmutable, .. }) |
|
||||||
TypeVariants::TyRawPtr(TypeAndMut { mutbl: MutImmutable, .. }) => {
|
ty::TyRawPtr(ty::TypeAndMut { mutbl: MutImmutable, .. }) => {
|
||||||
if let ExprAddrOf(MutMutable, _) = argument.node {
|
if let ExprAddrOf(MutMutable, _) = argument.node {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
UNNECESSARY_MUT_PASSED,
|
UNNECESSARY_MUT_PASSED,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//! This lint is **warn** by default
|
//! This lint is **warn** by default
|
||||||
|
|
||||||
use rustc::lint::{LintPass, LintArray, LateLintPass, LateContext};
|
use rustc::lint::{LintPass, LintArray, LateLintPass, LateContext};
|
||||||
use rustc::ty;
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::hir::Expr;
|
use rustc::hir::Expr;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use utils::{match_type, paths, span_lint};
|
use utils::{match_type, paths, span_lint};
|
||||||
@ -59,12 +59,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic {
|
|||||||
let ty = cx.tables.expr_ty(expr);
|
let ty = cx.tables.expr_ty(expr);
|
||||||
if let ty::TyAdt(_, subst) = ty.sty {
|
if let ty::TyAdt(_, subst) = ty.sty {
|
||||||
if match_type(cx, ty, &paths::MUTEX) {
|
if match_type(cx, ty, &paths::MUTEX) {
|
||||||
let mutex_param = &subst.type_at(0).sty;
|
let mutex_param = subst.type_at(0);
|
||||||
if let Some(atomic_name) = get_atomic_name(mutex_param) {
|
if let Some(atomic_name) = get_atomic_name(mutex_param) {
|
||||||
let msg = format!("Consider using an {} instead of a Mutex here. If you just want the locking \
|
let msg = format!("Consider using an {} instead of a Mutex here. If you just want the locking \
|
||||||
behaviour and not the internal type, consider using Mutex<()>.",
|
behaviour and not the internal type, consider using Mutex<()>.",
|
||||||
atomic_name);
|
atomic_name);
|
||||||
match *mutex_param {
|
match mutex_param.sty {
|
||||||
ty::TyUint(t) if t != ast::UintTy::Us => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
|
ty::TyUint(t) if t != ast::UintTy::Us => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
|
||||||
ty::TyInt(t) if t != ast::IntTy::Is => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
|
ty::TyInt(t) if t != ast::IntTy::Is => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
|
||||||
_ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg),
|
_ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg),
|
||||||
@ -75,8 +75,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_atomic_name(ty: &ty::TypeVariants) -> Option<(&'static str)> {
|
fn get_atomic_name(ty: Ty) -> Option<(&'static str)> {
|
||||||
match *ty {
|
match ty.sty {
|
||||||
ty::TyBool => Some("AtomicBool"),
|
ty::TyBool => Some("AtomicBool"),
|
||||||
ty::TyUint(_) => Some("AtomicUsize"),
|
ty::TyUint(_) => Some("AtomicUsize"),
|
||||||
ty::TyInt(_) => Some("AtomicIsize"),
|
ty::TyInt(_) => Some("AtomicIsize"),
|
||||||
|
@ -82,8 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
|
|||||||
let fn_def_id = cx.tcx.hir.local_def_id(node_id);
|
let fn_def_id = cx.tcx.hir.local_def_id(node_id);
|
||||||
|
|
||||||
let preds: Vec<ty::Predicate> = {
|
let preds: Vec<ty::Predicate> = {
|
||||||
let parameter_env = cx.tcx.param_env(fn_def_id);
|
traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.to_vec())
|
||||||
traits::elaborate_predicates(cx.tcx, parameter_env.caller_bounds.to_vec())
|
|
||||||
.filter(|p| !p.is_global())
|
.filter(|p| !p.is_global())
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
@ -91,12 +90,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
|
|||||||
// Collect moved variables and spans which will need dereferencings from the function body.
|
// Collect moved variables and spans which will need dereferencings from the function body.
|
||||||
let MovedVariablesCtxt { moved_vars, spans_need_deref, .. } = {
|
let MovedVariablesCtxt { moved_vars, spans_need_deref, .. } = {
|
||||||
let mut ctx = MovedVariablesCtxt::new(cx);
|
let mut ctx = MovedVariablesCtxt::new(cx);
|
||||||
cx.tcx.infer_ctxt(body.id()).enter(|infcx| {
|
let region_maps = &cx.tcx.region_maps(fn_def_id);
|
||||||
let param_env = cx.tcx.param_env(fn_def_id);
|
euv::ExprUseVisitor::new(&mut ctx, cx.tcx, cx.param_env, region_maps, cx.tables)
|
||||||
let region_maps = &cx.tcx.region_maps(fn_def_id);
|
.consume_body(body);
|
||||||
euv::ExprUseVisitor::new(&mut ctx, region_maps, &infcx, param_env)
|
|
||||||
.consume_body(body);
|
|
||||||
});
|
|
||||||
ctx
|
ctx
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -119,9 +115,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
|
|||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
!is_self(arg),
|
!is_self(arg),
|
||||||
!ty.is_mutable_pointer(),
|
!ty.is_mutable_pointer(),
|
||||||
!is_copy(cx, ty, fn_def_id),
|
!is_copy(cx, ty),
|
||||||
!implements_trait(cx, ty, fn_trait, &[], Some(node_id)),
|
!implements_trait(cx, ty, fn_trait, &[]),
|
||||||
!implements_trait(cx, ty, asref_trait, &[], Some(node_id)),
|
!implements_trait(cx, ty, asref_trait, &[]),
|
||||||
!implements_borrow_trait,
|
!implements_borrow_trait,
|
||||||
|
|
||||||
let PatKind::Binding(mode, defid, ..) = arg.pat.node,
|
let PatKind::Binding(mode, defid, ..) = arg.pat.node,
|
||||||
@ -190,7 +186,7 @@ struct MovedVariablesCtxt<'a, 'tcx: 'a> {
|
|||||||
spans_need_deref: HashMap<DefId, HashSet<Span>>,
|
spans_need_deref: HashMap<DefId, HashSet<Span>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx: 'a> MovedVariablesCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> {
|
||||||
fn new(cx: &'a LateContext<'a, 'tcx>) -> Self {
|
fn new(cx: &'a LateContext<'a, 'tcx>) -> Self {
|
||||||
MovedVariablesCtxt {
|
MovedVariablesCtxt {
|
||||||
cx: cx,
|
cx: cx,
|
||||||
@ -199,7 +195,7 @@ impl<'a, 'tcx: 'a> MovedVariablesCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_common(&mut self, _consume_id: NodeId, _span: Span, cmt: mc::cmt) {
|
fn move_common(&mut self, _consume_id: NodeId, _span: Span, cmt: mc::cmt<'tcx>) {
|
||||||
let cmt = unwrap_downcast_or_interior(cmt);
|
let cmt = unwrap_downcast_or_interior(cmt);
|
||||||
|
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
@ -210,7 +206,7 @@ impl<'a, 'tcx: 'a> MovedVariablesCtxt<'a, 'tcx> {
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn non_moving_pat(&mut self, matched_pat: &Pat, cmt: mc::cmt) {
|
fn non_moving_pat(&mut self, matched_pat: &Pat, cmt: mc::cmt<'tcx>) {
|
||||||
let cmt = unwrap_downcast_or_interior(cmt);
|
let cmt = unwrap_downcast_or_interior(cmt);
|
||||||
|
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
@ -262,7 +258,7 @@ impl<'a, 'tcx: 'a> MovedVariablesCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx: 'tcx, 'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt<'a, 'gcx> {
|
impl<'a, 'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt<'a, 'tcx> {
|
||||||
fn consume(&mut self, consume_id: NodeId, consume_span: Span, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) {
|
fn consume(&mut self, consume_id: NodeId, consume_span: Span, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) {
|
||||||
if let euv::ConsumeMode::Move(_) = mode {
|
if let euv::ConsumeMode::Move(_) = mode {
|
||||||
self.move_common(consume_id, consume_span, cmt);
|
self.move_common(consume_id, consume_span, cmt);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||||
use rustc::ty::TyAdt;
|
use rustc::ty;
|
||||||
use rustc::hir::{Expr, ExprStruct};
|
use rustc::hir::{Expr, ExprStruct};
|
||||||
use utils::span_lint;
|
use utils::span_lint;
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let ExprStruct(_, ref fields, Some(ref base)) = expr.node {
|
if let ExprStruct(_, ref fields, Some(ref base)) = expr.node {
|
||||||
let ty = cx.tables.expr_ty(expr);
|
let ty = cx.tables.expr_ty(expr);
|
||||||
if let TyAdt(def, _) = ty.sty {
|
if let ty::TyAdt(def, _) = ty.sty {
|
||||||
if fields.len() == def.struct_variant().fields.len() {
|
if fields.len() == def.struct_variant().fields.len() {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
NEEDLESS_UPDATE,
|
NEEDLESS_UPDATE,
|
||||||
|
@ -2,7 +2,7 @@ use rustc::hir::intravisit::FnKind;
|
|||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::ty;
|
use rustc::ty::{self, Ty};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::paths;
|
use utils::paths;
|
||||||
@ -108,15 +108,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
|
|||||||
// can't be implemented by default
|
// can't be implemented by default
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let def_id = cx.tcx.hir.local_def_id(id);
|
|
||||||
if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {
|
if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {
|
||||||
let self_ty = cx.tcx
|
let self_ty = cx.tcx
|
||||||
.type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)));
|
.type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)));
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics
|
same_tys(cx, self_ty, return_ty(cx, id)),
|
||||||
same_tys(cx, self_ty, return_ty(cx, id), def_id),
|
|
||||||
let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT),
|
let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT),
|
||||||
!implements_trait(cx, self_ty, default_trait_id, &[], None)
|
!implements_trait(cx, self_ty, default_trait_id, &[])
|
||||||
], {
|
], {
|
||||||
if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
|
if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
@ -152,16 +150,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_derive_default<'t, 'c>(ty: ty::Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> Option<Span> {
|
fn can_derive_default<'t, 'c>(ty: Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> Option<Span> {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyAdt(adt_def, substs) if adt_def.is_struct() => {
|
ty::TyAdt(adt_def, substs) if adt_def.is_struct() => {
|
||||||
for field in adt_def.all_fields() {
|
for field in adt_def.all_fields() {
|
||||||
let f_ty = field.ty(cx.tcx, substs);
|
let f_ty = field.ty(cx.tcx, substs);
|
||||||
if !implements_trait(cx, f_ty, default_trait_id, &[], None) {
|
if !implements_trait(cx, f_ty, default_trait_id, &[]) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cx.tcx.hir.span_if_local(adt_def.did)
|
Some(cx.tcx.def_span(adt_def.did))
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -49,10 +49,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ShouldAssertEq {
|
|||||||
let ty1 = cx.tables.expr_ty(expr1);
|
let ty1 = cx.tables.expr_ty(expr1);
|
||||||
let ty2 = cx.tables.expr_ty(expr2);
|
let ty2 = cx.tables.expr_ty(expr2);
|
||||||
|
|
||||||
let parent = cx.tcx.hir.get_parent(e.id);
|
if implements_trait(cx, ty1, debug_trait, &[]) &&
|
||||||
|
implements_trait(cx, ty2, debug_trait, &[]) {
|
||||||
if implements_trait(cx, ty1, debug_trait, &[], Some(parent)) &&
|
|
||||||
implements_trait(cx, ty2, debug_trait, &[], Some(parent)) {
|
|
||||||
span_lint(cx, SHOULD_ASSERT_EQ, e.span, &format!("use `{}{}` for better reporting", debug, sugg));
|
span_lint(cx, SHOULD_ASSERT_EQ, e.span, &format!("use `{}{}` for better reporting", debug, sugg));
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::ty::TypeVariants::{TyRawPtr, TyRef};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty;
|
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use utils::{match_def_path, paths, span_lint, span_lint_and_then, snippet, last_path_segment};
|
use utils::{match_def_path, paths, span_lint, span_lint_and_then, snippet, last_path_segment};
|
||||||
use utils::sugg;
|
use utils::sugg;
|
||||||
@ -101,7 +100,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||||||
e.span,
|
e.span,
|
||||||
&format!("transmute from a type (`{}`) to itself", from_ty))
|
&format!("transmute from a type (`{}`) to itself", from_ty))
|
||||||
},
|
},
|
||||||
(&TyRef(_, rty), &TyRawPtr(ptr_ty)) => {
|
(&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
USELESS_TRANSMUTE,
|
USELESS_TRANSMUTE,
|
||||||
e.span,
|
e.span,
|
||||||
@ -116,8 +115,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||||||
db.span_suggestion(e.span, "try", sugg.to_string());
|
db.span_suggestion(e.span, "try", sugg.to_string());
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
(&ty::TyInt(_), &TyRawPtr(_)) |
|
(&ty::TyInt(_), &ty::TyRawPtr(_)) |
|
||||||
(&ty::TyUint(_), &TyRawPtr(_)) => {
|
(&ty::TyUint(_), &ty::TyRawPtr(_)) => {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
USELESS_TRANSMUTE,
|
USELESS_TRANSMUTE,
|
||||||
e.span,
|
e.span,
|
||||||
@ -128,16 +127,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||||||
arg.as_ty(&to_ty.to_string()).to_string());
|
arg.as_ty(&to_ty.to_string()).to_string());
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
(&ty::TyFloat(_), &TyRef(..)) |
|
(&ty::TyFloat(_), &ty::TyRef(..)) |
|
||||||
(&ty::TyFloat(_), &TyRawPtr(_)) |
|
(&ty::TyFloat(_), &ty::TyRawPtr(_)) |
|
||||||
(&ty::TyChar, &TyRef(..)) |
|
(&ty::TyChar, &ty::TyRef(..)) |
|
||||||
(&ty::TyChar, &TyRawPtr(_)) => {
|
(&ty::TyChar, &ty::TyRawPtr(_)) => {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
WRONG_TRANSMUTE,
|
WRONG_TRANSMUTE,
|
||||||
e.span,
|
e.span,
|
||||||
&format!("transmute from a `{}` to a pointer", from_ty))
|
&format!("transmute from a `{}` to a pointer", from_ty))
|
||||||
},
|
},
|
||||||
(&TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => {
|
(&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
CROSSPOINTER_TRANSMUTE,
|
CROSSPOINTER_TRANSMUTE,
|
||||||
e.span,
|
e.span,
|
||||||
@ -145,7 +144,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||||||
from_ty,
|
from_ty,
|
||||||
to_ty))
|
to_ty))
|
||||||
},
|
},
|
||||||
(_, &TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => {
|
(_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
CROSSPOINTER_TRANSMUTE,
|
CROSSPOINTER_TRANSMUTE,
|
||||||
e.span,
|
e.span,
|
||||||
@ -153,7 +152,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||||||
from_ty,
|
from_ty,
|
||||||
to_ty))
|
to_ty))
|
||||||
},
|
},
|
||||||
(&TyRawPtr(from_pty), &TyRef(_, to_rty)) => {
|
(&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_rty)) => {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
TRANSMUTE_PTR_TO_REF,
|
TRANSMUTE_PTR_TO_REF,
|
||||||
e.span,
|
e.span,
|
||||||
@ -189,7 +188,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||||||
/// Get the snippet of `Bar` in `…::transmute<Foo, &Bar>`. If that snippet is not available , use
|
/// Get the snippet of `Bar` in `…::transmute<Foo, &Bar>`. If that snippet is not available , use
|
||||||
/// the type's `ToString` implementation. In weird cases it could lead to types with invalid `'_`
|
/// the type's `ToString` implementation. In weird cases it could lead to types with invalid `'_`
|
||||||
/// lifetime, but it should be rare.
|
/// lifetime, but it should be rare.
|
||||||
fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: ty::Ty) -> String {
|
fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: Ty) -> String {
|
||||||
let seg = last_path_segment(path);
|
let seg = last_path_segment(path);
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
let PathParameters::AngleBracketedParameters(ref ang) = seg.parameters,
|
let PathParameters::AngleBracketedParameters(ref ang) = seg.parameters,
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use reexport::*;
|
use reexport::*;
|
||||||
|
use rustc::hir;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::intravisit::{FnKind, Visitor, walk_ty, NestedVisitorMap};
|
use rustc::hir::intravisit::{FnKind, Visitor, walk_ty, NestedVisitorMap};
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::ty;
|
use rustc::ty::{self, Ty};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use syntax::ast::{IntTy, UintTy, FloatTy};
|
use syntax::ast::{IntTy, UintTy, FloatTy};
|
||||||
use syntax::attr::IntType;
|
use syntax::attr::IntType;
|
||||||
@ -106,7 +107,7 @@ fn check_fn_decl(cx: &LateContext, decl: &FnDecl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_ty(cx: &LateContext, ast_ty: &Ty) {
|
fn check_ty(cx: &LateContext, ast_ty: &hir::Ty) {
|
||||||
if in_macro(ast_ty.span) {
|
if in_macro(ast_ty.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -196,8 +197,7 @@ declare_lint! {
|
|||||||
|
|
||||||
fn check_let_unit(cx: &LateContext, decl: &Decl) {
|
fn check_let_unit(cx: &LateContext, decl: &Decl) {
|
||||||
if let DeclLocal(ref local) = decl.node {
|
if let DeclLocal(ref local) = decl.node {
|
||||||
let bindtype = &cx.tables.pat_ty(&local.pat).sty;
|
match cx.tables.pat_ty(&local.pat).sty {
|
||||||
match *bindtype {
|
|
||||||
ty::TyTuple(slice, _) if slice.is_empty() => {
|
ty::TyTuple(slice, _) if slice.is_empty() => {
|
||||||
if in_external_macro(cx, decl.span) || in_macro(local.pat.span) {
|
if in_external_macro(cx, decl.span) || in_macro(local.pat.span) {
|
||||||
return;
|
return;
|
||||||
@ -267,8 +267,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp {
|
|||||||
if let ExprBinary(ref cmp, ref left, _) = expr.node {
|
if let ExprBinary(ref cmp, ref left, _) = expr.node {
|
||||||
let op = cmp.node;
|
let op = cmp.node;
|
||||||
if op.is_comparison() {
|
if op.is_comparison() {
|
||||||
let sty = &cx.tables.expr_ty(left).sty;
|
match cx.tables.expr_ty(left).sty {
|
||||||
match *sty {
|
|
||||||
ty::TyTuple(slice, _) if slice.is_empty() => {
|
ty::TyTuple(slice, _) if slice.is_empty() => {
|
||||||
let result = match op {
|
let result = match op {
|
||||||
BiEq | BiLe | BiGe => "true",
|
BiEq | BiLe | BiGe => "true",
|
||||||
@ -398,7 +397,7 @@ declare_lint! {
|
|||||||
|
|
||||||
/// Returns the size in bits of an integral type.
|
/// Returns the size in bits of an integral type.
|
||||||
/// Will return 0 if the type is not an int or uint variant
|
/// Will return 0 if the type is not an int or uint variant
|
||||||
fn int_ty_to_nbits(typ: &ty::TyS) -> usize {
|
fn int_ty_to_nbits(typ: Ty) -> usize {
|
||||||
let n = match typ.sty {
|
let n = match typ.sty {
|
||||||
ty::TyInt(i) => 4 << (i as usize),
|
ty::TyInt(i) => 4 << (i as usize),
|
||||||
ty::TyUint(u) => 4 << (u as usize),
|
ty::TyUint(u) => 4 << (u as usize),
|
||||||
@ -412,7 +411,7 @@ fn int_ty_to_nbits(typ: &ty::TyS) -> usize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_isize_or_usize(typ: &ty::TyS) -> bool {
|
fn is_isize_or_usize(typ: Ty) -> bool {
|
||||||
match typ.sty {
|
match typ.sty {
|
||||||
ty::TyInt(IntTy::Is) |
|
ty::TyInt(IntTy::Is) |
|
||||||
ty::TyUint(UintTy::Us) => true,
|
ty::TyUint(UintTy::Us) => true,
|
||||||
@ -420,7 +419,7 @@ fn is_isize_or_usize(typ: &ty::TyS) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to_f64: bool) {
|
fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_to_f64: bool) {
|
||||||
let mantissa_nbits = if cast_to_f64 { 52 } else { 23 };
|
let mantissa_nbits = if cast_to_f64 { 52 } else { 23 };
|
||||||
let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64;
|
let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64;
|
||||||
let arch_dependent_str = "on targets with 64-bit wide pointers ";
|
let arch_dependent_str = "on targets with 64-bit wide pointers ";
|
||||||
@ -453,7 +452,7 @@ enum ArchSuffix {
|
|||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to: &ty::TyS) {
|
fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_to: Ty) {
|
||||||
let arch_64_suffix = " on targets with 64-bit wide pointers";
|
let arch_64_suffix = " on targets with 64-bit wide pointers";
|
||||||
let arch_32_suffix = " on targets with 32-bit wide pointers";
|
let arch_32_suffix = " on targets with 32-bit wide pointers";
|
||||||
let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed();
|
let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed();
|
||||||
@ -693,7 +692,7 @@ impl<'a, 'tcx> TypeComplexityPass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_type(&self, cx: &LateContext, ty: &Ty) {
|
fn check_type(&self, cx: &LateContext, ty: &hir::Ty) {
|
||||||
if in_macro(ty.span) {
|
if in_macro(ty.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -724,7 +723,7 @@ struct TypeComplexityVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
|
impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
|
||||||
fn visit_ty(&mut self, ty: &'tcx Ty) {
|
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
|
||||||
let (add_score, sub_nest) = match ty.node {
|
let (add_score, sub_nest) = match ty.node {
|
||||||
// _, &x and *x have only small overhead; don't mess with nesting level
|
// _, &x and *x have only small overhead; don't mess with nesting level
|
||||||
TyInfer | TyPtr(..) | TyRptr(..) => (1, 0),
|
TyInfer | TyPtr(..) | TyRptr(..) => (1, 0),
|
||||||
@ -909,9 +908,9 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
|
|||||||
use rustc_const_eval::*;
|
use rustc_const_eval::*;
|
||||||
use types::ExtremeType::*;
|
use types::ExtremeType::*;
|
||||||
|
|
||||||
let ty = &cx.tables.expr_ty(expr).sty;
|
let ty = cx.tables.expr_ty(expr);
|
||||||
|
|
||||||
match *ty {
|
match ty.sty {
|
||||||
ty::TyBool | ty::TyInt(_) | ty::TyUint(_) => (),
|
ty::TyBool | ty::TyInt(_) | ty::TyUint(_) => (),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
@ -921,7 +920,7 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
|
|||||||
Err(_) => return None,
|
Err(_) => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let which = match (ty, cv) {
|
let which = match (&ty.sty, cv) {
|
||||||
(&ty::TyBool, Bool(false)) |
|
(&ty::TyBool, Bool(false)) |
|
||||||
(&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) |
|
(&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) |
|
||||||
(&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) |
|
(&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) |
|
||||||
@ -1070,7 +1069,6 @@ impl Ord for FullInt {
|
|||||||
|
|
||||||
|
|
||||||
fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(FullInt, FullInt)> {
|
fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(FullInt, FullInt)> {
|
||||||
use rustc::ty::TypeVariants::{TyInt, TyUint};
|
|
||||||
use syntax::ast::{IntTy, UintTy};
|
use syntax::ast::{IntTy, UintTy};
|
||||||
use std::*;
|
use std::*;
|
||||||
|
|
||||||
@ -1082,7 +1080,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
match pre_cast_ty.sty {
|
match pre_cast_ty.sty {
|
||||||
TyInt(int_ty) => {
|
ty::TyInt(int_ty) => {
|
||||||
Some(match int_ty {
|
Some(match int_ty {
|
||||||
IntTy::I8 => (FullInt::S(i8::min_value() as i128), FullInt::S(i8::max_value() as i128)),
|
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::I16 => (FullInt::S(i16::min_value() as i128), FullInt::S(i16::max_value() as i128)),
|
||||||
@ -1092,7 +1090,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(
|
|||||||
IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)),
|
IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
TyUint(uint_ty) => {
|
ty::TyUint(uint_ty) => {
|
||||||
Some(match uint_ty {
|
Some(match uint_ty {
|
||||||
UintTy::U8 => (FullInt::U(u8::min_value() as u128), FullInt::U(u8::max_value() as u128)),
|
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::U16 => (FullInt::U(u16::min_value() as u128), FullInt::U(u16::max_value() as u128)),
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
use reexport::*;
|
use reexport::*;
|
||||||
|
use rustc::hir;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
|
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||||
use rustc::hir::def::Def;
|
use rustc::hir::def::Def;
|
||||||
use rustc::hir::map::Node;
|
use rustc::hir::map::Node;
|
||||||
use rustc::lint::{LintContext, LateContext, Level, Lint};
|
use rustc::lint::{LintContext, LateContext, Level, Lint};
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc::traits::Reveal;
|
|
||||||
use rustc::traits;
|
use rustc::traits;
|
||||||
use rustc::ty::subst::{Subst, Substs};
|
use rustc::ty::{self, TyCtxt, Ty};
|
||||||
use rustc::ty;
|
|
||||||
use rustc::mir::transform::MirSource;
|
use rustc::mir::transform::MirSource;
|
||||||
use rustc_errors;
|
use rustc_errors;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
@ -25,12 +24,12 @@ use syntax::symbol::keywords;
|
|||||||
pub mod comparisons;
|
pub mod comparisons;
|
||||||
pub mod conf;
|
pub mod conf;
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
mod hir;
|
mod hir_utils;
|
||||||
pub mod paths;
|
pub mod paths;
|
||||||
pub mod sugg;
|
pub mod sugg;
|
||||||
pub mod inspector;
|
pub mod inspector;
|
||||||
pub mod internal_lints;
|
pub mod internal_lints;
|
||||||
pub use self::hir::{SpanlessEq, SpanlessHash};
|
pub use self::hir_utils::{SpanlessEq, SpanlessHash};
|
||||||
|
|
||||||
pub type MethodArgs = HirVec<P<Expr>>;
|
pub type MethodArgs = HirVec<P<Expr>>;
|
||||||
|
|
||||||
@ -148,7 +147,7 @@ pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool {
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// See also the `paths` module.
|
/// See also the `paths` module.
|
||||||
pub fn match_def_path(tcx: ty::TyCtxt, def_id: DefId, path: &[&str]) -> bool {
|
pub fn match_def_path(tcx: TyCtxt, def_id: DefId, path: &[&str]) -> bool {
|
||||||
use syntax::symbol;
|
use syntax::symbol;
|
||||||
|
|
||||||
struct AbsolutePathBuffer {
|
struct AbsolutePathBuffer {
|
||||||
@ -174,7 +173,7 @@ pub fn match_def_path(tcx: ty::TyCtxt, def_id: DefId, path: &[&str]) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check if type is struct, enum or union type with given def path.
|
/// Check if type is struct, enum or union type with given def path.
|
||||||
pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool {
|
pub fn match_type(cx: &LateContext, ty: Ty, path: &[&str]) -> bool {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyAdt(adt, _) => match_def_path(cx.tcx, adt.did, path),
|
ty::TyAdt(adt, _) => match_def_path(cx.tcx, adt.did, path),
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -310,22 +309,14 @@ pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option<DefId> {
|
|||||||
/// See also `get_trait_def_id`.
|
/// See also `get_trait_def_id`.
|
||||||
pub fn implements_trait<'a, 'tcx>(
|
pub fn implements_trait<'a, 'tcx>(
|
||||||
cx: &LateContext<'a, 'tcx>,
|
cx: &LateContext<'a, 'tcx>,
|
||||||
ty: ty::Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
trait_id: DefId,
|
trait_id: DefId,
|
||||||
ty_params: &[ty::Ty<'tcx>],
|
ty_params: &[Ty<'tcx>]
|
||||||
parent_node_id: Option<NodeId>
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let ty = cx.tcx.erase_regions(&ty);
|
let ty = cx.tcx.erase_regions(&ty);
|
||||||
let param_env = if let Some(id) = parent_node_id {
|
let obligation = cx.tcx.predicate_for_trait_def(
|
||||||
let def_id = cx.tcx.hir.body_owner_def_id(BodyId { node_id: id });
|
cx.param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params);
|
||||||
cx.tcx.param_env(def_id).reveal_all()
|
cx.tcx.infer_ctxt().enter(|infcx| {
|
||||||
} else {
|
|
||||||
ty::ParamEnv::empty(Reveal::All)
|
|
||||||
};
|
|
||||||
cx.tcx.infer_ctxt(()).enter(|infcx| {
|
|
||||||
let obligation = cx.tcx.predicate_for_trait_def(
|
|
||||||
param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params);
|
|
||||||
|
|
||||||
traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation)
|
traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -591,7 +582,7 @@ pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: Vec<(S
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the base type for references and raw pointers.
|
/// Return the base type for references and raw pointers.
|
||||||
pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty {
|
pub fn walk_ptrs_ty(ty: Ty) -> Ty {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyRef(_, ref tm) => walk_ptrs_ty(tm.ty),
|
ty::TyRef(_, ref tm) => walk_ptrs_ty(tm.ty),
|
||||||
_ => ty,
|
_ => ty,
|
||||||
@ -599,8 +590,8 @@ pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the base type for references and raw pointers, and count reference depth.
|
/// Return the base type for references and raw pointers, and count reference depth.
|
||||||
pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) {
|
pub fn walk_ptrs_ty_depth(ty: Ty) -> (Ty, usize) {
|
||||||
fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) {
|
fn inner(ty: Ty, depth: usize) -> (Ty, usize) {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyRef(_, ref tm) => inner(tm.ty, depth + 1),
|
ty::TyRef(_, ref tm) => inner(tm.ty, depth + 1),
|
||||||
_ => (ty, depth),
|
_ => (ty, depth),
|
||||||
@ -764,7 +755,7 @@ pub fn camel_case_from(s: &str) -> usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function to get the return type of a function
|
/// Convenience function to get the return type of a function
|
||||||
pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> ty::Ty<'tcx> {
|
pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Ty<'tcx> {
|
||||||
let fn_def_id = cx.tcx.hir.local_def_id(fn_item);
|
let fn_def_id = cx.tcx.hir.local_def_id(fn_item);
|
||||||
let ret_ty = cx.tcx.type_of(fn_def_id).fn_sig().output();
|
let ret_ty = cx.tcx.type_of(fn_def_id).fn_sig().output();
|
||||||
cx.tcx.erase_late_bound_regions(&ret_ty)
|
cx.tcx.erase_late_bound_regions(&ret_ty)
|
||||||
@ -775,18 +766,16 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> ty::T
|
|||||||
// not for type parameters.
|
// not for type parameters.
|
||||||
pub fn same_tys<'a, 'tcx>(
|
pub fn same_tys<'a, 'tcx>(
|
||||||
cx: &LateContext<'a, 'tcx>,
|
cx: &LateContext<'a, 'tcx>,
|
||||||
a: ty::Ty<'tcx>,
|
a: Ty<'tcx>,
|
||||||
b: ty::Ty<'tcx>,
|
b: Ty<'tcx>
|
||||||
parameter_item: DefId
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let param_env = cx.tcx.param_env(parameter_item).reveal_all();
|
cx.tcx.infer_ctxt().enter(|infcx| {
|
||||||
cx.tcx.infer_ctxt(()).enter(|infcx| {
|
infcx.can_eq(cx.param_env, a, b).is_ok()
|
||||||
infcx.can_eq(param_env, a, b).is_ok()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return whether the given type is an `unsafe` function.
|
/// Return whether the given type is an `unsafe` function.
|
||||||
pub fn type_is_unsafe_function(ty: ty::Ty) -> bool {
|
pub fn type_is_unsafe_function(ty: Ty) -> bool {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyFnDef(_, _, f) |
|
ty::TyFnDef(_, _, f) |
|
||||||
ty::TyFnPtr(f) => f.unsafety() == Unsafety::Unsafe,
|
ty::TyFnPtr(f) => f.unsafety() == Unsafety::Unsafe,
|
||||||
@ -794,10 +783,8 @@ pub fn type_is_unsafe_function(ty: ty::Ty) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, env: DefId) -> bool {
|
pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
let substs = Substs::identity_for_item(cx.tcx, env);
|
!ty.moves_by_default(cx.tcx.global_tcx(), cx.param_env, DUMMY_SP)
|
||||||
let env = cx.tcx.param_env(env);
|
|
||||||
!ty.subst(cx.tcx, substs).moves_by_default(cx.tcx.global_tcx(), env, DUMMY_SP)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return whether a pattern is refutable.
|
/// Return whether a pattern is refutable.
|
||||||
@ -899,7 +886,7 @@ pub fn is_self(slf: &Arg) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_self_ty(slf: &Ty) -> bool {
|
pub fn is_self_ty(slf: &hir::Ty) -> bool {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let TyPath(ref qp) = slf.node,
|
let TyPath(ref qp) = slf.node,
|
||||||
let QPath::Resolved(None, ref path) = *qp,
|
let QPath::Resolved(None, ref path) = *qp,
|
||||||
@ -958,7 +945,6 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>) -> Option<u64> {
|
pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option<u64> {
|
||||||
ty.layout(cx.tcx, ty::ParamEnv::empty(Reveal::All))
|
ty.layout(cx.tcx, cx.param_env).ok().map(|layout| layout.size(cx.tcx).bytes())
|
||||||
.ok().map(|layout| layout.size(cx.tcx).bytes())
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::ty;
|
use rustc::ty::{self, Ty};
|
||||||
use rustc_const_eval::ConstContext;
|
use rustc_const_eval::ConstContext;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::{higher, is_copy, snippet, span_lint_and_then};
|
use utils::{higher, is_copy, snippet, span_lint_and_then};
|
||||||
@ -35,8 +35,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
// search for `&vec![_]` expressions where the adjusted type is `&[_]`
|
// search for `&vec![_]` expressions where the adjusted type is `&[_]`
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
let ty::TypeVariants::TyRef(_, ref ty) = cx.tables.expr_ty_adjusted(expr).sty,
|
let ty::TyRef(_, ref ty) = cx.tables.expr_ty_adjusted(expr).sty,
|
||||||
let ty::TypeVariants::TySlice(..) = ty.ty.sty,
|
let ty::TySlice(..) = ty.ty.sty,
|
||||||
let ExprAddrOf(_, ref addressee) = expr.node,
|
let ExprAddrOf(_, ref addressee) = expr.node,
|
||||||
let Some(vec_args) = higher::vec_macro(cx, addressee),
|
let Some(vec_args) = higher::vec_macro(cx, addressee),
|
||||||
], {
|
], {
|
||||||
@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
let Some((_, arg, _)) = higher::for_loop(expr),
|
let Some((_, arg, _)) = higher::for_loop(expr),
|
||||||
let Some(vec_args) = higher::vec_macro(cx, arg),
|
let Some(vec_args) = higher::vec_macro(cx, arg),
|
||||||
is_copy(cx, vec_type(cx.tables.expr_ty_adjusted(arg)), cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(expr.id))),
|
is_copy(cx, vec_type(cx.tables.expr_ty_adjusted(arg))),
|
||||||
], {
|
], {
|
||||||
// report the error around the `vec!` not inside `<std macros>:`
|
// report the error around the `vec!` not inside `<std macros>:`
|
||||||
let span = arg.span.ctxt.outer().expn_info().map(|info| info.call_site).expect("unable to get call_site");
|
let span = arg.span.ctxt.outer().expn_info().map(|info| info.call_site).expect("unable to get call_site");
|
||||||
@ -88,7 +88,7 @@ fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the item type of the vector (ie. the `T` in `Vec<T>`).
|
/// Return the item type of the vector (ie. the `T` in `Vec<T>`).
|
||||||
fn vec_type(ty: ty::Ty) -> ty::Ty {
|
fn vec_type(ty: Ty) -> Ty {
|
||||||
if let ty::TyAdt(_, substs) = ty.sty {
|
if let ty::TyAdt(_, substs) = ty.sty {
|
||||||
substs.type_at(0)
|
substs.type_at(0)
|
||||||
} else {
|
} else {
|
||||||
|
@ -166,6 +166,14 @@ error: manual implementation of an assign operation
|
|||||||
|
|
|
|
||||||
= note: `-D assign-op-pattern` implied by `-D warnings`
|
= note: `-D assign-op-pattern` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: manual implementation of an assign operation
|
||||||
|
--> assign_ops.rs:40:5
|
||||||
|
|
|
||||||
|
40 | s = s + "bla";
|
||||||
|
| ^^^^^^^^^^^^^ help: replace it with `s += "bla"`
|
||||||
|
|
|
||||||
|
= note: `-D assign-op-pattern` implied by `-D warnings`
|
||||||
|
|
||||||
error: aborting due to previous error(s)
|
error: aborting due to previous error(s)
|
||||||
|
|
||||||
error: Could not compile `clippy_tests`.
|
error: Could not compile `clippy_tests`.
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
error: manual implementation of an assign operation
|
||||||
|
--> strings.rs:10:9
|
||||||
|
|
|
||||||
|
10 | x = x + ".";
|
||||||
|
| ^^^^^^^^^^^ help: replace it with `x += "."`
|
||||||
|
|
|
||||||
|
= note: `-D assign-op-pattern` implied by `-D warnings`
|
||||||
|
|
||||||
error: you added something to a string. Consider using `String::push_str()` instead
|
error: you added something to a string. Consider using `String::push_str()` instead
|
||||||
--> strings.rs:10:13
|
--> strings.rs:10:13
|
||||||
|
|
|
|
||||||
@ -22,6 +30,14 @@ error: you assigned the result of adding something to this string. Consider usin
|
|||||||
|
|
|
|
||||||
= note: `-D string-add-assign` implied by `-D warnings`
|
= note: `-D string-add-assign` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: manual implementation of an assign operation
|
||||||
|
--> strings.rs:24:9
|
||||||
|
|
|
||||||
|
24 | x = x + ".";
|
||||||
|
| ^^^^^^^^^^^ help: replace it with `x += "."`
|
||||||
|
|
|
||||||
|
= note: `-D assign-op-pattern` implied by `-D warnings`
|
||||||
|
|
||||||
error: you assigned the result of adding something to this string. Consider using `String::push_str()` instead
|
error: you assigned the result of adding something to this string. Consider using `String::push_str()` instead
|
||||||
--> strings.rs:38:9
|
--> strings.rs:38:9
|
||||||
|
|
|
|
||||||
@ -30,6 +46,14 @@ error: you assigned the result of adding something to this string. Consider usin
|
|||||||
|
|
|
|
||||||
= note: `-D string-add-assign` implied by `-D warnings`
|
= note: `-D string-add-assign` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: manual implementation of an assign operation
|
||||||
|
--> strings.rs:38:9
|
||||||
|
|
|
||||||
|
38 | x = x + ".";
|
||||||
|
| ^^^^^^^^^^^ help: replace it with `x += "."`
|
||||||
|
|
|
||||||
|
= note: `-D assign-op-pattern` implied by `-D warnings`
|
||||||
|
|
||||||
error: you added something to a string. Consider using `String::push_str()` instead
|
error: you added something to a string. Consider using `String::push_str()` instead
|
||||||
--> strings.rs:42:13
|
--> strings.rs:42:13
|
||||||
|
|
|
|
||||||
|
Loading…
Reference in New Issue
Block a user