Skip to content

Commit 7f5b713

Browse files
committed
add pre_rfc examples
1 parent 40a4ed5 commit 7f5b713

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed

tests/ui/compile-fail/pre_rfc.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#![allow(clippy::disallowed_names)]
2+
3+
use std::mem::MaybeUninit;
4+
5+
use field_projection::compat::{HasFields, p, start_proj};
6+
7+
#[derive(HasFields)]
8+
struct Foo {
9+
field: usize,
10+
bar: Bar,
11+
}
12+
13+
#[derive(HasFields)]
14+
struct Bar {
15+
x: u32,
16+
}
17+
18+
// Very simple first example with type annotations.
19+
fn example1(mut foo: &mut MaybeUninit<Foo>) -> usize {
20+
fn validate(_: &MaybeUninit<usize>) {}
21+
22+
start_proj!(mut foo);
23+
let field: &MaybeUninit<usize> = p!(@foo->field);
24+
// we are allowed to share-project `field` again:
25+
validate(p!(@foo->field));
26+
let mut bar: &mut MaybeUninit<Bar> = p!(@mut foo->bar);
27+
start_proj!(mut bar);
28+
let x: &mut MaybeUninit<u32> = p!(@mut bar->x);
29+
x.write(42);
30+
unsafe { field.assume_init_read() }
31+
}
32+
33+
// Exclusive projections are exclusive, so this doesn't compile.
34+
fn example2(mut foo: &mut MaybeUninit<Foo>) {
35+
start_proj!(mut foo);
36+
let a = p!(@mut foo->field);
37+
// ------------------- first exclusive projection occurs here
38+
let b = p!(@mut foo->field);
39+
// ^^^^^^^^^^^^^^^^^^^ second exclusive projection occurs here
40+
MaybeUninit::write(a, 42);
41+
// - first projection later used here
42+
}
43+
44+
// When a value is being projected in any way, it must not be accessed normally.
45+
fn example3(foo: &mut MaybeUninit<Foo>) -> usize {
46+
start_proj!(foo);
47+
let field = p!(@foo->field);
48+
// --------------- shared projection occurs here
49+
let value = Foo {
50+
field: 42,
51+
bar: Bar { x: 72 },
52+
};
53+
MaybeUninit::write(foo, value);
54+
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^ projected value used here
55+
unsafe { field.assume_init_read() }
56+
// ----- shared projection used here
57+
}
58+
59+
fn example3_allowed_in_exp_impl(foo: &mut MaybeUninit<Foo>) -> usize {
60+
start_proj!(foo);
61+
let field = p!(@foo->field);
62+
let _ = unsafe { foo.assume_init_read() };
63+
unsafe { field.assume_init_read() }
64+
}
65+
66+
fn move_projections<'a>(foo: &'a mut MaybeUninit<Foo>) -> &'a mut MaybeUninit<Bar> {
67+
start_proj!(move foo);
68+
p!(@move mut foo->bar)
69+
}
70+
71+
fn move_projections_motivation<'a>(mut foo: &'a mut MaybeUninit<Foo>) -> &'a mut MaybeUninit<Bar> {
72+
start_proj!(mut foo);
73+
//------------------ `foo` is borrowed here
74+
p!(@mut foo->bar)
75+
// ^^^^^^^^^^^^^ returns a value referencing data owned by the current function
76+
}
77+
78+
fn main() {}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
error[E0599]: no function or associated item named `project_move_mut` found for struct `ProjectedField` in the current scope
2+
--> tests/ui/compile-fail/pre_rfc.rs:68:5
3+
|
4+
68 | p!(@move mut foo->bar)
5+
| ^^^^^^^^^^^^^^^^^^^^^^ function or associated item not found in `ProjectedField<_, _>`
6+
|
7+
note: if you're trying to build a new `ProjectedField<_, _>`, consider using `ProjectedField::<P, F>::__new` which returns `ProjectedField<_, _>`
8+
--> src/compat.rs
9+
|
10+
| pub unsafe fn __new() -> Self {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
help: there is a method `project_move` with a similar name, but with different arguments
13+
--> src/compat.rs
14+
|
15+
| / pub unsafe fn project_move<'a>(self, raw: *const P) -> <P as Project<F>>::Output<'a>
16+
| | where
17+
| | P: Project<F>,
18+
| |______________________^
19+
= note: this error originates in the macro `p` (in Nightly builds, run with -Z macro-backtrace for more info)
20+
21+
warning: unused variable: `b`
22+
--> tests/ui/compile-fail/pre_rfc.rs:38:9
23+
|
24+
38 | let b = p!(@mut foo->field);
25+
| ^ help: if this is intentional, prefix it with an underscore: `_b`
26+
|
27+
= note: `#[warn(unused_variables)]` on by default
28+
29+
error[E0499]: cannot borrow value as mutable more than once at a time
30+
--> tests/ui/compile-fail/pre_rfc.rs:38:13
31+
|
32+
36 | let a = p!(@mut foo->field);
33+
| ------------------- first mutable borrow occurs here
34+
37 | // ------------------- first exclusive projection occurs here
35+
38 | let b = p!(@mut foo->field);
36+
| ^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
37+
39 | // ^^^^^^^^^^^^^^^^^^^ second exclusive projection occurs here
38+
40 | MaybeUninit::write(a, 42);
39+
| - first borrow later used here
40+
|
41+
= note: this error originates in the macro `p` (in Nightly builds, run with -Z macro-backtrace for more info)
42+
43+
error[E0502]: cannot borrow `*foo` as mutable because it is also borrowed as immutable
44+
--> tests/ui/compile-fail/pre_rfc.rs:53:5
45+
|
46+
46 | start_proj!(foo);
47+
| ---------------- immutable borrow occurs here
48+
...
49+
53 | MaybeUninit::write(foo, value);
50+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
51+
54 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ projected value used here
52+
55 | unsafe { field.assume_init_read() }
53+
| ----- immutable borrow later used here
54+
55+
error[E0515]: cannot return value referencing function parameter `foo`
56+
--> tests/ui/compile-fail/pre_rfc.rs:74:8
57+
|
58+
72 | start_proj!(mut foo);
59+
| -------------------- `foo` is borrowed here
60+
73 | //------------------ `foo` is borrowed here
61+
74 | p!(@mut foo->bar)
62+
| ^^^^^^^^^^^^^ returns a value referencing data owned by the current function

0 commit comments

Comments
 (0)