Update for rustc 1.19.0-nightly (4bf5c99af 2017-06-10).

This commit is contained in:
Eduard-Mihai Burtescu
2017-06-11 05:34:47 +03:00
parent 72ed74adfb
commit cd89737b21
15 changed files with 93 additions and 112 deletions

View File

@@ -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,
} }

View File

@@ -136,8 +136,7 @@ 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::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;
} }

View File

@@ -136,7 +136,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
&msg, &msg,
arg.span, arg.span,
&format!("argument has type {}", arg_ty.sty)); &format!("argument has type {}", arg_ty.sty));
} 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();

View File

@@ -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));
} }
} }
} }

View File

@@ -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);

View File

@@ -8,7 +8,7 @@ use rustc::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,
@@ -42,9 +42,8 @@ fn is_non_trait_box(ty: ty::Ty) -> bool {
} }
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);
let mut vis = ExprUseVisitor::new(&mut v, region_maps, &infcx, param_env); ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_maps, cx.tables)
vis.consume_body(body); .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::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
} }
} }
}

View File

@@ -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,
@@ -822,7 +821,6 @@ 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::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,
@@ -1268,7 +1266,7 @@ 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::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,
} }
} }

View File

@@ -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;
} }

View File

@@ -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 param_env = cx.tcx.param_env(fn_def_id);
let region_maps = &cx.tcx.region_maps(fn_def_id); let region_maps = &cx.tcx.region_maps(fn_def_id);
euv::ExprUseVisitor::new(&mut ctx, region_maps, &infcx, param_env) euv::ExprUseVisitor::new(&mut ctx, cx.tcx, cx.param_env, region_maps, cx.tables)
.consume_body(body); .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);

View File

@@ -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,
@@ -157,7 +155,7 @@ fn can_derive_default<'t, 'c>(ty: ty::Ty<'t>, cx: &LateContext<'c, 't>, default_
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;
} }
} }

View File

@@ -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));
} }
}} }}

View File

@@ -5,9 +5,7 @@ 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; use rustc::ty;
use rustc::mir::transform::MirSource; use rustc::mir::transform::MirSource;
use rustc_errors; use rustc_errors;
@@ -312,20 +310,12 @@ pub fn implements_trait<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>, cx: &LateContext<'a, 'tcx>,
ty: ty::Ty<'tcx>, ty: ty::Ty<'tcx>,
trait_id: DefId, trait_id: DefId,
ty_params: &[ty::Ty<'tcx>], ty_params: &[ty::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 def_id = cx.tcx.hir.body_owner_def_id(BodyId { node_id: id });
cx.tcx.param_env(def_id).reveal_all()
} else {
ty::ParamEnv::empty(Reveal::All)
};
cx.tcx.infer_ctxt(()).enter(|infcx| {
let obligation = cx.tcx.predicate_for_trait_def( let obligation = cx.tcx.predicate_for_trait_def(
param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params); cx.param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params);
cx.tcx.infer_ctxt().enter(|infcx| {
traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation)
}) })
} }
@@ -776,12 +766,10 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> ty::T
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::Ty<'tcx>,
b: ty::Ty<'tcx>, b: ty::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()
}) })
} }
@@ -794,10 +782,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::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.
@@ -959,6 +945,5 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> {
} }
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::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())
} }

View File

@@ -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");

View File

@@ -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`.

View File

@@ -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
| |