3 use rustc_front::intravisit::FnKind;
5 use syntax::codemap::Span;
6 use utils::{get_trait_def_id, implements_trait, in_external_macro, returns_self, span_lint, DEFAULT_TRAIT_PATH};
8 /// **What it does:** This lints about type with a `fn new() -> Self` method and no `Default`
11 /// **Why is this bad?** User might expect to be able to use `Default` is the type can be
12 /// constructed without arguments.
14 /// **Known problems:** Hopefully none.
22 /// fn new() -> Self {
28 pub NEW_WITHOUT_DEFAULT,
30 "`fn new() -> Self` method without `Default` implementation"
34 pub struct NewWithoutDefault;
36 impl LintPass for NewWithoutDefault {
37 fn get_lints(&self) -> LintArray {
38 lint_array!(NEW_WITHOUT_DEFAULT)
42 impl LateLintPass for NewWithoutDefault {
43 fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, id: ast::NodeId) {
44 if in_external_macro(cx, span) {
48 if let FnKind::Method(name, _, _) = kind {
49 if decl.inputs.is_empty() && name.as_str() == "new" {
50 let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id))).ty;
52 if returns_self(cx, &decl.output, ty) {
53 if let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH) {
54 if !implements_trait(cx, ty, default_trait_id, Vec::new()) {
55 span_lint(cx, NEW_WITHOUT_DEFAULT, span,
56 &format!("you should consider adding a `Default` implementation for `{}`", ty));