@@ -8,6 +8,7 @@ use crate::mir::interpret::{sign_extend, truncate};
88use crate :: ich:: NodeIdHashingMode ;
99use crate :: traits:: { self , ObligationCause } ;
1010use crate :: ty:: { self , DefIdTree , Ty , TyCtxt , GenericParamDefKind , TypeFoldable } ;
11+ use crate :: ty:: fold:: TypeFolder ;
1112use crate :: ty:: subst:: { Subst , InternalSubsts , SubstsRef , GenericArgKind } ;
1213use crate :: ty:: query:: TyCtxtAt ;
1314use crate :: ty:: TyKind :: * ;
@@ -699,81 +700,32 @@ impl<'tcx> TyCtxt<'tcx> {
699700 }
700701 }
701702
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+
702717 /// Expands the given impl trait type, stopping if the type is recursive.
703718 pub fn try_expand_impl_trait_type (
704719 self ,
705720 def_id : DefId ,
706721 substs : SubstsRef < ' tcx > ,
707722 ) -> 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-
772723 let mut visitor = OpaqueTypeExpander {
773724 seen_opaque_tys : FxHashSet :: default ( ) ,
774725 expanded_cache : FxHashMap :: default ( ) ,
775- primary_def_id : def_id,
726+ primary_def_id : Some ( def_id) ,
776727 found_recursion : false ,
728+ check_recursion : true ,
777729 tcx : self ,
778730 } ;
779731 let expanded_type = visitor. expand_opaque_ty ( def_id, substs) . unwrap ( ) ;
@@ -785,6 +737,75 @@ impl<'tcx> TyCtxt<'tcx> {
785737 }
786738}
787739
740+ struct OpaqueTypeExpander < ' tcx > {
741+ // Contains the DefIds of the opaque types that are currently being
742+ // expanded. When we expand an opaque type we insert the DefId of
743+ // that type, and when we finish expanding that type we remove the
744+ // its DefId.
745+ seen_opaque_tys : FxHashSet < DefId > ,
746+ // Cache of all expansions we've seen so far. This is a critical
747+ // optimization for some large types produced by async fn trees.
748+ expanded_cache : FxHashMap < ( DefId , SubstsRef < ' tcx > ) , Ty < ' tcx > > ,
749+ primary_def_id : Option < DefId > ,
750+ found_recursion : bool ,
751+ // Whether or not to check for recursive opaque types.
752+ // This is 'true' when we're explicitly checking for opaque type
753+ // recursion, and 'false' otherwise to avoid unecessary work.
754+ check_recursion : bool ,
755+ tcx : TyCtxt < ' tcx > ,
756+ }
757+
758+ impl < ' tcx > OpaqueTypeExpander < ' tcx > {
759+ fn expand_opaque_ty (
760+ & mut self ,
761+ def_id : DefId ,
762+ substs : SubstsRef < ' tcx > ,
763+ ) -> Option < Ty < ' tcx > > {
764+ if self . found_recursion {
765+ return None ;
766+ }
767+ let substs = substs. fold_with ( self ) ;
768+ if !self . check_recursion || self . seen_opaque_tys . insert ( def_id) {
769+ let expanded_ty = match self . expanded_cache . get ( & ( def_id, substs) ) {
770+ Some ( expanded_ty) => expanded_ty,
771+ None => {
772+ let generic_ty = self . tcx . type_of ( def_id) ;
773+ let concrete_ty = generic_ty. subst ( self . tcx , substs) ;
774+ let expanded_ty = self . fold_ty ( concrete_ty) ;
775+ self . expanded_cache . insert ( ( def_id, substs) , expanded_ty) ;
776+ expanded_ty
777+ }
778+ } ;
779+ if self . check_recursion {
780+ self . seen_opaque_tys . remove ( & def_id) ;
781+ }
782+ Some ( expanded_ty)
783+ } else {
784+ // If another opaque type that we contain is recursive, then it
785+ // will report the error, so we don't have to.
786+ self . found_recursion = def_id == * self . primary_def_id . as_ref ( ) . unwrap ( ) ;
787+ None
788+ }
789+ }
790+ }
791+
792+ impl < ' tcx > TypeFolder < ' tcx > for OpaqueTypeExpander < ' tcx > {
793+ fn tcx ( & self ) -> TyCtxt < ' tcx > {
794+ self . tcx
795+ }
796+
797+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
798+ if let ty:: Opaque ( def_id, substs) = t. kind {
799+ self . expand_opaque_ty ( def_id, substs) . unwrap_or ( t)
800+ } else if t. has_projections ( ) {
801+ t. super_fold_with ( self )
802+ } else {
803+ t
804+ }
805+ }
806+ }
807+
808+
788809impl < ' tcx > ty:: TyS < ' tcx > {
789810 /// Checks whether values of this type `T` are *moved* or *copied*
790811 /// when referenced -- this amounts to a check for whether `T:
0 commit comments