Skip to content

Commit bbeb0c0

Browse files
authored
Rollup merge of rust-lang#40683 - nikomatsakis:incr-comp-coerce-unsized-info, r=eddyb
on-demand-ify `custom_coerce_unsized_kind` and `inherent-impls` This "on-demand" task both checks for errors and computes the custom unsized kind, if any. This task is only defined on impls of `CoerceUnsized`; invoking it on any other kind of impl results in a bug. This is just to avoid having an `Option`, could easily be changed. r? @eddyb
2 parents e5f66fe + a29ae30 commit bbeb0c0

File tree

17 files changed

+306
-220
lines changed

17 files changed

+306
-220
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ pub enum DepNode<D: Clone + Debug> {
7474
CoherenceCheckImpl(D),
7575
CoherenceOverlapCheck(D),
7676
CoherenceOverlapCheckSpecial(D),
77-
CoherenceOverlapInherentCheck(D),
7877
CoherenceOrphanCheck(D),
7978
Variance,
8079
WfCheck(D),
@@ -251,7 +250,6 @@ impl<D: Clone + Debug> DepNode<D> {
251250
CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
252251
CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),
253252
CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial),
254-
CoherenceOverlapInherentCheck(ref d) => op(d).map(CoherenceOverlapInherentCheck),
255253
CoherenceOrphanCheck(ref d) => op(d).map(CoherenceOrphanCheck),
256254
WfCheck(ref d) => op(d).map(WfCheck),
257255
TypeckItemType(ref d) => op(d).map(TypeckItemType),

src/librustc/dep_graph/dep_tracking_map.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -81,21 +81,6 @@ impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
8181
pub fn keys(&self) -> Vec<M::Key> {
8282
self.map.keys().cloned().collect()
8383
}
84-
85-
/// Append `elem` to the vector stored for `k`, creating a new vector if needed.
86-
/// This is considered a write to `k`.
87-
///
88-
/// NOTE: Caution is required when using this method. You should
89-
/// be sure that nobody is **reading from the vector** while you
90-
/// are writing to it. Eventually, it'd be nice to remove this.
91-
pub fn push<E: Clone>(&mut self, k: M::Key, elem: E)
92-
where M: DepTrackingMapConfig<Value=Vec<E>>
93-
{
94-
self.write(&k);
95-
self.map.entry(k)
96-
.or_insert(Vec::new())
97-
.push(elem);
98-
}
9984
}
10085

10186
impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {

src/librustc/middle/cstore.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ pub trait CrateStore {
176176
fn item_generics_cloned(&self, def: DefId) -> ty::Generics;
177177
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
178178
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>;
179-
fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId>;
180179

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

315313
// trait info
316314
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }

src/librustc/ty/adjustment.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,21 @@ pub enum AutoBorrow<'tcx> {
139139
RawPtr(hir::Mutability),
140140
}
141141

142+
/// Information for `CoerceUnsized` impls, storing information we
143+
/// have computed about the coercion.
144+
///
145+
/// This struct can be obtained via the `coerce_impl_info` query.
146+
/// Demanding this struct also has the side-effect of reporting errors
147+
/// for inappropriate impls.
148+
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
149+
pub struct CoerceUnsizedInfo {
150+
/// If this is a "custom coerce" impl, then what kind of custom
151+
/// coercion is it? This applies to impls of `CoerceUnsized` for
152+
/// structs, primarily, where we store a bit of info about which
153+
/// fields need to be coerced.
154+
pub custom_kind: Option<CustomCoerceUnsized>
155+
}
156+
142157
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
143158
pub enum CustomCoerceUnsized {
144159
/// Records the index of the field being coerced.

src/librustc/ty/maps.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
1212
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
1313
use middle::const_val::ConstVal;
1414
use mir;
15-
use ty::{self, Ty, TyCtxt};
15+
use ty::{self, CrateInherentImpls, Ty, TyCtxt};
1616

1717
use rustc_data_structures::indexed_vec::IndexVec;
1818
use std::cell::{RefCell, RefMut};
@@ -176,9 +176,15 @@ impl<'tcx> QueryDescription for queries::coherent_trait<'tcx> {
176176
}
177177
}
178178

179-
impl<'tcx> QueryDescription for queries::coherent_inherent_impls<'tcx> {
179+
impl<'tcx> QueryDescription for queries::crate_inherent_impls<'tcx> {
180+
fn describe(_: TyCtxt, k: CrateNum) -> String {
181+
format!("all inherent impls defined in crate `{:?}`", k)
182+
}
183+
}
184+
185+
impl<'tcx> QueryDescription for queries::crate_inherent_impls_overlap_check<'tcx> {
180186
fn describe(_: TyCtxt, _: CrateNum) -> String {
181-
format!("coherence checking all inherent impls")
187+
format!("check for overlap between inherent impls defined in this crate")
182188
}
183189
}
184190

@@ -375,7 +381,7 @@ define_maps! { <'tcx>
375381
/// Maps a DefId of a type to a list of its inherent impls.
376382
/// Contains implementations of methods that are inherent to a type.
377383
/// Methods in these implementations don't need to be exported.
378-
pub inherent_impls: InherentImpls(DefId) -> Vec<DefId>,
384+
pub inherent_impls: InherentImpls(DefId) -> Rc<Vec<DefId>>,
379385

380386
/// Maps from the def-id of a function/method or const/static
381387
/// to its MIR. Mutation is done at an item granularity to
@@ -400,16 +406,24 @@ define_maps! { <'tcx>
400406
pub closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
401407

402408
/// Caches CoerceUnsized kinds for impls on custom types.
403-
pub custom_coerce_unsized_kind: ItemSignature(DefId)
404-
-> ty::adjustment::CustomCoerceUnsized,
409+
pub coerce_unsized_info: ItemSignature(DefId)
410+
-> ty::adjustment::CoerceUnsizedInfo,
405411

406412
pub typeck_item_bodies: typeck_item_bodies_dep_node(CrateNum) -> (),
407413

408414
pub typeck_tables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,
409415

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

412-
pub coherent_inherent_impls: coherent_inherent_impls_dep_node(CrateNum) -> (),
418+
/// Gets a complete map from all types to their inherent impls.
419+
/// Not meant to be used directly outside of coherence.
420+
/// (Defined only for LOCAL_CRATE)
421+
pub crate_inherent_impls: crate_inherent_impls_dep_node(CrateNum) -> CrateInherentImpls,
422+
423+
/// Checks all types in the krate for overlap in their inherent impls. Reports errors.
424+
/// Not meant to be used directly outside of coherence.
425+
/// (Defined only for LOCAL_CRATE)
426+
pub crate_inherent_impls_overlap_check: crate_inherent_impls_dep_node(CrateNum) -> (),
413427

414428
/// Results of evaluating monomorphic constants embedded in
415429
/// other items, such as enum variant explicit discriminants.
@@ -422,7 +436,7 @@ fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
422436
DepNode::CoherenceCheckTrait(def_id)
423437
}
424438

425-
fn coherent_inherent_impls_dep_node(_: CrateNum) -> DepNode<DefId> {
439+
fn crate_inherent_impls_dep_node(_: CrateNum) -> DepNode<DefId> {
426440
DepNode::Coherence
427441
}
428442

src/librustc/ty/mod.rs

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use ty::subst::{Subst, Substs};
3131
use ty::util::IntTypeExt;
3232
use ty::walk::TypeWalker;
3333
use util::common::MemoizationMap;
34-
use util::nodemap::{NodeSet, FxHashMap};
34+
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
3535

3636
use serialize::{self, Encodable, Encoder};
3737
use std::borrow::Cow;
@@ -2054,8 +2054,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
20542054
})
20552055
}
20562056

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

20612061
pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
@@ -2345,34 +2345,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
23452345
def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL)
23462346
}
23472347

2348-
/// Populates the type context with all the inherent implementations for
2349-
/// the given type if necessary.
2350-
pub fn populate_inherent_implementations_for_type_if_necessary(self,
2351-
span: Span,
2352-
type_id: DefId) {
2353-
if type_id.is_local() {
2354-
// Make sure coherence of inherent impls ran already.
2355-
ty::queries::coherent_inherent_impls::force(self, span, LOCAL_CRATE);
2356-
return
2357-
}
2358-
2359-
// The type is not local, hence we are reading this out of
2360-
// metadata and don't need to track edges.
2361-
let _ignore = self.dep_graph.in_ignore();
2362-
2363-
if self.populated_external_types.borrow().contains(&type_id) {
2364-
return
2365-
}
2366-
2367-
debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}",
2368-
type_id);
2369-
2370-
let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id);
2371-
2372-
self.maps.inherent_impls.borrow_mut().insert(type_id, inherent_impls);
2373-
self.populated_external_types.borrow_mut().insert(type_id);
2374-
}
2375-
23762348
/// Populates the type context with all the implementations for the given
23772349
/// trait if necessary.
23782350
pub fn populate_implementations_for_trait_if_necessary(self, trait_id: DefId) {
@@ -2637,3 +2609,16 @@ pub fn provide(providers: &mut ty::maps::Providers) {
26372609
..*providers
26382610
};
26392611
}
2612+
2613+
2614+
/// A map for the local crate mapping each type to a vector of its
2615+
/// inherent impls. This is not meant to be used outside of coherence;
2616+
/// rather, you should request the vector for a specific type via
2617+
/// `ty::queries::inherent_impls::get(def_id)` so as to minimize your
2618+
/// dependencies (constructing this map requires touching the entire
2619+
/// crate).
2620+
#[derive(Clone, Debug)]
2621+
pub struct CrateInherentImpls {
2622+
pub inherent_impls: DefIdMap<Rc<Vec<DefId>>>,
2623+
}
2624+

src/librustc_metadata/cstore_impl.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ provide! { <'tcx> tcx, def_id, cdata
8888
}
8989
associated_item => { cdata.get_associated_item(def_id.index) }
9090
impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
91-
custom_coerce_unsized_kind => {
92-
cdata.get_custom_coerce_unsized_kind(def_id.index).unwrap_or_else(|| {
93-
bug!("custom_coerce_unsized_kind: `{:?}` is missing its kind", def_id);
91+
coerce_unsized_info => {
92+
cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
93+
bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
9494
})
9595
}
9696
mir => {
@@ -109,6 +109,7 @@ provide! { <'tcx> tcx, def_id, cdata
109109
typeck_tables => { cdata.item_body_tables(def_id.index, tcx) }
110110
closure_kind => { cdata.closure_kind(def_id.index) }
111111
closure_type => { cdata.closure_ty(def_id.index, tcx) }
112+
inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
112113
}
113114

114115
impl CrateStore for cstore::CStore {
@@ -162,12 +163,6 @@ impl CrateStore for cstore::CStore {
162163
self.get_crate_data(did.krate).get_fn_arg_names(did.index)
163164
}
164165

165-
fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId>
166-
{
167-
self.dep_graph.read(DepNode::MetaData(def_id));
168-
self.get_crate_data(def_id.krate).get_inherent_implementations_for_type(def_id.index)
169-
}
170-
171166
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>
172167
{
173168
if let Some(def_id) = filter {

src/librustc_metadata/decoder.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -643,10 +643,10 @@ impl<'a, 'tcx> CrateMetadata {
643643
self.get_impl_data(id).polarity
644644
}
645645

646-
pub fn get_custom_coerce_unsized_kind(&self,
647-
id: DefIndex)
648-
-> Option<ty::adjustment::CustomCoerceUnsized> {
649-
self.get_impl_data(id).coerce_unsized_kind
646+
pub fn get_coerce_unsized_info(&self,
647+
id: DefIndex)
648+
-> Option<ty::adjustment::CoerceUnsizedInfo> {
649+
self.get_impl_data(id).coerce_unsized_info
650650
}
651651

652652
pub fn get_impl_trait(&self,

src/librustc_metadata/encoder.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
695695
let data = ImplData {
696696
polarity: hir::ImplPolarity::Positive,
697697
parent_impl: None,
698-
coerce_unsized_kind: None,
698+
coerce_unsized_info: None,
699699
trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
700700
};
701701

@@ -715,13 +715,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
715715
None
716716
};
717717

718+
// if this is an impl of `CoerceUnsized`, create its
719+
// "unsized info", else just store None
720+
let coerce_unsized_info =
721+
trait_ref.and_then(|t| {
722+
if Some(t.def_id) == tcx.lang_items.coerce_unsized_trait() {
723+
Some(ty::queries::coerce_unsized_info::get(tcx, item.span, def_id))
724+
} else {
725+
None
726+
}
727+
});
728+
718729
let data = ImplData {
719730
polarity: polarity,
720731
parent_impl: parent,
721-
coerce_unsized_kind: tcx.maps.custom_coerce_unsized_kind
722-
.borrow()
723-
.get(&def_id)
724-
.cloned(),
732+
coerce_unsized_info: coerce_unsized_info,
725733
trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)),
726734
};
727735

src/librustc_metadata/schema.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,9 @@ pub struct TraitData<'tcx> {
285285
pub struct ImplData<'tcx> {
286286
pub polarity: hir::ImplPolarity,
287287
pub parent_impl: Option<DefId>,
288-
pub coerce_unsized_kind: Option<ty::adjustment::CustomCoerceUnsized>,
288+
289+
/// This is `Some` only for impls of `CoerceUnsized`.
290+
pub coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
289291
pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
290292
}
291293

src/librustc_trans/monomorphize.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx
287287

288288
match fulfill_obligation(scx, DUMMY_SP, trait_ref) {
289289
traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
290-
scx.tcx().custom_coerce_unsized_kind(impl_def_id)
290+
scx.tcx().coerce_unsized_info(impl_def_id).custom_kind.unwrap()
291291
}
292292
vtable => {
293293
bug!("invalid CoerceUnsized vtable: {:?}", vtable);

src/librustc_typeck/check/method/probe.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -479,14 +479,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
479479
}
480480

481481
fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
482-
// Read the inherent implementation candidates for this type from the
483-
// metadata if necessary.
484-
self.tcx.populate_inherent_implementations_for_type_if_necessary(self.span, def_id);
485-
486-
if let Some(impl_infos) = self.tcx.maps.inherent_impls.borrow().get(&def_id) {
487-
for &impl_def_id in impl_infos.iter() {
488-
self.assemble_inherent_impl_probe(impl_def_id);
489-
}
482+
let impl_def_ids = ty::queries::inherent_impls::get(self.tcx, self.span, def_id);
483+
for &impl_def_id in impl_def_ids.iter() {
484+
self.assemble_inherent_impl_probe(impl_def_id);
490485
}
491486
}
492487

0 commit comments

Comments
 (0)