Skip to content

Commit 07becc5

Browse files
committed
Fix regression in promotion of rvalues referencing a static
This commit makes librustc_passes::consts::CheckCrateVisitor properly mark expressions as promotable if they reference a static, as it's perfectly fine for one static to reference another. It fixes a regression that prevented a temporary rvalue from referencing a static if it was itself declared within a static. Prior to commit b8c05fe90bc, `region::ScopeTree` would only register a 'terminating scope' for function bodies. Thus, while rvalues in a static that referenced a static would be marked unpromotable, the lack of enclosing scope would cause mem_categorization::MemCategorizationContext::cat_rvalue_node to compute a 'temporary scope' of `ReStatic`. Since this had the same effect as explicitly selecting a scope of `ReStatic` due to the rvalue being marked by CheckCrateVisitor as promotable, no issue occurred. However, commit b8c05fe90bc made ScopeTree unconditionally register a 'terminating scope' Since mem_categorization would now compute a non-static 'temporary scope', the aforementioned rvalues would be erroneously marked as living for too short a time. By fixing the behavior of CheckCrateVisitor, this commit avoids changing mem_categorization's behavior, while ensuring that temporary values in statics are still allowed to reference other statics. Fixes issue #44373
1 parent dead08c commit 07becc5

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

src/librustc_passes/consts.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,28 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
327327
let def = v.tables.qpath_def(qpath, e.hir_id);
328328
match def {
329329
Def::VariantCtor(..) | Def::StructCtor(..) |
330-
Def::Fn(..) | Def::Method(..) => {}
330+
Def::Fn(..) | Def::Method(..) => {}
331+
332+
// References to a static are inherently promotable,
333+
// with the exception of "#[thread_loca]" statics.
334+
// The latter may not outlive the current function
335+
Def::Static(did, _) => {
336+
let mut thread_local = false;
337+
338+
for attr in &v.tcx.get_attrs(did)[..] {
339+
if attr.check_name("thread_local") {
340+
debug!("Static(id={:?}) is unpromotable \
341+
due to a #[thread_local] attribute", did);
342+
v.promotable = false;
343+
thread_local = true;
344+
break;
345+
}
346+
}
347+
348+
if !thread_local {
349+
debug!("Allowing promotion of reference to Static(id={:?})", did);
350+
}
351+
}
331352

332353
Def::Const(did) |
333354
Def::AssociatedConst(did) => {

src/test/run-pass/issue-44373.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
struct Foo(bool);
12+
13+
struct Container(&'static [&'static Foo]);
14+
15+
static FOO: Foo = Foo(true);
16+
static CONTAINER: Container = Container(&[&FOO]);
17+
18+
fn main() {}

0 commit comments

Comments
 (0)