Skip to content

Commit d60c64a

Browse files
authored
Rollup merge of #110514 - compiler-errors:remove-find_map_relevant_impl, r=b-naber
Remove `find_map_relevant_impl` Fixes #108895
2 parents 0f27161 + 1467877 commit d60c64a

File tree

6 files changed

+154
-142
lines changed

6 files changed

+154
-142
lines changed

compiler/rustc_middle/src/ty/trait_def.rs

+18-44
Original file line numberDiff line numberDiff line change
@@ -139,40 +139,6 @@ impl<'tcx> TyCtxt<'tcx> {
139139
treat_projections: TreatProjections,
140140
mut f: impl FnMut(DefId),
141141
) {
142-
let _: Option<()> =
143-
self.find_map_relevant_impl(trait_def_id, self_ty, treat_projections, |did| {
144-
f(did);
145-
None
146-
});
147-
}
148-
149-
/// `trait_def_id` MUST BE the `DefId` of a trait.
150-
pub fn non_blanket_impls_for_ty(
151-
self,
152-
trait_def_id: DefId,
153-
self_ty: Ty<'tcx>,
154-
) -> impl Iterator<Item = DefId> + 'tcx {
155-
let impls = self.trait_impls_of(trait_def_id);
156-
if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) {
157-
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
158-
return impls.iter().copied();
159-
}
160-
}
161-
162-
[].iter().copied()
163-
}
164-
165-
/// Applies function to every impl that could possibly match the self type `self_ty` and returns
166-
/// the first non-none value.
167-
///
168-
/// `trait_def_id` MUST BE the `DefId` of a trait.
169-
pub fn find_map_relevant_impl<T>(
170-
self,
171-
trait_def_id: DefId,
172-
self_ty: Ty<'tcx>,
173-
treat_projections: TreatProjections,
174-
mut f: impl FnMut(DefId) -> Option<T>,
175-
) -> Option<T> {
176142
// FIXME: This depends on the set of all impls for the trait. That is
177143
// unfortunate wrt. incremental compilation.
178144
//
@@ -181,9 +147,7 @@ impl<'tcx> TyCtxt<'tcx> {
181147
let impls = self.trait_impls_of(trait_def_id);
182148

183149
for &impl_def_id in impls.blanket_impls.iter() {
184-
if let result @ Some(_) = f(impl_def_id) {
185-
return result;
186-
}
150+
f(impl_def_id);
187151
}
188152

189153
// Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using
@@ -199,20 +163,30 @@ impl<'tcx> TyCtxt<'tcx> {
199163
if let Some(simp) = fast_reject::simplify_type(self, self_ty, treat_params) {
200164
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
201165
for &impl_def_id in impls {
202-
if let result @ Some(_) = f(impl_def_id) {
203-
return result;
204-
}
166+
f(impl_def_id);
205167
}
206168
}
207169
} else {
208170
for &impl_def_id in impls.non_blanket_impls.values().flatten() {
209-
if let result @ Some(_) = f(impl_def_id) {
210-
return result;
211-
}
171+
f(impl_def_id);
212172
}
213173
}
174+
}
214175

215-
None
176+
/// `trait_def_id` MUST BE the `DefId` of a trait.
177+
pub fn non_blanket_impls_for_ty(
178+
self,
179+
trait_def_id: DefId,
180+
self_ty: Ty<'tcx>,
181+
) -> impl Iterator<Item = DefId> + 'tcx {
182+
let impls = self.trait_impls_of(trait_def_id);
183+
if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) {
184+
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
185+
return impls.iter().copied();
186+
}
187+
}
188+
189+
[].iter().copied()
216190
}
217191

218192
/// Returns an iterator containing all impls for `trait_def_id`.

compiler/rustc_middle/src/ty/util.rs

+22-15
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
44
use crate::mir;
5-
use crate::ty::fast_reject::TreatProjections;
65
use crate::ty::layout::IntegerExt;
76
use crate::ty::{
87
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@@ -359,21 +358,29 @@ impl<'tcx> TyCtxt<'tcx> {
359358
self.ensure().coherent_trait(drop_trait);
360359

361360
let ty = self.type_of(adt_did).subst_identity();
362-
let (did, constness) = self.find_map_relevant_impl(
363-
drop_trait,
364-
ty,
365-
// FIXME: This could also be some other mode, like "unexpected"
366-
TreatProjections::ForLookup,
367-
|impl_did| {
368-
if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
369-
if validate(self, impl_did).is_ok() {
370-
return Some((*item_id, self.constness(impl_did)));
371-
}
372-
}
373-
None
374-
},
375-
)?;
361+
let mut dtor_candidate = None;
362+
self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
363+
let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
364+
self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function");
365+
return;
366+
};
367+
368+
if validate(self, impl_did).is_err() {
369+
// Already `ErrorGuaranteed`, no need to delay a span bug here.
370+
return;
371+
}
372+
373+
if let Some((old_item_id, _)) = dtor_candidate {
374+
self.sess
375+
.struct_span_err(self.def_span(item_id), "multiple drop impls found")
376+
.span_note(self.def_span(old_item_id), "other impl here")
377+
.delay_as_bug();
378+
}
379+
380+
dtor_candidate = Some((*item_id, self.constness(impl_did)));
381+
});
376382

383+
let (did, constness) = dtor_candidate?;
377384
Some(ty::Destructor { did, constness })
378385
}
379386

compiler/rustc_trait_selection/src/solve/trait_goals.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -645,12 +645,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
645645
// FIXME: Handling opaques here is kinda sus. Especially because we
646646
// simplify them to PlaceholderSimplifiedType.
647647
| ty::Alias(ty::Opaque, _) => {
648-
if let Some(def_id) = self.tcx().find_map_relevant_impl(
648+
let mut disqualifying_impl = None;
649+
self.tcx().for_each_relevant_impl_treating_projections(
649650
goal.predicate.def_id(),
650651
goal.predicate.self_ty(),
651652
TreatProjections::NextSolverLookup,
652-
Some,
653-
) {
653+
|impl_def_id| {
654+
disqualifying_impl = Some(impl_def_id);
655+
},
656+
);
657+
if let Some(def_id) = disqualifying_impl {
654658
debug!(?def_id, ?goal, "disqualified auto-trait implementation");
655659
// No need to actually consider the candidate here,
656660
// since we do that in `consider_impl_candidate`.

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+79-66
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ use rustc_infer::infer::{InferOk, TypeTrace};
3232
use rustc_middle::traits::select::OverflowError;
3333
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
3434
use rustc_middle::ty::error::{ExpectedFound, TypeError};
35-
use rustc_middle::ty::fast_reject::TreatProjections;
3635
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
3736
use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
3837
use rustc_middle::ty::{
@@ -1836,57 +1835,61 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
18361835
});
18371836
let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}");
18381837

1839-
let secondary_span = match predicate.kind().skip_binder() {
1840-
ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => self
1841-
.tcx
1842-
.opt_associated_item(proj.projection_ty.def_id)
1843-
.and_then(|trait_assoc_item| {
1844-
self.tcx
1845-
.trait_of_item(proj.projection_ty.def_id)
1846-
.map(|id| (trait_assoc_item, id))
1847-
})
1848-
.and_then(|(trait_assoc_item, id)| {
1849-
let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
1850-
self.tcx.find_map_relevant_impl(
1851-
id,
1852-
proj.projection_ty.self_ty(),
1853-
TreatProjections::ForLookup,
1854-
|did| {
1855-
self.tcx
1856-
.associated_items(did)
1857-
.in_definition_order()
1858-
.find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident)
1859-
},
1860-
)
1861-
})
1862-
.and_then(|item| match self.tcx.hir().get_if_local(item.def_id) {
1863-
Some(
1864-
hir::Node::TraitItem(hir::TraitItem {
1865-
kind: hir::TraitItemKind::Type(_, Some(ty)),
1866-
..
1867-
})
1868-
| hir::Node::ImplItem(hir::ImplItem {
1869-
kind: hir::ImplItemKind::Type(ty),
1870-
..
1871-
}),
1872-
) => Some((
1873-
ty.span,
1874-
with_forced_trimmed_paths!(format!(
1875-
"type mismatch resolving `{}`",
1876-
self.resolve_vars_if_possible(predicate)
1877-
.print(FmtPrinter::new_with_limit(
1878-
self.tcx,
1879-
Namespace::TypeNS,
1880-
rustc_session::Limit(5),
1881-
))
1882-
.unwrap()
1883-
.into_buffer()
1884-
)),
1838+
let secondary_span = (|| {
1839+
let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) =
1840+
predicate.kind().skip_binder()
1841+
else {
1842+
return None;
1843+
};
1844+
1845+
let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_ty.def_id)?;
1846+
let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
1847+
1848+
let mut associated_items = vec![];
1849+
self.tcx.for_each_relevant_impl(
1850+
self.tcx.trait_of_item(proj.projection_ty.def_id)?,
1851+
proj.projection_ty.self_ty(),
1852+
|impl_def_id| {
1853+
associated_items.extend(
1854+
self.tcx
1855+
.associated_items(impl_def_id)
1856+
.in_definition_order()
1857+
.find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident),
1858+
);
1859+
},
1860+
);
1861+
1862+
let [associated_item]: &[ty::AssocItem] = &associated_items[..] else {
1863+
return None;
1864+
};
1865+
match self.tcx.hir().get_if_local(associated_item.def_id) {
1866+
Some(
1867+
hir::Node::TraitItem(hir::TraitItem {
1868+
kind: hir::TraitItemKind::Type(_, Some(ty)),
1869+
..
1870+
})
1871+
| hir::Node::ImplItem(hir::ImplItem {
1872+
kind: hir::ImplItemKind::Type(ty),
1873+
..
1874+
}),
1875+
) => Some((
1876+
ty.span,
1877+
with_forced_trimmed_paths!(format!(
1878+
"type mismatch resolving `{}`",
1879+
self.resolve_vars_if_possible(predicate)
1880+
.print(FmtPrinter::new_with_limit(
1881+
self.tcx,
1882+
Namespace::TypeNS,
1883+
rustc_session::Limit(5),
1884+
))
1885+
.unwrap()
1886+
.into_buffer()
18851887
)),
1886-
_ => None,
1887-
}),
1888-
_ => None,
1889-
};
1888+
)),
1889+
_ => None,
1890+
}
1891+
})();
1892+
18901893
self.note_type_err(
18911894
&mut diag,
18921895
&obligation.cause,
@@ -2228,14 +2231,18 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
22282231
err: &mut Diagnostic,
22292232
trait_ref: &ty::PolyTraitRef<'tcx>,
22302233
) -> bool {
2231-
let get_trait_impl = |trait_def_id| {
2232-
self.tcx.find_map_relevant_impl(
2234+
let get_trait_impls = |trait_def_id| {
2235+
let mut trait_impls = vec![];
2236+
self.tcx.for_each_relevant_impl(
22332237
trait_def_id,
22342238
trait_ref.skip_binder().self_ty(),
2235-
TreatProjections::ForLookup,
2236-
Some,
2237-
)
2239+
|impl_def_id| {
2240+
trait_impls.push(impl_def_id);
2241+
},
2242+
);
2243+
trait_impls
22382244
};
2245+
22392246
let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
22402247
let traits_with_same_path: std::collections::BTreeSet<_> = self
22412248
.tcx
@@ -2245,17 +2252,23 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
22452252
.collect();
22462253
let mut suggested = false;
22472254
for trait_with_same_path in traits_with_same_path {
2248-
if let Some(impl_def_id) = get_trait_impl(trait_with_same_path) {
2249-
let impl_span = self.tcx.def_span(impl_def_id);
2250-
err.span_help(impl_span, "trait impl with same name found");
2251-
let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
2252-
let crate_msg = format!(
2253-
"perhaps two different versions of crate `{}` are being used?",
2254-
trait_crate
2255-
);
2256-
err.note(&crate_msg);
2257-
suggested = true;
2255+
let trait_impls = get_trait_impls(trait_with_same_path);
2256+
if trait_impls.is_empty() {
2257+
continue;
22582258
}
2259+
let impl_spans: Vec<_> =
2260+
trait_impls.iter().map(|impl_def_id| self.tcx.def_span(*impl_def_id)).collect();
2261+
err.span_help(
2262+
impl_spans,
2263+
format!("trait impl{} with same name found", pluralize!(trait_impls.len())),
2264+
);
2265+
let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
2266+
let crate_msg = format!(
2267+
"perhaps two different versions of crate `{}` are being used?",
2268+
trait_crate
2269+
);
2270+
err.note(&crate_msg);
2271+
suggested = true;
22592272
}
22602273
suggested
22612274
}

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+17-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use hir::LangItem;
1111
use rustc_hir as hir;
1212
use rustc_infer::traits::ObligationCause;
1313
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
14-
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections};
14+
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
1515
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
1616

1717
use crate::traits;
@@ -875,12 +875,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
875875
}
876876

877877
ty::Adt(..) => {
878-
// Find a custom `impl Drop` impl, if it exists
879-
let relevant_impl = self.tcx().find_map_relevant_impl(
878+
let mut relevant_impl = None;
879+
self.tcx().for_each_relevant_impl(
880880
self.tcx().require_lang_item(LangItem::Drop, None),
881881
obligation.predicate.skip_binder().trait_ref.self_ty(),
882-
TreatProjections::ForLookup,
883-
Some,
882+
|impl_def_id| {
883+
if let Some(old_impl_def_id) = relevant_impl {
884+
self.tcx()
885+
.sess
886+
.struct_span_err(
887+
self.tcx().def_span(impl_def_id),
888+
"multiple drop impls found",
889+
)
890+
.span_note(self.tcx().def_span(old_impl_def_id), "other impl here")
891+
.delay_as_bug();
892+
}
893+
894+
relevant_impl = Some(impl_def_id);
895+
},
884896
);
885897

886898
if let Some(impl_def_id) = relevant_impl {

0 commit comments

Comments
 (0)