about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAaron Hill <aa1ronham@gmail.com>2017-09-08 20:22:50 -0400
committerAaron Hill <aa1ronham@gmail.com>2017-09-08 20:22:50 -0400
commit07becc5f2438a2f628e8cb5d5a6128dd9ed2cc31 (patch)
tree9cdfcf01e197a5d611a7f4959be7e0ba6eec88de /src
parentdead08cb331343b84564628b139b657f93548320 (diff)
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 https://github.com/rust-lang/rust/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 https://github.com/rust-lang/rust/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
Diffstat (limited to 'src')
-rw-r--r--src/librustc_passes/consts.rs23
-rw-r--r--src/test/run-pass/issue-44373.rs18
2 files changed, 40 insertions, 1 deletions
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 6f2c448ceb6..f7581bb604f 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -327,7 +327,28 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
             let def = v.tables.qpath_def(qpath, e.hir_id);
             match def {
                 Def::VariantCtor(..) | Def::StructCtor(..) |
-                Def::Fn(..) | Def::Method(..) => {}
+                Def::Fn(..) | Def::Method(..) =>  {}
+
+                // References to a static are inherently promotable,
+                // with the exception of "#[thread_loca]" statics.
+                // The latter may not outlive the current function
+                Def::Static(did, _) => {
+                    let mut thread_local = false;
+
+                    for attr in &v.tcx.get_attrs(did)[..] {
+                        if attr.check_name("thread_local") {
+                            debug!("Static(id={:?}) is unpromotable \
+                                   due to a #[thread_local] attribute", did);
+                            v.promotable = false;
+                            thread_local = true;
+                            break;
+                        }
+                    }
+
+                    if !thread_local {
+                        debug!("Allowing promotion of reference to Static(id={:?})", did);
+                    }
+                }
 
                 Def::Const(did) |
                 Def::AssociatedConst(did) => {
diff --git a/src/test/run-pass/issue-44373.rs b/src/test/run-pass/issue-44373.rs
new file mode 100644
index 00000000000..06627e2ad93
--- /dev/null
+++ b/src/test/run-pass/issue-44373.rs
@@ -0,0 +1,18 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo(bool);
+
+struct Container(&'static [&'static Foo]);
+
+static FOO: Foo = Foo(true);
+static CONTAINER: Container = Container(&[&FOO]);
+
+fn main() {}