Skip to content

Commit 1f3b659

Browse files
committed
Auto merge of #69573 - pnkfelix:issue-53114-add-tests, r=Centril
tests encoding current behavior for various cases of "binding" to _. The `_` binding form is special, in that it encodes a "no-op": nothing is actually bound, and thus nothing is moved or borrowed in this scenario. Usually we do the "right" thing in all such cases. The exceptions are explicitly pointed out in this test case, so that we keep track of whether they are eventually fixed. Cc #53114. (This does not close the aforementioned issue; it just adds the tests encoding the current behavior, which we hope to eventually fix.)
2 parents f363450 + 22ea3a4 commit 1f3b659

4 files changed

+300
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Issue #53114: NLL's borrow check had some deviations from the old borrow
2+
// checker, and both had some deviations from our ideal state. This test
3+
// captures the behavior of how `_` bindings are handled with respect to how we
4+
// flag expressions that are meant to request unsafe blocks.
5+
#![allow(irrefutable_let_patterns)]
6+
struct M;
7+
8+
fn let_wild_gets_moved_expr() {
9+
let m = M;
10+
drop(m);
11+
let _ = m; // accepted, and want it to continue to be
12+
13+
let mm = (M, M); // variation on above with `_` in substructure
14+
let (_x, _) = mm;
15+
let (_, _y) = mm;
16+
let (_, _) = mm;
17+
}
18+
19+
fn match_moved_expr_to_wild() {
20+
let m = M;
21+
drop(m);
22+
match m { _ => { } } // #53114: should eventually be accepted too
23+
//~^ ERROR [E0382]
24+
25+
let mm = (M, M); // variation on above with `_` in substructure
26+
match mm { (_x, _) => { } }
27+
match mm { (_, _y) => { } }
28+
//~^ ERROR [E0382]
29+
match mm { (_, _) => { } }
30+
//~^ ERROR [E0382]
31+
}
32+
33+
fn if_let_moved_expr_to_wild() {
34+
let m = M;
35+
drop(m);
36+
if let _ = m { } // #53114: should eventually be accepted too
37+
//~^ ERROR [E0382]
38+
39+
let mm = (M, M); // variation on above with `_` in substructure
40+
if let (_x, _) = mm { }
41+
if let (_, _y) = mm { }
42+
//~^ ERROR [E0382]
43+
if let (_, _) = mm { }
44+
//~^ ERROR [E0382]
45+
}
46+
47+
fn let_wild_gets_borrowed_expr() {
48+
let mut m = M;
49+
let r = &mut m;
50+
let _ = m; // accepted, and want it to continue to be
51+
// let _x = m; // (compare with this error.)
52+
drop(r);
53+
54+
let mut mm = (M, M); // variation on above with `_` in substructure
55+
let (r1, r2) = (&mut mm.0, &mut mm.1);
56+
let (_, _) = mm;
57+
drop((r1, r2));
58+
}
59+
60+
fn match_borrowed_expr_to_wild() {
61+
let mut m = M;
62+
let r = &mut m;
63+
match m { _ => {} } ; // accepted, and want it to continue to be
64+
drop(r);
65+
66+
let mut mm = (M, M); // variation on above with `_` in substructure
67+
let (r1, r2) = (&mut mm.0, &mut mm.1);
68+
match mm { (_, _) => { } }
69+
drop((r1, r2));
70+
}
71+
72+
fn if_let_borrowed_expr_to_wild() {
73+
let mut m = M;
74+
let r = &mut m;
75+
if let _ = m { } // accepted, and want it to continue to be
76+
drop(r);
77+
78+
let mut mm = (M, M); // variation on above with `_` in substructure
79+
let (r1, r2) = (&mut mm.0, &mut mm.1);
80+
if let (_, _) = mm { }
81+
drop((r1, r2));
82+
}
83+
84+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
error[E0382]: use of moved value: `m`
2+
--> $DIR/issue-53114-borrow-checks.rs:22:11
3+
|
4+
LL | let m = M;
5+
| - move occurs because `m` has type `M`, which does not implement the `Copy` trait
6+
LL | drop(m);
7+
| - value moved here
8+
LL | match m { _ => { } } // #53114: should eventually be accepted too
9+
| ^ value used here after move
10+
11+
error[E0382]: use of moved value: `mm`
12+
--> $DIR/issue-53114-borrow-checks.rs:27:11
13+
|
14+
LL | match mm { (_x, _) => { } }
15+
| -- value moved here
16+
LL | match mm { (_, _y) => { } }
17+
| ^^ value used here after partial move
18+
|
19+
= note: move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait
20+
21+
error[E0382]: use of moved value: `mm`
22+
--> $DIR/issue-53114-borrow-checks.rs:29:11
23+
|
24+
LL | match mm { (_, _y) => { } }
25+
| -- value moved here
26+
LL |
27+
LL | match mm { (_, _) => { } }
28+
| ^^ value used here after partial move
29+
|
30+
= note: move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait
31+
32+
error[E0382]: use of moved value: `m`
33+
--> $DIR/issue-53114-borrow-checks.rs:36:16
34+
|
35+
LL | let m = M;
36+
| - move occurs because `m` has type `M`, which does not implement the `Copy` trait
37+
LL | drop(m);
38+
| - value moved here
39+
LL | if let _ = m { } // #53114: should eventually be accepted too
40+
| ^ value used here after move
41+
42+
error[E0382]: use of moved value: `mm`
43+
--> $DIR/issue-53114-borrow-checks.rs:41:22
44+
|
45+
LL | if let (_x, _) = mm { }
46+
| -- value moved here
47+
LL | if let (_, _y) = mm { }
48+
| ^^ value used here after partial move
49+
|
50+
= note: move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait
51+
52+
error[E0382]: use of moved value: `mm`
53+
--> $DIR/issue-53114-borrow-checks.rs:43:21
54+
|
55+
LL | if let (_, _y) = mm { }
56+
| -- value moved here
57+
LL |
58+
LL | if let (_, _) = mm { }
59+
| ^^ value used here after partial move
60+
|
61+
= note: move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait
62+
63+
error: aborting due to 6 previous errors
64+
65+
For more information about this error, try `rustc --explain E0382`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Issue #53114: NLL's borrow check had some deviations from the old borrow
2+
// checker, and both had some deviations from our ideal state. This test
3+
// captures the behavior of how `_` bindings are handled with respect to how we
4+
// flag expressions that are meant to request unsafe blocks.
5+
6+
#![feature(untagged_unions)]
7+
8+
struct I(i64);
9+
struct F(f64);
10+
11+
union U { a: I, b: F }
12+
13+
#[repr(packed)]
14+
struct P {
15+
a: &'static i8,
16+
b: &'static u32,
17+
}
18+
19+
fn let_wild_gets_unsafe_field() {
20+
let u1 = U { a: I(0) };
21+
let u2 = U { a: I(1) };
22+
let p = P { a: &2, b: &3 };
23+
let _ = &p.b; //~ WARN E0133
24+
//~^ WARN will become a hard error
25+
let _ = u1.a; // #53114: should eventually signal error as well
26+
let _ = &u2.a; //~ ERROR [E0133]
27+
28+
// variation on above with `_` in substructure
29+
let (_,) = (&p.b,); //~ WARN E0133
30+
//~^ WARN will become a hard error
31+
let (_,) = (u1.a,); //~ ERROR [E0133]
32+
let (_,) = (&u2.a,); //~ ERROR [E0133]
33+
}
34+
35+
fn match_unsafe_field_to_wild() {
36+
let u1 = U { a: I(0) };
37+
let u2 = U { a: I(1) };
38+
let p = P { a: &2, b: &3 };
39+
match &p.b { _ => { } } //~ WARN E0133
40+
//~^ WARN will become a hard error
41+
match u1.a { _ => { } } //~ ERROR [E0133]
42+
match &u2.a { _ => { } } //~ ERROR [E0133]
43+
44+
// variation on above with `_` in substructure
45+
match (&p.b,) { (_,) => { } } //~ WARN E0133
46+
//~^ WARN will become a hard error
47+
match (u1.a,) { (_,) => { } } //~ ERROR [E0133]
48+
match (&u2.a,) { (_,) => { } } //~ ERROR [E0133]
49+
}
50+
51+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
2+
--> $DIR/issue-53114-safety-checks.rs:23:13
3+
|
4+
LL | let _ = &p.b;
5+
| ^^^^
6+
|
7+
= note: `#[warn(safe_packed_borrows)]` on by default
8+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
9+
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
10+
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
11+
12+
error[E0133]: access to union field is unsafe and requires unsafe function or block
13+
--> $DIR/issue-53114-safety-checks.rs:26:13
14+
|
15+
LL | let _ = &u2.a;
16+
| ^^^^^ access to union field
17+
|
18+
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
19+
20+
warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
21+
--> $DIR/issue-53114-safety-checks.rs:29:17
22+
|
23+
LL | let (_,) = (&p.b,);
24+
| ^^^^
25+
|
26+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
27+
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
28+
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
29+
30+
error[E0133]: access to union field is unsafe and requires unsafe function or block
31+
--> $DIR/issue-53114-safety-checks.rs:31:17
32+
|
33+
LL | let (_,) = (u1.a,);
34+
| ^^^^ access to union field
35+
|
36+
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
37+
38+
error[E0133]: access to union field is unsafe and requires unsafe function or block
39+
--> $DIR/issue-53114-safety-checks.rs:32:17
40+
|
41+
LL | let (_,) = (&u2.a,);
42+
| ^^^^^ access to union field
43+
|
44+
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
45+
46+
warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
47+
--> $DIR/issue-53114-safety-checks.rs:39:11
48+
|
49+
LL | match &p.b { _ => { } }
50+
| ^^^^
51+
|
52+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
53+
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
54+
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
55+
56+
error[E0133]: access to union field is unsafe and requires unsafe function or block
57+
--> $DIR/issue-53114-safety-checks.rs:41:11
58+
|
59+
LL | match u1.a { _ => { } }
60+
| ^^^^ access to union field
61+
|
62+
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
63+
64+
error[E0133]: access to union field is unsafe and requires unsafe function or block
65+
--> $DIR/issue-53114-safety-checks.rs:42:11
66+
|
67+
LL | match &u2.a { _ => { } }
68+
| ^^^^^ access to union field
69+
|
70+
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
71+
72+
warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
73+
--> $DIR/issue-53114-safety-checks.rs:45:12
74+
|
75+
LL | match (&p.b,) { (_,) => { } }
76+
| ^^^^
77+
|
78+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
79+
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
80+
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
81+
82+
error[E0133]: access to union field is unsafe and requires unsafe function or block
83+
--> $DIR/issue-53114-safety-checks.rs:47:12
84+
|
85+
LL | match (u1.a,) { (_,) => { } }
86+
| ^^^^ access to union field
87+
|
88+
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
89+
90+
error[E0133]: access to union field is unsafe and requires unsafe function or block
91+
--> $DIR/issue-53114-safety-checks.rs:48:12
92+
|
93+
LL | match (&u2.a,) { (_,) => { } }
94+
| ^^^^^ access to union field
95+
|
96+
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
97+
98+
error: aborting due to 7 previous errors
99+
100+
For more information about this error, try `rustc --explain E0133`.

0 commit comments

Comments
 (0)