Skip to content

Commit cf57f50

Browse files
committed
Add mir opt tests to be sure we generate copy, clones and moves when corresponds
1 parent d7e95b0 commit cf57f50

5 files changed

+394
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// MIR for `ergonomic_clone_closure_copy` 0 nll
2+
3+
| Free Region Mapping
4+
| '?0 | Global | ['?0, '?1]
5+
| '?1 | Local | ['?1]
6+
|
7+
| Inferred Region Values
8+
| '?0 | U0 | {bb0[0..=19], '?0, '?1}
9+
| '?1 | U0 | {bb0[0..=19], '?1}
10+
|
11+
| Inference Constraints
12+
| '?0 live at {bb0[0..=19]}
13+
| '?1 live at {bb0[0..=19]}
14+
|
15+
fn ergonomic_clone_closure_copy() -> i32 {
16+
let mut _0: i32;
17+
let _1: i32;
18+
let mut _3: i32;
19+
let mut _5: i32;
20+
scope 1 {
21+
debug i => _1;
22+
let _2: {closure@$DIR/closure.rs:38:14: 38:20};
23+
scope 2 {
24+
debug i1 => _2;
25+
let _4: {closure@$DIR/closure.rs:40:14: 40:20};
26+
scope 3 {
27+
debug i2 => _4;
28+
}
29+
}
30+
}
31+
32+
bb0: {
33+
StorageLive(_1);
34+
_1 = const 1_i32;
35+
FakeRead(ForLet(None), _1);
36+
StorageLive(_2);
37+
StorageLive(_3);
38+
_3 = copy _1;
39+
_2 = {closure@$DIR/closure.rs:38:14: 38:20} { i: move _3 };
40+
StorageDead(_3);
41+
FakeRead(ForLet(None), _2);
42+
StorageLive(_4);
43+
StorageLive(_5);
44+
_5 = copy _1;
45+
_4 = {closure@$DIR/closure.rs:40:14: 40:20} { i: move _5 };
46+
StorageDead(_5);
47+
FakeRead(ForLet(None), _4);
48+
_0 = copy _1;
49+
StorageDead(_4);
50+
StorageDead(_2);
51+
StorageDead(_1);
52+
return;
53+
}
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// MIR for `ergonomic_clone_closure_move` 0 nll
2+
3+
| Free Region Mapping
4+
| '?0 | Global | ['?0, '?1]
5+
| '?1 | Local | ['?1]
6+
|
7+
| Inferred Region Values
8+
| '?0 | U0 | {bb0[0..=1], bb1[0..=5], bb2[0..=6], bb3[0..=2], bb4[0..=1], bb5[0..=1], bb6[0], bb7[0], bb8[0], bb9[0], '?0, '?1}
9+
| '?1 | U0 | {bb0[0..=1], bb1[0..=5], bb2[0..=6], bb3[0..=2], bb4[0..=1], bb5[0..=1], bb6[0], bb7[0], bb8[0], bb9[0], '?1}
10+
| '?2 | U0 | {bb0[1]}
11+
| '?3 | U0 | {bb0[1]}
12+
| '?4 | U0 | {bb0[1]}
13+
|
14+
| Inference Constraints
15+
| '?0 live at {bb0[0..=1], bb1[0..=5], bb2[0..=6], bb3[0..=2], bb4[0..=1], bb5[0..=1], bb6[0], bb7[0], bb8[0], bb9[0]}
16+
| '?1 live at {bb0[0..=1], bb1[0..=5], bb2[0..=6], bb3[0..=2], bb4[0..=1], bb5[0..=1], bb6[0], bb7[0], bb8[0], bb9[0]}
17+
| '?2 live at {bb0[1]}
18+
| '?3 live at {bb0[1]}
19+
| '?2: '?4 due to TypeAnnotation(GenericArg) at Single(bb0[1]) ($DIR/closure.rs:12:13: 12:31 (#0)
20+
| '?3: '?2 due to CallArgument(Some(FnDef(DefId(2:3321 ~ core[88f8]::convert::From::from), [std::string::String, &'{erased} str]))) at Single(bb0[1]) ($DIR/closure.rs:12:13: 12:31 (#0)
21+
| '?4: '?2 due to TypeAnnotation(GenericArg) at Single(bb0[1]) ($DIR/closure.rs:12:13: 12:31 (#0)
22+
|
23+
| User Type Annotations
24+
| 0: user_ty: Canonical { value: TypeOf(DefId(2:3321 ~ core[88f8]::convert::From::from), UserArgs { args: [std::string::String, ^0], user_self_ty: None }), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/closure.rs:12:13: 12:25, inferred_ty: fn(&str) -> std::string::String {<std::string::String as std::convert::From<&str>>::from}
25+
|
26+
fn ergonomic_clone_closure_move() -> String {
27+
let mut _0: std::string::String;
28+
let _1: std::string::String;
29+
let mut _3: std::string::String;
30+
let mut _4: {closure@$DIR/closure.rs:14:14: 14:20};
31+
let mut _5: ();
32+
scope 1 {
33+
debug s => _1;
34+
let _2: {closure@$DIR/closure.rs:14:14: 14:20};
35+
scope 2 {
36+
debug cl => _2;
37+
}
38+
}
39+
40+
bb0: {
41+
StorageLive(_1);
42+
_1 = <String as From<&str>>::from(const "hi") -> [return: bb1, unwind: bb9];
43+
}
44+
45+
bb1: {
46+
FakeRead(ForLet(None), _1);
47+
StorageLive(_2);
48+
StorageLive(_3);
49+
_3 = move _1;
50+
_2 = {closure@$DIR/closure.rs:14:14: 14:20} { s: move _3 };
51+
drop(_3) -> [return: bb2, unwind: bb8];
52+
}
53+
54+
bb2: {
55+
StorageDead(_3);
56+
FakeRead(ForLet(None), _2);
57+
StorageLive(_4);
58+
_4 = move _2;
59+
StorageLive(_5);
60+
_5 = ();
61+
_0 = <{closure@$DIR/closure.rs:14:14: 14:20} as FnOnce<()>>::call_once(move _4, move _5) -> [return: bb3, unwind: bb6];
62+
}
63+
64+
bb3: {
65+
StorageDead(_5);
66+
StorageDead(_4);
67+
drop(_2) -> [return: bb4, unwind: bb8];
68+
}
69+
70+
bb4: {
71+
StorageDead(_2);
72+
drop(_1) -> [return: bb5, unwind: bb9];
73+
}
74+
75+
bb5: {
76+
StorageDead(_1);
77+
return;
78+
}
79+
80+
bb6 (cleanup): {
81+
drop(_4) -> [return: bb7, unwind terminate(cleanup)];
82+
}
83+
84+
bb7 (cleanup): {
85+
drop(_2) -> [return: bb8, unwind terminate(cleanup)];
86+
}
87+
88+
bb8 (cleanup): {
89+
drop(_1) -> [return: bb9, unwind terminate(cleanup)];
90+
}
91+
92+
bb9 (cleanup): {
93+
resume;
94+
}
95+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// MIR for `ergonomic_clone_closure_use_cloned` 0 nll
2+
3+
| Free Region Mapping
4+
| '?0 | Global | ['?0, '?1]
5+
| '?1 | Local | ['?1]
6+
|
7+
| Inferred Region Values
8+
| '?0 | U0 | {bb0[0..=6], bb1[0..=6], bb2[0..=7], '?0, '?1}
9+
| '?1 | U0 | {bb0[0..=6], bb1[0..=6], bb2[0..=7], '?1}
10+
| '?2 | U0 | {bb0[5..=6]}
11+
| '?3 | U0 | {bb1[5..=6]}
12+
| '?4 | U0 | {bb0[6]}
13+
| '?5 | U0 | {bb1[6]}
14+
| '?6 | U0 | {bb0[6]}
15+
| '?7 | U0 | {bb1[6]}
16+
|
17+
| Inference Constraints
18+
| '?0 live at {bb0[0..=6], bb1[0..=6], bb2[0..=7]}
19+
| '?1 live at {bb0[0..=6], bb1[0..=6], bb2[0..=7]}
20+
| '?2 live at {bb0[5]}
21+
| '?3 live at {bb1[5]}
22+
| '?4 live at {bb0[6]}
23+
| '?5 live at {bb1[6]}
24+
| '?6 live at {bb0[6]}
25+
| '?7 live at {bb1[6]}
26+
| '?2: '?4 due to Boring at Single(bb0[5]) ($DIR/closure.rs:27:14: 27:22 (#0)
27+
| '?3: '?5 due to Boring at Single(bb1[5]) ($DIR/closure.rs:29:14: 29:22 (#0)
28+
| '?4: '?6 due to Boring at Single(bb0[6]) ($DIR/closure.rs:27:14: 27:22 (#0)
29+
| '?5: '?7 due to Boring at Single(bb1[6]) ($DIR/closure.rs:29:14: 29:22 (#0)
30+
|
31+
| Borrows
32+
| bw0: issued at bb0[5] in '?2
33+
| bw1: issued at bb1[5] in '?3
34+
|
35+
fn ergonomic_clone_closure_use_cloned() -> Foo {
36+
let mut _0: Foo;
37+
let _1: Foo;
38+
let mut _3: Foo;
39+
let mut _4: &Foo;
40+
let mut _6: Foo;
41+
let mut _7: &Foo;
42+
scope 1 {
43+
debug f => _1;
44+
let _2: {closure@$DIR/closure.rs:27:14: 27:20};
45+
scope 2 {
46+
debug f1 => _2;
47+
let _5: {closure@$DIR/closure.rs:29:14: 29:20};
48+
scope 3 {
49+
debug f2 => _5;
50+
}
51+
}
52+
}
53+
54+
bb0: {
55+
StorageLive(_1);
56+
_1 = Foo;
57+
FakeRead(ForLet(None), _1);
58+
StorageLive(_2);
59+
StorageLive(_3);
60+
_4 = &_1;
61+
_3 = <Foo as Clone>::clone(move _4) -> [return: bb1, unwind unreachable];
62+
}
63+
64+
bb1: {
65+
_2 = {closure@$DIR/closure.rs:27:14: 27:20} { f: move _3 };
66+
StorageDead(_3);
67+
FakeRead(ForLet(None), _2);
68+
StorageLive(_5);
69+
StorageLive(_6);
70+
_7 = &_1;
71+
_6 = <Foo as Clone>::clone(move _7) -> [return: bb2, unwind unreachable];
72+
}
73+
74+
bb2: {
75+
_5 = {closure@$DIR/closure.rs:29:14: 29:20} { f: move _6 };
76+
StorageDead(_6);
77+
FakeRead(ForLet(None), _5);
78+
_0 = move _1;
79+
StorageDead(_5);
80+
StorageDead(_2);
81+
StorageDead(_1);
82+
return;
83+
}
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// MIR for `ergonomic_clone_closure_use_cloned_generics` 0 nll
2+
3+
| Free Region Mapping
4+
| '?0 | Global | ['?0, '?1]
5+
| '?1 | Local | ['?1]
6+
|
7+
| Inferred Region Values
8+
| '?0 | U0 | {bb0[0..=3], bb1[0..=1], bb2[0..=5], bb3[0..=1], bb4[0..=3], bb5[0..=1], bb6[0..=1], bb7[0], bb8[0], bb9[0], bb10[0], '?0, '?1}
9+
| '?1 | U0 | {bb0[0..=3], bb1[0..=1], bb2[0..=5], bb3[0..=1], bb4[0..=3], bb5[0..=1], bb6[0..=1], bb7[0], bb8[0], bb9[0], bb10[0], '?1}
10+
| '?2 | U0 | {bb0[2..=3]}
11+
| '?3 | U0 | {bb2[4..=5]}
12+
| '?4 | U0 | {bb0[3]}
13+
| '?5 | U0 | {bb2[5]}
14+
| '?6 | U0 | {bb0[3]}
15+
| '?7 | U0 | {bb2[5]}
16+
|
17+
| Inference Constraints
18+
| '?0 live at {bb0[0..=3], bb1[0..=1], bb2[0..=5], bb3[0..=1], bb4[0..=3], bb5[0..=1], bb6[0..=1], bb7[0], bb8[0], bb9[0], bb10[0]}
19+
| '?1 live at {bb0[0..=3], bb1[0..=1], bb2[0..=5], bb3[0..=1], bb4[0..=3], bb5[0..=1], bb6[0..=1], bb7[0], bb8[0], bb9[0], bb10[0]}
20+
| '?2 live at {bb0[2]}
21+
| '?3 live at {bb2[4]}
22+
| '?4 live at {bb0[3]}
23+
| '?5 live at {bb2[5]}
24+
| '?6 live at {bb0[3]}
25+
| '?7 live at {bb2[5]}
26+
| '?2: '?4 due to Boring at Single(bb0[2]) ($DIR/closure.rs:47:14: 47:22 (#0)
27+
| '?3: '?5 due to Boring at Single(bb2[4]) ($DIR/closure.rs:49:14: 49:22 (#0)
28+
| '?4: '?6 due to Boring at Single(bb0[3]) ($DIR/closure.rs:47:14: 47:22 (#0)
29+
| '?5: '?7 due to Boring at Single(bb2[5]) ($DIR/closure.rs:49:14: 49:22 (#0)
30+
|
31+
| Borrows
32+
| bw0: issued at bb0[2] in '?2
33+
| bw1: issued at bb2[4] in '?3
34+
|
35+
fn ergonomic_clone_closure_use_cloned_generics(_1: T) -> T {
36+
debug f => _1;
37+
let mut _0: T;
38+
let _2: {closure@$DIR/closure.rs:47:14: 47:20};
39+
let mut _3: T;
40+
let mut _4: &T;
41+
let mut _6: T;
42+
let mut _7: &T;
43+
scope 1 {
44+
debug f1 => _2;
45+
let _5: {closure@$DIR/closure.rs:49:14: 49:20};
46+
scope 2 {
47+
debug f2 => _5;
48+
}
49+
}
50+
51+
bb0: {
52+
StorageLive(_2);
53+
StorageLive(_3);
54+
_4 = &_1;
55+
_3 = <T as Clone>::clone(move _4) -> [return: bb1, unwind unreachable];
56+
}
57+
58+
bb1: {
59+
_2 = {closure@$DIR/closure.rs:47:14: 47:20} { f: move _3 };
60+
drop(_3) -> [return: bb2, unwind: bb9];
61+
}
62+
63+
bb2: {
64+
StorageDead(_3);
65+
FakeRead(ForLet(None), _2);
66+
StorageLive(_5);
67+
StorageLive(_6);
68+
_7 = &_1;
69+
_6 = <T as Clone>::clone(move _7) -> [return: bb3, unwind unreachable];
70+
}
71+
72+
bb3: {
73+
_5 = {closure@$DIR/closure.rs:49:14: 49:20} { f: move _6 };
74+
drop(_6) -> [return: bb4, unwind: bb8];
75+
}
76+
77+
bb4: {
78+
StorageDead(_6);
79+
FakeRead(ForLet(None), _5);
80+
_0 = move _1;
81+
drop(_5) -> [return: bb5, unwind: bb8];
82+
}
83+
84+
bb5: {
85+
StorageDead(_5);
86+
drop(_2) -> [return: bb6, unwind: bb9];
87+
}
88+
89+
bb6: {
90+
StorageDead(_2);
91+
drop(_1) -> [return: bb7, unwind: bb10];
92+
}
93+
94+
bb7: {
95+
return;
96+
}
97+
98+
bb8 (cleanup): {
99+
drop(_2) -> [return: bb9, unwind terminate(cleanup)];
100+
}
101+
102+
bb9 (cleanup): {
103+
drop(_1) -> [return: bb10, unwind terminate(cleanup)];
104+
}
105+
106+
bb10 (cleanup): {
107+
resume;
108+
}
109+
}

Diff for: tests/mir-opt/ergonomic-clones/closure.rs

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// skip-filecheck
2+
3+
#![crate_type = "lib"]
4+
5+
#![feature(ergonomic_clones)]
6+
#![allow(incomplete_features)]
7+
8+
use std::clone::UseCloned;
9+
10+
// EMIT_MIR closure.ergonomic_clone_closure_move.nll.0.mir
11+
pub fn ergonomic_clone_closure_move() -> String {
12+
let s = String::from("hi");
13+
14+
let cl = use || s;
15+
cl()
16+
}
17+
18+
#[derive(Clone)]
19+
struct Foo;
20+
21+
impl UseCloned for Foo {}
22+
23+
// EMIT_MIR closure.ergonomic_clone_closure_use_cloned.nll.0.mir
24+
pub fn ergonomic_clone_closure_use_cloned() -> Foo {
25+
let f = Foo;
26+
27+
let f1 = use || f;
28+
29+
let f2 = use || f;
30+
31+
f
32+
}
33+
34+
// EMIT_MIR closure.ergonomic_clone_closure_copy.nll.0.mir
35+
pub fn ergonomic_clone_closure_copy() -> i32 {
36+
let i = 1;
37+
38+
let i1 = use || i;
39+
40+
let i2 = use || i;
41+
42+
i
43+
}
44+
45+
// EMIT_MIR closure.ergonomic_clone_closure_use_cloned_generics.nll.0.mir
46+
pub fn ergonomic_clone_closure_use_cloned_generics<T: UseCloned>(f: T) -> T {
47+
let f1 = use || f;
48+
49+
let f2 = use || f;
50+
51+
f
52+
}

0 commit comments

Comments
 (0)