@@ -7,15 +7,15 @@ use hir::{self, Node};
77use ich:: NodeIdHashingMode ;
88use traits:: { self , ObligationCause } ;
99use ty:: { self , Ty , TyCtxt , GenericParamDefKind , TypeFoldable } ;
10- use ty:: subst:: { Substs , UnpackedKind } ;
10+ use ty:: subst:: { Subst , Substs , UnpackedKind } ;
1111use ty:: query:: TyCtxtAt ;
1212use ty:: TyKind :: * ;
1313use ty:: layout:: { Integer , IntegerExt } ;
1414use util:: common:: ErrorReported ;
1515use middle:: lang_items;
1616
1717use rustc_data_structures:: stable_hasher:: { StableHasher , HashStable } ;
18- use rustc_data_structures:: fx:: FxHashMap ;
18+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
1919use std:: { cmp, fmt} ;
2020use syntax:: ast;
2121use syntax:: attr:: { self , SignedInt , UnsignedInt } ;
@@ -618,6 +618,76 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
618618 }
619619 }
620620 }
621+
622+ /// Expands the given impl trait type, stopping if the type is recursive.
623+ pub fn try_expand_impl_trait_type (
624+ self ,
625+ def_id : DefId ,
626+ substs : & ' tcx Substs < ' tcx > ,
627+ ) -> Result < Ty < ' tcx > , Ty < ' tcx > > {
628+ use crate :: ty:: fold:: TypeFolder ;
629+
630+ struct OpaqueTypeExpander < ' a , ' gcx , ' tcx > {
631+ // Contains the DefIds of the opaque types that are currently being
632+ // expanded. When we expand an opaque type we insert the DefId of
633+ // that type, and when we finish expanding that type we remove the
634+ // its DefId.
635+ seen_opaque_tys : FxHashSet < DefId > ,
636+ primary_def_id : DefId ,
637+ found_recursion : bool ,
638+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
639+ }
640+
641+ impl < ' a , ' gcx , ' tcx > OpaqueTypeExpander < ' a , ' gcx , ' tcx > {
642+ fn expand_opaque_ty (
643+ & mut self ,
644+ def_id : DefId ,
645+ substs : & ' tcx Substs < ' tcx > ,
646+ ) -> Option < Ty < ' tcx > > {
647+ if self . found_recursion {
648+ None
649+ } else if self . seen_opaque_tys . insert ( def_id) {
650+ let generic_ty = self . tcx . type_of ( def_id) ;
651+ let concrete_ty = generic_ty. subst ( self . tcx , substs) ;
652+ let expanded_ty = self . fold_ty ( concrete_ty) ;
653+ self . seen_opaque_tys . remove ( & def_id) ;
654+ Some ( expanded_ty)
655+ } else {
656+ // If another opaque type that we contain is recursive, then it
657+ // will report the error, so we don't have to.
658+ self . found_recursion = def_id == self . primary_def_id ;
659+ None
660+ }
661+ }
662+ }
663+
664+ impl < ' a , ' gcx , ' tcx > TypeFolder < ' gcx , ' tcx > for OpaqueTypeExpander < ' a , ' gcx , ' tcx > {
665+ fn tcx ( & self ) -> TyCtxt < ' _ , ' gcx , ' tcx > {
666+ self . tcx
667+ }
668+
669+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
670+ if let ty:: Opaque ( def_id, substs) = t. sty {
671+ self . expand_opaque_ty ( def_id, substs) . unwrap_or ( t)
672+ } else {
673+ t. super_fold_with ( self )
674+ }
675+ }
676+ }
677+
678+ let mut visitor = OpaqueTypeExpander {
679+ seen_opaque_tys : FxHashSet :: default ( ) ,
680+ primary_def_id : def_id,
681+ found_recursion : false ,
682+ tcx : self ,
683+ } ;
684+ let expanded_type = visitor. expand_opaque_ty ( def_id, substs) . unwrap ( ) ;
685+ if visitor. found_recursion {
686+ Err ( expanded_type)
687+ } else {
688+ Ok ( expanded_type)
689+ }
690+ }
621691}
622692
623693impl < ' a , ' tcx > ty:: TyS < ' tcx > {
0 commit comments