Skip to content

Commit

Permalink
Auto merge of #68911 - jonas-schievink:inherent-overlap, r=<try>
Browse files Browse the repository at this point in the history
Speed up the inherent impl overlap check

This gives a ~7% improvement in compile times for the stm32f0(x2) crate.

Also addresses @eddyb's comment in #68837 (comment).
  • Loading branch information
bors committed Feb 7, 2020
2 parents 442ae7f + 000243c commit a5b4dc5
Show file tree
Hide file tree
Showing 26 changed files with 118 additions and 80 deletions.
2 changes: 1 addition & 1 deletion src/librustc/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,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) }
}

Expand Down
1 change: 1 addition & 0 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,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).
Expand Down
6 changes: 5 additions & 1 deletion src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)),
);
Expand Down Expand Up @@ -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<_>>();
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1436,7 +1436,7 @@ fn assoc_ty_def(
{
return specialization_graph::NodeItem {
node: specialization_graph::Node::Impl(impl_def_id),
item,
item: *item,
};
}
}
Expand Down
11 changes: 7 additions & 4 deletions src/librustc/traits/types/specialization_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}

Expand All @@ -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)
Expand All @@ -112,7 +114,8 @@ impl<'tcx> Node {
| (OpaqueTy, _)
=> false,
}
})
})
.copied()
}

pub fn def_id(&self) -> DefId {
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/traits/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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| {
Expand Down Expand Up @@ -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)
});
Expand Down
1 change: 1 addition & 0 deletions src/librustc/ty/adjustment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/librustc/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
24 changes: 3 additions & 21 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2705,14 +2705,15 @@ 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) -> Vec<&'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> {
Expand Down Expand Up @@ -2974,25 +2975,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>]);

Expand Down
1 change: 1 addition & 0 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,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)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/util/elaborate_drops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, &[]);

Expand Down
1 change: 1 addition & 0 deletions src/librustc_passes/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_save_analysis/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down Expand Up @@ -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()
})
Expand Down
10 changes: 4 additions & 6 deletions src/librustc_ty/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
Expand Down Expand Up @@ -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");

Expand Down Expand Up @@ -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),
);
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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");

Expand Down
4 changes: 2 additions & 2 deletions src/librustc_typeck/check/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,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;
Expand Down Expand Up @@ -666,7 +666,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;
if output_assoc_item != predicate.projection_ty.item_def_id {
span_bug!(
cause_span,
Expand Down
1 change: 1 addition & 0 deletions src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 8 additions & 3 deletions src/librustc_typeck/check/method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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()
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1966,13 +1966,15 @@ fn check_impl_items_against_trait<'tcx>(
let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id));
let ty_trait_item = tcx
.associated_items(impl_trait_ref.def_id)
.iter()
.find(|ac| {
Namespace::from(&impl_item.kind) == Namespace::from(ac.kind)
&& tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id)
})
.or_else(|| {
// Not compatible, but needed for the error message
tcx.associated_items(impl_trait_ref.def_id)
.iter()
.find(|ac| tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id))
});

Expand Down Expand Up @@ -2086,7 +2088,7 @@ fn check_impl_items_against_trait<'tcx>(

if !is_implemented && !traits::impl_is_default(tcx, impl_id) {
if !trait_item.defaultness.has_value() {
missing_items.push(trait_item);
missing_items.push(*trait_item);
} else if associated_type_overridden {
invalidated_items.push(trait_item.ident);
}
Expand Down Expand Up @@ -5086,7 +5088,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Check for `Future` implementations by constructing a predicate to
// prove: `<T as Future>::Output == U`
let future_trait = self.tcx.lang_items().future_trait().unwrap();
let item_def_id = self.tcx.associated_items(future_trait).next().unwrap().def_id;
let item_def_id = self.tcx.associated_items(future_trait)[0].def_id;
let predicate =
ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate {
// `<T as Future>::Output`
Expand Down
Loading

0 comments on commit a5b4dc5

Please sign in to comment.