Emit one report for all fields in the same ADT
This commit is contained in:
parent
a81a5ad1a8
commit
ee74574876
3 changed files with 211 additions and 131 deletions
|
@ -1,11 +1,14 @@
|
||||||
use clippy_utils::diagnostics::span_lint_hir_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
|
use clippy_utils::is_lint_allowed;
|
||||||
use clippy_utils::ty::{implements_trait, is_copy};
|
use clippy_utils::ty::{implements_trait, is_copy};
|
||||||
use rustc_ast::ImplPolarity;
|
use rustc_ast::ImplPolarity;
|
||||||
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::{Item, ItemKind};
|
use rustc_hir::{Item, ItemKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
|
use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::sym;
|
use rustc_span::symbol::Symbol;
|
||||||
|
use rustc_span::{sym, Span};
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
|
@ -64,51 +67,98 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
|
||||||
if let self_ty = ty_trait_ref.self_ty();
|
if let self_ty = ty_trait_ref.self_ty();
|
||||||
if let ty::Adt(adt_def, impl_trait_substs) = self_ty.kind();
|
if let ty::Adt(adt_def, impl_trait_substs) = self_ty.kind();
|
||||||
then {
|
then {
|
||||||
|
let mut non_send_fields = Vec::new();
|
||||||
|
|
||||||
|
let hir_map = cx.tcx.hir();
|
||||||
for variant in &adt_def.variants {
|
for variant in &adt_def.variants {
|
||||||
for field in &variant.fields {
|
for field in &variant.fields {
|
||||||
let field_ty = field.ty(cx.tcx, impl_trait_substs);
|
if_chain! {
|
||||||
|
if let Some(field_hir_id) = field
|
||||||
if raw_pointer_in_ty_def(cx, field_ty)
|
.did
|
||||||
|| implements_trait(cx, field_ty, send_trait, &[])
|
.as_local()
|
||||||
|| is_copy(cx, field_ty)
|
.map(|local_def_id| hir_map.local_def_id_to_hir_id(local_def_id));
|
||||||
{
|
if !is_lint_allowed(cx, NON_SEND_FIELD_IN_SEND_TY, field_hir_id);
|
||||||
continue;
|
if let field_ty = field.ty(cx.tcx, impl_trait_substs);
|
||||||
}
|
if !ty_allowed_in_send(cx, field_ty, send_trait);
|
||||||
|
if let Some(field_span) = hir_map.span_if_local(field.did);
|
||||||
if let Some(field_hir_id) = field
|
then {
|
||||||
.did
|
non_send_fields.push(NonSendField {
|
||||||
.as_local()
|
name: hir_map.name(field_hir_id),
|
||||||
.map(|local_def_id| cx.tcx.hir().local_def_id_to_hir_id(local_def_id))
|
span: field_span,
|
||||||
{
|
ty: field_ty,
|
||||||
if let Some(field_span) = cx.tcx.hir().span_if_local(field.did) {
|
generic_params: collect_generic_params(cx, field_ty),
|
||||||
span_lint_hir_and_then(
|
})
|
||||||
cx,
|
|
||||||
NON_SEND_FIELD_IN_SEND_TY,
|
|
||||||
field_hir_id,
|
|
||||||
field_span,
|
|
||||||
"non-`Send` field found in a `Send` struct",
|
|
||||||
|diag| {
|
|
||||||
diag.span_note(
|
|
||||||
item.span,
|
|
||||||
&format!(
|
|
||||||
"type `{}` doesn't implement `Send` when `{}` is `Send`",
|
|
||||||
field_ty, self_ty
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if is_ty_param(field_ty) {
|
|
||||||
diag.help(&format!("add `{}: Send` bound", field_ty));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !non_send_fields.is_empty() {
|
||||||
|
span_lint_and_then(
|
||||||
|
cx,
|
||||||
|
NON_SEND_FIELD_IN_SEND_TY,
|
||||||
|
item.span,
|
||||||
|
&format!(
|
||||||
|
"this implementation is unsound, as some fields in `{}` are `!Send`",
|
||||||
|
self_ty
|
||||||
|
),
|
||||||
|
|diag| {
|
||||||
|
for field in non_send_fields {
|
||||||
|
diag.span_note(
|
||||||
|
field.span,
|
||||||
|
&format!("the field `{}` has type `{}` which is not `Send`", field.name, field.ty),
|
||||||
|
);
|
||||||
|
|
||||||
|
match field.generic_params.len() {
|
||||||
|
0 => diag.help("use a thread-safe type that implements `Send`"),
|
||||||
|
1 if is_ty_param(field.ty) => diag.help(&format!("add `{}: Send` bound in `Send` impl", field.ty)),
|
||||||
|
_ => diag.help(&format!(
|
||||||
|
"add bounds on type parameter{} `{}` that satisfy `{}: Send`",
|
||||||
|
if field.generic_params.len() > 1 { "s" } else { "" },
|
||||||
|
field.generic_params_string(),
|
||||||
|
field.ty
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct NonSendField<'tcx> {
|
||||||
|
name: Symbol,
|
||||||
|
span: Span,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
generic_params: Vec<Ty<'tcx>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> NonSendField<'tcx> {
|
||||||
|
fn generic_params_string(&self) -> String {
|
||||||
|
self.generic_params
|
||||||
|
.iter()
|
||||||
|
.map(ToString::to_string)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_generic_params<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Vec<Ty<'tcx>> {
|
||||||
|
ty.walk(cx.tcx)
|
||||||
|
.filter_map(|inner| match inner.unpack() {
|
||||||
|
GenericArgKind::Type(inner_ty) => Some(inner_ty),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.filter(|&inner_ty| is_ty_param(inner_ty))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ty_allowed_in_send<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, send_trait: DefId) -> bool {
|
||||||
|
raw_pointer_in_ty_def(cx, ty) || implements_trait(cx, ty, send_trait, &[]) || is_copy(cx, ty)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if the type itself is a raw pointer or has a raw pointer as a
|
/// Returns `true` if the type itself is a raw pointer or has a raw pointer as a
|
||||||
/// generic parameter, e.g., `Vec<*const u8>`.
|
/// generic parameter, e.g., `Vec<*const u8>`.
|
||||||
/// Note that it does not look into enum variants or struct fields.
|
/// Note that it does not look into enum variants or struct fields.
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
|
|
||||||
// disrustor / RUSTSEC-2020-0150
|
// disrustor / RUSTSEC-2020-0150
|
||||||
|
@ -47,6 +48,12 @@ pub struct DeviceHandle<T: UsbContext> {
|
||||||
unsafe impl<T: UsbContext> Send for DeviceHandle<T> {}
|
unsafe impl<T: UsbContext> Send for DeviceHandle<T> {}
|
||||||
|
|
||||||
// Other basic tests
|
// Other basic tests
|
||||||
|
pub struct NoGeneric {
|
||||||
|
rc_is_not_send: Rc<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for NoGeneric {}
|
||||||
|
|
||||||
pub struct MultiField<T> {
|
pub struct MultiField<T> {
|
||||||
field1: T,
|
field1: T,
|
||||||
field2: T,
|
field2: T,
|
||||||
|
@ -62,6 +69,13 @@ pub enum MyOption<T> {
|
||||||
|
|
||||||
unsafe impl<T> Send for MyOption<T> {}
|
unsafe impl<T> Send for MyOption<T> {}
|
||||||
|
|
||||||
|
// Multiple type parameters
|
||||||
|
pub struct MultiParam<A, B> {
|
||||||
|
vec: Vec<(A, B)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<A, B> Send for MultiParam<A, B> {}
|
||||||
|
|
||||||
// Raw pointers are allowed
|
// Raw pointers are allowed
|
||||||
extern "C" {
|
extern "C" {
|
||||||
type SomeFfiType;
|
type SomeFfiType;
|
||||||
|
|
|
@ -1,142 +1,158 @@
|
||||||
error: non-`Send` field found in a `Send` struct
|
error: this implementation is unsound, as some fields in `RingBuffer<T>` are `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:10:5
|
--> $DIR/non_send_field_in_send_ty.rs:16:1
|
||||||
|
|
|
||||||
LL | data: Vec<UnsafeCell<T>>,
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: `-D clippy::non-send-field-in-send-ty` implied by `-D warnings`
|
|
||||||
note: type `std::vec::Vec<std::cell::UnsafeCell<T>>` doesn't implement `Send` when `RingBuffer<T>` is `Send`
|
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:15:1
|
|
||||||
|
|
|
|
||||||
LL | unsafe impl<T> Send for RingBuffer<T> {}
|
LL | unsafe impl<T> Send for RingBuffer<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= 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`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:11:5
|
||||||
|
|
|
||||||
|
LL | data: Vec<UnsafeCell<T>>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= help: add bounds on type parameter `T` that satisfy `std::vec::Vec<std::cell::UnsafeCell<T>>: Send`
|
||||||
|
|
||||||
error: non-`Send` field found in a `Send` struct
|
error: this implementation is unsound, as some fields in `MvccRwLock<T>` are `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:20:5
|
--> $DIR/non_send_field_in_send_ty.rs:24:1
|
||||||
|
|
|
||||||
LL | lock: Mutex<Box<T>>,
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: type `std::sync::Mutex<std::boxed::Box<T>>` doesn't implement `Send` when `MvccRwLock<T>` is `Send`
|
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:23:1
|
|
||||||
|
|
|
|
||||||
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`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:21:5
|
||||||
|
|
|
||||||
|
LL | lock: Mutex<Box<T>>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
= help: add bounds on type parameter `T` that satisfy `std::sync::Mutex<std::boxed::Box<T>>: Send`
|
||||||
|
|
||||||
error: non-`Send` field found in a `Send` struct
|
error: this implementation is unsound, as some fields in `ArcGuard<RC, T>` are `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:28:5
|
--> $DIR/non_send_field_in_send_ty.rs:32:1
|
||||||
|
|
|
||||||
LL | head: Arc<RC>,
|
|
||||||
| ^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: type `std::sync::Arc<RC>` doesn't implement `Send` when `ArcGuard<RC, T>` is `Send`
|
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:31:1
|
|
||||||
|
|
|
|
||||||
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`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:29:5
|
||||||
|
|
|
||||||
|
LL | head: Arc<RC>,
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
= help: add bounds on type parameter `RC` that satisfy `std::sync::Arc<RC>: Send`
|
||||||
|
|
||||||
error: non-`Send` field found in a `Send` struct
|
error: this implementation is unsound, as some fields in `DeviceHandle<T>` are `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:43:5
|
--> $DIR/non_send_field_in_send_ty.rs:48:1
|
||||||
|
|
|
||||||
LL | context: T,
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: type `T` doesn't implement `Send` when `DeviceHandle<T>` is `Send`
|
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:47:1
|
|
||||||
|
|
|
|
||||||
LL | unsafe impl<T: UsbContext> Send for DeviceHandle<T> {}
|
LL | unsafe impl<T: UsbContext> Send for DeviceHandle<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: add `T: Send` bound
|
|
|
||||||
|
note: the field `context` has type `T` which is not `Send`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:44:5
|
||||||
|
|
|
||||||
|
LL | context: T,
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
= help: add `T: Send` bound in `Send` impl
|
||||||
|
|
||||||
error: non-`Send` field found in a `Send` struct
|
error: this implementation is unsound, as some fields in `NoGeneric` are `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:51:5
|
--> $DIR/non_send_field_in_send_ty.rs:55:1
|
||||||
|
|
|
||||||
|
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`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:52:5
|
||||||
|
|
|
||||||
|
LL | rc_is_not_send: Rc<String>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= help: use a thread-safe type that implements `Send`
|
||||||
|
|
||||||
|
error: this implementation is unsound, as some fields in `MultiField<T>` are `!Send`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:63:1
|
||||||
|
|
|
||||||
|
LL | unsafe impl<T> Send for MultiField<T> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: the field `field1` has type `T` which is not `Send`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:58:5
|
||||||
|
|
|
|
||||||
LL | field1: T,
|
LL | field1: T,
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
= help: add `T: Send` bound in `Send` impl
|
||||||
note: type `T` doesn't implement `Send` when `MultiField<T>` is `Send`
|
note: the field `field2` has type `T` which is not `Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:56:1
|
--> $DIR/non_send_field_in_send_ty.rs:59:5
|
||||||
|
|
|
||||||
LL | unsafe impl<T> Send for MultiField<T> {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: add `T: Send` bound
|
|
||||||
|
|
||||||
error: non-`Send` field found in a `Send` struct
|
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:52:5
|
|
||||||
|
|
|
|
||||||
LL | field2: T,
|
LL | field2: T,
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
= help: add `T: Send` bound in `Send` impl
|
||||||
note: type `T` doesn't implement `Send` when `MultiField<T>` is `Send`
|
note: the field `field3` has type `T` which is not `Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:56:1
|
--> $DIR/non_send_field_in_send_ty.rs:60:5
|
||||||
|
|
|
||||||
LL | unsafe impl<T> Send for MultiField<T> {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: add `T: Send` bound
|
|
||||||
|
|
||||||
error: non-`Send` field found in a `Send` struct
|
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:53:5
|
|
||||||
|
|
|
|
||||||
LL | field3: T,
|
LL | field3: T,
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
= help: add `T: Send` bound in `Send` impl
|
||||||
note: type `T` doesn't implement `Send` when `MultiField<T>` is `Send`
|
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:56:1
|
|
||||||
|
|
|
||||||
LL | unsafe impl<T> Send for MultiField<T> {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: add `T: Send` bound
|
|
||||||
|
|
||||||
error: non-`Send` field found in a `Send` struct
|
error: this implementation is unsound, as some fields in `MyOption<T>` are `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:59:12
|
--> $DIR/non_send_field_in_send_ty.rs:70:1
|
||||||
|
|
|
||||||
LL | MySome(T),
|
|
||||||
| ^
|
|
||||||
|
|
|
||||||
note: type `T` doesn't implement `Send` when `MyOption<T>` is `Send`
|
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:63:1
|
|
||||||
|
|
|
|
||||||
LL | unsafe impl<T> Send for MyOption<T> {}
|
LL | unsafe impl<T> Send for MyOption<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: add `T: Send` bound
|
|
|
||||||
|
note: the field `0` has type `T` which is not `Send`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:66:12
|
||||||
|
|
|
||||||
|
LL | MySome(T),
|
||||||
|
| ^
|
||||||
|
= help: add `T: Send` bound in `Send` impl
|
||||||
|
|
||||||
error: non-`Send` field found in a `Send` struct
|
error: this implementation is unsound, as some fields in `MultiParam<A, B>` are `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:88:11
|
--> $DIR/non_send_field_in_send_ty.rs:77:1
|
||||||
|
|
|
|
||||||
LL | Enum2(T),
|
LL | unsafe impl<A, B> Send for MultiParam<A, B> {}
|
||||||
| ^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: type `T` doesn't implement `Send` when `AttrTest3<T>` is `Send`
|
note: the field `vec` has type `std::vec::Vec<(A, B)>` which is not `Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:93:1
|
--> $DIR/non_send_field_in_send_ty.rs:74:5
|
||||||
|
|
|
||||||
|
LL | vec: Vec<(A, B)>,
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
= help: add bounds on type parameters `A, B` that satisfy `std::vec::Vec<(A, B)>: Send`
|
||||||
|
|
||||||
|
error: this implementation is unsound, as some fields in `AttrTest3<T>` are `!Send`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:107:1
|
||||||
|
|
|
|
||||||
LL | unsafe impl<T> Send for AttrTest3<T> {}
|
LL | unsafe impl<T> Send for AttrTest3<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: add `T: Send` bound
|
|
|
||||||
|
note: the field `0` has type `T` which is not `Send`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:102:11
|
||||||
|
|
|
||||||
|
LL | Enum2(T),
|
||||||
|
| ^
|
||||||
|
= help: add `T: Send` bound in `Send` impl
|
||||||
|
|
||||||
error: non-`Send` field found in a `Send` struct
|
error: this implementation is unsound, as some fields in `Complex<P, u32>` are `!Send`
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:97:5
|
--> $DIR/non_send_field_in_send_ty.rs:115:1
|
||||||
|
|
|
||||||
LL | field1: A,
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: type `P` doesn't implement `Send` when `Complex<P, u32>` is `Send`
|
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:101:1
|
|
||||||
|
|
|
|
||||||
LL | unsafe impl<P> Send for Complex<P, u32> {}
|
LL | unsafe impl<P> Send for Complex<P, u32> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: add `P: Send` bound
|
|
||||||
|
|
||||||
error: non-`Send` field found in a `Send` struct
|
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:98:5
|
|
||||||
|
|
|
|
||||||
LL | field2: B,
|
note: the field `field1` has type `P` which is not `Send`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:111:5
|
||||||
|
|
|
||||||
|
LL | field1: A,
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
= help: add `P: Send` bound in `Send` impl
|
||||||
note: type `std::sync::MutexGuard<'static, bool>` doesn't implement `Send` when `Complex<Q, std::sync::MutexGuard<'static, bool>>` is `Send`
|
|
||||||
--> $DIR/non_send_field_in_send_ty.rs:104:1
|
error: this implementation is unsound, as some fields in `Complex<Q, std::sync::MutexGuard<'static, bool>>` are `!Send`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:118:1
|
||||||
|
|
|
|
||||||
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`
|
||||||
|
--> $DIR/non_send_field_in_send_ty.rs:112:5
|
||||||
|
|
|
||||||
|
LL | field2: B,
|
||||||
|
| ^^^^^^^^^
|
||||||
|
= help: use a thread-safe type that implements `Send`
|
||||||
|
|
||||||
error: aborting due to 11 previous errors
|
error: aborting due to 11 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue