lint on by ref patterns for references
This commit is contained in:
parent
3464532294
commit
81c5757f44
23 changed files with 69 additions and 51 deletions
|
@ -58,7 +58,7 @@ impl LateLintPass for AttrPass {
|
||||||
if items.is_empty() || name != &"deprecated" {
|
if items.is_empty() || name != &"deprecated" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for ref item in items {
|
for item in items {
|
||||||
if let MetaItemKind::NameValue(ref name, ref lit) = item.node {
|
if let MetaItemKind::NameValue(ref name, ref lit) = item.node {
|
||||||
if name == &"since" {
|
if name == &"since" {
|
||||||
check_semver(cx, item.span, lit);
|
check_semver(cx, item.span, lit);
|
||||||
|
|
|
@ -114,7 +114,7 @@ impl LateLintPass for BlockInIfCondition {
|
||||||
} else {
|
} else {
|
||||||
let mut visitor = ExVisitor { found_block: None };
|
let mut visitor = ExVisitor { found_block: None };
|
||||||
walk_expr(&mut visitor, check);
|
walk_expr(&mut visitor, check);
|
||||||
if let Some(ref block) = visitor.found_block {
|
if let Some(block) = visitor.found_block {
|
||||||
span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE, "");
|
span_help_and_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,7 +320,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
|
||||||
/// A block can only yield a constant if it only has one constant expression
|
/// A block can only yield a constant if it only has one constant expression
|
||||||
fn block(&mut self, block: &Block) -> Option<Constant> {
|
fn block(&mut self, block: &Block) -> Option<Constant> {
|
||||||
if block.stmts.is_empty() {
|
if block.stmts.is_empty() {
|
||||||
block.expr.as_ref().and_then(|ref b| self.expr(b))
|
block.expr.as_ref().and_then(|b| self.expr(b))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref
|
||||||
TypeVariants::TyFnPtr(..) => {
|
TypeVariants::TyFnPtr(..) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TypeVariants::TyTuple(ref tys) if tys.len() > 12 => {
|
TypeVariants::TyTuple(tys) if tys.len() > 12 => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
|
@ -39,7 +39,7 @@ declare_lint! {
|
||||||
|
|
||||||
fn is_non_trait_box(ty: ty::Ty) -> bool {
|
fn is_non_trait_box(ty: ty::Ty) -> bool {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyBox(ref inner) => !inner.is_trait(),
|
ty::TyBox(inner) => !inner.is_trait(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,7 @@ impl<'a, 'tcx: 'a+'gcx, 'gcx: 'a> EscapeDelegate<'a, 'tcx, 'gcx> {
|
||||||
// Large types need to be boxed to avoid stack
|
// Large types need to be boxed to avoid stack
|
||||||
// overflows.
|
// overflows.
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyBox(ref inner) => {
|
ty::TyBox(inner) => {
|
||||||
if let Ok(layout) = inner.layout(self.infcx) {
|
if let Ok(layout) = inner.layout(self.infcx) {
|
||||||
let size = layout.size(&self.target);
|
let size = layout.size(&self.target);
|
||||||
size.bytes() > self.too_large_for_stack
|
size.bytes() > self.too_large_for_stack
|
||||||
|
|
|
@ -73,7 +73,7 @@ fn check_closure(cx: &LateContext, expr: &Expr) {
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
for (ref a1, ref a2) in decl.inputs.iter().zip(args) {
|
for (a1, a2) in decl.inputs.iter().zip(args) {
|
||||||
if let PatKind::Binding(_, ident, _) = a1.pat.node {
|
if let PatKind::Binding(_, ident, _) = a1.pat.node {
|
||||||
// XXXManishearth Should I be checking the binding mode here?
|
// XXXManishearth Should I be checking the binding mode here?
|
||||||
if let ExprPath(None, ref p) = a2.node {
|
if let ExprPath(None, ref p) = a2.node {
|
||||||
|
|
|
@ -71,7 +71,7 @@ impl LateLintPass for Functions {
|
||||||
fn check_fn(&mut self, cx: &LateContext, kind: intravisit::FnKind, decl: &hir::FnDecl, block: &hir::Block, span: Span, nodeid: ast::NodeId) {
|
fn check_fn(&mut self, cx: &LateContext, kind: intravisit::FnKind, decl: &hir::FnDecl, block: &hir::Block, span: Span, nodeid: ast::NodeId) {
|
||||||
use rustc::hir::map::Node::*;
|
use rustc::hir::map::Node::*;
|
||||||
|
|
||||||
let is_impl = if let Some(NodeItem(ref item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) {
|
let is_impl = if let Some(NodeItem(item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) {
|
||||||
matches!(item.node, hir::ItemImpl(_, _, _, Some(_), _, _) | hir::ItemDefaultImpl(..))
|
matches!(item.node, hir::ItemImpl(_, _, _, Some(_), _, _) | hir::ItemDefaultImpl(..))
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
|
|
@ -203,8 +203,8 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
|
||||||
.map_or(false, |ids| ids.iter().any(|i| is_is_empty(cx, i)))
|
.map_or(false, |ids| ids.iter().any(|i| is_is_empty(cx, i)))
|
||||||
}
|
}
|
||||||
ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, &id)),
|
ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, &id)),
|
||||||
ty::TyEnum(ref id, _) |
|
ty::TyEnum(id, _) |
|
||||||
ty::TyStruct(ref id, _) => has_is_empty_impl(cx, &id.did),
|
ty::TyStruct(id, _) => has_is_empty_impl(cx, &id.did),
|
||||||
ty::TyArray(..) | ty::TyStr => true,
|
ty::TyArray(..) | ty::TyStr => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ impl LintPass for LetIfSeq {
|
||||||
impl LateLintPass for LetIfSeq {
|
impl LateLintPass for LetIfSeq {
|
||||||
fn check_block(&mut self, cx: &LateContext, block: &hir::Block) {
|
fn check_block(&mut self, cx: &LateContext, block: &hir::Block) {
|
||||||
let mut it = block.stmts.iter().peekable();
|
let mut it = block.stmts.iter().peekable();
|
||||||
while let Some(ref stmt) = it.next() {
|
while let Some(stmt) = it.next() {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let Some(expr) = it.peek(),
|
let Some(expr) = it.peek(),
|
||||||
let hir::StmtDecl(ref decl, _) = stmt.node,
|
let hir::StmtDecl(ref decl, _) = stmt.node,
|
||||||
|
|
|
@ -138,7 +138,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
||||||
Ok(file_name) => {
|
Ok(file_name) => {
|
||||||
// if the user specified a file, it must exist, otherwise default to `clippy.toml` but
|
// if the user specified a file, it must exist, otherwise default to `clippy.toml` but
|
||||||
// do not require the file to exist
|
// do not require the file to exist
|
||||||
let (ref file_name, must_exist) = if let Some(ref file_name) = file_name {
|
let (file_name, must_exist) = if let Some(ref file_name) = file_name {
|
||||||
(&**file_name, true)
|
(&**file_name, true)
|
||||||
} else {
|
} else {
|
||||||
("clippy.toml", false)
|
("clippy.toml", false)
|
||||||
|
|
|
@ -391,7 +391,7 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E
|
||||||
/// Check for looping over a range and then indexing a sequence with it.
|
/// Check for looping over a range and then indexing a sequence with it.
|
||||||
/// The iteratee must be a range literal.
|
/// The iteratee must be a range literal.
|
||||||
fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) {
|
fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) {
|
||||||
if let Some(higher::Range { start: Some(ref start), ref end, limits }) = higher::range(arg) {
|
if let Some(higher::Range { start: Some(start), ref end, limits }) = higher::range(arg) {
|
||||||
// the var must be a single name
|
// the var must be a single name
|
||||||
if let PatKind::Binding(_, ref ident, _) = pat.node {
|
if let PatKind::Binding(_, ref ident, _) = pat.node {
|
||||||
let mut visitor = VarVisitor {
|
let mut visitor = VarVisitor {
|
||||||
|
@ -425,7 +425,7 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex
|
||||||
format!(".skip({})", snippet(cx, start.span, ".."))
|
format!(".skip({})", snippet(cx, start.span, ".."))
|
||||||
};
|
};
|
||||||
|
|
||||||
let take = if let Some(ref end) = *end {
|
let take = if let Some(end) = *end {
|
||||||
if is_len_call(end, &indexed) {
|
if is_len_call(end, &indexed) {
|
||||||
"".to_owned()
|
"".to_owned()
|
||||||
} else {
|
} else {
|
||||||
|
@ -494,7 +494,7 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool {
|
||||||
|
|
||||||
fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) {
|
fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) {
|
||||||
// if this for loop is iterating over a two-sided range...
|
// if this for loop is iterating over a two-sided range...
|
||||||
if let Some(higher::Range { start: Some(ref start), end: Some(ref end), limits }) = higher::range(arg) {
|
if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(arg) {
|
||||||
// ...and both sides are compile-time constant integers...
|
// ...and both sides are compile-time constant integers...
|
||||||
if let Ok(start_idx) = eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None) {
|
if let Ok(start_idx) = eval_const_expr_partial(cx.tcx, start, ExprTypeChecked, None) {
|
||||||
if let Ok(end_idx) = eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None) {
|
if let Ok(end_idx) = eval_const_expr_partial(cx.tcx, end, ExprTypeChecked, None) {
|
||||||
|
@ -873,7 +873,7 @@ fn is_break_expr(expr: &Expr) -> bool {
|
||||||
ExprBreak(None) => true,
|
ExprBreak(None) => true,
|
||||||
ExprBlock(ref b) => {
|
ExprBlock(ref b) => {
|
||||||
match extract_first_expr(b) {
|
match extract_first_expr(b) {
|
||||||
Some(ref subexpr) => is_break_expr(subexpr),
|
Some(subexpr) => is_break_expr(subexpr),
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,7 +262,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((ref true_expr, ref false_expr)) = exprs {
|
if let Some((true_expr, false_expr)) = exprs {
|
||||||
let sugg = match (is_unit_expr(true_expr), is_unit_expr(false_expr)) {
|
let sugg = match (is_unit_expr(true_expr), is_unit_expr(false_expr)) {
|
||||||
(false, false) => {
|
(false, false) => {
|
||||||
Some(format!("if {} {} else {}",
|
Some(format!("if {} {} else {}",
|
||||||
|
|
|
@ -674,7 +674,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr) {
|
||||||
|
|
||||||
/// Checks for the `CLONE_DOUBLE_REF` lint.
|
/// Checks for the `CLONE_DOUBLE_REF` lint.
|
||||||
fn lint_clone_double_ref(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, ty: ty::Ty) {
|
fn lint_clone_double_ref(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, ty: ty::Ty) {
|
||||||
if let ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) = ty.sty {
|
if let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = ty.sty {
|
||||||
if let ty::TyRef(..) = inner.sty {
|
if let ty::TyRef(..) = inner.sty {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
CLONE_DOUBLE_REF,
|
CLONE_DOUBLE_REF,
|
||||||
|
@ -694,7 +694,7 @@ fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &MethodArgs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let arg_ty = cx.tcx.expr_ty(&args[1]);
|
let arg_ty = cx.tcx.expr_ty(&args[1]);
|
||||||
if let Some(slice) = derefs_to_slice(cx, &args[1], &arg_ty) {
|
if let Some(slice) = derefs_to_slice(cx, &args[1], arg_ty) {
|
||||||
span_lint_and_then(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice", |db| {
|
span_lint_and_then(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice", |db| {
|
||||||
db.span_suggestion(expr.span,
|
db.span_suggestion(expr.span,
|
||||||
"try this",
|
"try this",
|
||||||
|
@ -725,7 +725,7 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr
|
||||||
// Type of MethodArgs is potentially a Vec
|
// Type of MethodArgs is potentially a Vec
|
||||||
fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_mut: bool){
|
fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_mut: bool){
|
||||||
let mut_str = if is_mut { "_mut" } else {""};
|
let mut_str = if is_mut { "_mut" } else {""};
|
||||||
let caller_type = if let Some(_) = derefs_to_slice(cx, &iter_args[0], &cx.tcx.expr_ty(&iter_args[0])) {
|
let caller_type = if let Some(_) = derefs_to_slice(cx, &iter_args[0], cx.tcx.expr_ty(&iter_args[0])) {
|
||||||
"slice"
|
"slice"
|
||||||
}
|
}
|
||||||
else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC) {
|
else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC) {
|
||||||
|
@ -747,20 +747,20 @@ fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
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::Ty) -> Option<sugg::Sugg<'static>> {
|
||||||
fn may_slice(cx: &LateContext, ty: &ty::Ty) -> bool {
|
fn may_slice(cx: &LateContext, ty: ty::Ty) -> bool {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TySlice(_) => true,
|
ty::TySlice(_) => true,
|
||||||
ty::TyStruct(..) => match_type(cx, ty, &paths::VEC),
|
ty::TyStruct(..) => match_type(cx, ty, &paths::VEC),
|
||||||
ty::TyArray(_, size) => size < 32,
|
ty::TyArray(_, size) => size < 32,
|
||||||
ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) |
|
ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) |
|
||||||
ty::TyBox(ref inner) => may_slice(cx, inner),
|
ty::TyBox(inner) => may_slice(cx, inner),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let hir::ExprMethodCall(name, _, ref args) = expr.node {
|
if let hir::ExprMethodCall(name, _, ref args) = expr.node {
|
||||||
if &name.node.as_str() == &"iter" && may_slice(cx, &cx.tcx.expr_ty(&args[0])) {
|
if &name.node.as_str() == &"iter" && may_slice(cx, cx.tcx.expr_ty(&args[0])) {
|
||||||
sugg::Sugg::hir_opt(cx, &*args[0]).map(|sugg| {
|
sugg::Sugg::hir_opt(cx, &*args[0]).map(|sugg| {
|
||||||
sugg.addr()
|
sugg.addr()
|
||||||
})
|
})
|
||||||
|
@ -770,8 +770,8 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: &ty::Ty) -> Option<su
|
||||||
} else {
|
} else {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TySlice(_) => sugg::Sugg::hir_opt(cx, expr),
|
ty::TySlice(_) => sugg::Sugg::hir_opt(cx, expr),
|
||||||
ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) |
|
ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) |
|
||||||
ty::TyBox(ref inner) => {
|
ty::TyBox(inner) => {
|
||||||
if may_slice(cx, inner) {
|
if may_slice(cx, inner) {
|
||||||
sugg::Sugg::hir_opt(cx, expr)
|
sugg::Sugg::hir_opt(cx, expr)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -55,7 +55,7 @@ impl LateLintPass for TopLevelRefPass {
|
||||||
// Does not apply to closures
|
// Does not apply to closures
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for ref arg in &decl.inputs {
|
for arg in &decl.inputs {
|
||||||
if let PatKind::Binding(BindByRef(_), _, _) = arg.pat.node {
|
if let PatKind::Binding(BindByRef(_), _, _) = arg.pat.node {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
TOPLEVEL_REF_ARG,
|
TOPLEVEL_REF_ARG,
|
||||||
|
@ -464,7 +464,7 @@ impl LateLintPass for UsedUnderscoreBinding {
|
||||||
/// Heuristic to see if an expression is used. Should be compatible with `unused_variables`'s idea
|
/// Heuristic to see if an expression is used. Should be compatible with `unused_variables`'s idea
|
||||||
/// of what it means for an expression to be "used".
|
/// of what it means for an expression to be "used".
|
||||||
fn is_used(cx: &LateContext, expr: &Expr) -> bool {
|
fn is_used(cx: &LateContext, expr: &Expr) -> bool {
|
||||||
if let Some(ref parent) = get_parent_expr(cx, expr) {
|
if let Some(parent) = get_parent_expr(cx, expr) {
|
||||||
match parent.node {
|
match parent.node {
|
||||||
ExprAssign(_, ref rhs) |
|
ExprAssign(_, ref rhs) |
|
||||||
ExprAssignOp(_, _, ref rhs) => **rhs == *expr,
|
ExprAssignOp(_, _, ref rhs) => **rhs == *expr,
|
||||||
|
|
|
@ -130,7 +130,7 @@ impl EarlyLintPass for MiscEarly {
|
||||||
fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
|
fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
|
||||||
let mut registered_names: HashMap<String, Span> = HashMap::new();
|
let mut registered_names: HashMap<String, Span> = HashMap::new();
|
||||||
|
|
||||||
for ref arg in &decl.inputs {
|
for arg in &decl.inputs {
|
||||||
if let PatKind::Ident(_, sp_ident, None) = arg.pat.node {
|
if let PatKind::Ident(_, sp_ident, None) = arg.pat.node {
|
||||||
let arg_name = sp_ident.node.to_string();
|
let arg_name = sp_ident.node.to_string();
|
||||||
|
|
||||||
|
|
|
@ -59,8 +59,8 @@ impl LateLintPass for UnnecessaryMutPassed {
|
||||||
|
|
||||||
fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &TyS, name: &str) {
|
fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &TyS, name: &str) {
|
||||||
match type_definition.sty {
|
match type_definition.sty {
|
||||||
TypeVariants::TyFnDef(_, _, ref fn_type) |
|
TypeVariants::TyFnDef(_, _, fn_type) |
|
||||||
TypeVariants::TyFnPtr(ref fn_type) => {
|
TypeVariants::TyFnPtr(fn_type) => {
|
||||||
let parameters = &fn_type.sig.skip_binder().inputs;
|
let parameters = &fn_type.sig.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 {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//! This lint is **warn** by default
|
//! This lint is **warn** by default
|
||||||
|
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::hir::{ExprAddrOf, Expr, MutImmutable};
|
use rustc::hir::{ExprAddrOf, Expr, MutImmutable, Pat, PatKind, BindingMode};
|
||||||
use rustc::ty::TyRef;
|
use rustc::ty::TyRef;
|
||||||
use utils::{span_lint, in_macro};
|
use utils::{span_lint, in_macro};
|
||||||
use rustc::ty::adjustment::AutoAdjustment::AdjustDerefRef;
|
use rustc::ty::adjustment::AutoAdjustment::AdjustDerefRef;
|
||||||
|
@ -53,4 +53,21 @@ impl LateLintPass for NeedlessBorrow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
|
||||||
|
if in_macro(cx, pat.span) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let PatKind::Binding(BindingMode::BindByRef(MutImmutable), _, _) = pat.node {
|
||||||
|
if let TyRef(_, ref tam) = cx.tcx.pat_ty(pat).sty {
|
||||||
|
if tam.mutbl == MutImmutable {
|
||||||
|
if let TyRef(..) = tam.ty.sty {
|
||||||
|
span_lint(cx,
|
||||||
|
NEEDLESS_BORROW,
|
||||||
|
pat.span,
|
||||||
|
"this pattern creates a reference to a reference")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ impl LateLintPass for NewWithoutDefault {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let FnKind::Method(name, ref sig, _, _) = kind {
|
if let FnKind::Method(name, sig, _, _) = kind {
|
||||||
if sig.constness == hir::Constness::Const {
|
if sig.constness == hir::Constness::Const {
|
||||||
// can't be implemented by default
|
// can't be implemented by default
|
||||||
return;
|
return;
|
||||||
|
@ -147,7 +147,7 @@ impl LateLintPass for NewWithoutDefault {
|
||||||
|
|
||||||
fn can_derive_default<'t, 'c>(ty: ty::Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> bool {
|
fn can_derive_default<'t, 'c>(ty: ty::Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> bool {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyStruct(ref adt_def, ref substs) => {
|
ty::TyStruct(adt_def, substs) => {
|
||||||
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, Vec::new()) {
|
if !implements_trait(cx, f_ty, default_trait_id, Vec::new()) {
|
||||||
|
|
|
@ -161,12 +161,12 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::Struct(_, ref pfields, _) => {
|
PatKind::Struct(_, ref pfields, _) => {
|
||||||
if let Some(ref init_struct) = *init {
|
if let Some(init_struct) = *init {
|
||||||
if let ExprStruct(_, ref efields, _) = init_struct.node {
|
if let ExprStruct(_, ref efields, _) = init_struct.node {
|
||||||
for field in pfields {
|
for field in pfields {
|
||||||
let name = field.node.name;
|
let name = field.node.name;
|
||||||
let efield = efields.iter()
|
let efield = efields.iter()
|
||||||
.find(|ref f| f.name.node == name)
|
.find(|f| f.name.node == name)
|
||||||
.map(|f| &*f.expr);
|
.map(|f| &*f.expr);
|
||||||
check_pat(cx, &field.node.pat, &efield, span, bindings);
|
check_pat(cx, &field.node.pat, &efield, span, bindings);
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::Tuple(ref inner, _) => {
|
PatKind::Tuple(ref inner, _) => {
|
||||||
if let Some(ref init_tup) = *init {
|
if let Some(init_tup) = *init {
|
||||||
if let ExprTup(ref tup) = init_tup.node {
|
if let ExprTup(ref tup) = init_tup.node {
|
||||||
for (i, p) in inner.iter().enumerate() {
|
for (i, p) in inner.iter().enumerate() {
|
||||||
check_pat(cx, p, &Some(&tup[i]), p.span, bindings);
|
check_pat(cx, p, &Some(&tup[i]), p.span, bindings);
|
||||||
|
@ -199,7 +199,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::Box(ref inner) => {
|
PatKind::Box(ref inner) => {
|
||||||
if let Some(ref initp) = *init {
|
if let Some(initp) = *init {
|
||||||
if let ExprBox(ref inner_init) = initp.node {
|
if let ExprBox(ref inner_init) = initp.node {
|
||||||
check_pat(cx, inner, &Some(&**inner_init), span, bindings);
|
check_pat(cx, inner, &Some(&**inner_init), span, bindings);
|
||||||
} else {
|
} else {
|
||||||
|
@ -276,7 +276,7 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) {
|
||||||
// ExprCall
|
// ExprCall
|
||||||
// ExprMethodCall
|
// ExprMethodCall
|
||||||
ExprVec(ref v) | ExprTup(ref v) => {
|
ExprVec(ref v) | ExprTup(ref v) => {
|
||||||
for ref e in v {
|
for e in v {
|
||||||
check_expr(cx, e, bindings)
|
check_expr(cx, e, bindings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,8 +294,8 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) {
|
||||||
ExprMatch(ref init, ref arms, _) => {
|
ExprMatch(ref init, ref arms, _) => {
|
||||||
check_expr(cx, init, bindings);
|
check_expr(cx, init, bindings);
|
||||||
let len = bindings.len();
|
let len = bindings.len();
|
||||||
for ref arm in arms {
|
for arm in arms {
|
||||||
for ref pat in &arm.pats {
|
for pat in &arm.pats {
|
||||||
check_pat(cx, pat, &Some(&**init), pat.span, bindings);
|
check_pat(cx, pat, &Some(&**init), pat.span, bindings);
|
||||||
// This is ugly, but needed to get the right type
|
// This is ugly, but needed to get the right type
|
||||||
if let Some(ref guard) = arm.guard {
|
if let Some(ref guard) = arm.guard {
|
||||||
|
@ -321,7 +321,7 @@ fn check_ty(cx: &LateContext, ty: &Ty, bindings: &mut Vec<(Name, Span)>) {
|
||||||
TyPtr(MutTy { ty: ref mty, .. }) |
|
TyPtr(MutTy { ty: ref mty, .. }) |
|
||||||
TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings),
|
TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings),
|
||||||
TyTup(ref tup) => {
|
TyTup(ref tup) => {
|
||||||
for ref t in tup {
|
for t in tup {
|
||||||
check_ty(cx, t, bindings)
|
check_ty(cx, t, bindings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -335,7 +335,7 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool {
|
||||||
ExprBox(ref inner) |
|
ExprBox(ref inner) |
|
||||||
ExprAddrOf(_, ref inner) => is_self_shadow(name, inner),
|
ExprAddrOf(_, ref inner) => is_self_shadow(name, inner),
|
||||||
ExprBlock(ref block) => {
|
ExprBlock(ref block) => {
|
||||||
block.stmts.is_empty() && block.expr.as_ref().map_or(false, |ref e| is_self_shadow(name, e))
|
block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e))
|
||||||
}
|
}
|
||||||
ExprUnary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner),
|
ExprUnary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner),
|
||||||
ExprPath(_, ref path) => path_eq_name(name, path),
|
ExprPath(_, ref path) => path_eq_name(name, path),
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl LateLintPass for StringAdd {
|
||||||
// the string_add_assign is allow, so no duplicates
|
// the string_add_assign is allow, so no duplicates
|
||||||
} else {
|
} else {
|
||||||
let parent = get_parent_expr(cx, e);
|
let parent = get_parent_expr(cx, e);
|
||||||
if let Some(ref p) = parent {
|
if let Some(p) = parent {
|
||||||
if let ExprAssign(ref target, _) = p.node {
|
if let ExprAssign(ref target, _) = p.node {
|
||||||
// avoid duplicate matches
|
// avoid duplicate matches
|
||||||
if SpanlessEq::new(cx).eq_expr(target, left) {
|
if SpanlessEq::new(cx).eq_expr(target, left) {
|
||||||
|
|
|
@ -55,7 +55,7 @@ impl fmt::Display for Error {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Error::Type(ref key, ref expected, ref got) => {
|
Error::Type(key, expected, got) => {
|
||||||
write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got)
|
write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got)
|
||||||
}
|
}
|
||||||
Error::UnknownKey(ref key) => write!(f, "unknown key `{}`", key),
|
Error::UnknownKey(ref key) => write!(f, "unknown key `{}`", key),
|
||||||
|
|
|
@ -154,8 +154,8 @@ pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool {
|
||||||
/// Check if type is struct or enum type with given def path.
|
/// Check if type is struct or enum 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::Ty, path: &[&str]) -> bool {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyEnum(ref adt, _) |
|
ty::TyEnum(adt, _) |
|
||||||
ty::TyStruct(ref adt, _) => match_def_path(cx, adt.did, path),
|
ty::TyStruct(adt, _) => match_def_path(cx, adt.did, path),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,7 +427,7 @@ pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c
|
||||||
.and_then(|enclosing_id| map.find(enclosing_id));
|
.and_then(|enclosing_id| map.find(enclosing_id));
|
||||||
if let Some(node) = enclosing_node {
|
if let Some(node) = enclosing_node {
|
||||||
match node {
|
match node {
|
||||||
Node::NodeBlock(ref block) => Some(block),
|
Node::NodeBlock(block) => Some(block),
|
||||||
Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block),
|
Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -719,8 +719,8 @@ pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: ty::Ty<'tcx>, b: ty::Ty
|
||||||
/// 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::Ty) -> bool {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyFnDef(_, _, ref f) |
|
ty::TyFnDef(_, _, f) |
|
||||||
ty::TyFnPtr(ref f) => f.unsafety == Unsafety::Unsafe,
|
ty::TyFnPtr(f) => f.unsafety == Unsafety::Unsafe,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ fn main() {
|
||||||
let vec = Vec::new();
|
let vec = Vec::new();
|
||||||
let vec_val = g(&vec); // should not error, because `&Vec<T>` derefs to `&[T]`
|
let vec_val = g(&vec); // should not error, because `&Vec<T>` derefs to `&[T]`
|
||||||
h(&"foo"); // should not error, because the `&&str` is required, due to `&Trait`
|
h(&"foo"); // should not error, because the `&&str` is required, due to `&Trait`
|
||||||
|
if let Some(ref cake) = Some(&5) {} //~ ERROR: this pattern creates a reference to a reference
|
||||||
}
|
}
|
||||||
|
|
||||||
fn f<T:Copy>(y: &T) -> T {
|
fn f<T:Copy>(y: &T) -> T {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue