Skip to content

Commit

Permalink
convert inherent-impl-related things to on-demand queries
Browse files Browse the repository at this point in the history
There are now 3 queries:

- inherent_impls(def-id): for a given type, get a `Rc<Vec<DefId>>` with
  all its inherent impls. This internally uses `crate_inherent_impls`,
  doing some hacks to keep the current deps (which, btw, are not clearly
  correct).
- crate_inherent_impls(crate): gathers up a map from types
  to `Rc<Vec<DefId>>`, touching the entire krate, possibly generating
  errors.
- crate_inherent_impls_overlap_check(crate): performs overlap checks
  between the inherent impls for a given type, generating errors.
  • Loading branch information
nikomatsakis committed Mar 23, 2017
1 parent 8e6b10a commit a29ae30
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 186 deletions.
2 changes: 0 additions & 2 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ pub enum DepNode<D: Clone + Debug> {
CoherenceCheckImpl(D),
CoherenceOverlapCheck(D),
CoherenceOverlapCheckSpecial(D),
CoherenceOverlapInherentCheck(D),
CoherenceOrphanCheck(D),
Variance,
WfCheck(D),
Expand Down Expand Up @@ -251,7 +250,6 @@ impl<D: Clone + Debug> DepNode<D> {
CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),
CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial),
CoherenceOverlapInherentCheck(ref d) => op(d).map(CoherenceOverlapInherentCheck),
CoherenceOrphanCheck(ref d) => op(d).map(CoherenceOrphanCheck),
WfCheck(ref d) => op(d).map(WfCheck),
TypeckItemType(ref d) => op(d).map(TypeckItemType),
Expand Down
15 changes: 0 additions & 15 deletions src/librustc/dep_graph/dep_tracking_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,6 @@ impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
pub fn keys(&self) -> Vec<M::Key> {
self.map.keys().cloned().collect()
}

/// Append `elem` to the vector stored for `k`, creating a new vector if needed.
/// This is considered a write to `k`.
///
/// NOTE: Caution is required when using this method. You should
/// be sure that nobody is **reading from the vector** while you
/// are writing to it. Eventually, it'd be nice to remove this.
pub fn push<E: Clone>(&mut self, k: M::Key, elem: E)
where M: DepTrackingMapConfig<Value=Vec<E>>
{
self.write(&k);
self.map.entry(k)
.or_insert(Vec::new())
.push(elem);
}
}

impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {
Expand Down
2 changes: 0 additions & 2 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ pub trait CrateStore {
fn item_generics_cloned(&self, def: DefId) -> ty::Generics;
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>;
fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId>;

// trait info
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
Expand Down Expand Up @@ -310,7 +309,6 @@ impl CrateStore for DummyCrateStore {
{ bug!("item_generics_cloned") }
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name> { bug!("fn_arg_names") }
fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId> { vec![] }

// trait info
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
Expand Down
26 changes: 20 additions & 6 deletions src/librustc/ty/maps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use middle::const_val::ConstVal;
use mir;
use ty::{self, Ty, TyCtxt};
use ty::{self, CrateInherentImpls, Ty, TyCtxt};

use rustc_data_structures::indexed_vec::IndexVec;
use std::cell::{RefCell, RefMut};
Expand Down Expand Up @@ -176,9 +176,15 @@ impl<'tcx> QueryDescription for queries::coherent_trait<'tcx> {
}
}

impl<'tcx> QueryDescription for queries::coherent_inherent_impls<'tcx> {
impl<'tcx> QueryDescription for queries::crate_inherent_impls<'tcx> {
fn describe(_: TyCtxt, k: CrateNum) -> String {
format!("all inherent impls defined in crate `{:?}`", k)
}
}

impl<'tcx> QueryDescription for queries::crate_inherent_impls_overlap_check<'tcx> {
fn describe(_: TyCtxt, _: CrateNum) -> String {
format!("coherence checking all inherent impls")
format!("check for overlap between inherent impls defined in this crate")
}
}

Expand Down Expand Up @@ -368,7 +374,7 @@ define_maps! { <'tcx>
/// Maps a DefId of a type to a list of its inherent impls.
/// Contains implementations of methods that are inherent to a type.
/// Methods in these implementations don't need to be exported.
pub inherent_impls: InherentImpls(DefId) -> Vec<DefId>,
pub inherent_impls: InherentImpls(DefId) -> Rc<Vec<DefId>>,

/// Maps from the def-id of a function/method or const/static
/// to its MIR. Mutation is done at an item granularity to
Expand Down Expand Up @@ -400,7 +406,15 @@ define_maps! { <'tcx>

pub coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),

pub coherent_inherent_impls: coherent_inherent_impls_dep_node(CrateNum) -> (),
/// Gets a complete map from all types to their inherent impls.
/// Not meant to be used directly outside of coherence.
/// (Defined only for LOCAL_CRATE)
pub crate_inherent_impls: crate_inherent_impls_dep_node(CrateNum) -> CrateInherentImpls,

/// Checks all types in the krate for overlap in their inherent impls. Reports errors.
/// Not meant to be used directly outside of coherence.
/// (Defined only for LOCAL_CRATE)
pub crate_inherent_impls_overlap_check: crate_inherent_impls_dep_node(CrateNum) -> (),

/// Results of evaluating monomorphic constants embedded in
/// other items, such as enum variant explicit discriminants.
Expand All @@ -413,7 +427,7 @@ fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
DepNode::CoherenceCheckTrait(def_id)
}

fn coherent_inherent_impls_dep_node(_: CrateNum) -> DepNode<DefId> {
fn crate_inherent_impls_dep_node(_: CrateNum) -> DepNode<DefId> {
DepNode::Coherence
}

Expand Down
43 changes: 14 additions & 29 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use ty::subst::{Subst, Substs};
use ty::util::IntTypeExt;
use ty::walk::TypeWalker;
use util::common::MemoizationMap;
use util::nodemap::{NodeSet, FxHashMap};
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};

use serialize::{self, Encodable, Encoder};
use std::borrow::Cow;
Expand Down Expand Up @@ -2345,34 +2345,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL)
}

/// Populates the type context with all the inherent implementations for
/// the given type if necessary.
pub fn populate_inherent_implementations_for_type_if_necessary(self,
span: Span,
type_id: DefId) {
if type_id.is_local() {
// Make sure coherence of inherent impls ran already.
ty::queries::coherent_inherent_impls::force(self, span, LOCAL_CRATE);
return
}

// The type is not local, hence we are reading this out of
// metadata and don't need to track edges.
let _ignore = self.dep_graph.in_ignore();

if self.populated_external_types.borrow().contains(&type_id) {
return
}

debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}",
type_id);

let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id);

self.maps.inherent_impls.borrow_mut().insert(type_id, inherent_impls);
self.populated_external_types.borrow_mut().insert(type_id);
}

/// Populates the type context with all the implementations for the given
/// trait if necessary.
pub fn populate_implementations_for_trait_if_necessary(self, trait_id: DefId) {
Expand Down Expand Up @@ -2637,3 +2609,16 @@ pub fn provide(providers: &mut ty::maps::Providers) {
..*providers
};
}


/// A map for the local crate mapping each type to a vector of its
/// inherent impls. This is not meant to be used outside of coherence;
/// rather, you should request the vector for a specific type via
/// `ty::queries::inherent_impls::get(def_id)` so as to minimize your
/// dependencies (constructing this map requires touching the entire
/// crate).
#[derive(Clone, Debug)]
pub struct CrateInherentImpls {
pub inherent_impls: DefIdMap<Rc<Vec<DefId>>>,
}

7 changes: 1 addition & 6 deletions src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ provide! { <'tcx> tcx, def_id, cdata
typeck_tables => { cdata.item_body_tables(def_id.index, tcx) }
closure_kind => { cdata.closure_kind(def_id.index) }
closure_type => { cdata.closure_ty(def_id.index, tcx) }
inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
}

impl CrateStore for cstore::CStore {
Expand Down Expand Up @@ -162,12 +163,6 @@ impl CrateStore for cstore::CStore {
self.get_crate_data(did.krate).get_fn_arg_names(did.index)
}

fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId>
{
self.dep_graph.read(DepNode::MetaData(def_id));
self.get_crate_data(def_id.krate).get_inherent_implementations_for_type(def_id.index)
}

fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>
{
if let Some(def_id) = filter {
Expand Down
11 changes: 3 additions & 8 deletions src/librustc_typeck/check/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,14 +479,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
}

fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
// Read the inherent implementation candidates for this type from the
// metadata if necessary.
self.tcx.populate_inherent_implementations_for_type_if_necessary(self.span, def_id);

if let Some(impl_infos) = self.tcx.maps.inherent_impls.borrow().get(&def_id) {
for &impl_def_id in impl_infos.iter() {
self.assemble_inherent_impl_probe(impl_def_id);
}
let impl_def_ids = ty::queries::inherent_impls::get(self.tcx, self.span, def_id);
for &impl_def_id in impl_def_ids.iter() {
self.assemble_inherent_impl_probe(impl_def_id);
}
}

Expand Down
Loading

0 comments on commit a29ae30

Please sign in to comment.