]> git.lizzy.rs Git - rust.git/commitdiff
rewrite foreign types lint not to trawl the HIR
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 16 Mar 2016 19:53:08 +0000 (15:53 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Thu, 24 Mar 2016 18:01:28 +0000 (14:01 -0400)
It no longer reads from `ast_ty_to_ty_cache`, which was very wrong. It
also correctly handles higher-ranked regions.

src/librustc_lint/types.rs

index 4d844bbf032b6f2d23b8fde149cad38dbcda9cc1..1a84afab86bfce9946476280aeca1b3437e6b1d8 100644 (file)
@@ -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);
+                        }
                     }
                 }
             }