1
Fork 0

add subst_identity_iter and subst_identity_iter_copied methods on EarlyBinder; use this to simplify some EarlyBinder noise around explicit_item_bounds calls

This commit is contained in:
Kyle Matsuda 2023-04-17 17:19:08 -06:00
parent f3b279fcc5
commit e54854f6a9
12 changed files with 43 additions and 50 deletions

View file

@ -318,11 +318,10 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
tcx, tcx,
selftys: vec![], selftys: vec![],
}; };
let prohibit_opaque = let prohibit_opaque = tcx
tcx.explicit_item_bounds(def_id).transpose_iter().try_for_each(|bound| { .explicit_item_bounds(def_id)
let predicate = bound.map_bound(|&(predicate, _)| predicate).subst_identity(); .subst_identity_iter_copied()
predicate.visit_with(&mut visitor) .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor));
});
if let Some(ty) = prohibit_opaque.break_value() { if let Some(ty) = prohibit_opaque.break_value() {
visitor.visit_item(&item); visitor.visit_item(&item);

View file

@ -361,8 +361,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
param_env, param_env,
item_def_id, item_def_id,
tcx.explicit_item_bounds(item_def_id) tcx.explicit_item_bounds(item_def_id)
.transpose_iter() .subst_identity_iter_copied()
.map(|bound| bound.map_bound(|b| *b).subst_identity())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
&FxIndexSet::default(), &FxIndexSet::default(),
gat_def_id.def_id, gat_def_id.def_id,
@ -1128,8 +1127,7 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
let bounds = wfcx.tcx().explicit_item_bounds(item.def_id); let bounds = wfcx.tcx().explicit_item_bounds(item.def_id);
debug!("check_associated_type_bounds: bounds={:?}", bounds); debug!("check_associated_type_bounds: bounds={:?}", bounds);
let wf_obligations = bounds.transpose_iter().flat_map(|b| { let wf_obligations = bounds.subst_identity_iter_copied().flat_map(|(bound, bound_span)| {
let (bound, bound_span) = b.map_bound(|b| *b).subst_identity();
let normalized_bound = wfcx.normalize(span, None, bound); let normalized_bound = wfcx.normalize(span, None, bound);
traits::wf::predicate_obligations( traits::wf::predicate_obligations(
wfcx.infcx, wfcx.infcx,

View file

@ -153,8 +153,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
let mut collector = let mut collector =
OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances }; OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances };
let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id); let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id);
for pred in tcx.explicit_item_bounds(item_def_id).transpose_iter() { for (pred, _) in tcx.explicit_item_bounds(item_def_id).subst_iter_copied(tcx, id_substs) {
let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs);
debug!(?pred); debug!(?pred);
// We only ignore opaque type substs if the opaque type is the outermost type. // We only ignore opaque type substs if the opaque type is the outermost type.

View file

@ -571,8 +571,7 @@ fn check_must_not_suspend_ty<'tcx>(
// FIXME: support adding the attribute to TAITs // FIXME: support adding the attribute to TAITs
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
let mut has_emitted = false; let mut has_emitted = false;
for bound in fcx.tcx.explicit_item_bounds(def).transpose_iter() { for (predicate, _) in fcx.tcx.explicit_item_bounds(def).subst_identity_iter_copied() {
let predicate = bound.map_bound(|&(pred, _)| pred).subst_identity();
// We only look at the `DefId`, so it is safe to skip the binder here. // We only look at the `DefId`, so it is safe to skip the binder here.
if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) =
predicate.kind().skip_binder() predicate.kind().skip_binder()

View file

@ -74,9 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
// For every projection predicate in the opaque type's explicit bounds, // For every projection predicate in the opaque type's explicit bounds,
// check that the type that we're assigning actually satisfies the bounds // check that the type that we're assigning actually satisfies the bounds
// of the associated type. // of the associated type.
for bound in cx.tcx.explicit_item_bounds(def_id).transpose_iter() { for (pred, pred_span) in cx.tcx.explicit_item_bounds(def_id).subst_identity_iter_copied() {
let (pred, pred_span) = bound.map_bound(|b| *b).subst_identity();
// Liberate bound regions in the predicate since we // Liberate bound regions in the predicate since we
// don't actually care about lifetimes in this check. // don't actually care about lifetimes in this check.
let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind()); let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind());

View file

@ -254,29 +254,23 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
} }
ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
elaborate( elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).subst_identity_iter_copied())
cx.tcx, // We only care about self bounds for the impl-trait
cx.tcx .filter_only_self()
.explicit_item_bounds(def) .find_map(|(pred, _span)| {
.transpose_iter() // We only look at the `DefId`, so it is safe to skip the binder here.
.map(|bound| bound.map_bound(|b| *b).subst_identity()), if let ty::PredicateKind::Clause(ty::Clause::Trait(
) ref poly_trait_predicate,
// We only care about self bounds for the impl-trait )) = pred.kind().skip_binder()
.filter_only_self() {
.find_map(|(pred, _span)| { let def_id = poly_trait_predicate.trait_ref.def_id;
// We only look at the `DefId`, so it is safe to skip the binder here.
if let ty::PredicateKind::Clause(ty::Clause::Trait(
ref poly_trait_predicate,
)) = pred.kind().skip_binder()
{
let def_id = poly_trait_predicate.trait_ref.def_id;
is_def_must_use(cx, def_id, span) is_def_must_use(cx, def_id, span)
} else { } else {
None None
} }
}) })
.map(|inner| MustUsePath::Opaque(Box::new(inner))) .map(|inner| MustUsePath::Opaque(Box::new(inner)))
} }
ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| { ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| {
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()

View file

@ -1611,7 +1611,7 @@ impl<'tcx> TyCtxt<'tcx> {
let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false }; let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false };
let future_trait = self.require_lang_item(LangItem::Future, None); let future_trait = self.require_lang_item(LangItem::Future, None);
self.explicit_item_bounds(def_id).skip_binder().iter().any(|(predicate, _)| { self.explicit_item_bounds(def_id).subst_identity_iter_copied().any(|(predicate, _)| {
let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else { let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else {
return false; return false;
}; };

View file

@ -625,6 +625,12 @@ where
) -> SubstIter<'s, 'tcx, I> { ) -> SubstIter<'s, 'tcx, I> {
SubstIter { it: self.0.into_iter(), tcx, substs } SubstIter { it: self.0.into_iter(), tcx, substs }
} }
/// Similar to [`subst_identity`](EarlyBinder::subst_identity),
/// but on an iterator of `TypeFoldable` values.
pub fn subst_identity_iter(self) -> I::IntoIter {
self.0.into_iter()
}
} }
pub struct SubstIter<'s, 'tcx, I: IntoIterator> { pub struct SubstIter<'s, 'tcx, I: IntoIterator> {
@ -677,6 +683,12 @@ where
) -> SubstIterCopied<'s, 'tcx, I> { ) -> SubstIterCopied<'s, 'tcx, I> {
SubstIterCopied { it: self.0.into_iter(), tcx, substs } SubstIterCopied { it: self.0.into_iter(), tcx, substs }
} }
/// Similar to [`subst_identity`](EarlyBinder::subst_identity),
/// but on an iterator of values that deref to a `TypeFoldable`.
pub fn subst_identity_iter_copied(self) -> impl Iterator<Item = <I::Item as Deref>::Target> {
self.0.into_iter().map(|v| *v)
}
} }
pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> { pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> {

View file

@ -1800,9 +1800,7 @@ fn check_must_not_suspend_ty<'tcx>(
// FIXME: support adding the attribute to TAITs // FIXME: support adding the attribute to TAITs
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
let mut has_emitted = false; let mut has_emitted = false;
for bound in tcx.explicit_item_bounds(def).transpose_iter() { for (predicate, _) in tcx.explicit_item_bounds(def).subst_identity_iter_copied() {
let predicate = bound.map_bound(|&(pred, _)| pred).subst_identity();
// We only look at the `DefId`, so it is safe to skip the binder here. // We only look at the `DefId`, so it is safe to skip the binder here.
if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) =
predicate.kind().skip_binder() predicate.kind().skip_binder()

View file

@ -297,8 +297,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span
tcx.associated_items(trait_def_id) tcx.associated_items(trait_def_id)
.in_definition_order() .in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Type) .filter(|item| item.kind == ty::AssocKind::Type)
.flat_map(|item| tcx.explicit_item_bounds(item.def_id).transpose_iter()) .flat_map(|item| tcx.explicit_item_bounds(item.def_id).subst_identity_iter_copied())
.map(|bound| bound.map_bound(|b| *b).subst_identity())
.filter_map(|pred_span| predicate_references_self(tcx, pred_span)) .filter_map(|pred_span| predicate_references_self(tcx, pred_span))
.collect() .collect()
} }

View file

@ -1315,10 +1315,8 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
} }
if let ty::TraitContainer = assoc_item.container { if let ty::TraitContainer = assoc_item.container {
let bounds = tcx let bounds =
.explicit_item_bounds(assoc_item.def_id) tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied();
.transpose_iter()
.map(|bound| bound.map_bound(|b| *b).subst_identity());
let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
let predicates = let predicates =
tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied()));

View file

@ -90,8 +90,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
return false; return false;
} }
for bound in cx.tcx.explicit_item_bounds(def_id).transpose_iter() { for (predicate, _span) in cx.tcx.explicit_item_bounds(def_id).subst_identity_iter_copied() {
let (predicate, _span) = bound.map_bound(|b| *b).subst_identity();
match predicate.kind().skip_binder() { match predicate.kind().skip_binder() {
// For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
// and check substituions to find `U`. // and check substituions to find `U`.