From cb60654f78468a76e55836aae97b71ceb19f2284 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 27 Oct 2019 14:05:38 +0000 Subject: [PATCH] improper ctypes: adjust lint msg for extern fns Signed-off-by: David Wood --- src/librustc_lint/types.rs | 37 +++++++++++++------- src/test/ui/lint/lint-ctypes-fn.stderr | 48 +++++++++++++------------- 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index cea57fc6293cd..f2ad400d5dd37 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -891,11 +891,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { sp: Span, note: &str, help: Option<&str>, + is_foreign_item: bool, ) { let mut diag = self.cx.struct_span_lint( IMPROPER_CTYPES, sp, - &format!("`extern` block uses type `{}`, which is not FFI-safe", ty), + &format!( + "`extern` {} uses type `{}`, which is not FFI-safe", + if is_foreign_item { "block" } else { "fn" }, + ty, + ), ); diag.span_label(sp, "not FFI-safe"); if let Some(help) = help { @@ -910,7 +915,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { diag.emit(); } - fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { + fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>, is_foreign_item: bool) -> bool { struct ProhibitOpaqueTypes<'tcx> { ty: Option>, }; @@ -934,6 +939,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { sp, "opaque types have no C equivalent", None, + is_foreign_item, ); true } else { @@ -941,10 +947,15 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } } - fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) { + fn check_type_for_ffi_and_report_errors( + &mut self, + sp: Span, + ty: Ty<'tcx>, + is_foreign_item: bool, + ) { // We have to check for opaque types before `normalize_erasing_regions`, // which will replace opaque types with their underlying concrete type. - if self.check_for_opaque_ty(sp, ty) { + if self.check_for_opaque_ty(sp, ty, is_foreign_item) { // We've already emitted an error due to an opaque type. return; } @@ -953,27 +964,29 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { match self.check_type_for_ffi(&mut FxHashSet::default(), ty) { FfiResult::FfiSafe => {} FfiResult::FfiPhantom(ty) => { - self.emit_ffi_unsafe_type_lint(ty, sp, "composed only of `PhantomData`", None); + self.emit_ffi_unsafe_type_lint( + ty, sp, "composed only of `PhantomData`", None, is_foreign_item); } FfiResult::FfiUnsafe { ty, reason, help } => { - self.emit_ffi_unsafe_type_lint(ty, sp, reason, help); + self.emit_ffi_unsafe_type_lint( + ty, sp, reason, help, is_foreign_item); } } } - fn check_foreign_fn(&mut self, id: hir::HirId, decl: &hir::FnDecl) { + fn check_foreign_fn(&mut self, id: hir::HirId, decl: &hir::FnDecl, is_foreign_item: bool) { let def_id = self.cx.tcx.hir().local_def_id(id); let sig = self.cx.tcx.fn_sig(def_id); 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.span, input_ty); + self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, is_foreign_item); } if let hir::Return(ref ret_hir) = decl.output { let ret_ty = sig.output(); if !ret_ty.is_unit() { - self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty); + self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty, is_foreign_item); } } } @@ -981,7 +994,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_foreign_static(&mut self, id: hir::HirId, span: Span) { let def_id = self.cx.tcx.hir().local_def_id(id); let ty = self.cx.tcx.type_of(def_id); - self.check_type_for_ffi_and_report_errors(span, ty); + self.check_type_for_ffi_and_report_errors(span, ty, true); } fn is_internal_abi(&self, abi: Abi) -> bool { @@ -1000,7 +1013,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes { if !vis.is_internal_abi(abi) { match it.kind { hir::ForeignItemKind::Fn(ref decl, _, _) => { - vis.check_foreign_fn(it.hir_id, decl); + vis.check_foreign_fn(it.hir_id, decl, true); } hir::ForeignItemKind::Static(ref ty, _) => { vis.check_foreign_static(it.hir_id, ty.span); @@ -1029,7 +1042,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes { let mut vis = ImproperCTypesVisitor { cx }; if !vis.is_internal_abi(abi) { - vis.check_foreign_fn(hir_id, decl); + vis.check_foreign_fn(hir_id, decl, false); } } } diff --git a/src/test/ui/lint/lint-ctypes-fn.stderr b/src/test/ui/lint/lint-ctypes-fn.stderr index c0ce1a1cfb9d6..59bd6bfc5afd2 100644 --- a/src/test/ui/lint/lint-ctypes-fn.stderr +++ b/src/test/ui/lint/lint-ctypes-fn.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `Foo`, which is not FFI-safe +error: `extern` fn uses type `Foo`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:63:35 | LL | pub extern "C" fn ptr_type1(size: *const Foo) { } @@ -17,7 +17,7 @@ note: type defined here LL | pub struct Foo; | ^^^^^^^^^^^^^^^ -error: `extern` block uses type `Foo`, which is not FFI-safe +error: `extern` fn uses type `Foo`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:66:35 | LL | pub extern "C" fn ptr_type2(size: *const Foo) { } @@ -31,7 +31,7 @@ note: type defined here LL | pub struct Foo; | ^^^^^^^^^^^^^^^ -error: `extern` block uses type `[u32]`, which is not FFI-safe +error: `extern` fn uses type `[u32]`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:69:33 | LL | pub extern "C" fn slice_type(p: &[u32]) { } @@ -40,7 +40,7 @@ LL | pub extern "C" fn slice_type(p: &[u32]) { } = help: consider using a raw pointer instead = note: slices have no C equivalent -error: `extern` block uses type `str`, which is not FFI-safe +error: `extern` fn uses type `str`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:72:31 | LL | pub extern "C" fn str_type(p: &str) { } @@ -49,7 +49,7 @@ LL | pub extern "C" fn str_type(p: &str) { } = help: consider using `*const u8` and a length instead = note: string slices have no C equivalent -error: `extern` block uses type `std::boxed::Box`, which is not FFI-safe +error: `extern` fn uses type `std::boxed::Box`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:75:31 | LL | pub extern "C" fn box_type(p: Box) { } @@ -58,7 +58,7 @@ LL | pub extern "C" fn box_type(p: Box) { } = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout -error: `extern` block uses type `char`, which is not FFI-safe +error: `extern` fn uses type `char`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:78:32 | LL | pub extern "C" fn char_type(p: char) { } @@ -67,7 +67,7 @@ LL | pub extern "C" fn char_type(p: char) { } = help: consider using `u32` or `libc::wchar_t` instead = note: the `char` type has no C equivalent -error: `extern` block uses type `i128`, which is not FFI-safe +error: `extern` fn uses type `i128`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:81:32 | LL | pub extern "C" fn i128_type(p: i128) { } @@ -75,7 +75,7 @@ LL | pub extern "C" fn i128_type(p: i128) { } | = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `u128`, which is not FFI-safe +error: `extern` fn uses type `u128`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:84:32 | LL | pub extern "C" fn u128_type(p: u128) { } @@ -83,7 +83,7 @@ LL | pub extern "C" fn u128_type(p: u128) { } | = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `(i32, i32)`, which is not FFI-safe +error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:87:33 | LL | pub extern "C" fn tuple_type(p: (i32, i32)) { } @@ -92,7 +92,7 @@ LL | pub extern "C" fn tuple_type(p: (i32, i32)) { } = help: consider using a struct instead = note: tuples have unspecified layout -error: `extern` block uses type `(i32, i32)`, which is not FFI-safe +error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:90:34 | LL | pub extern "C" fn tuple_type2(p: I32Pair) { } @@ -101,7 +101,7 @@ LL | pub extern "C" fn tuple_type2(p: I32Pair) { } = help: consider using a struct instead = note: tuples have unspecified layout -error: `extern` block uses type `ZeroSize`, which is not FFI-safe +error: `extern` fn uses type `ZeroSize`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:93:32 | LL | pub extern "C" fn zero_size(p: ZeroSize) { } @@ -115,7 +115,7 @@ note: type defined here LL | pub struct ZeroSize; | ^^^^^^^^^^^^^^^^^^^^ -error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe +error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:96:40 | LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { } @@ -128,7 +128,7 @@ note: type defined here LL | pub struct ZeroSizeWithPhantomData(PhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `extern` block uses type `std::marker::PhantomData`, which is not FFI-safe +error: `extern` fn uses type `std::marker::PhantomData`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:99:51 | LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData { @@ -136,7 +136,7 @@ LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData { | = note: composed only of `PhantomData` -error: `extern` block uses type `fn()`, which is not FFI-safe +error: `extern` fn uses type `fn()`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:104:30 | LL | pub extern "C" fn fn_type(p: RustFn) { } @@ -145,7 +145,7 @@ LL | pub extern "C" fn fn_type(p: RustFn) { } = help: consider using an `extern fn(...) -> ...` function pointer instead = note: this function pointer has Rust-specific calling convention -error: `extern` block uses type `fn()`, which is not FFI-safe +error: `extern` fn uses type `fn()`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:107:31 | LL | pub extern "C" fn fn_type2(p: fn()) { } @@ -154,7 +154,7 @@ LL | pub extern "C" fn fn_type2(p: fn()) { } = help: consider using an `extern fn(...) -> ...` function pointer instead = note: this function pointer has Rust-specific calling convention -error: `extern` block uses type `std::boxed::Box`, which is not FFI-safe +error: `extern` fn uses type `std::boxed::Box`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:110:35 | LL | pub extern "C" fn fn_contained(p: RustBadRet) { } @@ -163,7 +163,7 @@ LL | pub extern "C" fn fn_contained(p: RustBadRet) { } = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout -error: `extern` block uses type `i128`, which is not FFI-safe +error: `extern` fn uses type `i128`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:113:39 | LL | pub extern "C" fn transparent_i128(p: TransparentI128) { } @@ -171,7 +171,7 @@ LL | pub extern "C" fn transparent_i128(p: TransparentI128) { } | = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `str`, which is not FFI-safe +error: `extern` fn uses type `str`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:116:38 | LL | pub extern "C" fn transparent_str(p: TransparentStr) { } @@ -180,7 +180,7 @@ LL | pub extern "C" fn transparent_str(p: TransparentStr) { } = help: consider using `*const u8` and a length instead = note: string slices have no C equivalent -error: `extern` block uses type `std::boxed::Box`, which is not FFI-safe +error: `extern` fn uses type `std::boxed::Box`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:119:37 | LL | pub extern "C" fn transparent_fn(p: TransparentBadFn) { } @@ -189,7 +189,7 @@ LL | pub extern "C" fn transparent_fn(p: TransparentBadFn) { } = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout -error: `extern` block uses type `Foo`, which is not FFI-safe +error: `extern` fn uses type `Foo`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:161:44 | LL | pub extern "C" fn unused_generic1(size: *const Foo) { } @@ -203,7 +203,7 @@ note: type defined here LL | pub struct Foo; | ^^^^^^^^^^^^^^^ -error: `extern` block uses type `std::marker::PhantomData`, which is not FFI-safe +error: `extern` fn uses type `std::marker::PhantomData`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:164:43 | LL | pub extern "C" fn unused_generic2() -> PhantomData { @@ -211,7 +211,7 @@ LL | pub extern "C" fn unused_generic2() -> PhantomData { | = note: composed only of `PhantomData` -error: `extern` block uses type `Foo`, which is not FFI-safe +error: `extern` fn uses type `Foo`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:171:48 | LL | pub extern "C" fn used_generic2(x: T, size: *const Foo) { } @@ -225,7 +225,7 @@ note: type defined here LL | pub struct Foo; | ^^^^^^^^^^^^^^^ -error: `extern` block uses type `std::vec::Vec`, which is not FFI-safe +error: `extern` fn uses type `std::vec::Vec`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:178:39 | LL | pub extern "C" fn used_generic4(x: Vec) { } @@ -234,7 +234,7 @@ LL | pub extern "C" fn used_generic4(x: Vec) { } = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout -error: `extern` block uses type `std::vec::Vec`, which is not FFI-safe +error: `extern` fn uses type `std::vec::Vec`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:181:41 | LL | pub extern "C" fn used_generic5() -> Vec {