Add find_map_relevant_impl
This commit is contained in:
parent
2359ecc71f
commit
7993ddd89d
7 changed files with 51 additions and 27 deletions
|
@ -94,7 +94,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
|||
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
|
||||
adt_destructor => {
|
||||
let _ = cdata;
|
||||
tcx.calculate_dtor(def_id, &mut |_,_| Ok(()))
|
||||
tcx.calculate_dtor(def_id, |_,_| Ok(()))
|
||||
}
|
||||
variances_of => { tcx.arena.alloc_from_iter(cdata.get_item_variances(def_id.index)) }
|
||||
associated_item_def_ids => {
|
||||
|
|
|
@ -167,6 +167,41 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Applies function to every impl that could possibly match the self type `self_ty` and returns
|
||||
/// the first non-none value.
|
||||
pub fn find_map_relevant_impl<T, F: Fn(DefId) -> Option<T>>(
|
||||
self,
|
||||
def_id: DefId,
|
||||
self_ty: Ty<'tcx>,
|
||||
f: F,
|
||||
) -> Option<T> {
|
||||
let impls = self.trait_impls_of(def_id);
|
||||
|
||||
for &impl_def_id in impls.blanket_impls.iter() {
|
||||
if let result @ Some(_) = f(impl_def_id) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) {
|
||||
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
|
||||
for &impl_def_id in impls {
|
||||
if let result @ Some(_) = f(impl_def_id) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for &impl_def_id in impls.non_blanket_impls.values().flatten() {
|
||||
if let result @ Some(_) = f(impl_def_id) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns an iterator containing all impls
|
||||
pub fn all_impls(self, def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
|
||||
let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(def_id);
|
||||
|
|
|
@ -341,19 +341,19 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
pub fn calculate_dtor(
|
||||
self,
|
||||
adt_did: DefId,
|
||||
validate: &mut dyn FnMut(Self, DefId) -> Result<(), ErrorReported>,
|
||||
validate: impl Fn(Self, DefId) -> Result<(), ErrorReported>,
|
||||
) -> Option<ty::Destructor> {
|
||||
let drop_trait = self.lang_items().drop_trait()?;
|
||||
self.ensure().coherent_trait(drop_trait);
|
||||
|
||||
let mut dtor_did = None;
|
||||
let ty = self.type_of(adt_did);
|
||||
self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
|
||||
let dtor_did = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
|
||||
if let Some(item) = self.associated_items(impl_did).in_definition_order().next() {
|
||||
if validate(self, impl_did).is_ok() {
|
||||
dtor_did = Some(item.def_id);
|
||||
return Some(item.def_id);
|
||||
}
|
||||
}
|
||||
None
|
||||
});
|
||||
|
||||
Some(ty::Destructor { did: dtor_did? })
|
||||
|
|
|
@ -34,7 +34,6 @@ impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> {
|
|||
|
||||
fn is_const_item_without_destructor(&self, local: Local) -> Option<DefId> {
|
||||
let def_id = self.is_const_item(local)?;
|
||||
let mut any_dtor = |_tcx, _def_id| Ok(());
|
||||
|
||||
// We avoid linting mutation of a const item if the const's type has a
|
||||
// Drop impl. The Drop logic observes the mutation which was performed.
|
||||
|
@ -54,7 +53,7 @@ impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> {
|
|||
//
|
||||
// #[const_mutation_allowed]
|
||||
// pub const LOG: Log = Log { msg: "" };
|
||||
match self.tcx.calculate_dtor(def_id, &mut any_dtor) {
|
||||
match self.tcx.calculate_dtor(def_id, |_, _| Ok(())) {
|
||||
Some(_) => None,
|
||||
None => Some(def_id),
|
||||
}
|
||||
|
|
|
@ -1384,17 +1384,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
trait_ref: &ty::PolyTraitRef<'tcx>,
|
||||
) {
|
||||
let get_trait_impl = |trait_def_id| {
|
||||
let mut trait_impl = None;
|
||||
self.tcx.for_each_relevant_impl(
|
||||
self.tcx.find_map_relevant_impl(
|
||||
trait_def_id,
|
||||
trait_ref.skip_binder().self_ty(),
|
||||
|impl_def_id| {
|
||||
if trait_impl.is_none() {
|
||||
trait_impl = Some(impl_def_id);
|
||||
}
|
||||
},
|
||||
);
|
||||
trait_impl
|
||||
|impl_def_id| Some(impl_def_id),
|
||||
)
|
||||
};
|
||||
let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
|
||||
let all_traits = self.tcx.all_traits(LOCAL_CRATE);
|
||||
|
|
|
@ -264,7 +264,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
}
|
||||
|
||||
fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
|
||||
tcx.calculate_dtor(def_id, &mut dropck::check_drop_impl)
|
||||
tcx.calculate_dtor(def_id, dropck::check_drop_impl)
|
||||
}
|
||||
|
||||
/// If this `DefId` is a "primary tables entry", returns
|
||||
|
|
|
@ -650,14 +650,9 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx
|
|||
let ty = cx.tcx.type_of(type_);
|
||||
let iter = in_scope_traits.iter().flat_map(|&trait_| {
|
||||
trace!("considering explicit impl for trait {:?}", trait_);
|
||||
let mut saw_impl = false;
|
||||
// Look at each trait implementation to see if it's an impl for `did`
|
||||
cx.tcx.for_each_relevant_impl(trait_, ty, |impl_| {
|
||||
// FIXME: this is inefficient, find a way to short-circuit for_each_* so this doesn't take as long
|
||||
if saw_impl {
|
||||
return;
|
||||
}
|
||||
|
||||
// Look at each trait implementation to see if it's an impl for `did`
|
||||
cx.tcx.find_map_relevant_impl(trait_, ty, |impl_| {
|
||||
let trait_ref = cx.tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
|
||||
// Check if these are the same type.
|
||||
let impl_type = trait_ref.self_ty();
|
||||
|
@ -668,7 +663,7 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx
|
|||
type_
|
||||
);
|
||||
// Fast path: if this is a primitive simple `==` will work
|
||||
saw_impl = impl_type == ty
|
||||
let saw_impl = impl_type == ty
|
||||
|| match impl_type.kind() {
|
||||
// Check if these are the same def_id
|
||||
ty::Adt(def, _) => {
|
||||
|
@ -678,8 +673,9 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx
|
|||
ty::Foreign(def_id) => *def_id == type_,
|
||||
_ => false,
|
||||
};
|
||||
});
|
||||
if saw_impl { Some(trait_) } else { None }
|
||||
|
||||
if saw_impl { Some(trait_) } else { None }
|
||||
})
|
||||
});
|
||||
iter.collect()
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue