From: Niko Matsakis Date: Wed, 16 Mar 2016 19:53:08 +0000 (-0400) Subject: rewrite foreign types lint not to trawl the HIR X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=c74339052d990fa28472be60fab10eb9f0258b42;p=rust.git rewrite foreign types lint not to trawl the HIR It no longer reads from `ast_ty_to_ty_cache`, which was very wrong. It also correctly handles higher-ranked regions. --- diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 4d844bbf032..1a84afab86b 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -29,7 +29,6 @@ use syntax::codemap::{self, Span}; use rustc_front::hir; -use rustc_front::intravisit::{self, Visitor}; use rustc_front::util::is_shift_binop; register_long_diagnostics! { @@ -403,16 +402,6 @@ fn is_repr_nullable_ptr<'tcx>(tcx: &TyCtxt<'tcx>, false } -fn ast_ty_to_normalized<'tcx>(tcx: &TyCtxt<'tcx>, - id: ast::NodeId) - -> Ty<'tcx> { - let tty = match tcx.ast_ty_to_ty_cache.borrow().get(&id) { - Some(&t) => t, - None => panic!("ast_ty_to_ty_cache was incomplete after typeck!") - }; - infer::normalize_associated_type(tcx, &tty) -} - impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// Check if the given type is "ffi-safe" (has a stable, well-defined /// representation which can be exported to C code). @@ -604,10 +593,12 @@ fn check_type_for_ffi(&self, } } - fn check_def(&mut self, sp: Span, id: ast::NodeId) { - let tty = ast_ty_to_normalized(self.cx.tcx, id); + fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) { + // it is only OK to use this function because extern fns cannot have + // any generic types right now: + let ty = infer::normalize_associated_type(self.cx.tcx, &ty); - match ImproperCTypesVisitor::check_type_for_ffi(self, &mut FnvHashSet(), tty) { + match self.check_type_for_ffi(&mut FnvHashSet(), ty) { FfiResult::FfiSafe => {} FfiResult::FfiUnsafe(s) => { self.cx.span_lint(IMPROPER_CTYPES, sp, s); @@ -628,27 +619,30 @@ fn check_def(&mut self, sp: Span, id: ast::NodeId) { } } } -} -impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: &hir::Ty) { - match ty.node { - hir::TyPath(..) | - hir::TyBareFn(..) => self.check_def(ty.span, ty.id), - hir::TyVec(..) => { - self.cx.span_lint(IMPROPER_CTYPES, ty.span, - "found Rust slice type in foreign module, consider \ - using a raw pointer instead"); - } - hir::TyFixedLengthVec(ref ty, _) => self.visit_ty(ty), - hir::TyTup(..) => { - self.cx.span_lint(IMPROPER_CTYPES, ty.span, - "found Rust tuple type in foreign module; \ - consider using a struct instead`") + fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) { + let def_id = self.cx.tcx.map.local_def_id(id); + let scheme = self.cx.tcx.lookup_item_type(def_id); + let sig = scheme.ty.fn_sig(); + let sig = self.cx.tcx.erase_late_bound_regions(&sig); + + for (&input_ty, input_hir) in sig.inputs.iter().zip(&decl.inputs) { + self.check_type_for_ffi_and_report_errors(input_hir.ty.span, &input_ty); + } + + if let hir::Return(ref ret_hir) = decl.output { + let ret_ty = sig.output.unwrap(); + if !ret_ty.is_nil() { + self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty); } - _ => intravisit::walk_ty(self, ty) } } + + fn check_foreign_static(&mut self, id: ast::NodeId, span: Span) { + let def_id = self.cx.tcx.map.local_def_id(id); + let scheme = self.cx.tcx.lookup_item_type(def_id); + self.check_type_for_ffi_and_report_errors(span, scheme.ty); + } } #[derive(Copy, Clone)] @@ -662,29 +656,17 @@ fn get_lints(&self) -> LintArray { impl LateLintPass for ImproperCTypes { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { - fn check_ty(cx: &LateContext, ty: &hir::Ty) { - let mut vis = ImproperCTypesVisitor { cx: cx }; - vis.visit_ty(ty); - } - - fn check_foreign_fn(cx: &LateContext, decl: &hir::FnDecl) { - for input in &decl.inputs { - check_ty(cx, &input.ty); - } - if let hir::Return(ref ret_ty) = decl.output { - let tty = ast_ty_to_normalized(cx.tcx, ret_ty.id); - if !tty.is_nil() { - check_ty(cx, &ret_ty); - } - } - } - + let mut vis = ImproperCTypesVisitor { cx: cx }; if let hir::ItemForeignMod(ref nmod) = it.node { if nmod.abi != Abi::RustIntrinsic && nmod.abi != Abi::PlatformIntrinsic { for ni in &nmod.items { match ni.node { - hir::ForeignItemFn(ref decl, _) => check_foreign_fn(cx, &decl), - hir::ForeignItemStatic(ref t, _) => check_ty(cx, &t) + hir::ForeignItemFn(ref decl, _) => { + vis.check_foreign_fn(ni.id, decl); + } + hir::ForeignItemStatic(ref ty, _) => { + vis.check_foreign_static(ni.id, ty.span); + } } } }