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.
This commit is contained in:
Niko Matsakis 2016-03-16 15:53:08 -04:00
parent dc1f6831eb
commit c74339052d

View File

@ -29,7 +29,6 @@ use syntax::attr::{self, AttrMetaMethods};
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 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
}
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,26 +619,29 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
}
}
}
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`")
}
_ => intravisit::walk_ty(self, ty)
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);
}
}
}
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);
}
}
@ -662,29 +656,17 @@ impl LintPass for ImproperCTypes {
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);
}
}
}
}