Skip to content

Commit 3e7aabb

Browse files
committed
lint: check for unit ret type after normalization
This commit moves the check that skips unit return types to after where the return type has been normalized - therefore ensuring that FFI-safety lints are not emitted for types which normalize to unit. Signed-off-by: David Wood <[email protected]>
1 parent a8640cd commit 3e7aabb

File tree

3 files changed

+26
-25
lines changed

3 files changed

+26
-25
lines changed

src/librustc_lint/types.rs

+21-10
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
946946
}
947947
}
948948

949-
fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>, is_static: bool) {
949+
fn check_type_for_ffi_and_report_errors(
950+
&mut self,
951+
sp: Span,
952+
ty: Ty<'tcx>,
953+
is_static: bool,
954+
is_return_type: bool,
955+
) {
950956
// We have to check for opaque types before `normalize_erasing_regions`,
951957
// which will replace opaque types with their underlying concrete type.
952958
if self.check_for_opaque_ty(sp, ty) {
@@ -957,14 +963,21 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
957963
// it is only OK to use this function because extern fns cannot have
958964
// any generic types right now:
959965
let ty = self.cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
960-
// C doesn't really support passing arrays by value.
961-
// The only way to pass an array by value is through a struct.
962-
// So we first test that the top level isn't an array,
963-
// and then recursively check the types inside.
966+
967+
// C doesn't really support passing arrays by value - the only way to pass an array by value
968+
// is through a struct. So, first test that the top level isn't an array, and then
969+
// recursively check the types inside.
964970
if !is_static && self.check_for_array_ty(sp, ty) {
965971
return;
966972
}
967973

974+
// Don't report FFI errors for unit return types. This check exists here, and not in
975+
// `check_foreign_fn` (where it would make more sense) so that normalization has definitely
976+
// happened.
977+
if is_return_type && ty.is_unit() {
978+
return;
979+
}
980+
968981
match self.check_type_for_ffi(&mut FxHashSet::default(), ty) {
969982
FfiResult::FfiSafe => {}
970983
FfiResult::FfiPhantom(ty) => {
@@ -982,21 +995,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
982995
let sig = self.cx.tcx.erase_late_bound_regions(&sig);
983996

984997
for (input_ty, input_hir) in sig.inputs().iter().zip(decl.inputs) {
985-
self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, false);
998+
self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, false, false);
986999
}
9871000

9881001
if let hir::FnRetTy::Return(ref ret_hir) = decl.output {
9891002
let ret_ty = sig.output();
990-
if !ret_ty.is_unit() {
991-
self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty, false);
992-
}
1003+
self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty, false, true);
9931004
}
9941005
}
9951006

9961007
fn check_foreign_static(&mut self, id: hir::HirId, span: Span) {
9971008
let def_id = self.cx.tcx.hir().local_def_id(id);
9981009
let ty = self.cx.tcx.type_of(def_id);
999-
self.check_type_for_ffi_and_report_errors(span, ty, true);
1010+
self.check_type_for_ffi_and_report_errors(span, ty, true, false);
10001011
}
10011012
}
10021013

src/test/ui/lint/lint-ctypes-66202.rs

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ pub struct W<T>(T);
99
extern "C" {
1010
pub fn bare() -> ();
1111
pub fn normalize() -> <() as ToOwned>::Owned;
12-
//~^ ERROR uses type `()`
1312
pub fn transparent() -> W<()>;
1413
//~^ ERROR uses type `W<()>`
1514
}
+5-14
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,20 @@
1-
error: `extern` block uses type `()`, which is not FFI-safe
2-
--> $DIR/lint-ctypes-66202.rs:11:27
1+
error: `extern` block uses type `W<()>`, which is not FFI-safe
2+
--> $DIR/lint-ctypes-66202.rs:12:29
33
|
4-
LL | pub fn normalize() -> <() as ToOwned>::Owned;
5-
| ^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
4+
LL | pub fn transparent() -> W<()>;
5+
| ^^^^^ not FFI-safe
66
|
77
note: the lint level is defined here
88
--> $DIR/lint-ctypes-66202.rs:1:9
99
|
1010
LL | #![deny(improper_ctypes)]
1111
| ^^^^^^^^^^^^^^^
12-
= help: consider using a struct instead
13-
= note: tuples have unspecified layout
14-
15-
error: `extern` block uses type `W<()>`, which is not FFI-safe
16-
--> $DIR/lint-ctypes-66202.rs:13:29
17-
|
18-
LL | pub fn transparent() -> W<()>;
19-
| ^^^^^ not FFI-safe
20-
|
2112
= note: composed only of `PhantomData`
2213
note: the type is defined here
2314
--> $DIR/lint-ctypes-66202.rs:7:1
2415
|
2516
LL | pub struct W<T>(T);
2617
| ^^^^^^^^^^^^^^^^^^^
2718

28-
error: aborting due to 2 previous errors
19+
error: aborting due to previous error
2920

0 commit comments

Comments
 (0)