Skip to content

Commit 2f6628e

Browse files
committed
optimize let x: T = .. to avoid a temporary
For some weird reason this fixes `intrinsic-move-val`. It also affects various test heuristics. I removed one test (`reborrow_basic`) that didn't seem to really be testing anything in particular anymore, compared to all the other tests we've got.
1 parent 16f4e8a commit 2f6628e

12 files changed

+105
-122
lines changed

src/librustc_mir/build/matches/mod.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
253253
irrefutable_pat: Pattern<'tcx>,
254254
initializer: ExprRef<'tcx>,
255255
) -> BlockAnd<()> {
256-
// optimize the case of `let x = ...`
257256
match *irrefutable_pat.kind {
257+
// Optimize the case of `let x = ...` to write directly into `x`
258258
PatternKind::Binding {
259259
mode: BindingMode::ByValue,
260260
var,
@@ -267,6 +267,47 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
267267
self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
268268
block.unit()
269269
}
270+
271+
// Optimize the case of `let x: T = ...` to write directly
272+
// into `x` and then require that `T == typeof(x)`.
273+
//
274+
// Weirdly, this is needed to prevent the
275+
// `intrinsic-move-val.rs` test case from crashing. That
276+
// test works with uninitialized values in a rather
277+
// dubious way, so it may be that the test is kind of
278+
// broken.
279+
PatternKind::AscribeUserType {
280+
subpattern: Pattern {
281+
kind: box PatternKind::Binding {
282+
mode: BindingMode::ByValue,
283+
var,
284+
subpattern: None,
285+
..
286+
},
287+
..
288+
},
289+
user_ty: ascription_user_ty,
290+
} => {
291+
let place =
292+
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard);
293+
unpack!(block = self.into(&place, block, initializer));
294+
295+
let source_info = self.source_info(irrefutable_pat.span);
296+
self.cfg.push(
297+
block,
298+
Statement {
299+
source_info,
300+
kind: StatementKind::AscribeUserType(
301+
place.clone(),
302+
ty::Variance::Invariant,
303+
ascription_user_ty,
304+
),
305+
},
306+
);
307+
308+
self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
309+
block.unit()
310+
}
270311
_ => {
271312
let place = unpack!(block = self.as_place(block, initializer));
272313
self.place_into_pattern(block, irrefutable_pat, &place, true)

src/test/mir-opt/basic_assignment.rs

Lines changed: 32 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -19,70 +19,53 @@
1919
// option. This file may not be copied, modified, or distributed
2020
// except according to those terms.
2121

22-
// check that codegen of assignment expressions is sane. Assignments
23-
// tend to be absent in simple code, so subtle breakage in them can
24-
// leave a quite hard-to-find trail of destruction.
22+
// Check codegen for assignments (`a = b`) where the left-hand-side is
23+
// not yet initialized. Assignments tend to be absent in simple code,
24+
// so subtle breakage in them can leave a quite hard-to-find trail of
25+
// destruction.
2526

2627
// ignore-tidy-linelength
2728

2829
fn main() {
2930
let nodrop_x = false;
3031
let nodrop_y;
3132

33+
// Since boolean does not require drop, this can be a simple
34+
// assignment:
3235
nodrop_y = nodrop_x;
3336

3437
let drop_x : Option<Box<u32>> = None;
3538
let drop_y;
3639

40+
// Since the type of `drop_y` has drop, we generate a `replace`
41+
// terminator:
3742
drop_y = drop_x;
3843
}
3944

4045
// END RUST SOURCE
4146
// START rustc.main.SimplifyCfg-initial.after.mir
42-
// bb0: {
43-
// StorageLive(_1);
44-
// _1 = const false;
45-
// StorageLive(_2);
46-
// StorageLive(_3);
47-
// _3 = _1;
48-
// _2 = move _3;
49-
// StorageDead(_3);
50-
// StorageLive(_4);
51-
// AscribeUserType(_4, Canonical { variables: [], value: std::option::Option<std::boxed::Box<u32>> });
52-
// _4 = std::option::Option<std::boxed::Box<u32>>::None;
53-
// StorageLive(_5);
54-
// StorageLive(_6);
55-
// _6 = move _4;
56-
// replace(_5 <-move _6) -> [return: bb2, unwind: bb5];
57-
// }
58-
// bb1: {
59-
// resume;
60-
// }
61-
// bb2: {
62-
// drop(_6) -> [return: bb6, unwind: bb4];
63-
// }
64-
// bb3: {
65-
// drop(_4) -> bb1;
66-
// }
67-
// bb4: {
68-
// drop(_5) -> bb3;
69-
// }
70-
// bb5: {
71-
// drop(_6) -> bb4;
72-
// }
73-
// bb6: {
74-
// StorageDead(_6);
75-
// _0 = ();
76-
// drop(_5) -> [return: bb7, unwind: bb3];
77-
// }
78-
// bb7: {
79-
// StorageDead(_5);
80-
// drop(_4) -> [return: bb8, unwind: bb1];
81-
// }
82-
// bb8: {
83-
// StorageDead(_4);
84-
// StorageDead(_2);
85-
// StorageDead(_1);
86-
// return;
87-
// }
47+
// bb0: {
48+
// StorageLive(_1);
49+
// _1 = const false;
50+
// StorageLive(_2);
51+
// StorageLive(_3);
52+
// _3 = _1;
53+
// _2 = move _3;
54+
// StorageDead(_3);
55+
// StorageLive(_4);
56+
// _4 = std::option::Option<std::boxed::Box<u32>>::None;
57+
// AscribeUserType(_4, o, Canonical { variables: [], value: std::option::Option<std::boxed::Box<u32>> });
58+
// StorageLive(_5);
59+
// StorageLive(_6);
60+
// _6 = move _4;
61+
// replace(_5 <- move _6) -> [return: bb2, unwind: bb5];
62+
// }
63+
// ...
64+
// bb2: {
65+
// drop(_6) -> [return: bb6, unwind: bb4];
66+
// }
67+
// ...
68+
// bb5: {
69+
// drop(_6) -> bb4;
70+
// }
8871
// END rustc.main.SimplifyCfg-initial.after.mir

src/test/mir-opt/nll/reborrow-basic.rs

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
error: unsatisfied lifetime constraints
2-
--> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:32:19
2+
--> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:32:29
33
|
44
LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>(
55
| -- -- lifetime `'b` defined here
66
| |
77
| lifetime `'a` defined here
88
...
99
LL | let z: I::A = if cond { x } else { y };
10-
| ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b`
10+
| ^ assignment requires that `'a` must outlive `'b`
1111

1212
error: unsatisfied lifetime constraints
13-
--> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:32:19
13+
--> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:32:40
1414
|
1515
LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>(
1616
| -- -- lifetime `'b` defined here
1717
| |
1818
| lifetime `'a` defined here
1919
...
2020
LL | let z: I::A = if cond { x } else { y };
21-
| ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
21+
| ^ assignment requires that `'b` must outlive `'a`
2222

2323
error: aborting due to 2 previous errors
2424

src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` poin
3535
--> $DIR/borrowck-access-permissions.rs:56:23
3636
|
3737
LL | let ptr_x : *const _ = &x;
38-
| ----- help: consider changing this to be a mutable pointer: `*mut i32`
38+
| -- help: consider changing this to be a mutable pointer: `&mut x`
3939
...
4040
LL | let _y1 = &mut *ptr_x; //[ast]~ ERROR [E0596]
4141
| ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable

src/test/ui/borrowck/borrowck-access-permissions.mir.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` poin
3535
--> $DIR/borrowck-access-permissions.rs:56:23
3636
|
3737
LL | let ptr_x : *const _ = &x;
38-
| ----- help: consider changing this to be a mutable pointer: `*mut i32`
38+
| -- help: consider changing this to be a mutable pointer: `&mut x`
3939
...
4040
LL | let _y1 = &mut *ptr_x; //[ast]~ ERROR [E0596]
4141
| ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable

src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,17 @@ fn make_it() -> for<'a> fn(&'a u32, &'a u32) -> &'a u32 {
2020
panic!()
2121
}
2222

23-
fn main() {
23+
fn foo() {
2424
let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
2525
//~^ ERROR higher-ranked subtype error
26-
//~| ERROR higher-ranked subtype error
2726
drop(a);
2827
}
28+
29+
fn bar() {
30+
// The code path for patterns is mildly different, so go ahead and
31+
// test that too:
32+
let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
33+
//~^ ERROR higher-ranked subtype error
34+
}
35+
36+
fn main() { }

src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
55
| ^^^^^^^^^
66

77
error: higher-ranked subtype error
8-
--> $DIR/hr-fn-aaa-as-aba.rs:24:9
8+
--> $DIR/hr-fn-aaa-as-aba.rs:32:58
99
|
10-
LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
11-
| ^
10+
LL | let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
11+
| ^^^^^^^^^
1212

1313
error: aborting due to 2 previous errors
1414

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
error: higher-ranked subtype error
2-
--> $DIR/universe-violation.rs:14:9
3-
|
4-
LL | let a: fn(_) -> _ = make_it();
5-
| ^
6-
7-
error: higher-ranked subtype error
8-
--> $DIR/universe-violation.rs:15:9
2+
--> $DIR/universe-violation.rs:15:31
93
|
104
LL | let b: fn(&u32) -> &u32 = a;
11-
| ^
5+
| ^
126

13-
error: aborting due to 2 previous errors
7+
error: aborting due to previous error
148

src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
error[E0621]: explicit lifetime required in the type of `v`
2-
--> $DIR/region-object-lifetime-in-coercion.rs:20:5
2+
--> $DIR/region-object-lifetime-in-coercion.rs:18:33
33
|
44
LL | fn a(v: &[u8]) -> Box<Foo + 'static> {
55
| ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
6-
...
7-
LL | x
8-
| ^ lifetime `'static` required
6+
LL | let x: Box<Foo + 'static> = Box::new(v);
7+
| ^^^^^^^^^^^ lifetime `'static` required
98

109
error[E0621]: explicit lifetime required in the type of `v`
1110
--> $DIR/region-object-lifetime-in-coercion.rs:24:5

src/test/ui/slice-mut-2.nll.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
22
--> $DIR/slice-mut-2.rs:17:18
33
|
44
LL | let x: &[isize] = &[1, 2, 3, 4, 5];
5-
| - help: consider changing this to be a mutable reference: `&mut [isize]`
5+
| ---------------- help: consider changing this to be a mutable reference: `&mut [1, 2, 3, 4, 5]`
66
...
77
LL | let _ = &mut x[2..4]; //~ERROR cannot borrow immutable borrowed content `*x` as mutable
88
| ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable

src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.nll.stderr

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,9 @@ LL | let g = factorial.as_ref().unwrap();
3838
| ^^^^^^^^^ borrowed value does not live long enough
3939
...
4040
LL | }
41-
| -
42-
| |
43-
| `factorial` dropped here while still borrowed
44-
| borrow later used here, when `factorial` is dropped
41+
| - `factorial` dropped here while still borrowed
4542
|
46-
= note: values in a scope are dropped in the opposite order they are defined
43+
= note: borrowed value must be valid for the static lifetime...
4744

4845
error[E0506]: cannot assign to `factorial` because it is borrowed
4946
--> $DIR/unboxed-closures-failed-recursive-fn-1.rs:42:5
@@ -55,10 +52,9 @@ LL | let g = factorial.as_ref().unwrap();
5552
| --------- borrow occurs due to use in closure
5653
...
5754
LL | factorial = Some(Box::new(f));
58-
| ^^^^^^^^^
59-
| |
60-
| assignment to borrowed `factorial` occurs here
61-
| borrow later used here
55+
| ^^^^^^^^^ assignment to borrowed `factorial` occurs here
56+
|
57+
= note: borrowed value must be valid for the static lifetime...
6258

6359
error: aborting due to 4 previous errors
6460

0 commit comments

Comments
 (0)