about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-03-31 12:50:13 +0000
committerbors <bors@rust-lang.org>2018-03-31 12:50:13 +0000
commit70248b1fcf9bab8bdc9d259137ba257fed7134ac (patch)
tree3c9ceea05caf75d885c5d85b233505ef25e6e461 /src
parent8dd24c8ed4ac3e48068408fa21d491d7ffe45295 (diff)
parent8107b5606dafb35af08597d76fdaa11e8353937e (diff)
Auto merge of #49500 - oli-obk:mir_dep_graph, r=michaelwoerister
Introduce an edge from a const eval to the MIR of all statics it depends on

r? @michaelwoerister
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/interpret/const_eval.rs41
-rw-r--r--src/test/incremental/static_refering_to_other_static2/issue.rs20
2 files changed, 60 insertions, 1 deletions
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index 87219511e6f..57977b6201a 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -5,6 +5,7 @@ use rustc::mir;
 use rustc::ty::{self, TyCtxt, Ty, Instance};
 use rustc::ty::layout::{self, LayoutOf};
 use rustc::ty::subst::Subst;
+use rustc::util::nodemap::FxHashSet;
 
 use syntax::ast::Mutability;
 use syntax::codemap::Span;
@@ -504,7 +505,13 @@ pub fn const_eval_provider<'a, 'tcx>(
     };
 
     let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env);
-    res.map(|(miri_value, _, miri_ty)| {
+    res.map(|(miri_value, ptr, miri_ty)| {
+        if tcx.is_static(def_id).is_some() {
+            if let Ok(ptr) = ptr.primval.to_ptr() {
+                let mut seen = FxHashSet::default();
+                create_depgraph_edges(tcx, ptr.alloc_id, &mut seen);
+            }
+        }
         tcx.mk_const(ty::Const {
             val: ConstVal::Value(miri_value),
             ty: miri_ty,
@@ -521,3 +528,35 @@ pub fn const_eval_provider<'a, 'tcx>(
         }
     })
 }
+
+// This function creates dep graph edges from statics to all referred to statics.
+// This is necessary, because the `const_eval` query cannot directly call itself
+// for other statics, because we cannot prevent recursion in queries.
+//
+// see test/incremental/static_refering_to_other_static2/issue.rs for an example
+// where not creating those edges would cause static A, which refers to static B
+// to point to the old allocation of static B, even though B has changed.
+//
+// In the future we will want to remove this funcion in favour of a system that
+// makes sure that statics don't need to have edges to other statics as long as
+// they are only referring by reference and not inspecting the other static's body.
+fn create_depgraph_edges<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    alloc_id: AllocId,
+    seen: &mut FxHashSet<AllocId>,
+) {
+    trace!("create_depgraph_edges: {:?}, {:?}", alloc_id, seen);
+    if seen.insert(alloc_id) {
+        trace!("seen: {:?}, {:?}", alloc_id, seen);
+        if let Some(alloc) = tcx.interpret_interner.get_alloc(alloc_id) {
+            trace!("get_alloc: {:?}, {:?}, {:?}", alloc_id, seen, alloc);
+            for (_, &reloc) in &alloc.relocations {
+                if let Some(did) = tcx.interpret_interner.get_corresponding_static_def_id(reloc) {
+                    trace!("get_corresponding: {:?}, {:?}, {:?}, {:?}, {:?}", alloc_id, seen, alloc, did, reloc);
+                    let _ = tcx.maybe_optimized_mir(did);
+                }
+                create_depgraph_edges(tcx, reloc, seen);
+            }
+        }
+    }
+}
diff --git a/src/test/incremental/static_refering_to_other_static2/issue.rs b/src/test/incremental/static_refering_to_other_static2/issue.rs
new file mode 100644
index 00000000000..55847866895
--- /dev/null
+++ b/src/test/incremental/static_refering_to_other_static2/issue.rs
@@ -0,0 +1,20 @@
+// Copyright 2018 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.
+
+// revisions:rpass1 rpass2
+
+#[cfg(rpass1)]
+pub static A: i32 = 42;
+#[cfg(rpass2)]
+pub static A: i32 = 43;
+
+pub static B: &i32 = &A;
+
+fn main() {}