Skip to content

Commit c743390

Browse files
committed
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.
1 parent dc1f683 commit c743390

File tree

1 file changed

+32
-50
lines changed

1 file changed

+32
-50
lines changed

src/librustc_lint/types.rs

+32-50
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use syntax::attr::{self, AttrMetaMethods};
2929
use syntax::codemap::{self, Span};
3030

3131
use rustc_front::hir;
32-
use rustc_front::intravisit::{self, Visitor};
3332
use rustc_front::util::is_shift_binop;
3433

3534
register_long_diagnostics! {
@@ -403,16 +402,6 @@ fn is_repr_nullable_ptr<'tcx>(tcx: &TyCtxt<'tcx>,
403402
false
404403
}
405404

406-
fn ast_ty_to_normalized<'tcx>(tcx: &TyCtxt<'tcx>,
407-
id: ast::NodeId)
408-
-> Ty<'tcx> {
409-
let tty = match tcx.ast_ty_to_ty_cache.borrow().get(&id) {
410-
Some(&t) => t,
411-
None => panic!("ast_ty_to_ty_cache was incomplete after typeck!")
412-
};
413-
infer::normalize_associated_type(tcx, &tty)
414-
}
415-
416405
impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
417406
/// Check if the given type is "ffi-safe" (has a stable, well-defined
418407
/// representation which can be exported to C code).
@@ -604,10 +593,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
604593
}
605594
}
606595

607-
fn check_def(&mut self, sp: Span, id: ast::NodeId) {
608-
let tty = ast_ty_to_normalized(self.cx.tcx, id);
596+
fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) {
597+
// it is only OK to use this function because extern fns cannot have
598+
// any generic types right now:
599+
let ty = infer::normalize_associated_type(self.cx.tcx, &ty);
609600

610-
match ImproperCTypesVisitor::check_type_for_ffi(self, &mut FnvHashSet(), tty) {
601+
match self.check_type_for_ffi(&mut FnvHashSet(), ty) {
611602
FfiResult::FfiSafe => {}
612603
FfiResult::FfiUnsafe(s) => {
613604
self.cx.span_lint(IMPROPER_CTYPES, sp, s);
@@ -628,27 +619,30 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
628619
}
629620
}
630621
}
631-
}
632622

633-
impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> {
634-
fn visit_ty(&mut self, ty: &hir::Ty) {
635-
match ty.node {
636-
hir::TyPath(..) |
637-
hir::TyBareFn(..) => self.check_def(ty.span, ty.id),
638-
hir::TyVec(..) => {
639-
self.cx.span_lint(IMPROPER_CTYPES, ty.span,
640-
"found Rust slice type in foreign module, consider \
641-
using a raw pointer instead");
642-
}
643-
hir::TyFixedLengthVec(ref ty, _) => self.visit_ty(ty),
644-
hir::TyTup(..) => {
645-
self.cx.span_lint(IMPROPER_CTYPES, ty.span,
646-
"found Rust tuple type in foreign module; \
647-
consider using a struct instead`")
623+
fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) {
624+
let def_id = self.cx.tcx.map.local_def_id(id);
625+
let scheme = self.cx.tcx.lookup_item_type(def_id);
626+
let sig = scheme.ty.fn_sig();
627+
let sig = self.cx.tcx.erase_late_bound_regions(&sig);
628+
629+
for (&input_ty, input_hir) in sig.inputs.iter().zip(&decl.inputs) {
630+
self.check_type_for_ffi_and_report_errors(input_hir.ty.span, &input_ty);
631+
}
632+
633+
if let hir::Return(ref ret_hir) = decl.output {
634+
let ret_ty = sig.output.unwrap();
635+
if !ret_ty.is_nil() {
636+
self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty);
648637
}
649-
_ => intravisit::walk_ty(self, ty)
650638
}
651639
}
640+
641+
fn check_foreign_static(&mut self, id: ast::NodeId, span: Span) {
642+
let def_id = self.cx.tcx.map.local_def_id(id);
643+
let scheme = self.cx.tcx.lookup_item_type(def_id);
644+
self.check_type_for_ffi_and_report_errors(span, scheme.ty);
645+
}
652646
}
653647

654648
#[derive(Copy, Clone)]
@@ -662,29 +656,17 @@ impl LintPass for ImproperCTypes {
662656

663657
impl LateLintPass for ImproperCTypes {
664658
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
665-
fn check_ty(cx: &LateContext, ty: &hir::Ty) {
666-
let mut vis = ImproperCTypesVisitor { cx: cx };
667-
vis.visit_ty(ty);
668-
}
669-
670-
fn check_foreign_fn(cx: &LateContext, decl: &hir::FnDecl) {
671-
for input in &decl.inputs {
672-
check_ty(cx, &input.ty);
673-
}
674-
if let hir::Return(ref ret_ty) = decl.output {
675-
let tty = ast_ty_to_normalized(cx.tcx, ret_ty.id);
676-
if !tty.is_nil() {
677-
check_ty(cx, &ret_ty);
678-
}
679-
}
680-
}
681-
659+
let mut vis = ImproperCTypesVisitor { cx: cx };
682660
if let hir::ItemForeignMod(ref nmod) = it.node {
683661
if nmod.abi != Abi::RustIntrinsic && nmod.abi != Abi::PlatformIntrinsic {
684662
for ni in &nmod.items {
685663
match ni.node {
686-
hir::ForeignItemFn(ref decl, _) => check_foreign_fn(cx, &decl),
687-
hir::ForeignItemStatic(ref t, _) => check_ty(cx, &t)
664+
hir::ForeignItemFn(ref decl, _) => {
665+
vis.check_foreign_fn(ni.id, decl);
666+
}
667+
hir::ForeignItemStatic(ref ty, _) => {
668+
vis.check_foreign_static(ni.id, ty.span);
669+
}
688670
}
689671
}
690672
}

0 commit comments

Comments
 (0)