diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index d327d0570f1..8702ec1e716 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -149,7 +149,7 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref } } for subst in substs { - if let Some(subst) = subst.as_type() { + if let ty::subst::UnpackedKind::Type(subst) = subst.unpack() { if let ty::TyParam(_) = subst.sty { return; } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 7f3b176b889..9142ebdbf21 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -377,6 +377,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box question_mark::QuestionMarkPass); reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl); reg.register_late_lint_pass(box redundant_field_names::RedundantFieldNames); + reg.register_late_lint_pass(box misc::BareTraitLate); reg.register_lint_group("clippy_restrictions", vec![ diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 04cc488d562..97bfd3d0c95 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -636,3 +636,61 @@ fn check_cast(cx: &LateContext, span: Span, e: &Expr, ty: &Ty) { } } } + +declare_lint! { + pub BARE_TRAIT_OBJECT, + Warn, + "suggest using `dyn Trait` for trait objects" +} + +#[derive(Copy, Clone)] +pub struct BareTraitLate; + +impl LintPass for BareTraitLate { + fn get_lints(&self) -> LintArray { + lint_array!(BARE_TRAIT_OBJECT) + } +} + +use rustc::hir::intravisit::{walk_ty, NestedVisitorMap, Visitor}; + +struct TraitTyVisitor<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx> +} + +impl<'a, 'tcx> Visitor<'tcx> for TraitTyVisitor<'a, 'tcx> { + fn visit_ty(&mut self, ty: &'tcx Ty) { + println!("{:?}", ty.node); + if let TyPath(ref qpath) = ty.node { + println!("{:?}", qpath); + let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id); + let def = self.cx.tables.qpath_def(qpath, hir_id); + let t = self.cx.tcx.type_of(def.def_id()); + println!("{:?}", t); + if let ty::TyDynamic(..) = t.sty { + let mut err = self.cx.struct_span_lint(BARE_TRAIT_OBJECT, ty.span, + "Trait objects without an explicit `dyn` are deprecated"); + let sugg = match self.cx.tcx.sess.codemap().span_to_snippet(ty.span) { + Ok(s) => format!("dyn {}", s), + Err(_) => format!("dyn ") + }; + err.span_suggestion(ty.span, "use `dyn`", sugg); + err.emit(); + } + } + walk_ty(self, ty) + } + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BareTraitLate { + fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty) { + if !cx.sess().features.borrow().dyn_trait { + return; + } + println!("toplevel {:?}", ty); + TraitTyVisitor { cx }.visit_ty(ty) + } +}