clippy 0.0.6

A bunch of helpful lints to avoid common pitfalls in Rust
//! Checks for usage of &Vec[_] and &String
//!
//! This lint is **warn** by default

use rustc::plugin::Registry;
use rustc::lint::*;
use rustc::middle::const_eval::lookup_const_by_id;
use rustc::middle::def::*;
use syntax::ast::*;
use syntax::ast_util::{is_comparison_binop, binop_to_string};
use syntax::ptr::P;
use syntax::codemap::Span;
use types::match_ty_unwrap;

declare_lint! {
    pub PTR_ARG,
    Allow,
    "Warn on declaration of a &Vec- or &String-typed method argument"
}

#[derive(Copy,Clone)]
pub struct PtrArg;

impl LintPass for PtrArg {
    fn get_lints(&self) -> LintArray {
        lint_array!(PTR_ARG)
    }
    
    fn check_item(&mut self, cx: &Context, item: &Item) {
		if let &ItemFn(ref decl, _, _, _, _, _) = &item.node {
			check_fn(cx, decl);
		}
	}
    
    fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) { 
		if let &MethodImplItem(ref sig, _) = &item.node {
			check_fn(cx, &sig.decl);
		}
	}
        
	fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) {
		if let &MethodTraitItem(ref sig, _) = &item.node {
			check_fn(cx, &sig.decl);
		}
	}
}

fn check_fn(cx: &Context, decl: &FnDecl) {
	for arg in &decl.inputs {
		match &arg.ty.node {
			&TyPtr(ref p) | &TyRptr(_, ref p) => 
				check_ptr_subtype(cx, arg.ty.span, &p.ty),
			_ => ()
		}
	}
}

fn check_ptr_subtype(cx: &Context, span: Span, ty: &Ty) {
	match_ty_unwrap(ty, &["Vec"]).map_or_else(|| match_ty_unwrap(ty, 
			&["String"]).map_or((), |_| {
		cx.span_lint(PTR_ARG, span,
			"Writing '&String' instead of '&str' involves a new Object \
			where a slices will do. Consider changing the type to &str")
	}), |_| cx.span_lint(PTR_ARG, span, "Writing '&Vec<_>' instead of \
			'&[_]' involves one more reference and cannot be used with \
			non-vec-based slices. Consider changing the type to &[...]")
	)
}