// Copyright 2012-2015 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. use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; use isolated_encoder::IsolatedEncoder; use schema::*; use rustc::hir; use rustc::ty::{self, TyCtxt}; use rustc::ich::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[derive(RustcEncodable, RustcDecodable)] pub struct Ast<'tcx> { pub body: Lazy, pub tables: Lazy>, pub nested_bodies: LazySeq, pub rvalue_promotable_to_static: bool, pub stable_bodies_hash: Fingerprint, } impl_stable_hash_for!(struct Ast<'tcx> { body, tables, nested_bodies, rvalue_promotable_to_static, stable_bodies_hash }); impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> { pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy> { let body = self.tcx.hir.body(body_id); // In order to avoid having to hash hir::Bodies from extern crates, we // hash them here, during export, and store the hash with metadata. let stable_bodies_hash = { let mut hcx = self.tcx.create_stable_hashing_context(); let mut hasher = StableHasher::new(); hcx.while_hashing_hir_bodies(true, |hcx| { body.hash_stable(hcx, &mut hasher); }); hasher.finish() }; let lazy_body = self.lazy(body); let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id); let tables = self.tcx.typeck_tables_of(body_owner_def_id); let lazy_tables = self.lazy(tables); let mut visitor = NestedBodyCollector { tcx: self.tcx, bodies_found: Vec::new(), }; visitor.visit_body(body); let lazy_nested_bodies = self.lazy_seq_ref_from_slice(&visitor.bodies_found); let rvalue_promotable_to_static = self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id); self.lazy(&Ast { body: lazy_body, tables: lazy_tables, nested_bodies: lazy_nested_bodies, rvalue_promotable_to_static, stable_bodies_hash, }) } } struct NestedBodyCollector<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, bodies_found: Vec<&'tcx hir::Body>, } impl<'a, 'tcx: 'a> Visitor<'tcx> for NestedBodyCollector<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::None } fn visit_nested_body(&mut self, body: hir::BodyId) { let body = self.tcx.hir.body(body); self.bodies_found.push(body); self.visit_body(body); } }