Skip to content

Make traits_in_crate and impls_in_crate proper queries #100601

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

Closed
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
8925fcc
hashmap compiles
Robert-Cunningham Aug 13, 2022
d84ecf2
write all_local_trait_impls in terms of new query
Robert-Cunningham Aug 13, 2022
8acd145
remove fom resolver
Robert-Cunningham Aug 13, 2022
2d54ab7
convert hashmap to indexmap
Robert-Cunningham Aug 14, 2022
ab7c2ba
add eval_always
Robert-Cunningham Aug 15, 2022
d3426dd
stop prinnting dep graph
Robert-Cunningham Aug 15, 2022
251fcbc
clean up
Robert-Cunningham Aug 15, 2022
83ca511
revert derive formatting changes
Robert-Cunningham Aug 15, 2022
31222de
remove comments
Robert-Cunningham Aug 15, 2022
5a7d801
remove last robert-trait annotation
Robert-Cunningham Aug 15, 2022
058b8dc
implement cjg first suggestion
Robert-Cunningham Sep 12, 2022
c2a2636
Merge branch 'rust-lang:master' into impls_in_crate
Robert-Cunningham Sep 12, 2022
687280d
Merge branch 'impls_in_crate' of github.com:Robert-Cunningham/rust in…
Robert-Cunningham Sep 12, 2022
6b0ab18
temporary changed found january
Robert-Cunningham Jan 13, 2023
44364ae
resolve merge comfinclits
Robert-Cunningham Jan 13, 2023
11b2ade
make compile after merge
Robert-Cunningham Jan 13, 2023
3b486b2
fix git rename misses
Robert-Cunningham Jan 13, 2023
621ba62
debug checks
Robert-Cunningham Jan 14, 2023
bd35683
change type to option
Robert-Cunningham Jan 15, 2023
58d1577
remove local_impls_in_crate, find cycle
Robert-Cunningham Jan 15, 2023
90e12e8
passing tests
Robert-Cunningham Jan 15, 2023
0655439
revert everything
Robert-Cunningham Jan 16, 2023
ecc2c08
clean and clarify
Robert-Cunningham Jan 16, 2023
66179b9
passes tests
Robert-Cunningham Jan 16, 2023
6e61761
merge upstream changes
Robert-Cunningham Jan 17, 2023
a1bee1c
finish merge
Robert-Cunningham Jan 17, 2023
d313486
remove comment churn
Robert-Cunningham Jan 17, 2023
5c07123
remove last comment
Robert-Cunningham Jan 17, 2023
37aba45
add comment to address review
Robert-Cunningham Jan 21, 2023
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
22 changes: 21 additions & 1 deletion compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::rmeta::*;
use rustc_ast as ast;
use rustc_ast::ptr::P;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell};
use rustc_data_structures::unhash::UnhashMap;
Expand Down Expand Up @@ -1261,6 +1261,26 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
})
}

/// Decodes a map from trait to impls.
fn get_trait_impl_map(self) -> FxIndexMap<DefId, Vec<(DefId, Option<SimplifiedType>)>> {
self.cdata
.trait_impls
.iter()
.map(|(&(trait_cnum_raw, trait_index), impls)| {
let krate = self.cnum_map[CrateNum::from_u32(trait_cnum_raw)];
let trait_def_id = DefId { krate, index: trait_index };

return (
trait_def_id,
impls
.decode(self)
.map(|(impl_index, ty)| (DefId { krate, index: impl_index }, ty))
.collect(),
);
})
.collect()
}

fn get_all_incoherent_impls(self) -> impl Iterator<Item = DefId> + 'a {
self.cdata
.incoherent_impls
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
extra_filename => { cdata.root.extra_filename.clone() }

traits_in_crate => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
impls_in_crate => { tcx.arena.alloc(cdata.get_trait_impl_map()) }
implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) }
crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) }

Expand Down
73 changes: 50 additions & 23 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::rmeta::table::TableBuilder;
use crate::rmeta::*;

use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::memmap::{Mmap, MmapMut};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
Expand Down Expand Up @@ -1818,25 +1818,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
debug!("EncodeContext::encode_traits_and_impls()");
empty_proc_macro!(self);
let tcx = self.tcx;
let mut fx_hash_map: FxHashMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>> =
FxHashMap::default();

for id in tcx.hir().items() {
if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) {
let simplified_self_ty = fast_reject::simplify_type(
self.tcx,
trait_ref.self_ty(),
TreatParams::AsInfer,
);

fx_hash_map
.entry(trait_ref.def_id)
.or_default()
.push((id.def_id.local_def_index, simplified_self_ty));
}
}
}
let fx_hash_map = self.tcx.impls_in_crate(LOCAL_CRATE).to_owned();

let mut all_impls: Vec<_> = fx_hash_map.into_iter().collect();

Expand All @@ -1848,9 +1830,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
.map(|(trait_def_id, mut impls)| {
// Bring everything into deterministic order for hashing
impls.sort_by_cached_key(|&(index, _)| {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get rid of this sort and the one above?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

impls_in_crate returns a FxIndexMap<DefId, Vec<(DefId, Option<SimplifiedType>)>>; The Vec part should be in source code order, and the Map<TraitId, ...> part is ordered by the source code order of the Impls. Since the source code is hashed into crate_hash, I believe you're right, we can remove both of these sorts.

In fact, if I understand correctly, we can also remove a third sort in encode_incoherent_impls, since it ultimately relies on a similarly stable iteration through tcx.hir().items().

tcx.hir().def_path_hash(LocalDefId { local_def_index: index })
tcx.hir().def_path_hash(LocalDefId {
local_def_index: index.expect_local().local_def_index,
})
});

let impls: Vec<_> = impls
.iter()
.map(|(def_id, ty)| (def_id.expect_local().local_def_index, *ty))
.collect();

TraitImpls {
trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
impls: self.lazy_array(&impls),
Expand Down Expand Up @@ -2282,6 +2271,20 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {

pub fn provide(providers: &mut Providers) {
*providers = Providers {
all_local_trait_impls: |tcx, _| {
let o: FxIndexMap<_, _> = tcx
.impls_in_crate(LOCAL_CRATE)
.iter()
.map(|(trait_id, impls)| {
(
*trait_id,
impls.iter().map(|(id, _)| id.expect_local()).collect::<Vec<LocalDefId>>(),
)
})
.collect();

tcx.arena.alloc(o)
},
traits_in_crate: |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);

Expand All @@ -2292,11 +2295,35 @@ pub fn provide(providers: &mut Providers) {
}
}

// Bring everything into deterministic order.
traits.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id));
// We don't need to sort, since the default order is source-code order.
// The source code is hashed into crate_hash, so if crate_hash is stable then it must be stable too.

tcx.arena.alloc_slice(&traits)
},
impls_in_crate: |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
let mut fx_hash_map: FxIndexMap<DefId, Vec<(DefId, Option<SimplifiedType>)>> =
FxIndexMap::default();

for id in tcx.hir().items() {
if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) {
let simplified_self_ty = fast_reject::simplify_type(
tcx,
trait_ref.self_ty(),
TreatParams::AsInfer,
);

fx_hash_map
.entry(trait_ref.def_id)
.or_default()
.push((id.def_id.to_def_id(), simplified_self_ty));
}
}
}

tcx.arena.alloc(fx_hash_map)
},
..*providers
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ macro_rules! arena_types {
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>>
>,
[] all_traits: Vec<rustc_hir::def_id::DefId>,
[] trait_to_impl_and_ty: rustc_data_structures::fx::FxIndexMap<rustc_hir::def_id::DefId, Vec<(rustc_hir::def_id::DefId, Option<rustc_middle::ty::fast_reject::SimplifiedTypeGen<rustc_hir::def_id::DefId>>)>>,
[] trait_to_impl: rustc_data_structures::fx::FxIndexMap<rustc_hir::def_id::DefId, Vec<rustc_hir::def_id::LocalDefId>>,
[] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels,
[] foreign_module: rustc_session::cstore::ForeignModule,
[] foreign_modules: Vec<rustc_session::cstore::ForeignModule>,
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ pub fn provide(providers: &mut Providers) {
}
};
providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
providers.expn_that_defined = |tcx, id| {
let id = id.expect_local();
tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root())
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1742,6 +1742,13 @@ rustc_queries! {
separate_provide_extern
}

/// A list of all traits in a crate mapped to their impls in that crate.
query impls_in_crate(_: CrateNum) -> &'tcx FxIndexMap<DefId, Vec<(DefId, Option<rustc_middle::ty::fast_reject::SimplifiedTypeGen<DefId>>)>> {
eval_always
desc { "fetching trait to impl map in a crate" }
separate_provide_extern
}

/// The list of symbols exported from the given crate.
///
/// - All names contained in `exported_symbols(cnum)` are guaranteed to
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use rustc_ast as ast;
use rustc_ast::node_id::NodeMap;
use rustc_attr as attr;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::intern::{Interned, WithStableHash};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
Expand Down Expand Up @@ -153,7 +153,6 @@ pub struct ResolverOutputs {
/// via `extern crate` item and not `--extern` option or compiler built-in.
pub extern_prelude: FxHashMap<Symbol, bool>,
pub main_def: Option<MainDefinition>,
pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
/// A list of proc macro LocalDefIds, written out in the order in which
/// they are declared in the static array generated by proc_macro_harness.
pub proc_macros: Vec<LocalDefId>,
Expand Down
13 changes: 1 addition & 12 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2618,18 +2618,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
opt_trait_reference.as_ref(),
self_type,
|this, trait_id| {
let item_def_id = this.r.local_def_id(item_id);

// Register the trait definitions from here.
if let Some(trait_id) = trait_id {
this.r
.trait_impls
.entry(trait_id)
.or_default()
.push(item_def_id);
}

let item_def_id = item_def_id.to_def_id();
let item_def_id = this.r.local_def_id(item_id).to_def_id();
let res = Res::SelfTy {
trait_: trait_id,
alias_to: Some((item_def_id, false)),
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1048,7 +1048,6 @@ pub struct Resolver<'a> {
item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>,

main_def: Option<MainDefinition>,
trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
/// A list of proc macro LocalDefIds, written out in the order in which
/// they are declared in the static array generated by proc_macro_harness.
proc_macros: Vec<NodeId>,
Expand Down Expand Up @@ -1358,7 +1357,6 @@ impl<'a> Resolver<'a> {
legacy_const_generic_args: Default::default(),
item_generics_num_lifetimes: Default::default(),
main_def: Default::default(),
trait_impls: Default::default(),
proc_macros: Default::default(),
confused_type_with_std_module: Default::default(),
access_levels: Default::default(),
Expand Down Expand Up @@ -1439,7 +1437,6 @@ impl<'a> Resolver<'a> {
.map(|(ident, entry)| (ident.name, entry.introduced_by_item))
.collect(),
main_def,
trait_impls: self.trait_impls,
proc_macros,
confused_type_with_std_module,
registered_tools: self.registered_tools,
Expand Down Expand Up @@ -1483,7 +1480,6 @@ impl<'a> Resolver<'a> {
.map(|(ident, entry)| (ident.name, entry.introduced_by_item))
.collect(),
main_def: self.main_def,
trait_impls: self.trait_impls.clone(),
proc_macros,
confused_type_with_std_module: self.confused_type_with_std_module.clone(),
registered_tools: self.registered_tools.clone(),
Expand Down