@@ -35,6 +35,7 @@ use rustc_hir as hir;
3535use rustc_hir:: def_id:: DefId ;
3636
3737use rustc_data_structures:: fx:: FxHashSet ;
38+ use rustc_data_structures:: sso:: SsoHashSet ;
3839use std:: collections:: BTreeMap ;
3940use std:: fmt;
4041use std:: ops:: ControlFlow ;
@@ -702,10 +703,109 @@ impl<'tcx> TyCtxt<'tcx> {
702703 r
703704 } )
704705 . 0 ,
706+ self ,
705707 )
706708 }
707709}
708710
711+ pub struct BoundVarsCollector < ' tcx > {
712+ binder_index : ty:: DebruijnIndex ,
713+ vars : BTreeMap < u32 , ty:: BoundVariableKind > ,
714+ // We may encounter the same variable at different levels of binding, so
715+ // this can't just be `Ty`
716+ visited : SsoHashSet < ( ty:: DebruijnIndex , Ty < ' tcx > ) > ,
717+ }
718+
719+ impl < ' tcx > BoundVarsCollector < ' tcx > {
720+ pub fn new ( ) -> Self {
721+ BoundVarsCollector {
722+ binder_index : ty:: INNERMOST ,
723+ vars : BTreeMap :: new ( ) ,
724+ visited : SsoHashSet :: default ( ) ,
725+ }
726+ }
727+
728+ pub fn into_vars ( self , tcx : TyCtxt < ' tcx > ) -> & ' tcx ty:: List < ty:: BoundVariableKind > {
729+ let max = self . vars . iter ( ) . map ( |( k, _) | * k) . max ( ) . unwrap_or_else ( || 0 ) ;
730+ for i in 0 ..max {
731+ if let None = self . vars . get ( & i) {
732+ panic ! ( "Unknown variable: {:?}" , i) ;
733+ }
734+ }
735+
736+ tcx. mk_bound_variable_kinds ( self . vars . into_iter ( ) . map ( |( _, v) | v) )
737+ }
738+ }
739+
740+ impl < ' tcx > TypeVisitor < ' tcx > for BoundVarsCollector < ' tcx > {
741+ type BreakTy = ( ) ;
742+
743+ fn visit_binder < T : TypeFoldable < ' tcx > > (
744+ & mut self ,
745+ t : & Binder < ' tcx , T > ,
746+ ) -> ControlFlow < Self :: BreakTy > {
747+ self . binder_index . shift_in ( 1 ) ;
748+ let result = t. super_visit_with ( self ) ;
749+ self . binder_index . shift_out ( 1 ) ;
750+ result
751+ }
752+
753+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
754+ if t. outer_exclusive_binder < self . binder_index
755+ || !self . visited . insert ( ( self . binder_index , t) )
756+ {
757+ return ControlFlow :: CONTINUE ;
758+ }
759+ use std:: collections:: btree_map:: Entry ;
760+ match * t. kind ( ) {
761+ ty:: Bound ( debruijn, bound_ty) if debruijn == self . binder_index => {
762+ match self . vars . entry ( bound_ty. var . as_u32 ( ) ) {
763+ Entry :: Vacant ( entry) => {
764+ entry. insert ( ty:: BoundVariableKind :: Ty ( bound_ty. kind ) ) ;
765+ }
766+ Entry :: Occupied ( entry) => match entry. get ( ) {
767+ ty:: BoundVariableKind :: Ty ( _) => { }
768+ _ => bug ! ( "Conflicting bound vars" ) ,
769+ } ,
770+ }
771+ }
772+
773+ _ => ( ) ,
774+ } ;
775+
776+ t. super_visit_with ( self )
777+ }
778+
779+ fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
780+ use std:: collections:: btree_map:: Entry ;
781+ match r {
782+ ty:: ReLateBound ( index, br) if * index == self . binder_index => match br. kind {
783+ ty:: BrNamed ( _def_id, _name) => {
784+ // FIXME
785+ }
786+
787+ ty:: BrAnon ( var) => match self . vars . entry ( var) {
788+ Entry :: Vacant ( entry) => {
789+ entry. insert ( ty:: BoundVariableKind :: Region ( br. kind ) ) ;
790+ }
791+ Entry :: Occupied ( entry) => match entry. get ( ) {
792+ ty:: BoundVariableKind :: Region ( _) => { }
793+ _ => bug ! ( "Conflicting bound vars" ) ,
794+ } ,
795+ } ,
796+
797+ ty:: BrEnv => {
798+ // FIXME
799+ }
800+ } ,
801+
802+ _ => ( ) ,
803+ } ;
804+
805+ r. super_visit_with ( self )
806+ }
807+ }
808+
709809///////////////////////////////////////////////////////////////////////////
710810// Shifter
711811//
@@ -907,57 +1007,6 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
9071007#[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
9081008struct FoundFlags ;
9091009
910- crate struct CountBoundVars {
911- crate outer_index : ty:: DebruijnIndex ,
912- crate bound_tys : FxHashSet < ty:: BoundTy > ,
913- crate bound_regions : FxHashSet < ty:: BoundRegion > ,
914- crate bound_consts : FxHashSet < ty:: BoundVar > ,
915- }
916-
917- impl < ' tcx > TypeVisitor < ' tcx > for CountBoundVars {
918- type BreakTy = ( ) ;
919-
920- fn visit_binder < T : TypeFoldable < ' tcx > > (
921- & mut self ,
922- t : & Binder < ' tcx , T > ,
923- ) -> ControlFlow < Self :: BreakTy > {
924- self . outer_index . shift_in ( 1 ) ;
925- let result = t. super_visit_with ( self ) ;
926- self . outer_index . shift_out ( 1 ) ;
927- result
928- }
929-
930- fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
931- match t. kind {
932- ty:: Bound ( debruijn, ty) if debruijn == self . outer_index => {
933- self . bound_tys . insert ( ty) ;
934- ControlFlow :: CONTINUE
935- }
936- _ => t. super_visit_with ( self ) ,
937- }
938- }
939-
940- fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
941- match r {
942- ty:: ReLateBound ( debruijn, re) if * debruijn == self . outer_index => {
943- self . bound_regions . insert ( * re) ;
944- ControlFlow :: CONTINUE
945- }
946- _ => r. super_visit_with ( self ) ,
947- }
948- }
949-
950- fn visit_const ( & mut self , ct : & ' tcx ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
951- match ct. val {
952- ty:: ConstKind :: Bound ( debruijn, c) if debruijn == self . outer_index => {
953- self . bound_consts . insert ( c) ;
954- ControlFlow :: CONTINUE
955- }
956- _ => ct. super_visit_with ( self ) ,
957- }
958- }
959- }
960-
9611010// FIXME: Optimize for checking for infer flags
9621011struct HasTypeFlagsVisitor {
9631012 flags : ty:: TypeFlags ,
0 commit comments