@@ -7,15 +7,15 @@ use hir::{self, Node};
7
7
use ich:: NodeIdHashingMode ;
8
8
use traits:: { self , ObligationCause } ;
9
9
use ty:: { self , Ty , TyCtxt , GenericParamDefKind , TypeFoldable } ;
10
- use ty:: subst:: { Substs , UnpackedKind } ;
10
+ use ty:: subst:: { Subst , Substs , UnpackedKind } ;
11
11
use ty:: query:: TyCtxtAt ;
12
12
use ty:: TyKind :: * ;
13
13
use ty:: layout:: { Integer , IntegerExt } ;
14
14
use util:: common:: ErrorReported ;
15
15
use middle:: lang_items;
16
16
17
17
use rustc_data_structures:: stable_hasher:: { StableHasher , HashStable } ;
18
- use rustc_data_structures:: fx:: FxHashMap ;
18
+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
19
19
use std:: { cmp, fmt} ;
20
20
use syntax:: ast;
21
21
use syntax:: attr:: { self , SignedInt , UnsignedInt } ;
@@ -618,6 +618,76 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
618
618
}
619
619
}
620
620
}
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
+ }
621
691
}
622
692
623
693
impl < ' a , ' tcx > ty:: TyS < ' tcx > {
0 commit comments