[improper_ctypes] Use a 'help:' line for possible fixes
This commit is contained in:
parent
1f0e1a0439
commit
7ac5e96f4a
@ -353,13 +353,18 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
|
||||
cx: &'a LateContext<'a, 'tcx>,
|
||||
}
|
||||
|
||||
struct FfiError {
|
||||
message: &'static str,
|
||||
help: Option<&'static str>,
|
||||
}
|
||||
|
||||
enum FfiResult {
|
||||
FfiSafe,
|
||||
FfiPhantom,
|
||||
FfiUnsafe(&'static str),
|
||||
FfiBadStruct(DefId, &'static str),
|
||||
FfiBadUnion(DefId, &'static str),
|
||||
FfiBadEnum(DefId, &'static str),
|
||||
FfiUnsafe(FfiError),
|
||||
FfiBadStruct(DefId, FfiError),
|
||||
FfiBadUnion(DefId, FfiError),
|
||||
FfiBadEnum(DefId, FfiError),
|
||||
}
|
||||
|
||||
/// Check if this enum can be safely exported based on the
|
||||
@ -434,14 +439,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
match def.adt_kind() {
|
||||
AdtKind::Struct => {
|
||||
if !def.repr.c() && !def.repr.transparent() {
|
||||
return FfiUnsafe("found struct without foreign-function-safe \
|
||||
representation annotation in foreign module, \
|
||||
consider adding a #[repr(C)] attribute to the type");
|
||||
return FfiUnsafe(FfiError {
|
||||
message: "found struct without foreign-function-safe \
|
||||
representation annotation in foreign module",
|
||||
help: Some("consider adding a #[repr(C)] attribute to the type"),
|
||||
});
|
||||
}
|
||||
|
||||
if def.non_enum_variant().fields.is_empty() {
|
||||
return FfiUnsafe("found zero-size struct in foreign module, consider \
|
||||
adding a member to this struct");
|
||||
return FfiUnsafe(FfiError {
|
||||
message: "found zero-size struct in foreign module",
|
||||
help: Some("consider adding a member to this struct"),
|
||||
});
|
||||
}
|
||||
|
||||
// We can't completely trust repr(C) and repr(transparent) markings;
|
||||
@ -471,8 +480,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => {
|
||||
return r;
|
||||
}
|
||||
FfiUnsafe(s) => {
|
||||
return FfiBadStruct(def.did, s);
|
||||
FfiUnsafe(err) => {
|
||||
return FfiBadStruct(def.did, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -481,14 +490,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
AdtKind::Union => {
|
||||
if !def.repr.c() {
|
||||
return FfiUnsafe("found union without foreign-function-safe \
|
||||
representation annotation in foreign module, \
|
||||
consider adding a #[repr(C)] attribute to the type");
|
||||
return FfiUnsafe(FfiError {
|
||||
message: "found union without foreign-function-safe \
|
||||
representation annotation in foreign module",
|
||||
help: Some("consider adding a #[repr(C)] attribute to the type"),
|
||||
});
|
||||
}
|
||||
|
||||
if def.non_enum_variant().fields.is_empty() {
|
||||
return FfiUnsafe("found zero-size union in foreign module, consider \
|
||||
adding a member to this union");
|
||||
return FfiUnsafe(FfiError {
|
||||
message: "found zero-size union in foreign module",
|
||||
help: Some("consider adding a member to this union"),
|
||||
});
|
||||
}
|
||||
|
||||
let mut all_phantom = true;
|
||||
@ -505,8 +518,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => {
|
||||
return r;
|
||||
}
|
||||
FfiUnsafe(s) => {
|
||||
return FfiBadUnion(def.did, s);
|
||||
FfiUnsafe(err) => {
|
||||
return FfiBadUnion(def.did, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -524,10 +537,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
if !def.repr.c() && def.repr.int.is_none() {
|
||||
// Special-case types like `Option<extern fn()>`.
|
||||
if !is_repr_nullable_ptr(cx, def, substs) {
|
||||
return FfiUnsafe("found enum without foreign-function-safe \
|
||||
representation annotation in foreign \
|
||||
module, consider adding a #[repr(...)] \
|
||||
attribute to the type");
|
||||
return FfiUnsafe(FfiError {
|
||||
message: "found enum without foreign-function-safe \
|
||||
representation annotation in foreign module",
|
||||
help: Some("consider adding a #[repr(...)] attribute \
|
||||
to the type"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,7 +550,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
if !is_ffi_safe(int_ty) {
|
||||
// FIXME: This shouldn't be reachable: we should check
|
||||
// this earlier.
|
||||
return FfiUnsafe("enum has unexpected #[repr(...)] attribute");
|
||||
return FfiUnsafe(FfiError {
|
||||
message: "enum has unexpected #[repr(...)] attribute",
|
||||
help: None,
|
||||
});
|
||||
}
|
||||
|
||||
// Enum with an explicitly sized discriminant; either
|
||||
@ -558,11 +576,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
return r;
|
||||
}
|
||||
FfiPhantom => {
|
||||
return FfiBadEnum(def.did,
|
||||
"Found phantom data in enum variant");
|
||||
return FfiBadEnum(def.did, FfiError {
|
||||
message: "Found phantom data in enum variant",
|
||||
help: None,
|
||||
});
|
||||
}
|
||||
FfiUnsafe(s) => {
|
||||
return FfiBadEnum(def.did, s);
|
||||
FfiUnsafe(err) => {
|
||||
return FfiBadEnum(def.did, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -573,43 +593,57 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
ty::TyChar => {
|
||||
FfiUnsafe("found Rust type `char` in foreign module, while \
|
||||
`u32` or `libc::wchar_t` should be used")
|
||||
FfiUnsafe(FfiError {
|
||||
message: "found Rust type `char` in foreign module",
|
||||
help: Some("consider using `u32` or `libc::wchar_t`"),
|
||||
})
|
||||
}
|
||||
|
||||
ty::TyInt(ast::IntTy::I128) => {
|
||||
FfiUnsafe("found Rust type `i128` in foreign module, but \
|
||||
128-bit integers don't currently have a known \
|
||||
stable ABI")
|
||||
FfiUnsafe(FfiError {
|
||||
message: "found Rust type `i128` in foreign module, but 128-bit \
|
||||
integers don't currently have a known stable ABI",
|
||||
help: None,
|
||||
})
|
||||
}
|
||||
|
||||
ty::TyUint(ast::UintTy::U128) => {
|
||||
FfiUnsafe("found Rust type `u128` in foreign module, but \
|
||||
128-bit integers don't currently have a known \
|
||||
stable ABI")
|
||||
FfiUnsafe(FfiError {
|
||||
message: "found Rust type `u128` in foreign module, but 128-bit \
|
||||
integers don't currently have a known stable ABI",
|
||||
help: None,
|
||||
})
|
||||
}
|
||||
|
||||
// Primitive types with a stable representation.
|
||||
ty::TyBool | ty::TyInt(..) | ty::TyUint(..) | ty::TyFloat(..) | ty::TyNever => FfiSafe,
|
||||
|
||||
ty::TySlice(_) => {
|
||||
FfiUnsafe("found Rust slice type in foreign module, \
|
||||
consider using a raw pointer instead")
|
||||
FfiUnsafe(FfiError {
|
||||
message: "found Rust slice type in foreign module",
|
||||
help: Some("consider using a raw pointer instead"),
|
||||
})
|
||||
}
|
||||
|
||||
ty::TyDynamic(..) => {
|
||||
FfiUnsafe("found Rust trait type in foreign module, \
|
||||
consider using a raw pointer instead")
|
||||
FfiUnsafe(FfiError {
|
||||
message: "found Rust trait type in foreign module",
|
||||
help: Some("consider using a raw pointer instead"),
|
||||
})
|
||||
}
|
||||
|
||||
ty::TyStr => {
|
||||
FfiUnsafe("found Rust type `str` in foreign module; \
|
||||
consider using a `*const libc::c_char`")
|
||||
FfiUnsafe(FfiError {
|
||||
message: "found Rust type `str` in foreign module",
|
||||
help: Some("consider using a `*const libc::c_char`"),
|
||||
})
|
||||
}
|
||||
|
||||
ty::TyTuple(..) => {
|
||||
FfiUnsafe("found Rust tuple type in foreign module; \
|
||||
consider using a struct instead")
|
||||
FfiUnsafe(FfiError {
|
||||
message: "found Rust tuple type in foreign module",
|
||||
help: Some("consider using a struct instead"),
|
||||
})
|
||||
}
|
||||
|
||||
ty::TyRawPtr(ref m) |
|
||||
@ -620,9 +654,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
ty::TyFnPtr(sig) => {
|
||||
match sig.abi() {
|
||||
Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => {
|
||||
return FfiUnsafe("found function pointer with Rust calling convention in \
|
||||
foreign module; consider using an `extern` function \
|
||||
pointer")
|
||||
return FfiUnsafe(FfiError {
|
||||
message: "found function pointer with Rust calling convention in \
|
||||
foreign module",
|
||||
help: Some("consider using an `extern` function pointer"),
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -676,34 +712,45 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
&format!("found zero-sized type composed only \
|
||||
of phantom-data in a foreign-function."));
|
||||
}
|
||||
FfiResult::FfiUnsafe(s) => {
|
||||
self.cx.span_lint(IMPROPER_CTYPES, sp, s);
|
||||
FfiResult::FfiUnsafe(err) => {
|
||||
let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, err.message);
|
||||
if let Some(s) = err.help {
|
||||
diag.help(s);
|
||||
}
|
||||
diag.emit();
|
||||
}
|
||||
FfiResult::FfiBadStruct(_, s) => {
|
||||
FfiResult::FfiBadStruct(_, err) => {
|
||||
// FIXME: This diagnostic is difficult to read, and doesn't
|
||||
// point at the relevant field.
|
||||
self.cx.span_lint(IMPROPER_CTYPES,
|
||||
sp,
|
||||
&format!("found non-foreign-function-safe member in struct \
|
||||
marked #[repr(C)]: {}",
|
||||
s));
|
||||
let msg = format!("found non-foreign-function-safe member in struct \
|
||||
marked #[repr(C)]: {}", err.message);
|
||||
let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, &msg);
|
||||
if let Some(s) = err.help {
|
||||
diag.help(s);
|
||||
}
|
||||
diag.emit();
|
||||
}
|
||||
FfiResult::FfiBadUnion(_, s) => {
|
||||
FfiResult::FfiBadUnion(_, err) => {
|
||||
// FIXME: This diagnostic is difficult to read, and doesn't
|
||||
// point at the relevant field.
|
||||
self.cx.span_lint(IMPROPER_CTYPES,
|
||||
sp,
|
||||
&format!("found non-foreign-function-safe member in union \
|
||||
marked #[repr(C)]: {}",
|
||||
s));
|
||||
let msg = format!("found non-foreign-function-safe member in union \
|
||||
marked #[repr(C)]: {}", err.message);
|
||||
let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, &msg);
|
||||
if let Some(s) = err.help {
|
||||
diag.help(s);
|
||||
}
|
||||
diag.emit();
|
||||
}
|
||||
FfiResult::FfiBadEnum(_, s) => {
|
||||
FfiResult::FfiBadEnum(_, err) => {
|
||||
// FIXME: This diagnostic is difficult to read, and doesn't
|
||||
// point at the relevant variant.
|
||||
self.cx.span_lint(IMPROPER_CTYPES,
|
||||
sp,
|
||||
&format!("found non-foreign-function-safe member in enum: {}",
|
||||
s));
|
||||
let msg = format!("found non-foreign-function-safe member in enum: {}",
|
||||
err.message);
|
||||
let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, &msg);
|
||||
if let Some(s) = err.help {
|
||||
diag.help(s);
|
||||
}
|
||||
diag.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: found struct without foreign-function-safe representation annotation in foreign module, consider adding a #[repr(C)] attribute to the type
|
||||
error: found struct without foreign-function-safe representation annotation in foreign module
|
||||
--> $DIR/lint-ctypes.rs:54:28
|
||||
|
|
||||
54 | pub fn ptr_type1(size: *const Foo); //~ ERROR: found struct without
|
||||
@ -9,36 +9,47 @@ note: lint level defined here
|
||||
|
|
||||
11 | #![deny(improper_ctypes)]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
= help: consider adding a #[repr(C)] attribute to the type
|
||||
|
||||
error: found struct without foreign-function-safe representation annotation in foreign module, consider adding a #[repr(C)] attribute to the type
|
||||
error: found struct without foreign-function-safe representation annotation in foreign module
|
||||
--> $DIR/lint-ctypes.rs:55:28
|
||||
|
|
||||
55 | pub fn ptr_type2(size: *const Foo); //~ ERROR: found struct without
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= help: consider adding a #[repr(C)] attribute to the type
|
||||
|
||||
error: found Rust slice type in foreign module, consider using a raw pointer instead
|
||||
error: found Rust slice type in foreign module
|
||||
--> $DIR/lint-ctypes.rs:56:26
|
||||
|
|
||||
56 | pub fn slice_type(p: &[u32]); //~ ERROR: found Rust slice type
|
||||
| ^^^^^^
|
||||
|
|
||||
= help: consider using a raw pointer instead
|
||||
|
||||
error: found Rust type `str` in foreign module; consider using a `*const libc::c_char`
|
||||
error: found Rust type `str` in foreign module
|
||||
--> $DIR/lint-ctypes.rs:57:24
|
||||
|
|
||||
57 | pub fn str_type(p: &str); //~ ERROR: found Rust type
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider using a `*const libc::c_char`
|
||||
|
||||
error: found struct without foreign-function-safe representation annotation in foreign module, consider adding a #[repr(C)] attribute to the type
|
||||
error: found struct without foreign-function-safe representation annotation in foreign module
|
||||
--> $DIR/lint-ctypes.rs:58:24
|
||||
|
|
||||
58 | pub fn box_type(p: Box<u32>); //~ ERROR found struct without
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= help: consider adding a #[repr(C)] attribute to the type
|
||||
|
||||
error: found Rust type `char` in foreign module, while `u32` or `libc::wchar_t` should be used
|
||||
error: found Rust type `char` in foreign module
|
||||
--> $DIR/lint-ctypes.rs:59:25
|
||||
|
|
||||
59 | pub fn char_type(p: char); //~ ERROR found Rust type
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider using `u32` or `libc::wchar_t`
|
||||
|
||||
error: found Rust type `i128` in foreign module, but 128-bit integers don't currently have a known stable ABI
|
||||
--> $DIR/lint-ctypes.rs:60:25
|
||||
@ -52,29 +63,37 @@ error: found Rust type `u128` in foreign module, but 128-bit integers don't curr
|
||||
61 | pub fn u128_type(p: u128); //~ ERROR found Rust type
|
||||
| ^^^^
|
||||
|
||||
error: found Rust trait type in foreign module, consider using a raw pointer instead
|
||||
error: found Rust trait type in foreign module
|
||||
--> $DIR/lint-ctypes.rs:62:26
|
||||
|
|
||||
62 | pub fn trait_type(p: &Clone); //~ ERROR found Rust trait type
|
||||
| ^^^^^^
|
||||
|
|
||||
= help: consider using a raw pointer instead
|
||||
|
||||
error: found Rust tuple type in foreign module; consider using a struct instead
|
||||
error: found Rust tuple type in foreign module
|
||||
--> $DIR/lint-ctypes.rs:63:26
|
||||
|
|
||||
63 | pub fn tuple_type(p: (i32, i32)); //~ ERROR found Rust tuple type
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= help: consider using a struct instead
|
||||
|
||||
error: found Rust tuple type in foreign module; consider using a struct instead
|
||||
error: found Rust tuple type in foreign module
|
||||
--> $DIR/lint-ctypes.rs:64:27
|
||||
|
|
||||
64 | pub fn tuple_type2(p: I32Pair); //~ ERROR found Rust tuple type
|
||||
| ^^^^^^^
|
||||
|
|
||||
= help: consider using a struct instead
|
||||
|
||||
error: found zero-size struct in foreign module, consider adding a member to this struct
|
||||
error: found zero-size struct in foreign module
|
||||
--> $DIR/lint-ctypes.rs:65:25
|
||||
|
|
||||
65 | pub fn zero_size(p: ZeroSize); //~ ERROR found zero-size struct
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= help: consider adding a member to this struct
|
||||
|
||||
error: found zero-sized type composed only of phantom-data in a foreign-function.
|
||||
--> $DIR/lint-ctypes.rs:66:33
|
||||
@ -88,23 +107,29 @@ error: found zero-sized type composed only of phantom-data in a foreign-function
|
||||
68 | -> ::std::marker::PhantomData<bool>; //~ ERROR: found zero-sized type
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: found function pointer with Rust calling convention in foreign module; consider using an `extern` function pointer
|
||||
error: found function pointer with Rust calling convention in foreign module
|
||||
--> $DIR/lint-ctypes.rs:69:23
|
||||
|
|
||||
69 | pub fn fn_type(p: RustFn); //~ ERROR found function pointer with Rust
|
||||
| ^^^^^^
|
||||
|
|
||||
= help: consider using an `extern` function pointer
|
||||
|
||||
error: found function pointer with Rust calling convention in foreign module; consider using an `extern` function pointer
|
||||
error: found function pointer with Rust calling convention in foreign module
|
||||
--> $DIR/lint-ctypes.rs:70:24
|
||||
|
|
||||
70 | pub fn fn_type2(p: fn()); //~ ERROR found function pointer with Rust
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider using an `extern` function pointer
|
||||
|
||||
error: found struct without foreign-function-safe representation annotation in foreign module, consider adding a #[repr(C)] attribute to the type
|
||||
error: found struct without foreign-function-safe representation annotation in foreign module
|
||||
--> $DIR/lint-ctypes.rs:71:28
|
||||
|
|
||||
71 | pub fn fn_contained(p: RustBadRet); //~ ERROR: found struct without
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= help: consider adding a #[repr(C)] attribute to the type
|
||||
|
||||
error: found non-foreign-function-safe member in struct marked #[repr(C)]: found Rust type `i128` in foreign module, but 128-bit integers don't currently have a known stable ABI
|
||||
--> $DIR/lint-ctypes.rs:72:32
|
||||
@ -112,17 +137,21 @@ error: found non-foreign-function-safe member in struct marked #[repr(C)]: found
|
||||
72 | pub fn transparent_i128(p: TransparentI128); //~ ERROR: found Rust type `i128`
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: found non-foreign-function-safe member in struct marked #[repr(C)]: found Rust type `str` in foreign module; consider using a `*const libc::c_char`
|
||||
error: found non-foreign-function-safe member in struct marked #[repr(C)]: found Rust type `str` in foreign module
|
||||
--> $DIR/lint-ctypes.rs:73:31
|
||||
|
|
||||
73 | pub fn transparent_str(p: TransparentStr); //~ ERROR: found Rust type `str`
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using a `*const libc::c_char`
|
||||
|
||||
error: found non-foreign-function-safe member in struct marked #[repr(C)]: found struct without foreign-function-safe representation annotation in foreign module, consider adding a #[repr(C)] attribute to the type
|
||||
error: found non-foreign-function-safe member in struct marked #[repr(C)]: found struct without foreign-function-safe representation annotation in foreign module
|
||||
--> $DIR/lint-ctypes.rs:74:30
|
||||
|
|
||||
74 | pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: found struct without
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider adding a #[repr(C)] attribute to the type
|
||||
|
||||
error: aborting due to 20 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user