11//! Code for projecting associated types out of trait references.
22
33use super :: elaborate_predicates;
4+ use super :: projection_cache:: NormalizedTy ;
45use super :: specialization_graph;
56use super :: translate_substs;
67use super :: util;
8+ use super :: MismatchedProjectionTypes ;
79use super :: Obligation ;
810use super :: ObligationCause ;
911use super :: PredicateObligation ;
1012use super :: Selection ;
1113use super :: SelectionContext ;
1214use super :: SelectionError ;
15+ use super :: { Normalized , ProjectionCacheEntry , ProjectionCacheKey } ;
1316use super :: { VtableClosureData , VtableFnPointerData , VtableGeneratorData , VtableImplData } ;
1417
1518use crate :: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
@@ -18,7 +21,6 @@ use rustc::ty::fold::{TypeFoldable, TypeFolder};
1821use rustc:: ty:: subst:: { InternalSubsts , Subst } ;
1922use rustc:: ty:: { self , ToPolyTraitRef , ToPredicate , Ty , TyCtxt , WithConstness } ;
2023use rustc_ast:: ast:: Ident ;
21- use rustc_data_structures:: snapshot_map:: { Snapshot , SnapshotMap } ;
2224use rustc_hir:: def_id:: DefId ;
2325use rustc_span:: symbol:: sym;
2426use rustc_span:: DUMMY_SP ;
@@ -41,11 +43,6 @@ pub enum ProjectionTyError<'tcx> {
4143 TraitSelectionError ( SelectionError < ' tcx > ) ,
4244}
4345
44- #[ derive( Clone ) ]
45- pub struct MismatchedProjectionTypes < ' tcx > {
46- pub err : ty:: error:: TypeError < ' tcx > ,
47- }
48-
4946#[ derive( PartialEq , Eq , Debug ) ]
5047enum ProjectionTyCandidate < ' tcx > {
5148 // 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> {
393390 }
394391}
395392
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-
410393/// The guts of `normalize`: normalize a specific projection like `<T
411394/// as Trait>::Item`. The result is always a type (and possibly
412395/// additional obligations). If ambiguity arises, which implies that
@@ -1500,47 +1483,6 @@ fn assoc_ty_def(
15001483 }
15011484}
15021485
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-
15441486impl < ' cx , ' tcx > ProjectionCacheKey < ' tcx > {
15451487 pub fn from_poly_projection_predicate (
15461488 selcx : & mut SelectionContext < ' cx , ' tcx > ,
@@ -1558,119 +1500,3 @@ impl<'cx, 'tcx> ProjectionCacheKey<'tcx> {
15581500 } )
15591501 }
15601502}
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