1
Fork 0

Rollup merge of #110514 - compiler-errors:remove-find_map_relevant_impl, r=b-naber

Remove `find_map_relevant_impl`

Fixes #108895
This commit is contained in:
Matthias Krüger 2023-04-24 07:53:24 +02:00 committed by GitHub
commit d60c64a0c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 168 additions and 156 deletions

View file

@ -139,11 +139,38 @@ impl<'tcx> TyCtxt<'tcx> {
treat_projections: TreatProjections,
mut f: impl FnMut(DefId),
) {
let _: Option<()> =
self.find_map_relevant_impl(trait_def_id, self_ty, treat_projections, |did| {
f(did);
None
});
// FIXME: This depends on the set of all impls for the trait. That is
// unfortunate wrt. incremental compilation.
//
// If we want to be faster, we could have separate queries for
// blanket and non-blanket impls, and compare them separately.
let impls = self.trait_impls_of(trait_def_id);
for &impl_def_id in impls.blanket_impls.iter() {
f(impl_def_id);
}
// Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using
// `TreatParams::AsCandidateKey` while actually adding them.
let treat_params = match treat_projections {
TreatProjections::NextSolverLookup => TreatParams::NextSolverLookup,
TreatProjections::ForLookup => TreatParams::ForLookup,
};
// This way, when searching for some impl for `T: Trait`, we do not look at any impls
// whose outer level is not a parameter or projection. Especially for things like
// `T: Clone` this is incredibly useful as we would otherwise look at all the impls
// of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
if let Some(simp) = fast_reject::simplify_type(self, self_ty, treat_params) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls {
f(impl_def_id);
}
}
} else {
for &impl_def_id in impls.non_blanket_impls.values().flatten() {
f(impl_def_id);
}
}
}
/// `trait_def_id` MUST BE the `DefId` of a trait.
@ -162,59 +189,6 @@ impl<'tcx> TyCtxt<'tcx> {
[].iter().copied()
}
/// Applies function to every impl that could possibly match the self type `self_ty` and returns
/// the first non-none value.
///
/// `trait_def_id` MUST BE the `DefId` of a trait.
pub fn find_map_relevant_impl<T>(
self,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
treat_projections: TreatProjections,
mut f: impl FnMut(DefId) -> Option<T>,
) -> Option<T> {
// FIXME: This depends on the set of all impls for the trait. That is
// unfortunate wrt. incremental compilation.
//
// If we want to be faster, we could have separate queries for
// blanket and non-blanket impls, and compare them separately.
let impls = self.trait_impls_of(trait_def_id);
for &impl_def_id in impls.blanket_impls.iter() {
if let result @ Some(_) = f(impl_def_id) {
return result;
}
}
// Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using
// `TreatParams::AsCandidateKey` while actually adding them.
let treat_params = match treat_projections {
TreatProjections::NextSolverLookup => TreatParams::NextSolverLookup,
TreatProjections::ForLookup => TreatParams::ForLookup,
};
// This way, when searching for some impl for `T: Trait`, we do not look at any impls
// whose outer level is not a parameter or projection. Especially for things like
// `T: Clone` this is incredibly useful as we would otherwise look at all the impls
// of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
if let Some(simp) = fast_reject::simplify_type(self, self_ty, treat_params) {
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 for `trait_def_id`.
///
/// `trait_def_id` MUST BE the `DefId` of a trait.

View file

@ -2,7 +2,6 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir;
use crate::ty::fast_reject::TreatProjections;
use crate::ty::layout::IntegerExt;
use crate::ty::{
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@ -359,21 +358,29 @@ impl<'tcx> TyCtxt<'tcx> {
self.ensure().coherent_trait(drop_trait);
let ty = self.type_of(adt_did).subst_identity();
let (did, constness) = self.find_map_relevant_impl(
drop_trait,
ty,
// FIXME: This could also be some other mode, like "unexpected"
TreatProjections::ForLookup,
|impl_did| {
if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
if validate(self, impl_did).is_ok() {
return Some((*item_id, self.constness(impl_did)));
}
}
None
},
)?;
let mut dtor_candidate = None;
self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function");
return;
};
if validate(self, impl_did).is_err() {
// Already `ErrorGuaranteed`, no need to delay a span bug here.
return;
}
if let Some((old_item_id, _)) = dtor_candidate {
self.sess
.struct_span_err(self.def_span(item_id), "multiple drop impls found")
.span_note(self.def_span(old_item_id), "other impl here")
.delay_as_bug();
}
dtor_candidate = Some((*item_id, self.constness(impl_did)));
});
let (did, constness) = dtor_candidate?;
Some(ty::Destructor { did, constness })
}