Skip to content

Commit 67dfc17

Browse files
committed
Auto merge of #25323 - eddyb:coherent-coherence, r=pnkfelix
The loop to load all the known impls from external crates seems to have been used because `ty::populate_implementations_for_trait_if_necessary` wasn't doing its job, and solely relying on it resulted in loading only impls in the same crate as the trait. Coherence for `librustc` was reduced from 18.310s to 0.610s, from stage1 to stage2. Interestingly, type checking also went from 46.232s to 42.003s, though that could be noise or unrelated improvements. On a smaller scale, `fn main() {}` now spends 0.003s in coherence instead of 0.368s, which fixes #22068. It also peaks at only 1.2MB, instead of 16MB of heap usage.
2 parents feac9f1 + 75cd8f9 commit 67dfc17

File tree

9 files changed

+148
-244
lines changed

9 files changed

+148
-244
lines changed

src/librustc/metadata/common.rs

+1
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ pub const tag_item_impl_vtables: usize = 0x7e;
189189

190190
pub const tag_impls: usize = 0x109; // top-level only
191191
pub const tag_impls_impl: usize = 0x7f;
192+
pub const tag_impls_impl_trait_def_id: usize = 0x8d;
192193

193194
pub const tag_items_data_item_inherent_impl: usize = 0x80;
194195
pub const tag_items_data_item_extension_impl: usize = 0x81;

src/librustc/metadata/csearch.rs

+8-16
Original file line numberDiff line numberDiff line change
@@ -304,31 +304,23 @@ pub fn get_native_libraries(cstore: &cstore::CStore, crate_num: ast::CrateNum)
304304
decoder::get_native_libraries(&*cdata)
305305
}
306306

307-
pub fn each_impl<F>(cstore: &cstore::CStore,
308-
crate_num: ast::CrateNum,
309-
callback: F) where
310-
F: FnMut(ast::DefId),
311-
{
312-
let cdata = cstore.get_crate_data(crate_num);
313-
decoder::each_impl(&*cdata, callback)
314-
}
315-
316-
pub fn each_implementation_for_type<F>(cstore: &cstore::CStore,
317-
def_id: ast::DefId,
318-
callback: F) where
307+
pub fn each_inherent_implementation_for_type<F>(cstore: &cstore::CStore,
308+
def_id: ast::DefId,
309+
callback: F) where
319310
F: FnMut(ast::DefId),
320311
{
321312
let cdata = cstore.get_crate_data(def_id.krate);
322-
decoder::each_implementation_for_type(&*cdata, def_id.node, callback)
313+
decoder::each_inherent_implementation_for_type(&*cdata, def_id.node, callback)
323314
}
324315

325316
pub fn each_implementation_for_trait<F>(cstore: &cstore::CStore,
326317
def_id: ast::DefId,
327-
callback: F) where
318+
mut callback: F) where
328319
F: FnMut(ast::DefId),
329320
{
330-
let cdata = cstore.get_crate_data(def_id.krate);
331-
decoder::each_implementation_for_trait(&*cdata, def_id.node, callback)
321+
cstore.iter_crate_data(|_, cdata| {
322+
decoder::each_implementation_for_trait(cdata, def_id, &mut callback)
323+
})
332324
}
333325

334326
/// If the given def ID describes an item belonging to a trait (either a

src/librustc/metadata/decoder.rs

+85-78
Large diffs are not rendered by default.

src/librustc/metadata/encoder.rs

+32-29
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ fn encode_impl_type_basename(rbml_w: &mut Encoder, name: ast::Name) {
9191
rbml_w.wr_tagged_str(tag_item_impl_type_basename, &token::get_name(name));
9292
}
9393

94-
pub fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
95-
rbml_w.wr_tagged_str(tag_def_id, &def_to_string(id));
94+
fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
95+
rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id));
9696
}
9797

9898
#[derive(Clone)]
@@ -122,6 +122,10 @@ fn encode_family(rbml_w: &mut Encoder, c: char) {
122122
rbml_w.wr_tagged_u8(tag_items_data_item_family, c as u8);
123123
}
124124

125+
pub fn def_to_u64(did: DefId) -> u64 {
126+
(did.krate as u64) << 32 | (did.node as u64)
127+
}
128+
125129
pub fn def_to_string(did: DefId) -> String {
126130
format!("{}:{}", did.krate, did.node)
127131
}
@@ -153,9 +157,9 @@ fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
153157
}
154158

155159
fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
156-
let s = def_to_string(vid);
157-
rbml_w.wr_tagged_str(tag_items_data_item_variant, &s[..]);
158-
rbml_w.wr_tagged_str(tag_mod_child, &s[..]);
160+
let id = def_to_u64(vid);
161+
rbml_w.wr_tagged_u64(tag_items_data_item_variant, id);
162+
rbml_w.wr_tagged_u64(tag_mod_child, id);
159163
}
160164

161165
pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
@@ -260,7 +264,7 @@ fn encode_disr_val(_: &EncodeContext,
260264
}
261265

262266
fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
263-
rbml_w.wr_tagged_str(tag_items_data_parent_item, &def_to_string(id));
267+
rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(id));
264268
}
265269

266270
fn encode_struct_fields(rbml_w: &mut Encoder,
@@ -275,7 +279,7 @@ fn encode_struct_fields(rbml_w: &mut Encoder,
275279
}
276280
encode_struct_field_family(rbml_w, f.vis);
277281
encode_def_id(rbml_w, f.id);
278-
rbml_w.wr_tagged_str(tag_item_field_origin, &def_to_string(origin));
282+
rbml_w.wr_tagged_u64(tag_item_field_origin, def_to_u64(origin));
279283
rbml_w.end_tag();
280284
}
281285
}
@@ -358,8 +362,8 @@ fn encode_reexported_static_method(rbml_w: &mut Encoder,
358362
debug!("(encode reexported static method) {}::{}",
359363
exp.name, token::get_name(method_name));
360364
rbml_w.start_tag(tag_items_data_item_reexport);
361-
rbml_w.wr_tagged_str(tag_items_data_item_reexport_def_id,
362-
&def_to_string(method_def_id));
365+
rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
366+
def_to_u64(method_def_id));
363367
rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
364368
&format!("{}::{}", exp.name,
365369
token::get_name(method_name)));
@@ -495,8 +499,8 @@ fn encode_reexports(ecx: &EncodeContext,
495499
exp.def_id.node,
496500
id);
497501
rbml_w.start_tag(tag_items_data_item_reexport);
498-
rbml_w.wr_tagged_str(tag_items_data_item_reexport_def_id,
499-
&def_to_string(exp.def_id));
502+
rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
503+
def_to_u64(exp.def_id));
500504
rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
501505
exp.name.as_str());
502506
rbml_w.end_tag();
@@ -526,12 +530,12 @@ fn encode_info_for_mod(ecx: &EncodeContext,
526530

527531
// Encode info about all the module children.
528532
for item in &md.items {
529-
rbml_w.wr_tagged_str(tag_mod_child,
530-
&def_to_string(local_def(item.id)));
533+
rbml_w.wr_tagged_u64(tag_mod_child,
534+
def_to_u64(local_def(item.id)));
531535

532536
each_auxiliary_node_id(&**item, |auxiliary_node_id| {
533-
rbml_w.wr_tagged_str(tag_mod_child,
534-
&def_to_string(local_def(auxiliary_node_id)));
537+
rbml_w.wr_tagged_u64(tag_mod_child,
538+
def_to_u64(local_def(auxiliary_node_id)));
535539
true
536540
});
537541

@@ -541,8 +545,7 @@ fn encode_info_for_mod(ecx: &EncodeContext,
541545
token::get_ident(ident),
542546
did, ecx.tcx.map.node_to_string(did));
543547

544-
rbml_w.wr_tagged_str(tag_mod_impl,
545-
&def_to_string(local_def(did)));
548+
rbml_w.wr_tagged_u64(tag_mod_impl, def_to_u64(local_def(did)));
546549
}
547550
}
548551

@@ -619,8 +622,7 @@ fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
619622
fn encode_provided_source(rbml_w: &mut Encoder,
620623
source_opt: Option<DefId>) {
621624
if let Some(source) = source_opt {
622-
rbml_w.wr_tagged_str(tag_item_method_provided_source,
623-
&def_to_string(source));
625+
rbml_w.wr_tagged_u64(tag_item_method_provided_source, def_to_u64(source));
624626
}
625627
}
626628

@@ -725,8 +727,8 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
725727
encode_name(rbml_w, param.name);
726728
rbml_w.end_tag();
727729

728-
rbml_w.wr_tagged_str(tag_region_param_def_def_id,
729-
&def_to_string(param.def_id));
730+
rbml_w.wr_tagged_u64(tag_region_param_def_def_id,
731+
def_to_u64(param.def_id));
730732

731733
rbml_w.wr_tagged_u64(tag_region_param_def_space,
732734
param.space.to_uint() as u64);
@@ -1089,8 +1091,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
10891091

10901092
// Encode all the items in this module.
10911093
for foreign_item in &fm.items {
1092-
rbml_w.wr_tagged_str(tag_mod_child,
1093-
&def_to_string(local_def(foreign_item.id)));
1094+
rbml_w.wr_tagged_u64(tag_mod_child,
1095+
def_to_u64(local_def(foreign_item.id)));
10941096
}
10951097
encode_visibility(rbml_w, vis);
10961098
encode_stability(rbml_w, stab);
@@ -1335,8 +1337,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
13351337
}
13361338
rbml_w.end_tag();
13371339

1338-
rbml_w.wr_tagged_str(tag_mod_child,
1339-
&def_to_string(method_def_id.def_id()));
1340+
rbml_w.wr_tagged_u64(tag_mod_child,
1341+
def_to_u64(method_def_id.def_id()));
13401342
}
13411343
encode_path(rbml_w, path.clone());
13421344

@@ -1893,6 +1895,7 @@ impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
18931895
def_id.krate != ast::LOCAL_CRATE {
18941896
self.rbml_w.start_tag(tag_impls_impl);
18951897
encode_def_id(self.rbml_w, local_def(item.id));
1898+
self.rbml_w.wr_tagged_u64(tag_impls_impl_trait_def_id, def_to_u64(def_id));
18961899
self.rbml_w.end_tag();
18971900
}
18981901
}
@@ -1932,12 +1935,12 @@ fn encode_misc_info(ecx: &EncodeContext,
19321935
rbml_w.start_tag(tag_misc_info);
19331936
rbml_w.start_tag(tag_misc_info_crate_items);
19341937
for item in &krate.module.items {
1935-
rbml_w.wr_tagged_str(tag_mod_child,
1936-
&def_to_string(local_def(item.id)));
1938+
rbml_w.wr_tagged_u64(tag_mod_child,
1939+
def_to_u64(local_def(item.id)));
19371940

19381941
each_auxiliary_node_id(&**item, |auxiliary_node_id| {
1939-
rbml_w.wr_tagged_str(tag_mod_child,
1940-
&def_to_string(local_def(auxiliary_node_id)));
1942+
rbml_w.wr_tagged_u64(tag_mod_child,
1943+
def_to_u64(local_def(auxiliary_node_id)));
19411944
true
19421945
});
19431946
}

src/librustc/middle/ty.rs

+16-36
Original file line numberDiff line numberDiff line change
@@ -2564,9 +2564,11 @@ impl<'tcx> TraitDef<'tcx> {
25642564
tcx: &ctxt<'tcx>,
25652565
impl_def_id: DefId,
25662566
impl_trait_ref: TraitRef<'tcx>) {
2567+
debug!("TraitDef::record_impl for {}, from {}",
2568+
self.repr(tcx), impl_trait_ref.repr(tcx));
2569+
25672570
// We don't want to borrow_mut after we already populated all impls,
25682571
// so check if an impl is present with an immutable borrow first.
2569-
25702572
if let Some(sty) = fast_reject::simplify_type(tcx,
25712573
impl_trait_ref.self_ty(), false) {
25722574
if let Some(is) = self.nonblanket_impls.borrow().get(&sty) {
@@ -6336,10 +6338,10 @@ pub fn populate_implementations_for_primitive_if_necessary(tcx: &ctxt,
63366338
tcx.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id);
63376339
}
63386340

6339-
/// Populates the type context with all the implementations for the given type
6340-
/// if necessary.
6341-
pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
6342-
type_id: ast::DefId) {
6341+
/// Populates the type context with all the inherent implementations for
6342+
/// the given type if necessary.
6343+
pub fn populate_inherent_implementations_for_type_if_necessary(tcx: &ctxt,
6344+
type_id: ast::DefId) {
63436345
if type_id.krate == LOCAL_CRATE {
63446346
return
63456347
}
@@ -6348,37 +6350,15 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
63486350
return
63496351
}
63506352

6351-
debug!("populate_implementations_for_type_if_necessary: searching for {:?}", type_id);
6353+
debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}", type_id);
63526354

63536355
let mut inherent_impls = Vec::new();
6354-
csearch::each_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| {
6355-
let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id);
6356-
6357-
// Record the implementation, if needed
6358-
if let Some(trait_ref) = csearch::get_impl_trait(tcx, impl_def_id) {
6359-
let trait_def = lookup_trait_def(tcx, trait_ref.def_id);
6360-
trait_def.record_impl(tcx, impl_def_id, trait_ref);
6361-
} else {
6362-
inherent_impls.push(impl_def_id);
6363-
}
6364-
6365-
// For any methods that use a default implementation, add them to
6366-
// the map. This is a bit unfortunate.
6367-
for impl_item_def_id in &impl_items {
6368-
let method_def_id = impl_item_def_id.def_id();
6369-
match impl_or_trait_item(tcx, method_def_id) {
6370-
MethodTraitItem(method) => {
6371-
if let Some(source) = method.provided_source {
6372-
tcx.provided_method_sources
6373-
.borrow_mut()
6374-
.insert(method_def_id, source);
6375-
}
6376-
}
6377-
_ => {}
6378-
}
6379-
}
6356+
csearch::each_inherent_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| {
6357+
// Record the implementation.
6358+
inherent_impls.push(impl_def_id);
63806359

63816360
// Store the implementation info.
6361+
let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id);
63826362
tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
63836363
});
63846364

@@ -6388,18 +6368,18 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
63886368

63896369
/// Populates the type context with all the implementations for the given
63906370
/// trait if necessary.
6391-
pub fn populate_implementations_for_trait_if_necessary(
6392-
tcx: &ctxt,
6393-
trait_id: ast::DefId) {
6371+
pub fn populate_implementations_for_trait_if_necessary(tcx: &ctxt, trait_id: ast::DefId) {
63946372
if trait_id.krate == LOCAL_CRATE {
63956373
return
63966374
}
63976375

63986376
let def = lookup_trait_def(tcx, trait_id);
63996377
if def.flags.get().intersects(TraitFlags::IMPLS_VALID) {
6400-
return
6378+
return;
64016379
}
64026380

6381+
debug!("populate_implementations_for_trait_if_necessary: searching for {}", def.repr(tcx));
6382+
64036383
if csearch::is_defaulted_trait(&tcx.sess.cstore, trait_id) {
64046384
record_trait_has_default_impl(tcx, trait_id);
64056385
}

src/librustc_typeck/check/method/probe.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
371371
fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: ast::DefId) {
372372
// Read the inherent implementation candidates for this type from the
373373
// metadata if necessary.
374-
ty::populate_implementations_for_type_if_necessary(self.tcx(), def_id);
374+
ty::populate_inherent_implementations_for_type_if_necessary(self.tcx(), def_id);
375375

376376
if let Some(impl_infos) = self.tcx().inherent_impls.borrow().get(&def_id) {
377377
for &impl_def_id in &***impl_infos {

0 commit comments

Comments
 (0)