Skip to content

Commit 317e97b

Browse files
committed
1 parent e62727e commit 317e97b

File tree

2 files changed

+67
-62
lines changed

2 files changed

+67
-62
lines changed

clippy_lints/src/new_without_default.rs

+61-62
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
use rustc::hir::intravisit::FnKind;
21
use rustc::hir::def_id::DefId;
32
use rustc::hir;
43
use rustc::lint::*;
54
use rustc::ty::{self, Ty};
6-
use syntax::ast;
75
use syntax::codemap::Span;
86
use utils::paths;
97
use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then};
@@ -90,66 +88,67 @@ impl LintPass for NewWithoutDefault {
9088
}
9189

9290
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
93-
fn check_fn(
94-
&mut self,
95-
cx: &LateContext<'a, 'tcx>,
96-
kind: FnKind<'tcx>,
97-
decl: &'tcx hir::FnDecl,
98-
_: &'tcx hir::Body,
99-
span: Span,
100-
id: ast::NodeId,
101-
) {
102-
if in_external_macro(cx, span) {
103-
return;
104-
}
105-
106-
if let FnKind::Method(name, sig, _, _) = kind {
107-
if sig.constness == hir::Constness::Const {
108-
// can't be implemented by default
109-
return;
110-
}
111-
if !cx.generics
112-
.expect("method must have generics")
113-
.ty_params
114-
.is_empty()
115-
{
116-
// when the result of `new()` depends on a type parameter we should not require
117-
// an
118-
// impl of `Default`
119-
return;
120-
}
121-
if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {
122-
let self_ty = cx.tcx
123-
.type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)));
124-
if_chain! {
125-
if same_tys(cx, self_ty, return_ty(cx, id));
126-
if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
127-
if !implements_trait(cx, self_ty, default_trait_id, &[]);
128-
then {
129-
if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
130-
span_lint_and_then(
131-
cx,
132-
NEW_WITHOUT_DEFAULT_DERIVE,
133-
span,
134-
&format!("you should consider deriving a `Default` implementation for `{}`", self_ty),
135-
|db| {
136-
db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]");
137-
});
138-
} else {
139-
span_lint_and_then(
140-
cx,
141-
NEW_WITHOUT_DEFAULT,
142-
span,
143-
&format!("you should consider adding a `Default` implementation for `{}`", self_ty),
144-
|db| {
145-
db.suggest_prepend_item(
146-
cx,
147-
span,
148-
"try this",
149-
&create_new_without_default_suggest_msg(self_ty),
150-
);
151-
},
152-
);
91+
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) {
92+
if let hir::ItemImpl(_, _, _, _, None, _, ref items) = item.node {
93+
for assoc_item in items {
94+
if let hir::AssociatedItemKind::Method { has_self: false } = assoc_item.kind {
95+
let impl_item = cx.tcx.hir.impl_item(assoc_item.id);
96+
if in_external_macro(cx, impl_item.span) {
97+
return;
98+
}
99+
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
100+
let name = impl_item.name;
101+
let span = impl_item.span;
102+
let id = impl_item.id;
103+
let decl = &sig.decl;
104+
if sig.constness == hir::Constness::Const {
105+
// can't be implemented by default
106+
return;
107+
}
108+
if !impl_item.generics
109+
.ty_params
110+
.is_empty()
111+
{
112+
// when the result of `new()` depends on a type parameter we should not require
113+
// an
114+
// impl of `Default`
115+
return;
116+
}
117+
if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {
118+
let self_ty = cx.tcx
119+
.type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)));
120+
if_chain! {
121+
if same_tys(cx, self_ty, return_ty(cx, id));
122+
if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
123+
if !implements_trait(cx, self_ty, default_trait_id, &[]);
124+
then {
125+
if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
126+
span_lint_and_then(
127+
cx,
128+
NEW_WITHOUT_DEFAULT_DERIVE,
129+
span,
130+
&format!("you should consider deriving a `Default` implementation for `{}`", self_ty),
131+
|db| {
132+
db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]");
133+
});
134+
} else {
135+
span_lint_and_then(
136+
cx,
137+
NEW_WITHOUT_DEFAULT,
138+
span,
139+
&format!("you should consider adding a `Default` implementation for `{}`", self_ty),
140+
|db| {
141+
db.suggest_prepend_item(
142+
cx,
143+
span,
144+
"try this",
145+
&create_new_without_default_suggest_msg(self_ty),
146+
);
147+
},
148+
);
149+
}
150+
}
151+
}
153152
}
154153
}
155154
}

tests/ui/new_without_default.rs

+6
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,10 @@ impl IgnoreGenericNew {
8383
pub fn new<T>() -> Self { IgnoreGenericNew } // the derived Default does not make sense here as the result depends on T
8484
}
8585

86+
pub trait TraitWithNew: Sized {
87+
fn new() -> Self {
88+
panic!()
89+
}
90+
}
91+
8692
fn main() {}

0 commit comments

Comments
 (0)