Minor changes from PR feedback
This commit is contained in:
parent
427a09ba7b
commit
08f0aecffd
@ -535,8 +535,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
store.register_late_pass(move || Box::new(feature_name::FeatureName));
|
store.register_late_pass(move || Box::new(feature_name::FeatureName));
|
||||||
store.register_late_pass(move || Box::new(iter_not_returning_iterator::IterNotReturningIterator));
|
store.register_late_pass(move || Box::new(iter_not_returning_iterator::IterNotReturningIterator));
|
||||||
store.register_late_pass(move || Box::new(if_then_panic::IfThenPanic));
|
store.register_late_pass(move || Box::new(if_then_panic::IfThenPanic));
|
||||||
let enable_raw_pointer_heuristic = conf.enable_raw_pointer_heuristic;
|
let enable_raw_pointer_heuristic_for_send = conf.enable_raw_pointer_heuristic_for_send;
|
||||||
store.register_late_pass(move || Box::new(non_send_field_in_send_ty::NonSendFieldInSendTy::new(enable_raw_pointer_heuristic)));
|
store.register_late_pass(move || Box::new(non_send_field_in_send_ty::NonSendFieldInSendTy::new(enable_raw_pointer_heuristic_for_send)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
/// unsafe impl<T> Send for ExampleStruct<T> {}
|
/// unsafe impl<T> Send for ExampleStruct<T> {}
|
||||||
/// ```
|
/// ```
|
||||||
/// Use thread-safe types like [`std::sync::Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html)
|
/// Use thread-safe types like [`std::sync::Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html)
|
||||||
/// and specify correct bounds on generic type parameters (`T: Send`).
|
/// or specify correct bounds on generic type parameters (`T: Send`).
|
||||||
pub NON_SEND_FIELD_IN_SEND_TY,
|
pub NON_SEND_FIELD_IN_SEND_TY,
|
||||||
nursery,
|
nursery,
|
||||||
"there is field that does not implement `Send` in a `Send` struct"
|
"there is field that does not implement `Send` in a `Send` struct"
|
||||||
@ -125,7 +125,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
|||||||
for field in non_send_fields {
|
for field in non_send_fields {
|
||||||
diag.span_note(
|
diag.span_note(
|
||||||
field.span,
|
field.span,
|
||||||
&format!("the field `{}` has type `{}` which is not `Send`", field.name, field.ty),
|
&format!("the field `{}` has type `{}` which is `!Send`", field.name, field.ty),
|
||||||
);
|
);
|
||||||
|
|
||||||
match field.generic_params.len() {
|
match field.generic_params.len() {
|
||||||
@ -165,7 +165,7 @@ fn generic_params_string(&self) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Given a type, collect all of its generic parameters.
|
/// Given a type, collect all of its generic parameters.
|
||||||
/// Example: MyStruct<P, Box<Q, R>> => vec![P, Q, R]
|
/// Example: `MyStruct<P, Box<Q, R>>` => `vec![P, Q, R]`
|
||||||
fn collect_generic_params<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Vec<Ty<'tcx>> {
|
fn collect_generic_params<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Vec<Ty<'tcx>> {
|
||||||
ty.walk(cx.tcx)
|
ty.walk(cx.tcx)
|
||||||
.filter_map(|inner| match inner.unpack() {
|
.filter_map(|inner| match inner.unpack() {
|
||||||
@ -184,31 +184,34 @@ fn ty_implements_send_or_copy(cx: &LateContext<'tcx>, ty: Ty<'tcx>, send_trait:
|
|||||||
/// Heuristic to allow cases like `Vec<*const u8>`
|
/// Heuristic to allow cases like `Vec<*const u8>`
|
||||||
fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, send_trait: DefId) -> bool {
|
fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, send_trait: DefId) -> bool {
|
||||||
if ty_implements_send_or_copy(cx, ty, send_trait) {
|
if ty_implements_send_or_copy(cx, ty, send_trait) {
|
||||||
true
|
return true;
|
||||||
} else {
|
}
|
||||||
// The type is known to be `!Send` and `!Copy`
|
|
||||||
match ty.kind() {
|
// The type is known to be `!Send` and `!Copy`
|
||||||
ty::Tuple(_) => ty
|
match ty.kind() {
|
||||||
.tuple_fields()
|
ty::Tuple(_) => ty
|
||||||
.all(|ty| ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait)),
|
.tuple_fields()
|
||||||
ty::Array(ty, _) | ty::Slice(ty) => ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait),
|
.all(|ty| ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait)),
|
||||||
ty::Adt(_, substs) => {
|
ty::Array(ty, _) | ty::Slice(ty) => ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait),
|
||||||
if contains_raw_pointer(cx, ty) {
|
ty::Adt(_, substs) => {
|
||||||
// descends only if ADT contains any raw pointers
|
if contains_raw_pointer(cx, ty) {
|
||||||
substs.iter().all(|generic_arg| match generic_arg.unpack() {
|
// descends only if ADT contains any raw pointers
|
||||||
GenericArgKind::Type(ty) => ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait),
|
substs.iter().all(|generic_arg| match generic_arg.unpack() {
|
||||||
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => true,
|
GenericArgKind::Type(ty) => ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait),
|
||||||
})
|
// Lifetimes and const generics are not solid part of ADT and ignored
|
||||||
} else {
|
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => true,
|
||||||
false
|
})
|
||||||
}
|
} else {
|
||||||
},
|
false
|
||||||
ty::RawPtr(_) => true,
|
}
|
||||||
_ => false,
|
},
|
||||||
}
|
// Raw pointers are `!Send` but allowed by the heuristic
|
||||||
|
ty::RawPtr(_) => true,
|
||||||
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if the type contains any raw pointers in substs (including nested ones).
|
||||||
fn contains_raw_pointer<'tcx>(cx: &LateContext<'tcx>, target_ty: Ty<'tcx>) -> bool {
|
fn contains_raw_pointer<'tcx>(cx: &LateContext<'tcx>, target_ty: Ty<'tcx>) -> bool {
|
||||||
for ty_node in target_ty.walk(cx.tcx) {
|
for ty_node in target_ty.walk(cx.tcx) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
|
@ -287,7 +287,7 @@ pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
|
|||||||
/// Lint: NON_SEND_FIELD_IN_SEND_TY.
|
/// Lint: NON_SEND_FIELD_IN_SEND_TY.
|
||||||
///
|
///
|
||||||
/// Whether to apply the raw pointer heuristic in `non_send_field_in_send_ty` lint.
|
/// Whether to apply the raw pointer heuristic in `non_send_field_in_send_ty` lint.
|
||||||
(enable_raw_pointer_heuristic: bool = true),
|
(enable_raw_pointer_heuristic_for_send: bool = true),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search for the configuration file.
|
/// Search for the configuration file.
|
||||||
|
@ -5,7 +5,7 @@ LL | unsafe impl<T> Send for RingBuffer<T> {}
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `-D clippy::non-send-field-in-send-ty` implied by `-D warnings`
|
= note: `-D clippy::non-send-field-in-send-ty` implied by `-D warnings`
|
||||||
note: the field `data` has type `std::vec::Vec<std::cell::UnsafeCell<T>>` which is not `Send`
|
note: the field `data` has type `std::vec::Vec<std::cell::UnsafeCell<T>>` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:11:5
|
--> $DIR/non_send_field_in_send_ty.rs:11:5
|
||||||
|
|
|
|
||||||
LL | data: Vec<UnsafeCell<T>>,
|
LL | data: Vec<UnsafeCell<T>>,
|
||||||
@ -18,7 +18,7 @@ error: this implementation is unsound, as some fields in `MvccRwLock<T>` are `!S
|
|||||||
LL | unsafe impl<T> Send for MvccRwLock<T> {}
|
LL | unsafe impl<T> Send for MvccRwLock<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the field `lock` has type `std::sync::Mutex<std::boxed::Box<T>>` which is not `Send`
|
note: the field `lock` has type `std::sync::Mutex<std::boxed::Box<T>>` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:21:5
|
--> $DIR/non_send_field_in_send_ty.rs:21:5
|
||||||
|
|
|
|
||||||
LL | lock: Mutex<Box<T>>,
|
LL | lock: Mutex<Box<T>>,
|
||||||
@ -31,7 +31,7 @@ error: this implementation is unsound, as some fields in `ArcGuard<RC, T>` are `
|
|||||||
LL | unsafe impl<RC, T: Send> Send for ArcGuard<RC, T> {}
|
LL | unsafe impl<RC, T: Send> Send for ArcGuard<RC, T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the field `head` has type `std::sync::Arc<RC>` which is not `Send`
|
note: the field `head` has type `std::sync::Arc<RC>` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:29:5
|
--> $DIR/non_send_field_in_send_ty.rs:29:5
|
||||||
|
|
|
|
||||||
LL | head: Arc<RC>,
|
LL | head: Arc<RC>,
|
||||||
@ -44,7 +44,7 @@ error: this implementation is unsound, as some fields in `DeviceHandle<T>` are `
|
|||||||
LL | unsafe impl<T: UsbContext> Send for DeviceHandle<T> {}
|
LL | unsafe impl<T: UsbContext> Send for DeviceHandle<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the field `context` has type `T` which is not `Send`
|
note: the field `context` has type `T` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:44:5
|
--> $DIR/non_send_field_in_send_ty.rs:44:5
|
||||||
|
|
|
|
||||||
LL | context: T,
|
LL | context: T,
|
||||||
@ -57,7 +57,7 @@ error: this implementation is unsound, as some fields in `NoGeneric` are `!Send`
|
|||||||
LL | unsafe impl Send for NoGeneric {}
|
LL | unsafe impl Send for NoGeneric {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the field `rc_is_not_send` has type `std::rc::Rc<std::string::String>` which is not `Send`
|
note: the field `rc_is_not_send` has type `std::rc::Rc<std::string::String>` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:52:5
|
--> $DIR/non_send_field_in_send_ty.rs:52:5
|
||||||
|
|
|
|
||||||
LL | rc_is_not_send: Rc<String>,
|
LL | rc_is_not_send: Rc<String>,
|
||||||
@ -70,19 +70,19 @@ error: this implementation is unsound, as some fields in `MultiField<T>` are `!S
|
|||||||
LL | unsafe impl<T> Send for MultiField<T> {}
|
LL | unsafe impl<T> Send for MultiField<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the field `field1` has type `T` which is not `Send`
|
note: the field `field1` has type `T` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:58:5
|
--> $DIR/non_send_field_in_send_ty.rs:58:5
|
||||||
|
|
|
|
||||||
LL | field1: T,
|
LL | field1: T,
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
= help: add `T: Send` bound in `Send` impl
|
= help: add `T: Send` bound in `Send` impl
|
||||||
note: the field `field2` has type `T` which is not `Send`
|
note: the field `field2` has type `T` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:59:5
|
--> $DIR/non_send_field_in_send_ty.rs:59:5
|
||||||
|
|
|
|
||||||
LL | field2: T,
|
LL | field2: T,
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
= help: add `T: Send` bound in `Send` impl
|
= help: add `T: Send` bound in `Send` impl
|
||||||
note: the field `field3` has type `T` which is not `Send`
|
note: the field `field3` has type `T` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:60:5
|
--> $DIR/non_send_field_in_send_ty.rs:60:5
|
||||||
|
|
|
|
||||||
LL | field3: T,
|
LL | field3: T,
|
||||||
@ -95,7 +95,7 @@ error: this implementation is unsound, as some fields in `MyOption<T>` are `!Sen
|
|||||||
LL | unsafe impl<T> Send for MyOption<T> {}
|
LL | unsafe impl<T> Send for MyOption<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the field `0` has type `T` which is not `Send`
|
note: the field `0` has type `T` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:66:12
|
--> $DIR/non_send_field_in_send_ty.rs:66:12
|
||||||
|
|
|
|
||||||
LL | MySome(T),
|
LL | MySome(T),
|
||||||
@ -108,7 +108,7 @@ error: this implementation is unsound, as some fields in `MultiParam<A, B>` are
|
|||||||
LL | unsafe impl<A, B> Send for MultiParam<A, B> {}
|
LL | unsafe impl<A, B> Send for MultiParam<A, B> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the field `vec` has type `std::vec::Vec<(A, B)>` which is not `Send`
|
note: the field `vec` has type `std::vec::Vec<(A, B)>` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:74:5
|
--> $DIR/non_send_field_in_send_ty.rs:74:5
|
||||||
|
|
|
|
||||||
LL | vec: Vec<(A, B)>,
|
LL | vec: Vec<(A, B)>,
|
||||||
@ -121,7 +121,7 @@ error: this implementation is unsound, as some fields in `HeuristicTest` are `!S
|
|||||||
LL | unsafe impl Send for HeuristicTest {}
|
LL | unsafe impl Send for HeuristicTest {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the field `field4` has type `(*const NonSend, std::rc::Rc<u8>)` which is not `Send`
|
note: the field `field4` has type `(*const NonSend, std::rc::Rc<u8>)` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:90:5
|
--> $DIR/non_send_field_in_send_ty.rs:90:5
|
||||||
|
|
|
|
||||||
LL | field4: (*const NonSend, Rc<u8>),
|
LL | field4: (*const NonSend, Rc<u8>),
|
||||||
@ -134,7 +134,7 @@ error: this implementation is unsound, as some fields in `AttrTest3<T>` are `!Se
|
|||||||
LL | unsafe impl<T> Send for AttrTest3<T> {}
|
LL | unsafe impl<T> Send for AttrTest3<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the field `0` has type `T` which is not `Send`
|
note: the field `0` has type `T` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:109:11
|
--> $DIR/non_send_field_in_send_ty.rs:109:11
|
||||||
|
|
|
|
||||||
LL | Enum2(T),
|
LL | Enum2(T),
|
||||||
@ -147,7 +147,7 @@ error: this implementation is unsound, as some fields in `Complex<P, u32>` are `
|
|||||||
LL | unsafe impl<P> Send for Complex<P, u32> {}
|
LL | unsafe impl<P> Send for Complex<P, u32> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the field `field1` has type `P` which is not `Send`
|
note: the field `field1` has type `P` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:118:5
|
--> $DIR/non_send_field_in_send_ty.rs:118:5
|
||||||
|
|
|
|
||||||
LL | field1: A,
|
LL | field1: A,
|
||||||
@ -160,7 +160,7 @@ error: this implementation is unsound, as some fields in `Complex<Q, std::sync::
|
|||||||
LL | unsafe impl<Q: Send> Send for Complex<Q, MutexGuard<'static, bool>> {}
|
LL | unsafe impl<Q: Send> Send for Complex<Q, MutexGuard<'static, bool>> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the field `field2` has type `std::sync::MutexGuard<'static, bool>` which is not `Send`
|
note: the field `field2` has type `std::sync::MutexGuard<'static, bool>` which is `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:119:5
|
--> $DIR/non_send_field_in_send_ty.rs:119:5
|
||||||
|
|
|
|
||||||
LL | field2: B,
|
LL | field2: B,
|
||||||
|
Loading…
Reference in New Issue
Block a user