Skip to content

Don’t warn for types used in trait implementation #1393

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 73 additions & 5 deletions clippy_lints/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,47 @@ impl LintPass for TypePass {
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass {
fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ast_ty: &'tcx Ty) {
if in_macro(cx, ast_ty.span) {
return;
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Expr, _: Span, id: NodeId) {
// skip trait implementations, see #605
if let Some(map::NodeItem(item)) = cx.tcx.map.find(cx.tcx.map.get_parent(id)) {
if let ItemImpl(_, _, _, Some(..), _, _) = item.node {
return;
}
}

check_fn_decl(cx, decl);
}

fn check_struct_field(&mut self, cx: &LateContext, field: &StructField) {
check_ty(cx, &field.ty);
}

fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
match item.node {
ConstTraitItem(ref ty, _) |
TypeTraitItem(_, Some(ref ty)) => check_ty(cx, ty),
MethodTraitItem(ref sig, _) => check_fn_decl(cx, &sig.decl),
_ => (),
}
if let TyPath(ref qpath) = ast_ty.node {
}
}

fn check_fn_decl(cx: &LateContext, decl: &FnDecl) {
for input in &decl.inputs {
check_ty(cx, &input.ty);
}

if let FunctionRetTy::Return(ref ty) = decl.output {
check_ty(cx, ty);
}
}

fn check_ty(cx: &LateContext, ast_ty: &Ty) {
if in_macro(cx, ast_ty.span) {
return;
}
match ast_ty.node {
TyPath(ref qpath) => {
let def = cx.tcx.tables().qpath_def(qpath, ast_ty.id);
if let Some(def_id) = opt_def_id(def) {
if Some(def_id) == cx.tcx.lang_items.owned_box() {
Expand All @@ -92,16 +128,48 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass {
ast_ty.span,
"you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`",
"`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation.");
return; // don't recurse into the type
}}
} else if match_def_path(cx, def_id, &paths::LINKED_LIST) {
span_help_and_lint(cx,
LINKEDLIST,
ast_ty.span,
"I see you're using a LinkedList! Perhaps you meant some other data structure?",
"a VecDeque might work");
return; // don't recurse into the type
}
}
}
match *qpath {
QPath::Resolved(Some(ref ty), ref p) => {
check_ty(cx, ty);
for ty in p.segments.iter().flat_map(|seg| seg.parameters.types()) {
check_ty(cx, ty);
}
},
QPath::Resolved(None, ref p) => {
for ty in p.segments.iter().flat_map(|seg| seg.parameters.types()) {
check_ty(cx, ty);
}
},
QPath::TypeRelative(ref ty, ref seg) => {
check_ty(cx, ty);
for ty in seg.parameters.types() {
check_ty(cx, ty);
}
},
}
},
// recurse
TySlice(ref ty) |
TyArray(ref ty, _) |
TyPtr(MutTy { ref ty, .. }) |
TyRptr(_, MutTy { ref ty, .. }) => check_ty(cx, ty),
TyTup(ref tys) => {
for ty in tys {
check_ty(cx, ty);
}
},
_ => {},
}
}

Expand Down
29 changes: 27 additions & 2 deletions tests/compile-fail/dlist.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
#![feature(plugin, collections)]
#![feature(associated_type_defaults)]
#![feature(associated_consts)]

#![plugin(clippy)]
#![deny(clippy)]
#![allow(dead_code)]

extern crate collections;
use collections::linked_list::LinkedList;

pub fn test(_: LinkedList<u8>) { //~ ERROR I see you're using a LinkedList!
trait Foo {
type Baz = LinkedList<u8>; //~ ERROR I see you're using a LinkedList!
fn foo(LinkedList<u8>); //~ ERROR I see you're using a LinkedList!
const BAR : Option<LinkedList<u8>>; //~ ERROR I see you're using a LinkedList!
}

// ok, we don’t want to warn for implementations, see #605
impl Foo for LinkedList<u8> {
fn foo(_: LinkedList<u8>) {}
const BAR : Option<LinkedList<u8>> = None;
}

struct Bar;
impl Bar {
fn foo(_: LinkedList<u8>) {} //~ ERROR I see you're using a LinkedList!
}

pub fn test(my_favourite_linked_list: LinkedList<u8>) { //~ ERROR I see you're using a LinkedList!
println!("{:?}", my_favourite_linked_list)
}

pub fn test_ret() -> Option<LinkedList<u8>> { //~ ERROR I see you're using a LinkedList!
unimplemented!();
}

fn main(){
test(LinkedList::new()); //~ ERROR I see you're using a LinkedList!
test(LinkedList::new());
}