Skip to content

Commit 3b7d496

Browse files
matthewjaspercamelid
authored andcommitted
Add query to avoid name comparison in leaf_def
1 parent 1b057a3 commit 3b7d496

File tree

8 files changed

+114
-89
lines changed

8 files changed

+114
-89
lines changed

compiler/rustc_middle/src/query/mod.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,32 @@ rustc_queries! {
630630
desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) }
631631
}
632632

633+
/// Maps from associated items on a trait to the corresponding associated
634+
/// item on the impl specified by `impl_id`.
635+
///
636+
/// For example, with the following code
637+
///
638+
/// ```
639+
/// struct Type {}
640+
/// // DefId
641+
/// trait Trait { // trait_id
642+
/// fn f(); // trait_f
643+
/// fn g() {} // trait_g
644+
/// }
645+
///
646+
/// impl Trait for Type { // impl_id
647+
/// fn f() {} // impl_f
648+
/// fn g() {} // impl_g
649+
/// }
650+
/// ```
651+
///
652+
/// The map returned for `tcx.impl_item_implementor_ids(impl_id)` would be
653+
///`{ trait_f: impl_f, trait_g: impl_g }`
654+
query impl_item_implementor_ids(impl_id: DefId) -> FxHashMap<DefId, DefId> {
655+
desc { |tcx| "comparing impl items against trait for {}", tcx.def_path_str(impl_id) }
656+
storage(ArenaCacheSelector<'tcx>)
657+
}
658+
633659
/// Given an `impl_id`, return the trait it implements.
634660
/// Return `None` if this is an inherent impl.
635661
query impl_trait_ref(impl_id: DefId) -> Option<ty::TraitRef<'tcx>> {

compiler/rustc_middle/src/traits/specialization_graph.rs

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use crate::ty::{self, TyCtxt};
44
use rustc_data_structures::fx::FxIndexMap;
55
use rustc_errors::ErrorReported;
66
use rustc_hir::def_id::{DefId, DefIdMap};
7-
use rustc_span::symbol::Ident;
87

98
/// A per-trait graph of impls in specialization order. At the moment, this
109
/// graph forms a tree rooted with the trait itself, with all other nodes
@@ -75,34 +74,28 @@ pub enum Node {
7574
Trait(DefId),
7675
}
7776

78-
impl<'tcx> Node {
77+
impl Node {
7978
pub fn is_from_trait(&self) -> bool {
8079
matches!(self, Node::Trait(..))
8180
}
8281

83-
/// Iterate over the items defined directly by the given (impl or trait) node.
84-
pub fn items(&self, tcx: TyCtxt<'tcx>) -> impl 'tcx + Iterator<Item = &'tcx ty::AssocItem> {
85-
tcx.associated_items(self.def_id()).in_definition_order()
86-
}
87-
88-
/// Finds an associated item defined in this node.
82+
/// Trys to find the associated item that implements `trait_item_def_id`
83+
/// defined in this node.
8984
///
9085
/// If this returns `None`, the item can potentially still be found in
9186
/// parents of this node.
92-
pub fn item(
87+
pub fn item<'tcx>(
9388
&self,
9489
tcx: TyCtxt<'tcx>,
95-
trait_item_name: Ident,
96-
trait_item_kind: ty::AssocKind,
97-
trait_def_id: DefId,
98-
) -> Option<ty::AssocItem> {
99-
tcx.associated_items(self.def_id())
100-
.filter_by_name_unhygienic(trait_item_name.name)
101-
.find(move |impl_item| {
102-
trait_item_kind == impl_item.kind
103-
&& tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id)
104-
})
105-
.copied()
90+
trait_item_def_id: DefId,
91+
) -> Option<&'tcx ty::AssocItem> {
92+
match *self {
93+
Node::Trait(_) => Some(tcx.associated_item(trait_item_def_id)),
94+
Node::Impl(impl_def_id) => {
95+
let id = tcx.impl_item_implementor_ids(impl_def_id).get(&trait_item_def_id)?;
96+
Some(tcx.associated_item(*id))
97+
}
98+
}
10699
}
107100

108101
pub fn def_id(&self) -> DefId {
@@ -181,17 +174,11 @@ impl LeafDef {
181174
impl<'tcx> Ancestors<'tcx> {
182175
/// Finds the bottom-most (ie. most specialized) definition of an associated
183176
/// item.
184-
pub fn leaf_def(
185-
mut self,
186-
tcx: TyCtxt<'tcx>,
187-
trait_item_name: Ident,
188-
trait_item_kind: ty::AssocKind,
189-
) -> Option<LeafDef> {
190-
let trait_def_id = self.trait_def_id;
177+
pub fn leaf_def(mut self, tcx: TyCtxt<'tcx>, trait_item_def_id: DefId) -> Option<LeafDef> {
191178
let mut finalizing_node = None;
192179

193180
self.find_map(|node| {
194-
if let Some(item) = node.item(tcx, trait_item_name, trait_item_kind, trait_def_id) {
181+
if let Some(item) = node.item(tcx, trait_item_def_id) {
195182
if finalizing_node.is_none() {
196183
let is_specializable = item.defaultness.is_default()
197184
|| tcx.impl_defaultness(node.def_id()).is_default();
@@ -201,7 +188,7 @@ impl<'tcx> Ancestors<'tcx> {
201188
}
202189
}
203190

204-
Some(LeafDef { item, defining_node: node, finalizing_node })
191+
Some(LeafDef { item: *item, defining_node: node, finalizing_node })
205192
} else {
206193
// Item not mentioned. This "finalizes" any defaulted item provided by an ancestor.
207194
finalizing_node = Some(node);

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,10 +1310,9 @@ fn create_mono_items_for_default_impls<'tcx>(
13101310
if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
13111311
let param_env = ty::ParamEnv::reveal_all();
13121312
let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
1313-
let overridden_methods: FxHashSet<_> =
1314-
impl_.items.iter().map(|iiref| iiref.ident.normalize_to_macros_2_0()).collect();
1313+
let overridden_methods = tcx.impl_item_implementor_ids(item.def_id);
13151314
for method in tcx.provided_trait_methods(trait_ref.def_id) {
1316-
if overridden_methods.contains(&method.ident.normalize_to_macros_2_0()) {
1315+
if overridden_methods.contains_key(&method.def_id) {
13171316
continue;
13181317
}
13191318

compiler/rustc_passes/src/check_const.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,26 +93,29 @@ impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<
9393
for trait_item in self.tcx.associated_items(trait_def_id).in_definition_order()
9494
{
9595
if let ty::AssocItem {
96-
kind: ty::AssocKind::Fn, ident, defaultness, ..
97-
} = trait_item
96+
kind: ty::AssocKind::Fn,
97+
defaultness,
98+
def_id: trait_item_id,
99+
..
100+
} = *trait_item
98101
{
99102
// we can ignore functions that do not have default bodies:
100103
// if those are unimplemented it will be catched by typeck.
101104
if !defaultness.has_value()
102105
|| self
103106
.tcx
104-
.has_attr(trait_item.def_id, sym::default_method_body_is_const)
107+
.has_attr(trait_item_id, sym::default_method_body_is_const)
105108
{
106109
continue;
107110
}
108111

109112
let is_implemented = ancestors
110-
.leaf_def(self.tcx, trait_item.ident, trait_item.kind)
113+
.leaf_def(self.tcx, trait_item_id)
111114
.map(|node_item| !node_item.defining_node.is_from_trait())
112115
.unwrap_or(false);
113116

114117
if !is_implemented {
115-
to_implement.push(ident.to_string());
118+
to_implement.push(self.tcx.item_name(trait_item_id).to_string());
116119
}
117120
}
118121
}

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1883,7 +1883,6 @@ fn assoc_ty_def(
18831883
assoc_ty_def_id: DefId,
18841884
) -> Result<specialization_graph::LeafDef, ErrorReported> {
18851885
let tcx = selcx.tcx();
1886-
let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident;
18871886
let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
18881887
let trait_def = tcx.trait_def(trait_def_id);
18891888

@@ -1893,21 +1892,18 @@ fn assoc_ty_def(
18931892
// for the associated item at the given impl.
18941893
// If there is no such item in that impl, this function will fail with a
18951894
// cycle error if the specialization graph is currently being built.
1896-
let impl_node = specialization_graph::Node::Impl(impl_def_id);
1897-
for item in impl_node.items(tcx) {
1898-
if matches!(item.kind, ty::AssocKind::Type)
1899-
&& tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
1900-
{
1901-
return Ok(specialization_graph::LeafDef {
1902-
item: *item,
1903-
defining_node: impl_node,
1904-
finalizing_node: if item.defaultness.is_default() { None } else { Some(impl_node) },
1905-
});
1906-
}
1895+
if let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&assoc_ty_def_id) {
1896+
let item = tcx.associated_item(impl_item_id);
1897+
let impl_node = specialization_graph::Node::Impl(impl_def_id);
1898+
return Ok(specialization_graph::LeafDef {
1899+
item: *item,
1900+
defining_node: impl_node,
1901+
finalizing_node: if item.defaultness.is_default() { None } else { Some(impl_node) },
1902+
});
19071903
}
19081904

19091905
let ancestors = trait_def.ancestors(tcx, impl_def_id)?;
1910-
if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) {
1906+
if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_ty_def_id) {
19111907
Ok(assoc_item)
19121908
} else {
19131909
// This is saying that neither the trait nor
@@ -1916,7 +1912,11 @@ fn assoc_ty_def(
19161912
// could only arise through a compiler bug --
19171913
// if the user wrote a bad item name, it
19181914
// should have failed in astconv.
1919-
bug!("No associated type `{}` for {}", assoc_ty_name, tcx.def_path_str(impl_def_id))
1915+
bug!(
1916+
"No associated type `{}` for {}",
1917+
tcx.item_name(assoc_ty_def_id),
1918+
tcx.def_path_str(impl_def_id)
1919+
)
19201920
}
19211921
}
19221922

compiler/rustc_trait_selection/src/traits/wf.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -197,14 +197,13 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
197197
item: Option<&hir::Item<'tcx>>,
198198
cause: &mut traits::ObligationCause<'tcx>,
199199
pred: &ty::Predicate<'tcx>,
200-
mut trait_assoc_items: impl Iterator<Item = &'tcx ty::AssocItem>,
201200
) {
202201
debug!(
203202
"extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}",
204203
trait_ref, item, cause, pred
205204
);
206-
let items = match item {
207-
Some(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.items,
205+
let (items, impl_def_id) = match item {
206+
Some(hir::Item { kind: hir::ItemKind::Impl(impl_), def_id, .. }) => (impl_.items, *def_id),
208207
_ => return,
209208
};
210209
let fix_span =
@@ -222,11 +221,16 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
222221
// `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
223222
// `traits-assoc-type-in-supertrait-bad.rs`.
224223
if let ty::Projection(projection_ty) = proj.ty.kind() {
225-
let trait_assoc_item = tcx.associated_item(projection_ty.item_def_id);
226-
if let Some(impl_item_span) =
227-
items.iter().find(|item| item.ident == trait_assoc_item.ident).map(fix_span)
224+
if let Some(&impl_item_id) =
225+
tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
228226
{
229-
cause.span = impl_item_span;
227+
if let Some(impl_item_span) = items
228+
.iter()
229+
.find(|item| item.id.def_id.to_def_id() == impl_item_id)
230+
.map(fix_span)
231+
{
232+
cause.span = impl_item_span;
233+
}
230234
}
231235
}
232236
}
@@ -235,13 +239,16 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
235239
// can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
236240
debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
237241
if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind() {
238-
if let Some(impl_item_span) = trait_assoc_items
239-
.find(|i| i.def_id == item_def_id)
240-
.and_then(|trait_assoc_item| {
241-
items.iter().find(|i| i.ident == trait_assoc_item.ident).map(fix_span)
242-
})
242+
if let Some(&impl_item_id) =
243+
tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id)
243244
{
244-
cause.span = impl_item_span;
245+
if let Some(impl_item_span) = items
246+
.iter()
247+
.find(|item| item.id.def_id.to_def_id() == impl_item_id)
248+
.map(fix_span)
249+
{
250+
cause.span = impl_item_span;
251+
}
245252
}
246253
}
247254
}
@@ -312,7 +319,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
312319
item,
313320
&mut cause,
314321
&obligation.predicate,
315-
tcx.associated_items(trait_ref.def_id).in_definition_order(),
316322
);
317323
traits::Obligation::with_depth(cause, depth, param_env, obligation.predicate)
318324
};

compiler/rustc_ty_utils/src/assoc.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_data_structures::fx::FxHashMap;
12
use rustc_errors::struct_span_err;
23
use rustc_hir as hir;
34
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -8,6 +9,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
89
associated_item,
910
associated_item_def_ids,
1011
associated_items,
12+
impl_item_implementor_ids,
1113
trait_of_item,
1214
..*providers
1315
};
@@ -32,6 +34,13 @@ fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> {
3234
ty::AssocItems::new(items)
3335
}
3436

37+
fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId, DefId> {
38+
tcx.associated_items(impl_id)
39+
.in_definition_order()
40+
.filter_map(|item| item.trait_item_def_id.map(|trait_item| (trait_item, item.def_id)))
41+
.collect()
42+
}
43+
3544
/// If the given `DefId` describes an item belonging to a trait,
3645
/// returns the `DefId` of the trait that the trait item belongs to;
3746
/// otherwise, returns `None`.

0 commit comments

Comments
 (0)