Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

on-demand-ify custom_coerce_unsized_kind and inherent-impls #40683

Merged
merged 3 commits into from
Mar 29, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
15 changes: 15 additions & 0 deletions src/librustc/ty/adjustment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,21 @@ pub enum AutoBorrow<'tcx> {
RawPtr(hir::Mutability),
}

/// Information for `CoerceUnsized` impls, storing information we
/// have computed about the coercion.
///
/// This struct can be obtained via the `coerce_impl_info` query.
/// Demanding this struct also has the side-effect of reporting errors
/// for inappropriate impls.
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
pub struct CoerceUnsizedInfo {
/// If this is a "custom coerce" impl, then what kind of custom
/// coercion is it? This applies to impls of `CoerceUnsized` for
/// structs, primarily, where we store a bit of info about which
/// fields need to be coerced.
pub custom_kind: Option<CustomCoerceUnsized>
}

#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
pub enum CustomCoerceUnsized {
/// Records the index of the field being coerced.
Expand Down
30 changes: 22 additions & 8 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 All @@ -393,14 +399,22 @@ define_maps! { <'tcx>
pub closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,

/// Caches CoerceUnsized kinds for impls on custom types.
pub custom_coerce_unsized_kind: ItemSignature(DefId)
-> ty::adjustment::CustomCoerceUnsized,
pub coerce_unsized_info: ItemSignature(DefId)
-> ty::adjustment::CoerceUnsizedInfo,

pub typeck_tables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'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
47 changes: 16 additions & 31 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 @@ -2054,8 +2054,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
})
}

pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized {
queries::custom_coerce_unsized_kind::get(self, DUMMY_SP, did)
pub fn coerce_unsized_info(self, did: DefId) -> adjustment::CoerceUnsizedInfo {
queries::coerce_unsized_info::get(self, DUMMY_SP, did)
}

pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
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>>>,
}

13 changes: 4 additions & 9 deletions src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ provide! { <'tcx> tcx, def_id, cdata
}
associated_item => { cdata.get_associated_item(def_id.index) }
impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
custom_coerce_unsized_kind => {
cdata.get_custom_coerce_unsized_kind(def_id.index).unwrap_or_else(|| {
bug!("custom_coerce_unsized_kind: `{:?}` is missing its kind", def_id);
coerce_unsized_info => {
cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
})
}
mir => {
Expand All @@ -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
8 changes: 4 additions & 4 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,10 +643,10 @@ impl<'a, 'tcx> CrateMetadata {
self.get_impl_data(id).polarity
}

pub fn get_custom_coerce_unsized_kind(&self,
id: DefIndex)
-> Option<ty::adjustment::CustomCoerceUnsized> {
self.get_impl_data(id).coerce_unsized_kind
pub fn get_coerce_unsized_info(&self,
id: DefIndex)
-> Option<ty::adjustment::CoerceUnsizedInfo> {
self.get_impl_data(id).coerce_unsized_info
}

pub fn get_impl_trait(&self,
Expand Down
18 changes: 13 additions & 5 deletions src/librustc_metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let data = ImplData {
polarity: hir::ImplPolarity::Positive,
parent_impl: None,
coerce_unsized_kind: None,
coerce_unsized_info: None,
trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
};

Expand All @@ -715,13 +715,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
None
};

// if this is an impl of `CoerceUnsized`, create its
// "unsized info", else just store None
let coerce_unsized_info =
trait_ref.and_then(|t| {
if Some(t.def_id) == tcx.lang_items.coerce_unsized_trait() {
Some(ty::queries::coerce_unsized_info::get(tcx, item.span, def_id))
} else {
None
}
});

let data = ImplData {
polarity: polarity,
parent_impl: parent,
coerce_unsized_kind: tcx.maps.custom_coerce_unsized_kind
.borrow()
.get(&def_id)
.cloned(),
coerce_unsized_info: coerce_unsized_info,
trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)),
};

Expand Down
4 changes: 3 additions & 1 deletion src/librustc_metadata/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,9 @@ pub struct TraitData<'tcx> {
pub struct ImplData<'tcx> {
pub polarity: hir::ImplPolarity,
pub parent_impl: Option<DefId>,
pub coerce_unsized_kind: Option<ty::adjustment::CustomCoerceUnsized>,

/// This is `Some` only for impls of `CoerceUnsized`.
pub coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/monomorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx

match fulfill_obligation(scx, DUMMY_SP, trait_ref) {
traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
scx.tcx().custom_coerce_unsized_kind(impl_def_id)
scx.tcx().coerce_unsized_info(impl_def_id).custom_kind.unwrap()
}
vtable => {
bug!("invalid CoerceUnsized vtable: {:?}", vtable);
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