diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 33e0d0e694497..04b725957b627 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -15,6 +15,7 @@ use hir::map::definitions::Definitions; use ich::{self, CachingCodemapView, Fingerprint}; use middle::cstore::CrateStore; use ty::{TyCtxt, fast_reject}; +use mir::interpret::AllocId; use session::Session; use std::cmp::Ord; @@ -59,6 +60,8 @@ pub struct StableHashingContext<'a> { // CachingCodemapView, so we initialize it lazily. raw_codemap: &'a CodeMap, caching_codemap: Option>, + + pub(super) alloc_id_recursion_tracker: FxHashSet, } #[derive(PartialEq, Eq, Clone, Copy)] @@ -102,6 +105,7 @@ impl<'a> StableHashingContext<'a> { hash_spans: hash_spans_initial, hash_bodies: true, node_id_hashing_mode: NodeIdHashingMode::HashDefPath, + alloc_id_recursion_tracker: Default::default(), } } diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 9a442e0529938..832f49d5b2368 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -379,13 +379,13 @@ impl_stable_hash_for!(struct mir::interpret::MemoryPointer { }); enum AllocDiscriminant { - Static, - Constant, + Alloc, + ExternStatic, Function, } impl_stable_hash_for!(enum self::AllocDiscriminant { - Static, - Constant, + Alloc, + ExternStatic, Function }); @@ -397,17 +397,23 @@ impl<'a> HashStable> for mir::interpret::AllocId { ) { ty::tls::with_opt(|tcx| { let tcx = tcx.expect("can't hash AllocIds during hir lowering"); - if let Some(def_id) = tcx.interpret_interner.get_corresponding_static_def_id(*self) { - AllocDiscriminant::Static.hash_stable(hcx, hasher); - // statics are unique via their DefId - def_id.hash_stable(hcx, hasher); - } else if let Some(alloc) = tcx.interpret_interner.get_alloc(*self) { - // not a static, can't be recursive, hash the allocation - AllocDiscriminant::Constant.hash_stable(hcx, hasher); - alloc.hash_stable(hcx, hasher); + if let Some(alloc) = tcx.interpret_interner.get_alloc(*self) { + AllocDiscriminant::Alloc.hash_stable(hcx, hasher); + if !hcx.alloc_id_recursion_tracker.insert(*self) { + tcx + .interpret_interner + .get_corresponding_static_def_id(*self) + .hash_stable(hcx, hasher); + alloc.hash_stable(hcx, hasher); + assert!(hcx.alloc_id_recursion_tracker.remove(self)); + } } else if let Some(inst) = tcx.interpret_interner.get_fn(*self) { AllocDiscriminant::Function.hash_stable(hcx, hasher); inst.hash_stable(hcx, hasher); + } else if let Some(def_id) = tcx.interpret_interner + .get_corresponding_static_def_id(*self) { + AllocDiscriminant::ExternStatic.hash_stable(hcx, hasher); + def_id.hash_stable(hcx, hasher); } else { bug!("no allocation for {}", self); } diff --git a/src/test/incremental/static_stable_hash/issue-49301.rs b/src/test/incremental/static_stable_hash/issue-49301.rs new file mode 100644 index 0000000000000..3e421b27c11bc --- /dev/null +++ b/src/test/incremental/static_stable_hash/issue-49301.rs @@ -0,0 +1,28 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// /~https://github.com/rust-lang/rust/issues/49081 + +// revisions:rpass1 rpass2 + +#[cfg(rpass1)] +pub static A: &str = "hello"; +#[cfg(rpass2)] +pub static A: &str = "xxxxx"; + +#[cfg(rpass1)] +fn main() { + assert_eq!(A, "hello"); +} + +#[cfg(rpass2)] +fn main() { + assert_eq!(A, "xxxxx"); +}