Skip to content

Commit 5b13bff

Browse files
committed
Auto merge of #42023 - nikomatsakis:issue-36799-ostn15_phf, r=arielb1
introduce local-scope to prevent `StorageLive`/`StorageDead` in statics In investigating #36799, I found that we were creating storage-live/storage-dead instructions in statics/constants, where they are not needed. This arose due to the fix for local scopes. This PR tries to fix that (and adds a test -- I'm curious if there is a way to make that test more targeted, though). r? @arielb1
2 parents 9fa25a7 + 8a4e593 commit 5b13bff

File tree

7 files changed

+154
-11
lines changed

7 files changed

+154
-11
lines changed

src/librustc_mir/build/expr/as_operand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
2727
-> BlockAnd<Operand<'tcx>>
2828
where M: Mirror<'tcx, Output = Expr<'tcx>>
2929
{
30-
let topmost_scope = self.topmost_scope(); // FIXME(#6393)
31-
self.as_operand(block, Some(topmost_scope), expr)
30+
let local_scope = self.local_scope();
31+
self.as_operand(block, local_scope, expr)
3232
}
3333

3434
/// Compile `expr` into a value that can be used as an operand.

src/librustc_mir/build/expr/as_rvalue.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
3333
-> BlockAnd<Rvalue<'tcx>>
3434
where M: Mirror<'tcx, Output = Expr<'tcx>>
3535
{
36-
let topmost_scope = self.topmost_scope(); // FIXME(#6393)
37-
self.as_rvalue(block, Some(topmost_scope), expr)
36+
let local_scope = self.local_scope();
37+
self.as_rvalue(block, local_scope, expr)
3838
}
3939

4040
/// Compile `expr`, yielding an rvalue.
@@ -51,7 +51,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
5151
scope: Option<CodeExtent>,
5252
expr: Expr<'tcx>)
5353
-> BlockAnd<Rvalue<'tcx>> {
54-
debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);
54+
debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr);
5555

5656
let this = self;
5757
let expr_span = expr.span;

src/librustc_mir/build/expr/as_temp.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
3535
temp_lifetime: Option<CodeExtent>,
3636
expr: Expr<'tcx>)
3737
-> BlockAnd<Lvalue<'tcx>> {
38-
debug!("expr_as_temp(block={:?}, expr={:?})", block, expr);
38+
debug!("expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?})",
39+
block, temp_lifetime, expr);
3940
let this = self;
4041

4142
if let ExprKind::Scope { extent, value } = expr.kind {

src/librustc_mir/build/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,9 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
392392
mir
393393
}
394394

395-
pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
396-
body_id: hir::BodyId)
397-
-> Mir<'tcx> {
395+
fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
396+
body_id: hir::BodyId)
397+
-> Mir<'tcx> {
398398
let tcx = hir.tcx();
399399
let ast_expr = &tcx.hir.body(body_id).value;
400400
let ty = hir.tables().expr_ty_adjusted(ast_expr);
@@ -415,7 +415,7 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
415415
builder.finish(vec![], ty)
416416
}
417417

418-
pub fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
418+
fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
419419
body_id: hir::BodyId)
420420
-> Mir<'tcx> {
421421
let span = hir.tcx().hir.span(hir.tcx().hir.body_owner(body_id));

src/librustc_mir/build/scope.rs

+36
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ use rustc::middle::const_val::ConstVal;
9393
use rustc::ty::subst::{Kind, Subst};
9494
use rustc::ty::{Ty, TyCtxt};
9595
use rustc::mir::*;
96+
use rustc::mir::transform::MirSource;
9697
use syntax_pos::Span;
9798
use rustc_data_structures::indexed_vec::Idx;
9899
use rustc_data_structures::fx::FxHashMap;
@@ -428,6 +429,41 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
428429
self.scopes.last().expect("topmost_scope: no scopes present").extent
429430
}
430431

432+
/// Returns the scope that we should use as the lifetime of an
433+
/// operand. Basically, an operand must live until it is consumed.
434+
/// This is similar to, but not quite the same as, the temporary
435+
/// scope (which can be larger or smaller).
436+
///
437+
/// Consider:
438+
///
439+
/// let x = foo(bar(X, Y));
440+
///
441+
/// We wish to pop the storage for X and Y after `bar()` is
442+
/// called, not after the whole `let` is completed.
443+
///
444+
/// As another example, if the second argument diverges:
445+
///
446+
/// foo(Box::new(2), panic!())
447+
///
448+
/// We would allocate the box but then free it on the unwinding
449+
/// path; we would also emit a free on the 'success' path from
450+
/// panic, but that will turn out to be removed as dead-code.
451+
///
452+
/// When building statics/constants, returns `None` since
453+
/// intermediate values do not have to be dropped in that case.
454+
pub fn local_scope(&self) -> Option<CodeExtent> {
455+
match self.hir.src {
456+
MirSource::Const(_) |
457+
MirSource::Static(..) =>
458+
// No need to free storage in this context.
459+
None,
460+
MirSource::Fn(_) =>
461+
Some(self.topmost_scope()),
462+
MirSource::Promoted(..) =>
463+
bug!(),
464+
}
465+
}
466+
431467
// Scheduling drops
432468
// ================
433469
/// Indicates that `lvalue` should be dropped on exit from

src/librustc_mir/hair/cx/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,14 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
3636
tcx: TyCtxt<'a, 'gcx, 'tcx>,
3737
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
3838
pub region_maps: Rc<RegionMaps>,
39+
40+
/// This is `Constness::Const` if we are compiling a `static`,
41+
/// `const`, or the body of a `const fn`.
3942
constness: hir::Constness,
4043

44+
/// What are we compiling?
45+
pub src: MirSource,
46+
4147
/// True if this constant/function needs overflow checks.
4248
check_overflow: bool,
4349
}
@@ -74,7 +80,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
7480
// Constants and const fn's always need overflow checks.
7581
check_overflow |= constness == hir::Constness::Const;
7682

77-
Cx { tcx, infcx, region_maps, constness, check_overflow }
83+
Cx { tcx, infcx, region_maps, constness, src, check_overflow }
7884
}
7985
}
8086

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Check that when we compile the static `XXX` into MIR, we do not
12+
// generate `StorageStart` or `StorageEnd` statements.
13+
14+
// ignore-tidy-linelength
15+
16+
static XXX: &'static Foo = &Foo {
17+
tup: "hi",
18+
data: &[
19+
(0, 1), (0, 2), (0, 3),
20+
(0, 1), (0, 2), (0, 3),
21+
(0, 1), (0, 2), (0, 3),
22+
(0, 1), (0, 2), (0, 3),
23+
(0, 1), (0, 2), (0, 3),
24+
(0, 1), (0, 2), (0, 3),
25+
(0, 1), (0, 2), (0, 3),
26+
(0, 1), (0, 2), (0, 3),
27+
(0, 1), (0, 2), (0, 3),
28+
(0, 1), (0, 2), (0, 3),
29+
(0, 1), (0, 2), (0, 3),
30+
(0, 1), (0, 2), (0, 3),
31+
(0, 1), (0, 2), (0, 3),
32+
(0, 1), (0, 2), (0, 3),
33+
]
34+
};
35+
36+
#[derive(Debug)]
37+
struct Foo {
38+
tup: &'static str,
39+
data: &'static [(u32, u32)]
40+
}
41+
42+
fn main() {
43+
println!("{:?}", XXX);
44+
}
45+
46+
// END RUST SOURCE
47+
// START rustc.node4.mir_map.0.mir
48+
// bb0: {
49+
// _7 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:29:9: 29:15
50+
// _8 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:29:17: 29:23
51+
// _9 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:29:25: 29:31
52+
// _10 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:30:9: 30:15
53+
// _11 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:30:17: 30:23
54+
// _12 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:30:25: 30:31
55+
// _13 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:31:9: 31:15
56+
// _14 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:31:17: 31:23
57+
// _15 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:31:25: 31:31
58+
// _16 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:32:9: 32:15
59+
// _17 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:32:17: 32:23
60+
// _18 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:32:25: 32:31
61+
// _19 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:33:9: 33:15
62+
// _20 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:33:17: 33:23
63+
// _21 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:33:25: 33:31
64+
// _22 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:34:9: 34:15
65+
// _23 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:34:17: 34:23
66+
// _24 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:34:25: 34:31
67+
// _25 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:35:9: 35:15
68+
// _26 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:35:17: 35:23
69+
// _27 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:35:25: 35:31
70+
// _28 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:36:9: 36:15
71+
// _29 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:36:17: 36:23
72+
// _30 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:36:25: 36:31
73+
// _31 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:37:9: 37:15
74+
// _32 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:37:17: 37:23
75+
// _33 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:37:25: 37:31
76+
// _34 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:38:9: 38:15
77+
// _35 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:38:17: 38:23
78+
// _36 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:38:25: 38:31
79+
// _37 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:39:9: 39:15
80+
// _38 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:39:17: 39:23
81+
// _39 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:39:25: 39:31
82+
// _40 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:40:9: 40:15
83+
// _41 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:40:17: 40:23
84+
// _42 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:40:25: 40:31
85+
// _43 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:41:9: 41:15
86+
// _44 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:41:17: 41:23
87+
// _45 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:41:25: 41:31
88+
// _46 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:42:9: 42:15
89+
// _47 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:42:17: 42:23
90+
// _48 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:42:25: 42:31
91+
// _6 = [_7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48]; // scope 0 at src/test/mir-opt/basic_assignment.rs:28:12: 43:6
92+
// _5 = &_6; // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
93+
// _4 = &(*_5); // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
94+
// _3 = _4 as &'static [(u32, u32)] (Unsize); // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
95+
// _2 = Foo { tup: const "hi", data: _3 }; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:29: 44:2
96+
// _1 = &_2; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:28: 44:2
97+
// _0 = &(*_1); // scope 0 at src/test/mir-opt/basic_assignment.rs:26:28: 44:2
98+
// return; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:1: 44:3
99+
// }
100+
// END rustc.node4.mir_map.0.mir

0 commit comments

Comments
 (0)