1
1
//! Code for projecting associated types out of trait references.
2
2
3
3
use super :: elaborate_predicates;
4
+ use super :: projection_cache:: NormalizedTy ;
4
5
use super :: specialization_graph;
5
6
use super :: translate_substs;
6
7
use super :: util;
8
+ use super :: MismatchedProjectionTypes ;
7
9
use super :: Obligation ;
8
10
use super :: ObligationCause ;
9
11
use super :: PredicateObligation ;
10
12
use super :: Selection ;
11
13
use super :: SelectionContext ;
12
14
use super :: SelectionError ;
15
+ use super :: { Normalized , ProjectionCacheEntry , ProjectionCacheKey } ;
13
16
use super :: { VtableClosureData , VtableFnPointerData , VtableGeneratorData , VtableImplData } ;
14
17
15
18
use crate :: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
@@ -18,7 +21,6 @@ use rustc::ty::fold::{TypeFoldable, TypeFolder};
18
21
use rustc:: ty:: subst:: { InternalSubsts , Subst } ;
19
22
use rustc:: ty:: { self , ToPolyTraitRef , ToPredicate , Ty , TyCtxt , WithConstness } ;
20
23
use rustc_ast:: ast:: Ident ;
21
- use rustc_data_structures:: snapshot_map:: { Snapshot , SnapshotMap } ;
22
24
use rustc_hir:: def_id:: DefId ;
23
25
use rustc_span:: symbol:: sym;
24
26
use rustc_span:: DUMMY_SP ;
@@ -41,11 +43,6 @@ pub enum ProjectionTyError<'tcx> {
41
43
TraitSelectionError ( SelectionError < ' tcx > ) ,
42
44
}
43
45
44
- #[ derive( Clone ) ]
45
- pub struct MismatchedProjectionTypes < ' tcx > {
46
- pub err : ty:: error:: TypeError < ' tcx > ,
47
- }
48
-
49
46
#[ derive( PartialEq , Eq , Debug ) ]
50
47
enum ProjectionTyCandidate < ' tcx > {
51
48
// from a where-clause in the env or object type
@@ -393,20 +390,6 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
393
390
}
394
391
}
395
392
396
- #[ derive( Clone , TypeFoldable ) ]
397
- pub struct Normalized < ' tcx , T > {
398
- pub value : T ,
399
- pub obligations : Vec < PredicateObligation < ' tcx > > ,
400
- }
401
-
402
- pub type NormalizedTy < ' tcx > = Normalized < ' tcx , Ty < ' tcx > > ;
403
-
404
- impl < ' tcx , T > Normalized < ' tcx , T > {
405
- pub fn with < U > ( self , value : U ) -> Normalized < ' tcx , U > {
406
- Normalized { value, obligations : self . obligations }
407
- }
408
- }
409
-
410
393
/// The guts of `normalize`: normalize a specific projection like `<T
411
394
/// as Trait>::Item`. The result is always a type (and possibly
412
395
/// additional obligations). If ambiguity arises, which implies that
@@ -1500,47 +1483,6 @@ fn assoc_ty_def(
1500
1483
}
1501
1484
}
1502
1485
1503
- // # Cache
1504
-
1505
- /// The projection cache. Unlike the standard caches, this can include
1506
- /// infcx-dependent type variables, therefore we have to roll the
1507
- /// cache back each time we roll a snapshot back, to avoid assumptions
1508
- /// on yet-unresolved inference variables. Types with placeholder
1509
- /// regions also have to be removed when the respective snapshot ends.
1510
- ///
1511
- /// Because of that, projection cache entries can be "stranded" and left
1512
- /// inaccessible when type variables inside the key are resolved. We make no
1513
- /// attempt to recover or remove "stranded" entries, but rather let them be
1514
- /// (for the lifetime of the infcx).
1515
- ///
1516
- /// Entries in the projection cache might contain inference variables
1517
- /// that will be resolved by obligations on the projection cache entry (e.g.,
1518
- /// when a type parameter in the associated type is constrained through
1519
- /// an "RFC 447" projection on the impl).
1520
- ///
1521
- /// When working with a fulfillment context, the derived obligations of each
1522
- /// projection cache entry will be registered on the fulfillcx, so any users
1523
- /// that can wait for a fulfillcx fixed point need not care about this. However,
1524
- /// users that don't wait for a fixed point (e.g., trait evaluation) have to
1525
- /// resolve the obligations themselves to make sure the projected result is
1526
- /// ok and avoid issues like #43132.
1527
- ///
1528
- /// If that is done, after evaluation the obligations, it is a good idea to
1529
- /// call `ProjectionCache::complete` to make sure the obligations won't be
1530
- /// re-evaluated and avoid an exponential worst-case.
1531
- //
1532
- // FIXME: we probably also want some sort of cross-infcx cache here to
1533
- // reduce the amount of duplication. Let's see what we get with the Chalk reforms.
1534
- #[ derive( Default ) ]
1535
- pub struct ProjectionCache < ' tcx > {
1536
- map : SnapshotMap < ProjectionCacheKey < ' tcx > , ProjectionCacheEntry < ' tcx > > ,
1537
- }
1538
-
1539
- #[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq ) ]
1540
- pub struct ProjectionCacheKey < ' tcx > {
1541
- ty : ty:: ProjectionTy < ' tcx > ,
1542
- }
1543
-
1544
1486
impl < ' cx , ' tcx > ProjectionCacheKey < ' tcx > {
1545
1487
pub fn from_poly_projection_predicate (
1546
1488
selcx : & mut SelectionContext < ' cx , ' tcx > ,
@@ -1558,119 +1500,3 @@ impl<'cx, 'tcx> ProjectionCacheKey<'tcx> {
1558
1500
} )
1559
1501
}
1560
1502
}
1561
-
1562
- #[ derive( Clone , Debug ) ]
1563
- enum ProjectionCacheEntry < ' tcx > {
1564
- InProgress ,
1565
- Ambiguous ,
1566
- Error ,
1567
- NormalizedTy ( NormalizedTy < ' tcx > ) ,
1568
- }
1569
-
1570
- // N.B., intentionally not Clone
1571
- pub struct ProjectionCacheSnapshot {
1572
- snapshot : Snapshot ,
1573
- }
1574
-
1575
- impl < ' tcx > ProjectionCache < ' tcx > {
1576
- pub fn clear ( & mut self ) {
1577
- self . map . clear ( ) ;
1578
- }
1579
-
1580
- pub fn snapshot ( & mut self ) -> ProjectionCacheSnapshot {
1581
- ProjectionCacheSnapshot { snapshot : self . map . snapshot ( ) }
1582
- }
1583
-
1584
- pub fn rollback_to ( & mut self , snapshot : ProjectionCacheSnapshot ) {
1585
- self . map . rollback_to ( snapshot. snapshot ) ;
1586
- }
1587
-
1588
- pub fn rollback_placeholder ( & mut self , snapshot : & ProjectionCacheSnapshot ) {
1589
- self . map . partial_rollback ( & snapshot. snapshot , & |k| k. ty . has_re_placeholders ( ) ) ;
1590
- }
1591
-
1592
- pub fn commit ( & mut self , snapshot : ProjectionCacheSnapshot ) {
1593
- self . map . commit ( snapshot. snapshot ) ;
1594
- }
1595
-
1596
- /// Try to start normalize `key`; returns an error if
1597
- /// normalization already occurred (this error corresponds to a
1598
- /// cache hit, so it's actually a good thing).
1599
- fn try_start (
1600
- & mut self ,
1601
- key : ProjectionCacheKey < ' tcx > ,
1602
- ) -> Result < ( ) , ProjectionCacheEntry < ' tcx > > {
1603
- if let Some ( entry) = self . map . get ( & key) {
1604
- return Err ( entry. clone ( ) ) ;
1605
- }
1606
-
1607
- self . map . insert ( key, ProjectionCacheEntry :: InProgress ) ;
1608
- Ok ( ( ) )
1609
- }
1610
-
1611
- /// Indicates that `key` was normalized to `value`.
1612
- fn insert_ty ( & mut self , key : ProjectionCacheKey < ' tcx > , value : NormalizedTy < ' tcx > ) {
1613
- debug ! (
1614
- "ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}" ,
1615
- key, value
1616
- ) ;
1617
- let fresh_key = self . map . insert ( key, ProjectionCacheEntry :: NormalizedTy ( value) ) ;
1618
- assert ! ( !fresh_key, "never started projecting `{:?}`" , key) ;
1619
- }
1620
-
1621
- /// Mark the relevant projection cache key as having its derived obligations
1622
- /// complete, so they won't have to be re-computed (this is OK to do in a
1623
- /// snapshot - if the snapshot is rolled back, the obligations will be
1624
- /// marked as incomplete again).
1625
- pub fn complete ( & mut self , key : ProjectionCacheKey < ' tcx > ) {
1626
- let ty = match self . map . get ( & key) {
1627
- Some ( & ProjectionCacheEntry :: NormalizedTy ( ref ty) ) => {
1628
- debug ! ( "ProjectionCacheEntry::complete({:?}) - completing {:?}" , key, ty) ;
1629
- ty. value
1630
- }
1631
- ref value => {
1632
- // Type inference could "strand behind" old cache entries. Leave
1633
- // them alone for now.
1634
- debug ! ( "ProjectionCacheEntry::complete({:?}) - ignoring {:?}" , key, value) ;
1635
- return ;
1636
- }
1637
- } ;
1638
-
1639
- self . map . insert (
1640
- key,
1641
- ProjectionCacheEntry :: NormalizedTy ( Normalized { value : ty, obligations : vec ! [ ] } ) ,
1642
- ) ;
1643
- }
1644
-
1645
- /// A specialized version of `complete` for when the key's value is known
1646
- /// to be a NormalizedTy.
1647
- pub fn complete_normalized ( & mut self , key : ProjectionCacheKey < ' tcx > , ty : & NormalizedTy < ' tcx > ) {
1648
- // We want to insert `ty` with no obligations. If the existing value
1649
- // already has no obligations (as is common) we don't insert anything.
1650
- if !ty. obligations . is_empty ( ) {
1651
- self . map . insert (
1652
- key,
1653
- ProjectionCacheEntry :: NormalizedTy ( Normalized {
1654
- value : ty. value ,
1655
- obligations : vec ! [ ] ,
1656
- } ) ,
1657
- ) ;
1658
- }
1659
- }
1660
-
1661
- /// Indicates that trying to normalize `key` resulted in
1662
- /// ambiguity. No point in trying it again then until we gain more
1663
- /// type information (in which case, the "fully resolved" key will
1664
- /// be different).
1665
- fn ambiguous ( & mut self , key : ProjectionCacheKey < ' tcx > ) {
1666
- let fresh = self . map . insert ( key, ProjectionCacheEntry :: Ambiguous ) ;
1667
- assert ! ( !fresh, "never started projecting `{:?}`" , key) ;
1668
- }
1669
-
1670
- /// Indicates that trying to normalize `key` resulted in
1671
- /// error.
1672
- fn error ( & mut self , key : ProjectionCacheKey < ' tcx > ) {
1673
- let fresh = self . map . insert ( key, ProjectionCacheEntry :: Error ) ;
1674
- assert ! ( !fresh, "never started projecting `{:?}`" , key) ;
1675
- }
1676
- }
0 commit comments