Auto merge of #119849 - lcnr:eagerly-instantiate-binders, r= · rust-lang/rust@21bc403 (original) (raw)
`@@ -33,6 +33,7 @@ use rustc_errors::Diagnostic;
`
33
33
`use rustc_hir as hir;
`
34
34
`use rustc_hir::def_id::DefId;
`
35
35
`use rustc_infer::infer::BoundRegionConversionTime;
`
``
36
`+
use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
`
36
37
`use rustc_infer::infer::DefineOpaqueTypes;
`
37
38
`use rustc_infer::traits::TraitObligation;
`
38
39
`use rustc_middle::dep_graph::dep_kinds;
`
`@@ -43,7 +44,7 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable;
`
43
44
`use rustc_middle::ty::fold::BottomUpFolder;
`
44
45
`use rustc_middle::ty::relate::TypeRelation;
`
45
46
`use rustc_middle::ty::GenericArgsRef;
`
46
``
`-
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
`
``
47
`+
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPredicate};
`
47
48
`use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
`
48
49
`use rustc_span::symbol::sym;
`
49
50
`use rustc_span::Symbol;
`
`@@ -1627,33 +1628,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
`
1627
1628
`};
`
1628
1629
`let bounds = tcx.item_bounds(def_id).instantiate(tcx, args);
`
1629
1630
``
1630
``
`` -
// The bounds returned by item_bounds
may contain duplicates after
``
1631
``
`-
// normalization, so try to deduplicate when possible to avoid
`
1632
``
`-
// unnecessary ambiguity.
`
1633
``
`-
let mut distinct_normalized_bounds = FxHashSet::default();
`
1634
``
-
1635
1631
` bounds
`
1636
1632
`.iter()
`
1637
1633
`.enumerate()
`
1638
1634
`.filter_map(|(idx, bound)| {
`
1639
1635
`let bound_predicate = bound.kind();
`
1640
1636
`if let ty::ClauseKind::Trait(pred) = bound_predicate.skip_binder() {
`
1641
1637
`let bound = bound_predicate.rebind(pred.trait_ref);
`
1642
``
`-
if self.infcx.probe(|_| {
`
1643
``
`-
match self.match_normalize_trait_ref(
`
1644
``
`-
obligation,
`
1645
``
`-
bound,
`
1646
``
`-
placeholder_trait_predicate.trait_ref,
`
1647
``
`-
) {
`
1648
``
`-
Ok(None) => true,
`
1649
``
`-
Ok(Some(normalized_trait))
`
1650
``
`-
if distinct_normalized_bounds.insert(normalized_trait) =>
`
1651
``
`-
{
`
1652
``
`-
true
`
1653
``
`-
}
`
1654
``
`-
_ => false,
`
1655
``
`-
}
`
1656
``
`-
}) {
`
``
1638
`+
if self.matches_trait_ref(
`
``
1639
`+
obligation,
`
``
1640
`+
placeholder_trait_predicate.trait_ref,
`
``
1641
`+
bound,
`
``
1642
`+
) {
`
1657
1643
`return Some(idx);
`
1658
1644
`}
`
1659
1645
`}
`
`@@ -1662,43 +1648,40 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
`
1662
1648
`.collect()
`
1663
1649
`}
`
1664
1650
``
1665
``
`` -
/// Equates the trait in obligation
with trait bound. If the two traits
``
1666
``
`-
/// can be equated and the normalized trait bound doesn't contain inference
`
1667
``
`-
/// variables or placeholders, the normalized bound is returned.
`
1668
``
`-
fn match_normalize_trait_ref(
`
``
1651
`` +
/// Equates the trait in obligation
with trait bound and returns
``
``
1652
`+
/// true if the two traits can be equated.
`
``
1653
`+
fn matches_trait_ref(
`
1669
1654
`&mut self,
`
1670
1655
`obligation: &PolyTraitObligation<'tcx>,
`
1671
``
`-
trait_bound: ty::PolyTraitRef<'tcx>,
`
1672
1656
`placeholder_trait_ref: ty::TraitRef<'tcx>,
`
1673
``
`-
) -> Result<Option<ty::PolyTraitRef<'tcx>>, ()> {
`
``
1657
`+
trait_bound: ty::PolyTraitRef<'tcx>,
`
``
1658
`+
) -> bool {
`
1674
1659
`debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());
`
1675
1660
`if placeholder_trait_ref.def_id != trait_bound.def_id() {
`
1676
1661
`// Avoid unnecessary normalization
`
1677
``
`-
return Err(());
`
``
1662
`+
return false;
`
1678
1663
`}
`
1679
1664
``
1680
``
`-
let Normalized { value: trait_bound, obligations: _ } = ensure_sufficient_stack(|| {
`
1681
``
`-
project::normalize_with_depth(
`
1682
``
`-
self,
`
1683
``
`-
obligation.param_env,
`
1684
``
`-
obligation.cause.clone(),
`
1685
``
`-
obligation.recursion_depth + 1,
`
``
1665
`+
self.infcx.probe(|_| {
`
``
1666
`+
let trait_bound = self.infcx.instantiate_binder_with_fresh_vars(
`
``
1667
`+
obligation.cause.span,
`
``
1668
`+
HigherRankedType,
`
1686
1669
` trait_bound,
`
1687
``
`-
)
`
1688
``
`-
});
`
1689
``
`-
self.infcx
`
1690
``
`-
.at(&obligation.cause, obligation.param_env)
`
1691
``
`-
.sup(DefineOpaqueTypes::No, ty::Binder::dummy(placeholder_trait_ref), trait_bound)
`
1692
``
`-
.map(|InferOk { obligations: _, value: () }| {
`
1693
``
`-
// This method is called within a probe, so we can't have
`
1694
``
`-
// inference variables and placeholders escape.
`
1695
``
`-
if !trait_bound.has_infer() && !trait_bound.has_placeholders() {
`
1696
``
`-
Some(trait_bound)
`
1697
``
`-
} else {
`
1698
``
`-
None
`
1699
``
`-
}
`
1700
``
`-
})
`
1701
``
`-
.map_err(|_| ())
`
``
1670
`+
);
`
``
1671
`+
let Normalized { value: trait_bound, obligations: _ } = ensure_sufficient_stack(|| {
`
``
1672
`+
project::normalize_with_depth(
`
``
1673
`+
self,
`
``
1674
`+
obligation.param_env,
`
``
1675
`+
obligation.cause.clone(),
`
``
1676
`+
obligation.recursion_depth + 1,
`
``
1677
`+
trait_bound,
`
``
1678
`+
)
`
``
1679
`+
});
`
``
1680
`+
self.infcx
`
``
1681
`+
.at(&obligation.cause, obligation.param_env)
`
``
1682
`+
.eq(DefineOpaqueTypes::No, placeholder_trait_ref, trait_bound)
`
``
1683
`+
.is_ok()
`
``
1684
`+
})
`
1702
1685
`}
`
1703
1686
``
1704
1687
`fn where_clause_may_apply<'o>(
`
`@@ -1750,7 +1733,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
`
1750
1733
`let is_match = self
`
1751
1734
`.infcx
`
1752
1735
`.at(&obligation.cause, obligation.param_env)
`
1753
``
`-
.sup(DefineOpaqueTypes::No, obligation.predicate, infer_projection)
`
``
1736
`+
.eq(DefineOpaqueTypes::No, obligation.predicate, infer_projection)
`
1754
1737
`.is_ok_and(|InferOk { obligations, value: () }| {
`
1755
1738
`self.evaluate_predicates_recursively(
`
1756
1739
`TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
`
`@@ -2532,7 +2515,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
`
2532
2515
` nested.extend(
`
2533
2516
`self.infcx
`
2534
2517
`.at(&obligation.cause, obligation.param_env)
`
2535
``
`-
.sup(
`
``
2518
`+
.eq(
`
2536
2519
`DefineOpaqueTypes::No,
`
2537
2520
` upcast_principal.map_bound(|trait_ref| {
`
2538
2521
` ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
`
`@@ -2570,7 +2553,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
`
2570
2553
` nested.extend(
`
2571
2554
`self.infcx
`
2572
2555
`.at(&obligation.cause, obligation.param_env)
`
2573
``
`-
.sup(DefineOpaqueTypes::No, source_projection, target_projection)
`
``
2556
`+
.eq(DefineOpaqueTypes::No, source_projection, target_projection)
`
2574
2557
`.map_err(|_| SelectionError::Unimplemented)?
`
2575
2558
`.into_obligations(),
`
2576
2559
`);
`
`@@ -2614,9 +2597,15 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
`
2614
2597
`obligation: &PolyTraitObligation<'tcx>,
`
2615
2598
`poly_trait_ref: ty::PolyTraitRef<'tcx>,
`
2616
2599
`) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
`
``
2600
`+
let predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
`
``
2601
`+
let trait_ref = self.infcx.instantiate_binder_with_fresh_vars(
`
``
2602
`+
obligation.cause.span,
`
``
2603
`+
HigherRankedType,
`
``
2604
`+
poly_trait_ref,
`
``
2605
`+
);
`
2617
2606
`self.infcx
`
2618
2607
`.at(&obligation.cause, obligation.param_env)
`
2619
``
`-
.sup(DefineOpaqueTypes::No, obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
`
``
2608
`+
.eq(DefineOpaqueTypes::No, predicate.trait_ref, trait_ref)
`
2620
2609
`.map(|InferOk { obligations, .. }| obligations)
`
2621
2610
`.map_err(|_| ())
`
2622
2611
`}
`