Skip to content

Commit 4f01656

Browse files
committed
Add ui-test for enable-raw-pointer-heuristic-for-send config
1 parent 08f0aec commit 4f01656

File tree

5 files changed

+149
-6
lines changed

5 files changed

+149
-6
lines changed

clippy_lints/src/non_send_field_in_send_ty.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
6868
let ty_allowed_in_send = if self.enable_raw_pointer_heuristic {
6969
ty_allowed_with_raw_pointer_heuristic
7070
} else {
71-
ty_implements_send_or_copy
71+
ty_allowed_without_raw_pointer_heuristic
7272
};
7373

7474
// Checks if we are in `Send` impl item.
@@ -176,14 +176,22 @@ fn collect_generic_params<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Vec<Ty<
176176
.collect()
177177
}
178178

179-
/// Determine if the given type is `Send` or `Copy`
180-
fn ty_implements_send_or_copy(cx: &LateContext<'tcx>, ty: Ty<'tcx>, send_trait: DefId) -> bool {
181-
implements_trait(cx, ty, send_trait, &[]) || is_copy(cx, ty)
179+
/// Be more strict when the heuristic is disabled
180+
fn ty_allowed_without_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, send_trait: DefId) -> bool {
181+
if implements_trait(cx, ty, send_trait, &[]) {
182+
return true;
183+
}
184+
185+
if is_copy(cx, ty) && !contains_raw_pointer(cx, ty) {
186+
return true;
187+
}
188+
189+
false
182190
}
183191

184192
/// Heuristic to allow cases like `Vec<*const u8>`
185193
fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, send_trait: DefId) -> bool {
186-
if ty_implements_send_or_copy(cx, ty, send_trait) {
194+
if implements_trait(cx, ty, send_trait, &[]) || is_copy(cx, ty) {
187195
return true;
188196
}
189197

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
enable-raw-pointer-heuristic-for-send = false
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#![warn(clippy::non_send_field_in_send_ty)]
2+
#![feature(extern_types)]
3+
4+
use std::rc::Rc;
5+
6+
// Basic tests should not be affected
7+
pub struct NoGeneric {
8+
rc_is_not_send: Rc<String>,
9+
}
10+
11+
unsafe impl Send for NoGeneric {}
12+
13+
pub struct MultiField<T> {
14+
field1: T,
15+
field2: T,
16+
field3: T,
17+
}
18+
19+
unsafe impl<T> Send for MultiField<T> {}
20+
21+
pub enum MyOption<T> {
22+
MySome(T),
23+
MyNone,
24+
}
25+
26+
unsafe impl<T> Send for MyOption<T> {}
27+
28+
// All fields are disallowed when raw pointer heuristic is off
29+
extern "C" {
30+
type NonSend;
31+
}
32+
33+
pub struct HeuristicTest {
34+
field1: Vec<*const NonSend>,
35+
field2: [*const NonSend; 3],
36+
field3: (*const NonSend, *const NonSend, *const NonSend),
37+
field4: (*const NonSend, Rc<u8>),
38+
field5: Vec<Vec<*const NonSend>>,
39+
}
40+
41+
unsafe impl Send for HeuristicTest {}
42+
43+
fn main() {}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
error: this implementation is unsound, as some fields in `NoGeneric` are `!Send`
2+
--> $DIR/test.rs:11:1
3+
|
4+
LL | unsafe impl Send for NoGeneric {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::non-send-field-in-send-ty` implied by `-D warnings`
8+
note: the field `rc_is_not_send` has type `std::rc::Rc<std::string::String>` which is `!Send`
9+
--> $DIR/test.rs:8:5
10+
|
11+
LL | rc_is_not_send: Rc<String>,
12+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
= help: use a thread-safe type that implements `Send`
14+
15+
error: this implementation is unsound, as some fields in `MultiField<T>` are `!Send`
16+
--> $DIR/test.rs:19:1
17+
|
18+
LL | unsafe impl<T> Send for MultiField<T> {}
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
|
21+
note: the field `field1` has type `T` which is `!Send`
22+
--> $DIR/test.rs:14:5
23+
|
24+
LL | field1: T,
25+
| ^^^^^^^^^
26+
= help: add `T: Send` bound in `Send` impl
27+
note: the field `field2` has type `T` which is `!Send`
28+
--> $DIR/test.rs:15:5
29+
|
30+
LL | field2: T,
31+
| ^^^^^^^^^
32+
= help: add `T: Send` bound in `Send` impl
33+
note: the field `field3` has type `T` which is `!Send`
34+
--> $DIR/test.rs:16:5
35+
|
36+
LL | field3: T,
37+
| ^^^^^^^^^
38+
= help: add `T: Send` bound in `Send` impl
39+
40+
error: this implementation is unsound, as some fields in `MyOption<T>` are `!Send`
41+
--> $DIR/test.rs:26:1
42+
|
43+
LL | unsafe impl<T> Send for MyOption<T> {}
44+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
45+
|
46+
note: the field `0` has type `T` which is `!Send`
47+
--> $DIR/test.rs:22:12
48+
|
49+
LL | MySome(T),
50+
| ^
51+
= help: add `T: Send` bound in `Send` impl
52+
53+
error: this implementation is unsound, as some fields in `HeuristicTest` are `!Send`
54+
--> $DIR/test.rs:41:1
55+
|
56+
LL | unsafe impl Send for HeuristicTest {}
57+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
58+
|
59+
note: the field `field1` has type `std::vec::Vec<*const NonSend>` which is `!Send`
60+
--> $DIR/test.rs:34:5
61+
|
62+
LL | field1: Vec<*const NonSend>,
63+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
64+
= help: use a thread-safe type that implements `Send`
65+
note: the field `field2` has type `[*const NonSend; 3]` which is `!Send`
66+
--> $DIR/test.rs:35:5
67+
|
68+
LL | field2: [*const NonSend; 3],
69+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
70+
= help: use a thread-safe type that implements `Send`
71+
note: the field `field3` has type `(*const NonSend, *const NonSend, *const NonSend)` which is `!Send`
72+
--> $DIR/test.rs:36:5
73+
|
74+
LL | field3: (*const NonSend, *const NonSend, *const NonSend),
75+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
76+
= help: use a thread-safe type that implements `Send`
77+
note: the field `field4` has type `(*const NonSend, std::rc::Rc<u8>)` which is `!Send`
78+
--> $DIR/test.rs:37:5
79+
|
80+
LL | field4: (*const NonSend, Rc<u8>),
81+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
82+
= help: use a thread-safe type that implements `Send`
83+
note: the field `field5` has type `std::vec::Vec<std::vec::Vec<*const NonSend>>` which is `!Send`
84+
--> $DIR/test.rs:38:5
85+
|
86+
LL | field5: Vec<Vec<*const NonSend>>,
87+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
88+
= help: use a thread-safe type that implements `Send`
89+
90+
error: aborting due to 4 previous errors
91+
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `avoid-breaking-exported-api`, `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `disallowed-types`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `standard-macro-braces`, `enforced-import-renames`, `allowed-scripts`, `enable-raw-pointer-heuristic`, `third-party` at line 5 column 1
1+
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `avoid-breaking-exported-api`, `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `disallowed-types`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `standard-macro-braces`, `enforced-import-renames`, `allowed-scripts`, `enable-raw-pointer-heuristic-for-send`, `third-party` at line 5 column 1
22

33
error: aborting due to previous error
44

0 commit comments

Comments
 (0)