Skip to content

Speed up the inherent impl overlap check #68911

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

Merged
merged 5 commits into from
Feb 9, 2020
Merged
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: 1 addition & 1 deletion src/librustc/query/mod.rs
Original file line number Diff line number Diff line change
@@ -323,7 +323,7 @@ rustc_queries! {
query associated_item(_: DefId) -> ty::AssocItem {}

/// Collects the associated items defined on a trait or impl.
query associated_items(key: DefId) -> ty::AssocItemsIterator<'tcx> {
query associated_items(key: DefId) -> &'tcx [ty::AssocItem] {
desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) }
}

1 change: 1 addition & 0 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -539,6 +539,7 @@ fn vtable_methods<'tcx>(
tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
let trait_methods = tcx
.associated_items(trait_ref.def_id())
.iter()
.filter(|item| item.kind == ty::AssocKind::Method);

// Now list each method's DefId and InternalSubsts (for within its trait).
6 changes: 5 additions & 1 deletion src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
@@ -212,6 +212,7 @@ fn object_safety_violations_for_trait(
// Check methods for violations.
let mut violations: Vec<_> = tcx
.associated_items(trait_def_id)
.iter()
.filter(|item| item.kind == ty::AssocKind::Method)
.filter_map(|item| {
object_safety_violation_for_method(tcx, trait_def_id, &item)
@@ -277,6 +278,7 @@ fn object_safety_violations_for_trait(

violations.extend(
tcx.associated_items(trait_def_id)
.iter()
.filter(|item| item.kind == ty::AssocKind::Const)
.map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)),
);
@@ -632,7 +634,9 @@ fn object_ty_for_trait<'tcx>(

let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref))
.flat_map(|super_trait_ref| {
tcx.associated_items(super_trait_ref.def_id()).map(move |item| (super_trait_ref, item))
tcx.associated_items(super_trait_ref.def_id())
.iter()
.map(move |item| (super_trait_ref, item))
})
.filter(|(_, item)| item.kind == ty::AssocKind::Type)
.collect::<Vec<_>>();
2 changes: 1 addition & 1 deletion src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
@@ -1436,7 +1436,7 @@ fn assoc_ty_def(
{
return specialization_graph::NodeItem {
node: specialization_graph::Node::Impl(impl_def_id),
item,
item: *item,
};
}
}
11 changes: 7 additions & 4 deletions src/librustc/traits/types/specialization_graph.rs
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ impl<'tcx> Node {
}

/// Iterate over the items defined directly by the given (impl or trait) node.
pub fn items(&self, tcx: TyCtxt<'tcx>) -> ty::AssocItemsIterator<'tcx> {
pub fn items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ty::AssocItem] {
tcx.associated_items(self.def_id())
}

@@ -98,8 +98,10 @@ impl<'tcx> Node {
) -> Option<ty::AssocItem> {
use crate::ty::AssocKind::*;

tcx.associated_items(self.def_id()).find(move |impl_item| {
match (trait_item_kind, impl_item.kind) {
tcx.associated_items(self.def_id())
.iter()
.find(move |impl_item| {
match (trait_item_kind, impl_item.kind) {
| (Const, Const)
| (Method, Method)
| (Type, Type)
@@ -112,7 +114,8 @@ impl<'tcx> Node {
| (OpaqueTy, _)
=> false,
}
})
})
.copied()
}

pub fn def_id(&self) -> DefId {
5 changes: 3 additions & 2 deletions src/librustc/traits/wf.rs
Original file line number Diff line number Diff line change
@@ -166,7 +166,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let extend_cause_with_original_assoc_item_obligation =
|cause: &mut traits::ObligationCause<'_>,
pred: &ty::Predicate<'_>,
trait_assoc_items: ty::AssocItemsIterator<'_>| {
trait_assoc_items: &[ty::AssocItem]| {
let trait_item = tcx
.hir()
.as_local_hir_id(trait_ref.def_id)
@@ -283,6 +283,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind))
{
if let Some((impl_item, trait_assoc_item)) = trait_assoc_items
.iter()
.filter(|i| i.def_id == *item_def_id)
.next()
.and_then(|trait_assoc_item| {
@@ -325,7 +326,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
extend_cause_with_original_assoc_item_obligation(
&mut cause,
&pred,
trait_assoc_items.clone(),
trait_assoc_items,
);
traits::Obligation::new(cause, param_env, pred)
});
1 change: 1 addition & 0 deletions src/librustc/ty/adjustment.rs
Original file line number Diff line number Diff line change
@@ -122,6 +122,7 @@ impl<'tcx> OverloadedDeref<'tcx> {
};
let method_def_id = tcx
.associated_items(trait_def_id.unwrap())
.iter()
.find(|m| m.kind == ty::AssocKind::Method)
.unwrap()
.def_id;
1 change: 1 addition & 0 deletions src/librustc/ty/instance.rs
Original file line number Diff line number Diff line change
@@ -376,6 +376,7 @@ impl<'tcx> Instance<'tcx> {
let fn_once = tcx.lang_items().fn_once_trait().unwrap();
let call_once = tcx
.associated_items(fn_once)
.iter()
.find(|it| it.kind == ty::AssocKind::Method)
.unwrap()
.def_id;
25 changes: 3 additions & 22 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -2705,14 +2705,14 @@ impl<'tcx> TyCtxt<'tcx> {
.for_each(|&body_id| f(self.hir().body_owner_def_id(body_id)));
}

pub fn provided_trait_methods(self, id: DefId) -> Vec<AssocItem> {
pub fn provided_trait_methods(self, id: DefId) -> impl Iterator<Item = &'tcx AssocItem> {
self.associated_items(id)
.iter()
.filter(|item| item.kind == AssocKind::Method && item.defaultness.has_value())
.collect()
}

pub fn trait_relevant_for_never(self, did: DefId) -> bool {
self.associated_items(did).any(|item| item.relevant_for_never())
self.associated_items(did).iter().any(|item| item.relevant_for_never())
}

pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> {
@@ -2974,25 +2974,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}

#[derive(Copy, Clone, HashStable)]
pub struct AssocItemsIterator<'tcx> {
pub items: &'tcx [AssocItem],
}

impl<'tcx> Iterator for AssocItemsIterator<'tcx> {
type Item = AssocItem;

#[inline]
fn next(&mut self) -> Option<AssocItem> {
if let Some((first, rest)) = self.items.split_first() {
self.items = rest;
Some(*first)
} else {
None
}
}
}

#[derive(Clone, HashStable)]
pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]);

1 change: 1 addition & 0 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
@@ -1066,6 +1066,7 @@ impl<'tcx> ProjectionTy<'tcx> {
) -> ProjectionTy<'tcx> {
let item_def_id = tcx
.associated_items(trait_ref.def_id)
.iter()
.find(|item| {
item.kind == ty::AssocKind::Type
&& tcx.hygienic_eq(item_name, item.ident, trait_ref.def_id)
2 changes: 1 addition & 1 deletion src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
@@ -355,7 +355,7 @@ impl<'tcx> TyCtxt<'tcx> {
let mut dtor_did = None;
let ty = self.type_of(adt_did);
self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
if let Some(item) = self.associated_items(impl_did).next() {
if let Some(item) = self.associated_items(impl_did).first() {
if validate(self, impl_did).is_ok() {
dtor_did = Some(item.def_id);
}
1 change: 1 addition & 0 deletions src/librustc_mir/shim.rs
Original file line number Diff line number Diff line change
@@ -68,6 +68,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
let fn_mut = tcx.lang_items().fn_mut_trait().unwrap();
let call_mut = tcx
.associated_items(fn_mut)
.iter()
.find(|it| it.kind == ty::AssocKind::Method)
.unwrap()
.def_id;
2 changes: 1 addition & 1 deletion src/librustc_mir/util/elaborate_drops.rs
Original file line number Diff line number Diff line change
@@ -539,7 +539,7 @@ where
debug!("destructor_call_block({:?}, {:?})", self, succ);
let tcx = self.tcx();
let drop_trait = tcx.lang_items().drop_trait().unwrap();
let drop_fn = tcx.associated_items(drop_trait).next().unwrap();
let drop_fn = tcx.associated_items(drop_trait)[0];
let ty = self.place_ty(self.place);
let substs = tcx.mk_substs_trait(ty, &[]);

12 changes: 6 additions & 6 deletions src/librustc_passes/reachable.rs
Original file line number Diff line number Diff line change
@@ -362,12 +362,12 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx
return;
}

let provided_trait_methods = self.tcx.provided_trait_methods(trait_def_id);
self.worklist.reserve(provided_trait_methods.len());
for default_method in provided_trait_methods {
let hir_id = self.tcx.hir().as_local_hir_id(default_method.def_id).unwrap();
self.worklist.push(hir_id);
}
// FIXME(#53488) remove `let`
let tcx = self.tcx;
self.worklist.extend(
tcx.provided_trait_methods(trait_def_id)
.map(|assoc| tcx.hir().as_local_hir_id(assoc.def_id).unwrap()),
);
}
}
}
1 change: 1 addition & 0 deletions src/librustc_passes/stability.rs
Original file line number Diff line number Diff line change
@@ -468,6 +468,7 @@ impl Visitor<'tcx> for Checker<'tcx> {
let trait_item_def_id = self
.tcx
.associated_items(trait_did)
.iter()
.find(|item| item.ident.name == impl_item.ident.name)
.map(|item| item.def_id);
if let Some(def_id) = trait_item_def_id {
2 changes: 2 additions & 0 deletions src/librustc_save_analysis/lib.rs
Original file line number Diff line number Diff line change
@@ -423,6 +423,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
qualname.push_str(&self.tcx.def_path_str(def_id));
self.tcx
.associated_items(def_id)
.iter()
.find(|item| item.ident.name == ident.name)
.map(|item| decl_id = Some(item.def_id));
}
@@ -717,6 +718,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
let ti = self.tcx.associated_item(decl_id);
self.tcx
.associated_items(ti.container.id())
.iter()
.find(|item| {
item.ident.name == ti.ident.name && item.defaultness.has_value()
})
10 changes: 4 additions & 6 deletions src/librustc_ty/ty.rs
Original file line number Diff line number Diff line change
@@ -206,12 +206,10 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
}
}

fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AssocItemsIterator<'tcx> {
ty::AssocItemsIterator {
items: tcx.arena.alloc_from_iter(
tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)),
),
}
fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [ty::AssocItem] {
tcx.arena.alloc_from_iter(
tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)),
)
}

fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
6 changes: 5 additions & 1 deletion src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
@@ -1109,7 +1109,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_def_id: DefId,
assoc_name: ast::Ident,
) -> bool {
self.tcx().associated_items(trait_def_id).any(|item| {
self.tcx().associated_items(trait_def_id).iter().any(|item| {
item.kind == ty::AssocKind::Type
&& self.tcx().hygienic_eq(assoc_name, item.ident, trait_def_id)
})
@@ -1347,6 +1347,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
let assoc_ty = tcx
.associated_items(candidate.def_id())
.iter()
.find(|i| i.kind == ty::AssocKind::Type && i.ident.modern() == assoc_ident)
.expect("missing associated type");

@@ -1512,6 +1513,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty::Predicate::Trait(pred, _) => {
associated_types.entry(span).or_default().extend(
tcx.associated_items(pred.def_id())
.iter()
.filter(|item| item.kind == ty::AssocKind::Type)
.map(|item| item.def_id),
);
@@ -1969,6 +1971,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let bound_span = self
.tcx()
.associated_items(bound.def_id())
.iter()
.find(|item| {
item.kind == ty::AssocKind::Type
&& self.tcx().hygienic_eq(assoc_name, item.ident, bound.def_id())
@@ -2198,6 +2201,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id);
let item = tcx
.associated_items(trait_did)
.iter()
.find(|i| Namespace::from(i.kind) == Namespace::Type && i.ident.modern() == assoc_ident)
.expect("missing associated type");

4 changes: 2 additions & 2 deletions src/librustc_typeck/check/closure.rs
Original file line number Diff line number Diff line change
@@ -248,7 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if is_gen {
// Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
// associated item and not yield.
let return_assoc_item = self.tcx.associated_items(gen_trait).nth(1).unwrap().def_id;
let return_assoc_item = self.tcx.associated_items(gen_trait)[1].def_id;
if return_assoc_item != projection.projection_def_id() {
debug!("deduce_sig_from_projection: not return assoc item of generator");
return None;
@@ -673,7 +673,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// The `Future` trait has only one associted item, `Output`,
// so check that this is what we see.
let output_assoc_item = self.tcx.associated_items(future_trait).nth(0).unwrap().def_id;
let output_assoc_item = self.tcx.associated_items(future_trait)[0].def_id;
Copy link
Member

Choose a reason for hiding this comment

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

I think this pattern (or worse, looking things up by name) should be replaced with lang items.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, definintely. This was a huge pain when working on generators, since the declaration order of the assoc. types is significant. Not something I'll try to fit in this PR though.

if output_assoc_item != predicate.projection_ty.item_def_id {
span_bug!(
cause_span,
1 change: 1 addition & 0 deletions src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
@@ -536,6 +536,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let item_def_id = self
.tcx
.associated_items(deref_trait)
.iter()
.find(|item| item.kind == ty::AssocKind::Type)
.unwrap()
.def_id;
11 changes: 8 additions & 3 deletions src/librustc_typeck/check/method/mod.rs
Original file line number Diff line number Diff line change
@@ -474,8 +474,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
item_name: ast::Ident,
ns: Namespace,
) -> Option<ty::AssocItem> {
self.tcx.associated_items(def_id).find(|item| {
Namespace::from(item.kind) == ns && self.tcx.hygienic_eq(item_name, item.ident, def_id)
})
self.tcx
.associated_items(def_id)
.iter()
.find(|item| {
Namespace::from(item.kind) == ns
&& self.tcx.hygienic_eq(item_name, item.ident, def_id)
})
.copied()
}
}
4 changes: 3 additions & 1 deletion src/librustc_typeck/check/method/probe.rs
Original file line number Diff line number Diff line change
@@ -1696,18 +1696,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let max_dist = max(name.as_str().len(), 3) / 3;
self.tcx
.associated_items(def_id)
.iter()
.filter(|x| {
let dist = lev_distance(&*name.as_str(), &x.ident.as_str());
Namespace::from(x.kind) == Namespace::Value && dist > 0 && dist <= max_dist
})
.copied()
.collect()
} else {
self.fcx
.associated_item(def_id, name, Namespace::Value)
.map_or(Vec::new(), |x| vec![x])
}
} else {
self.tcx.associated_items(def_id).collect()
self.tcx.associated_items(def_id).to_vec()
}
}
}
Loading