lint on by ref patterns for references

This commit is contained in:
Oliver Schneider 2016-08-01 16:59:14 +02:00
parent 3464532294
commit 81c5757f44
No known key found for this signature in database
GPG key ID: 56D6EEA0FC67AC46
23 changed files with 69 additions and 51 deletions

View file

@ -58,7 +58,7 @@ impl LateLintPass for AttrPass {
if items.is_empty() || name != &"deprecated" {
return;
}
for ref item in items {
for item in items {
if let MetaItemKind::NameValue(ref name, ref lit) = item.node {
if name == &"since" {
check_semver(cx, item.span, lit);

View file

@ -114,7 +114,7 @@ impl LateLintPass for BlockInIfCondition {
} else {
let mut visitor = ExVisitor { found_block: None };
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, "");
}
}

View file

@ -320,7 +320,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
/// A block can only yield a constant if it only has one constant expression
fn block(&mut self, block: &Block) -> Option<Constant> {
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 {
None
}

View file

@ -149,7 +149,7 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref
TypeVariants::TyFnPtr(..) => {
return;
}
TypeVariants::TyTuple(ref tys) if tys.len() > 12 => {
TypeVariants::TyTuple(tys) if tys.len() > 12 => {
return;
}
_ => (),

View file

@ -39,7 +39,7 @@ declare_lint! {
fn is_non_trait_box(ty: ty::Ty) -> bool {
match ty.sty {
ty::TyBox(ref inner) => !inner.is_trait(),
ty::TyBox(inner) => !inner.is_trait(),
_ => 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
// overflows.
match ty.sty {
ty::TyBox(ref inner) => {
ty::TyBox(inner) => {
if let Ok(layout) = inner.layout(self.infcx) {
let size = layout.size(&self.target);
size.bytes() > self.too_large_for_stack

View file

@ -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 {
// XXXManishearth Should I be checking the binding mode here?
if let ExprPath(None, ref p) = a2.node {

View file

@ -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) {
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(..))
} else {
false

View file

@ -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)))
}
ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, &id)),
ty::TyEnum(ref id, _) |
ty::TyStruct(ref id, _) => has_is_empty_impl(cx, &id.did),
ty::TyEnum(id, _) |
ty::TyStruct(id, _) => has_is_empty_impl(cx, &id.did),
ty::TyArray(..) | ty::TyStr => true,
_ => false,
}

View file

@ -60,7 +60,7 @@ impl LintPass for LetIfSeq {
impl LateLintPass for LetIfSeq {
fn check_block(&mut self, cx: &LateContext, block: &hir::Block) {
let mut it = block.stmts.iter().peekable();
while let Some(ref stmt) = it.next() {
while let Some(stmt) = it.next() {
if_let_chain! {[
let Some(expr) = it.peek(),
let hir::StmtDecl(ref decl, _) = stmt.node,

View file

@ -138,7 +138,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
Ok(file_name) => {
// if the user specified a file, it must exist, otherwise default to `clippy.toml` but
// 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)
} else {
("clippy.toml", false)

View file

@ -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.
/// The iteratee must be a range literal.
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
if let PatKind::Binding(_, ref ident, _) = pat.node {
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, ".."))
};
let take = if let Some(ref end) = *end {
let take = if let Some(end) = *end {
if is_len_call(end, &indexed) {
"".to_owned()
} 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) {
// 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...
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) {
@ -873,7 +873,7 @@ fn is_break_expr(expr: &Expr) -> bool {
ExprBreak(None) => true,
ExprBlock(ref b) => {
match extract_first_expr(b) {
Some(ref subexpr) => is_break_expr(subexpr),
Some(subexpr) => is_break_expr(subexpr),
None => false,
}
}

View file

@ -262,7 +262,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
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)) {
(false, false) => {
Some(format!("if {} {} else {}",

View file

@ -674,7 +674,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr) {
/// Checks for the `CLONE_DOUBLE_REF` lint.
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 {
span_lint_and_then(cx,
CLONE_DOUBLE_REF,
@ -694,7 +694,7 @@ fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &MethodArgs) {
return;
}
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| {
db.span_suggestion(expr.span,
"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
fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_mut: bool){
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"
}
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 may_slice(cx: &LateContext, ty: &ty::Ty) -> bool {
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 {
match ty.sty {
ty::TySlice(_) => true,
ty::TyStruct(..) => match_type(cx, ty, &paths::VEC),
ty::TyArray(_, size) => size < 32,
ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) |
ty::TyBox(ref inner) => may_slice(cx, inner),
ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) |
ty::TyBox(inner) => may_slice(cx, inner),
_ => false,
}
}
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.addr()
})
@ -770,8 +770,8 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: &ty::Ty) -> Option<su
} else {
match ty.sty {
ty::TySlice(_) => sugg::Sugg::hir_opt(cx, expr),
ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) |
ty::TyBox(ref inner) => {
ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) |
ty::TyBox(inner) => {
if may_slice(cx, inner) {
sugg::Sugg::hir_opt(cx, expr)
} else {

View file

@ -55,7 +55,7 @@ impl LateLintPass for TopLevelRefPass {
// Does not apply to closures
return;
}
for ref arg in &decl.inputs {
for arg in &decl.inputs {
if let PatKind::Binding(BindByRef(_), _, _) = arg.pat.node {
span_lint(cx,
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
/// of what it means for an expression to be "used".
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 {
ExprAssign(_, ref rhs) |
ExprAssignOp(_, _, ref rhs) => **rhs == *expr,

View file

@ -130,7 +130,7 @@ impl EarlyLintPass for MiscEarly {
fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
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 {
let arg_name = sp_ident.node.to_string();

View file

@ -59,8 +59,8 @@ impl LateLintPass for UnnecessaryMutPassed {
fn check_arguments(cx: &LateContext, arguments: &[P<Expr>], type_definition: &TyS, name: &str) {
match type_definition.sty {
TypeVariants::TyFnDef(_, _, ref fn_type) |
TypeVariants::TyFnPtr(ref fn_type) => {
TypeVariants::TyFnDef(_, _, fn_type) |
TypeVariants::TyFnPtr(fn_type) => {
let parameters = &fn_type.sig.skip_binder().inputs;
for (argument, parameter) in arguments.iter().zip(parameters.iter()) {
match parameter.sty {

View file

@ -3,7 +3,7 @@
//! This lint is **warn** by default
use rustc::lint::*;
use rustc::hir::{ExprAddrOf, Expr, MutImmutable};
use rustc::hir::{ExprAddrOf, Expr, MutImmutable, Pat, PatKind, BindingMode};
use rustc::ty::TyRef;
use utils::{span_lint, in_macro};
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")
}
}
}
}
}
}

View file

@ -95,7 +95,7 @@ impl LateLintPass for NewWithoutDefault {
return;
}
if let FnKind::Method(name, ref sig, _, _) = kind {
if let FnKind::Method(name, sig, _, _) = kind {
if sig.constness == hir::Constness::Const {
// can't be implemented by default
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 {
match ty.sty {
ty::TyStruct(ref adt_def, ref substs) => {
ty::TyStruct(adt_def, substs) => {
for field in adt_def.all_fields() {
let f_ty = field.ty(cx.tcx, substs);
if !implements_trait(cx, f_ty, default_trait_id, Vec::new()) {

View file

@ -161,12 +161,12 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
}
}
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 {
for field in pfields {
let name = field.node.name;
let efield = efields.iter()
.find(|ref f| f.name.node == name)
.find(|f| f.name.node == name)
.map(|f| &*f.expr);
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, _) => {
if let Some(ref init_tup) = *init {
if let Some(init_tup) = *init {
if let ExprTup(ref tup) = init_tup.node {
for (i, p) in inner.iter().enumerate() {
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) => {
if let Some(ref initp) = *init {
if let Some(initp) = *init {
if let ExprBox(ref inner_init) = initp.node {
check_pat(cx, inner, &Some(&**inner_init), span, bindings);
} else {
@ -276,7 +276,7 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) {
// ExprCall
// ExprMethodCall
ExprVec(ref v) | ExprTup(ref v) => {
for ref e in v {
for e in v {
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, _) => {
check_expr(cx, init, bindings);
let len = bindings.len();
for ref arm in arms {
for ref pat in &arm.pats {
for arm in arms {
for pat in &arm.pats {
check_pat(cx, pat, &Some(&**init), pat.span, bindings);
// This is ugly, but needed to get the right type
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, .. }) |
TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings),
TyTup(ref tup) => {
for ref t in tup {
for t in tup {
check_ty(cx, t, bindings)
}
}
@ -335,7 +335,7 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool {
ExprBox(ref inner) |
ExprAddrOf(_, ref inner) => is_self_shadow(name, inner),
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),
ExprPath(_, ref path) => path_eq_name(name, path),

View file

@ -82,7 +82,7 @@ impl LateLintPass for StringAdd {
// the string_add_assign is allow, so no duplicates
} else {
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 {
// avoid duplicate matches
if SpanlessEq::new(cx).eq_expr(target, left) {

View file

@ -55,7 +55,7 @@ impl fmt::Display for Error {
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)
}
Error::UnknownKey(ref key) => write!(f, "unknown key `{}`", key),

View file

@ -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.
pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool {
match ty.sty {
ty::TyEnum(ref adt, _) |
ty::TyStruct(ref adt, _) => match_def_path(cx, adt.did, path),
ty::TyEnum(adt, _) |
ty::TyStruct(adt, _) => match_def_path(cx, adt.did, path),
_ => 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));
if let Some(node) = enclosing_node {
match node {
Node::NodeBlock(ref block) => Some(block),
Node::NodeBlock(block) => Some(block),
Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block),
_ => 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.
pub fn type_is_unsafe_function(ty: ty::Ty) -> bool {
match ty.sty {
ty::TyFnDef(_, _, ref f) |
ty::TyFnPtr(ref f) => f.unsafety == Unsafety::Unsafe,
ty::TyFnDef(_, _, f) |
ty::TyFnPtr(f) => f.unsafety == Unsafety::Unsafe,
_ => false,
}
}

View file

@ -17,6 +17,7 @@ fn main() {
let vec = Vec::new();
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`
if let Some(ref cake) = Some(&5) {} //~ ERROR: this pattern creates a reference to a reference
}
fn f<T:Copy>(y: &T) -> T {