Skip to content

Commit d12412c

Browse files
committed
Auto merge of #106395 - compiler-errors:rework-predicates, r=eholk
Rework some `predicates_of`/`{Generic,Instantiated}Predicates` code 1. Make `instantiate_own` return an iterator, since it's a bit more efficient and easier to work with 2. Remove `bound_{explicit,}_predicates_of` -- these `bound_` methods in particular were a bit awkward to work with since `ty::GenericPredicates` *already* acts kinda like an `EarlyBinder` with its own `instantiate_*` methods, and had only a few call sites anyways. 3. Implement `IntoIterator` for `InstantiatedPredicates`, since it's *very* commonly being `zip`'d together.
2 parents 41edaac + 90df86f commit d12412c

File tree

22 files changed

+155
-156
lines changed

22 files changed

+155
-156
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+21-27
Original file line numberDiff line numberDiff line change
@@ -673,40 +673,34 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
673673
let tcx = self.infcx.tcx;
674674

675675
// Find out if the predicates show that the type is a Fn or FnMut
676-
let find_fn_kind_from_did = |predicates: ty::EarlyBinder<
677-
&[(ty::Predicate<'tcx>, Span)],
678-
>,
679-
substs| {
680-
predicates.0.iter().find_map(|(pred, _)| {
681-
let pred = if let Some(substs) = substs {
682-
predicates.rebind(*pred).subst(tcx, substs).kind().skip_binder()
683-
} else {
684-
pred.kind().skip_binder()
685-
};
686-
if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = pred && pred.self_ty() == ty {
687-
if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
688-
return Some(hir::Mutability::Not);
689-
} else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() {
690-
return Some(hir::Mutability::Mut);
691-
}
676+
let find_fn_kind_from_did = |(pred, _): (ty::Predicate<'tcx>, _)| {
677+
if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = pred.kind().skip_binder()
678+
&& pred.self_ty() == ty
679+
{
680+
if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
681+
return Some(hir::Mutability::Not);
682+
} else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() {
683+
return Some(hir::Mutability::Mut);
692684
}
693-
None
694-
})
685+
}
686+
None
695687
};
696688

697689
// If the type is opaque/param/closure, and it is Fn or FnMut, let's suggest (mutably)
698690
// borrowing the type, since `&mut F: FnMut` iff `F: FnMut` and similarly for `Fn`.
699691
// These types seem reasonably opaque enough that they could be substituted with their
700692
// borrowed variants in a function body when we see a move error.
701-
let borrow_level = match ty.kind() {
702-
ty::Param(_) => find_fn_kind_from_did(
703-
tcx.bound_explicit_predicates_of(self.mir_def_id().to_def_id())
704-
.map_bound(|p| p.predicates),
705-
None,
706-
),
707-
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
708-
find_fn_kind_from_did(tcx.bound_explicit_item_bounds(*def_id), Some(*substs))
709-
}
693+
let borrow_level = match *ty.kind() {
694+
ty::Param(_) => tcx
695+
.explicit_predicates_of(self.mir_def_id().to_def_id())
696+
.predicates
697+
.iter()
698+
.copied()
699+
.find_map(find_fn_kind_from_did),
700+
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx
701+
.bound_explicit_item_bounds(def_id)
702+
.subst_iter_copied(tcx, substs)
703+
.find_map(find_fn_kind_from_did),
710704
ty::Closure(_, substs) => match substs.as_closure().kind() {
711705
ty::ClosureKind::Fn => Some(hir::Mutability::Not),
712706
ty::ClosureKind::FnMut => Some(hir::Mutability::Mut),

compiler/rustc_borrowck/src/type_check/canonical.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
107107
instantiated_predicates: ty::InstantiatedPredicates<'tcx>,
108108
locations: Locations,
109109
) {
110-
for (predicate, span) in instantiated_predicates
111-
.predicates
112-
.into_iter()
113-
.zip(instantiated_predicates.spans.into_iter())
114-
{
110+
for (predicate, span) in instantiated_predicates {
115111
debug!(?predicate);
116112
let category = ConstraintCategory::Predicate(span);
117113
let predicate = self.normalize_with_category(predicate, locations, category);

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+13-12
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,11 @@ fn compare_method_predicate_entailment<'tcx>(
209209
//
210210
// We then register the obligations from the impl_m and check to see
211211
// if all constraints hold.
212-
hybrid_preds
213-
.predicates
214-
.extend(trait_m_predicates.instantiate_own(tcx, trait_to_placeholder_substs).predicates);
212+
hybrid_preds.predicates.extend(
213+
trait_m_predicates
214+
.instantiate_own(tcx, trait_to_placeholder_substs)
215+
.map(|(predicate, _)| predicate),
216+
);
215217

216218
// Construct trait parameter environment and then shift it into the placeholder viewpoint.
217219
// The key step here is to update the caller_bounds's predicates to be
@@ -230,7 +232,7 @@ fn compare_method_predicate_entailment<'tcx>(
230232
debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
231233

232234
let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
233-
for (predicate, span) in iter::zip(impl_m_own_bounds.predicates, impl_m_own_bounds.spans) {
235+
for (predicate, span) in impl_m_own_bounds {
234236
let normalize_cause = traits::ObligationCause::misc(span, impl_m_hir_id);
235237
let predicate = ocx.normalize(&normalize_cause, param_env, predicate);
236238

@@ -1828,8 +1830,7 @@ fn compare_type_predicate_entailment<'tcx>(
18281830
check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
18291831

18301832
let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_substs);
1831-
1832-
if impl_ty_own_bounds.is_empty() {
1833+
if impl_ty_own_bounds.len() == 0 {
18331834
// Nothing to check.
18341835
return Ok(());
18351836
}
@@ -1844,9 +1845,11 @@ fn compare_type_predicate_entailment<'tcx>(
18441845
// associated type in the trait are assumed.
18451846
let impl_predicates = tcx.predicates_of(impl_ty_predicates.parent.unwrap());
18461847
let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
1847-
hybrid_preds
1848-
.predicates
1849-
.extend(trait_ty_predicates.instantiate_own(tcx, trait_to_impl_substs).predicates);
1848+
hybrid_preds.predicates.extend(
1849+
trait_ty_predicates
1850+
.instantiate_own(tcx, trait_to_impl_substs)
1851+
.map(|(predicate, _)| predicate),
1852+
);
18501853

18511854
debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds);
18521855

@@ -1862,9 +1865,7 @@ fn compare_type_predicate_entailment<'tcx>(
18621865

18631866
debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
18641867

1865-
assert_eq!(impl_ty_own_bounds.predicates.len(), impl_ty_own_bounds.spans.len());
1866-
for (span, predicate) in std::iter::zip(impl_ty_own_bounds.spans, impl_ty_own_bounds.predicates)
1867-
{
1868+
for (predicate, span) in impl_ty_own_bounds {
18681869
let cause = ObligationCause::misc(span, impl_ty_hir_id);
18691870
let predicate = ocx.normalize(&cause, param_env, predicate);
18701871

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+13-16
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ use rustc_trait_selection::traits::{
3232
};
3333

3434
use std::cell::LazyCell;
35-
use std::iter;
3635
use std::ops::{ControlFlow, Deref};
3736

3837
pub(super) struct WfCheckingCtxt<'a, 'tcx> {
@@ -1310,7 +1309,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
13101309
let infcx = wfcx.infcx;
13111310
let tcx = wfcx.tcx();
13121311

1313-
let predicates = tcx.bound_predicates_of(def_id.to_def_id());
1312+
let predicates = tcx.predicates_of(def_id.to_def_id());
13141313
let generics = tcx.generics_of(def_id);
13151314

13161315
let is_our_default = |def: &ty::GenericParamDef| match def.kind {
@@ -1411,7 +1410,6 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
14111410

14121411
// Now we build the substituted predicates.
14131412
let default_obligations = predicates
1414-
.0
14151413
.predicates
14161414
.iter()
14171415
.flat_map(|&(pred, sp)| {
@@ -1442,13 +1440,13 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
14421440
}
14431441
let mut param_count = CountParams::default();
14441442
let has_region = pred.visit_with(&mut param_count).is_break();
1445-
let substituted_pred = predicates.rebind(pred).subst(tcx, substs);
1443+
let substituted_pred = ty::EarlyBinder(pred).subst(tcx, substs);
14461444
// Don't check non-defaulted params, dependent defaults (including lifetimes)
14471445
// or preds with multiple params.
14481446
if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
14491447
{
14501448
None
1451-
} else if predicates.0.predicates.iter().any(|&(p, _)| p == substituted_pred) {
1449+
} else if predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) {
14521450
// Avoid duplication of predicates that contain no parameters, for example.
14531451
None
14541452
} else {
@@ -1474,22 +1472,21 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
14741472
traits::Obligation::new(tcx, cause, wfcx.param_env, pred)
14751473
});
14761474

1477-
let predicates = predicates.0.instantiate_identity(tcx);
1475+
let predicates = predicates.instantiate_identity(tcx);
14781476

14791477
let predicates = wfcx.normalize(span, None, predicates);
14801478

14811479
debug!(?predicates.predicates);
14821480
assert_eq!(predicates.predicates.len(), predicates.spans.len());
1483-
let wf_obligations =
1484-
iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| {
1485-
traits::wf::predicate_obligations(
1486-
infcx,
1487-
wfcx.param_env.without_const(),
1488-
wfcx.body_id,
1489-
p,
1490-
sp,
1491-
)
1492-
});
1481+
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
1482+
traits::wf::predicate_obligations(
1483+
infcx,
1484+
wfcx.param_env.without_const(),
1485+
wfcx.body_id,
1486+
p,
1487+
sp,
1488+
)
1489+
});
14931490

14941491
let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
14951492
wfcx.register_obligations(obligations);

compiler/rustc_hir_typeck/src/callee.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -375,14 +375,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
375375
if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) {
376376
let predicates = self.tcx.predicates_of(def_id);
377377
let predicates = predicates.instantiate(self.tcx, subst);
378-
for (predicate, predicate_span) in
379-
predicates.predicates.iter().zip(&predicates.spans)
380-
{
378+
for (predicate, predicate_span) in predicates {
381379
let obligation = Obligation::new(
382380
self.tcx,
383381
ObligationCause::dummy_with_span(callee_expr.span),
384382
self.param_env,
385-
*predicate,
383+
predicate,
386384
);
387385
let result = self.evaluate_obligation(&obligation);
388386
self.tcx
@@ -391,7 +389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
391389
callee_expr.span,
392390
&format!("evaluate({:?}) = {:?}", predicate, result),
393391
)
394-
.span_label(*predicate_span, "predicate")
392+
.span_label(predicate_span, "predicate")
395393
.emit();
396394
}
397395
}

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -2140,8 +2140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21402140
// FIXME(compiler-errors): This could be problematic if something has two
21412141
// fn-like predicates with different args, but callable types really never
21422142
// do that, so it's OK.
2143-
for (predicate, span) in
2144-
std::iter::zip(instantiated.predicates, instantiated.spans)
2143+
for (predicate, span) in instantiated
21452144
{
21462145
if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = predicate.kind().skip_binder()
21472146
&& pred.self_ty().peel_refs() == callee_ty

compiler/rustc_hir_typeck/src/method/confirm.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use rustc_middle::ty::{InternalSubsts, UserSubsts, UserType};
1919
use rustc_span::{Span, DUMMY_SP};
2020
use rustc_trait_selection::traits;
2121

22-
use std::iter;
2322
use std::ops::Deref;
2423

2524
struct ConfirmContext<'a, 'tcx> {
@@ -101,7 +100,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
101100
let filler_substs = rcvr_substs
102101
.extend_to(self.tcx, pick.item.def_id, |def, _| self.tcx.mk_param_from_def(def));
103102
let illegal_sized_bound = self.predicates_require_illegal_sized_bound(
104-
&self.tcx.predicates_of(pick.item.def_id).instantiate(self.tcx, filler_substs),
103+
self.tcx.predicates_of(pick.item.def_id).instantiate(self.tcx, filler_substs),
105104
);
106105

107106
// Unify the (adjusted) self type with what the method expects.
@@ -565,7 +564,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
565564

566565
fn predicates_require_illegal_sized_bound(
567566
&self,
568-
predicates: &ty::InstantiatedPredicates<'tcx>,
567+
predicates: ty::InstantiatedPredicates<'tcx>,
569568
) -> Option<Span> {
570569
let sized_def_id = self.tcx.lang_items().sized_trait()?;
571570

@@ -575,10 +574,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
575574
ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred))
576575
if trait_pred.def_id() == sized_def_id =>
577576
{
578-
let span = iter::zip(&predicates.predicates, &predicates.spans)
577+
let span = predicates
578+
.iter()
579579
.find_map(
580580
|(p, span)| {
581-
if *p == obligation.predicate { Some(*span) } else { None }
581+
if p == obligation.predicate { Some(span) } else { None }
582582
},
583583
)
584584
.unwrap_or(rustc_span::DUMMY_SP);

compiler/rustc_infer/src/infer/error_reporting/note.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
330330

331331
let Ok(trait_predicates) = self
332332
.tcx
333-
.bound_explicit_predicates_of(trait_item_def_id)
334-
.map_bound(|p| p.predicates)
335-
.subst_iter_copied(self.tcx, trait_item_substs)
333+
.explicit_predicates_of(trait_item_def_id)
334+
.instantiate_own(self.tcx, trait_item_substs)
336335
.map(|(pred, _)| {
337336
if pred.is_suggestable(self.tcx, false) {
338337
Ok(pred.to_string())

compiler/rustc_middle/src/ty/generics.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -341,15 +341,9 @@ impl<'tcx> GenericPredicates<'tcx> {
341341
&self,
342342
tcx: TyCtxt<'tcx>,
343343
substs: SubstsRef<'tcx>,
344-
) -> InstantiatedPredicates<'tcx> {
345-
InstantiatedPredicates {
346-
predicates: self
347-
.predicates
348-
.iter()
349-
.map(|(p, _)| EarlyBinder(*p).subst(tcx, substs))
350-
.collect(),
351-
spans: self.predicates.iter().map(|(_, sp)| *sp).collect(),
352-
}
344+
) -> impl Iterator<Item = (Predicate<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
345+
{
346+
EarlyBinder(self.predicates).subst_iter_copied(tcx, substs)
353347
}
354348

355349
#[instrument(level = "debug", skip(self, tcx))]

compiler/rustc_middle/src/ty/mod.rs

+29
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,35 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
12521252
pub fn is_empty(&self) -> bool {
12531253
self.predicates.is_empty()
12541254
}
1255+
1256+
pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
1257+
(&self).into_iter()
1258+
}
1259+
}
1260+
1261+
impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> {
1262+
type Item = (Predicate<'tcx>, Span);
1263+
1264+
type IntoIter = std::iter::Zip<std::vec::IntoIter<Predicate<'tcx>>, std::vec::IntoIter<Span>>;
1265+
1266+
fn into_iter(self) -> Self::IntoIter {
1267+
debug_assert_eq!(self.predicates.len(), self.spans.len());
1268+
std::iter::zip(self.predicates, self.spans)
1269+
}
1270+
}
1271+
1272+
impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> {
1273+
type Item = (Predicate<'tcx>, Span);
1274+
1275+
type IntoIter = std::iter::Zip<
1276+
std::iter::Copied<std::slice::Iter<'a, Predicate<'tcx>>>,
1277+
std::iter::Copied<std::slice::Iter<'a, Span>>,
1278+
>;
1279+
1280+
fn into_iter(self) -> Self::IntoIter {
1281+
debug_assert_eq!(self.predicates.len(), self.spans.len());
1282+
std::iter::zip(self.predicates.iter().copied(), self.spans.iter().copied())
1283+
}
12551284
}
12561285

12571286
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)]

compiler/rustc_middle/src/ty/subst.rs

+15
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,13 @@ where
639639
}
640640
}
641641

642+
impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIter<'_, 'tcx, I>
643+
where
644+
I::IntoIter: ExactSizeIterator,
645+
I::Item: TypeFoldable<'tcx>,
646+
{
647+
}
648+
642649
impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
643650
where
644651
I::Item: Deref,
@@ -686,6 +693,14 @@ where
686693
}
687694
}
688695

696+
impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIterCopied<'_, 'tcx, I>
697+
where
698+
I::IntoIter: ExactSizeIterator,
699+
I::Item: Deref,
700+
<I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
701+
{
702+
}
703+
689704
pub struct EarlyBinderIter<T> {
690705
t: T,
691706
}

0 commit comments

Comments
 (0)