@@ -8,6 +8,7 @@ use crate::mir::interpret::{sign_extend, truncate};
8
8
use crate :: ich:: NodeIdHashingMode ;
9
9
use crate :: traits:: { self , ObligationCause } ;
10
10
use crate :: ty:: { self , DefIdTree , Ty , TyCtxt , GenericParamDefKind , TypeFoldable } ;
11
+ use crate :: ty:: fold:: TypeFolder ;
11
12
use crate :: ty:: subst:: { Subst , InternalSubsts , SubstsRef , GenericArgKind } ;
12
13
use crate :: ty:: query:: TyCtxtAt ;
13
14
use crate :: ty:: TyKind :: * ;
@@ -699,81 +700,32 @@ impl<'tcx> TyCtxt<'tcx> {
699
700
}
700
701
}
701
702
703
+ /// Normalizes all opaque types in the given value, replacing them
704
+ /// with their underlying types.
705
+ pub fn normalize_impl_trait_types < T : TypeFoldable < ' tcx > > ( self , val : & T ) -> T {
706
+ let mut visitor = OpaqueTypeExpander {
707
+ seen_opaque_tys : FxHashSet :: default ( ) ,
708
+ expanded_cache : FxHashMap :: default ( ) ,
709
+ primary_def_id : None ,
710
+ found_recursion : false ,
711
+ check_recursion : false ,
712
+ tcx : self ,
713
+ } ;
714
+ val. fold_with ( & mut visitor)
715
+ }
716
+
702
717
/// Expands the given impl trait type, stopping if the type is recursive.
703
718
pub fn try_expand_impl_trait_type (
704
719
self ,
705
720
def_id : DefId ,
706
721
substs : SubstsRef < ' tcx > ,
707
722
) -> Result < Ty < ' tcx > , Ty < ' tcx > > {
708
- use crate :: ty:: fold:: TypeFolder ;
709
-
710
- struct OpaqueTypeExpander < ' tcx > {
711
- // Contains the DefIds of the opaque types that are currently being
712
- // expanded. When we expand an opaque type we insert the DefId of
713
- // that type, and when we finish expanding that type we remove the
714
- // its DefId.
715
- seen_opaque_tys : FxHashSet < DefId > ,
716
- // Cache of all expansions we've seen so far. This is a critical
717
- // optimization for some large types produced by async fn trees.
718
- expanded_cache : FxHashMap < ( DefId , SubstsRef < ' tcx > ) , Ty < ' tcx > > ,
719
- primary_def_id : DefId ,
720
- found_recursion : bool ,
721
- tcx : TyCtxt < ' tcx > ,
722
- }
723
-
724
- impl < ' tcx > OpaqueTypeExpander < ' tcx > {
725
- fn expand_opaque_ty (
726
- & mut self ,
727
- def_id : DefId ,
728
- substs : SubstsRef < ' tcx > ,
729
- ) -> Option < Ty < ' tcx > > {
730
- if self . found_recursion {
731
- return None ;
732
- }
733
- let substs = substs. fold_with ( self ) ;
734
- if self . seen_opaque_tys . insert ( def_id) {
735
- let expanded_ty = match self . expanded_cache . get ( & ( def_id, substs) ) {
736
- Some ( expanded_ty) => expanded_ty,
737
- None => {
738
- let generic_ty = self . tcx . type_of ( def_id) ;
739
- let concrete_ty = generic_ty. subst ( self . tcx , substs) ;
740
- let expanded_ty = self . fold_ty ( concrete_ty) ;
741
- self . expanded_cache . insert ( ( def_id, substs) , expanded_ty) ;
742
- expanded_ty
743
- }
744
- } ;
745
- self . seen_opaque_tys . remove ( & def_id) ;
746
- Some ( expanded_ty)
747
- } else {
748
- // If another opaque type that we contain is recursive, then it
749
- // will report the error, so we don't have to.
750
- self . found_recursion = def_id == self . primary_def_id ;
751
- None
752
- }
753
- }
754
- }
755
-
756
- impl < ' tcx > TypeFolder < ' tcx > for OpaqueTypeExpander < ' tcx > {
757
- fn tcx ( & self ) -> TyCtxt < ' tcx > {
758
- self . tcx
759
- }
760
-
761
- fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
762
- if let ty:: Opaque ( def_id, substs) = t. kind {
763
- self . expand_opaque_ty ( def_id, substs) . unwrap_or ( t)
764
- } else if t. has_projections ( ) {
765
- t. super_fold_with ( self )
766
- } else {
767
- t
768
- }
769
- }
770
- }
771
-
772
723
let mut visitor = OpaqueTypeExpander {
773
724
seen_opaque_tys : FxHashSet :: default ( ) ,
774
725
expanded_cache : FxHashMap :: default ( ) ,
775
- primary_def_id : def_id,
726
+ primary_def_id : Some ( def_id) ,
776
727
found_recursion : false ,
728
+ check_recursion : true ,
777
729
tcx : self ,
778
730
} ;
779
731
let expanded_type = visitor. expand_opaque_ty ( def_id, substs) . unwrap ( ) ;
@@ -785,6 +737,77 @@ impl<'tcx> TyCtxt<'tcx> {
785
737
}
786
738
}
787
739
740
+ /// Expands any nested opaque types, caching the expansion
741
+ /// of each (DefId, SubstsRef) pair
742
+ struct OpaqueTypeExpander < ' tcx > {
743
+ /// Contains the `DefId`s of the opaque types that are currently being
744
+ /// expanded. When we expand an opaque type we insert the `DefId` of
745
+ /// that type, and when we finish expanding that type we remove the
746
+ /// its `DefId`.
747
+ seen_opaque_tys : FxHashSet < DefId > ,
748
+ /// Cache of all expansions we've seen so far. This is a critical
749
+ /// optimization for some large types produced by `async fn` trees.
750
+ expanded_cache : FxHashMap < ( DefId , SubstsRef < ' tcx > ) , Ty < ' tcx > > ,
751
+ primary_def_id : Option < DefId > ,
752
+ found_recursion : bool ,
753
+ /// Whether or not to check for recursive opaque types.
754
+ /// This is `true` when we're explicitly checking for opaque type
755
+ /// recursion, and 'false' otherwise to avoid unecessary work.
756
+ check_recursion : bool ,
757
+ tcx : TyCtxt < ' tcx > ,
758
+ }
759
+
760
+ impl < ' tcx > OpaqueTypeExpander < ' tcx > {
761
+ fn expand_opaque_ty (
762
+ & mut self ,
763
+ def_id : DefId ,
764
+ substs : SubstsRef < ' tcx > ,
765
+ ) -> Option < Ty < ' tcx > > {
766
+ if self . found_recursion {
767
+ return None ;
768
+ }
769
+ let substs = substs. fold_with ( self ) ;
770
+ if !self . check_recursion || self . seen_opaque_tys . insert ( def_id) {
771
+ let expanded_ty = match self . expanded_cache . get ( & ( def_id, substs) ) {
772
+ Some ( expanded_ty) => expanded_ty,
773
+ None => {
774
+ let generic_ty = self . tcx . type_of ( def_id) ;
775
+ let concrete_ty = generic_ty. subst ( self . tcx , substs) ;
776
+ let expanded_ty = self . fold_ty ( concrete_ty) ;
777
+ self . expanded_cache . insert ( ( def_id, substs) , expanded_ty) ;
778
+ expanded_ty
779
+ }
780
+ } ;
781
+ if self . check_recursion {
782
+ self . seen_opaque_tys . remove ( & def_id) ;
783
+ }
784
+ Some ( expanded_ty)
785
+ } else {
786
+ // If another opaque type that we contain is recursive, then it
787
+ // will report the error, so we don't have to.
788
+ self . found_recursion = def_id == * self . primary_def_id . as_ref ( ) . unwrap ( ) ;
789
+ None
790
+ }
791
+ }
792
+ }
793
+
794
+ impl < ' tcx > TypeFolder < ' tcx > for OpaqueTypeExpander < ' tcx > {
795
+ fn tcx ( & self ) -> TyCtxt < ' tcx > {
796
+ self . tcx
797
+ }
798
+
799
+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
800
+ if let ty:: Opaque ( def_id, substs) = t. kind {
801
+ self . expand_opaque_ty ( def_id, substs) . unwrap_or ( t)
802
+ } else if t. has_projections ( ) {
803
+ t. super_fold_with ( self )
804
+ } else {
805
+ t
806
+ }
807
+ }
808
+ }
809
+
810
+
788
811
impl < ' tcx > ty:: TyS < ' tcx > {
789
812
/// Checks whether values of this type `T` are *moved* or *copied*
790
813
/// when referenced -- this amounts to a check for whether `T:
0 commit comments