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

`}

`