11//! An iterator over the type substructure.
22//! WARNING: this does not keep track of the region depth.
33
4+ use crate :: ty:: subst:: { GenericArg , GenericArgKind } ;
45use crate :: ty:: { self , Ty } ;
56use smallvec:: { self , SmallVec } ;
67
78// The TypeWalker's stack is hot enough that it's worth going to some effort to
89// avoid heap allocations.
9- pub type TypeWalkerArray < ' tcx > = [ Ty < ' tcx > ; 8 ] ;
10- pub type TypeWalkerStack < ' tcx > = SmallVec < TypeWalkerArray < ' tcx > > ;
10+ type TypeWalkerStack < ' tcx > = SmallVec < [ GenericArg < ' tcx > ; 8 ] > ;
1111
1212pub struct TypeWalker < ' tcx > {
1313 stack : TypeWalkerStack < ' tcx > ,
1414 last_subtree : usize ,
1515}
1616
1717impl < ' tcx > TypeWalker < ' tcx > {
18- pub fn new ( ty : Ty < ' tcx > ) -> TypeWalker < ' tcx > {
19- TypeWalker { stack : smallvec ! [ ty ] , last_subtree : 1 }
18+ pub fn new ( root : GenericArg < ' tcx > ) -> TypeWalker < ' tcx > {
19+ TypeWalker { stack : smallvec ! [ root ] , last_subtree : 1 }
2020 }
2121
22- /// Skips the subtree of types corresponding to the last type
22+ /// Skips the subtree corresponding to the last type
2323 /// returned by `next()`.
2424 ///
2525 /// Example: Imagine you are walking `Foo<Bar<int>, usize>`.
@@ -41,98 +41,120 @@ impl<'tcx> Iterator for TypeWalker<'tcx> {
4141
4242 fn next ( & mut self ) -> Option < Ty < ' tcx > > {
4343 debug ! ( "next(): stack={:?}" , self . stack) ;
44- match self . stack . pop ( ) {
45- None => None ,
46- Some ( ty) => {
47- self . last_subtree = self . stack . len ( ) ;
48- push_subtypes ( & mut self . stack , ty) ;
49- debug ! ( "next: stack={:?}" , self . stack) ;
50- Some ( ty)
44+ while let Some ( next) = self . stack . pop ( ) {
45+ self . last_subtree = self . stack . len ( ) ;
46+ push_inner ( & mut self . stack , next) ;
47+ debug ! ( "next: stack={:?}" , self . stack) ;
48+
49+ // FIXME(eddyb) remove this filter and expose all `GenericArg`s.
50+ match next. unpack ( ) {
51+ GenericArgKind :: Type ( ty) => return Some ( ty) ,
52+ GenericArgKind :: Lifetime ( _) | GenericArgKind :: Const ( _) => { }
5153 }
5254 }
55+
56+ None
5357 }
5458}
5559
56- pub fn walk_shallow ( ty : Ty < ' _ > ) -> smallvec :: IntoIter < TypeWalkerArray < ' _ > > {
60+ pub fn walk_shallow ( parent : GenericArg < ' tcx > ) -> impl Iterator < Item = Ty < ' tcx > > {
5761 let mut stack = SmallVec :: new ( ) ;
58- push_subtypes ( & mut stack, ty) ;
59- stack. into_iter ( )
62+ push_inner ( & mut stack, parent) ;
63+ stack. into_iter ( ) . filter_map ( |child| {
64+ // FIXME(eddyb) remove this filter and expose all `GenericArg`s.
65+ match child. unpack ( ) {
66+ GenericArgKind :: Type ( ty) => Some ( ty) ,
67+ GenericArgKind :: Lifetime ( _) | GenericArgKind :: Const ( _) => None ,
68+ }
69+ } )
6070}
6171
62- // We push types on the stack in reverse order so as to
72+ // We push `GenericArg`s on the stack in reverse order so as to
6373// maintain a pre-order traversal. As of the time of this
6474// writing, the fact that the traversal is pre-order is not
6575// known to be significant to any code, but it seems like the
6676// natural order one would expect (basically, the order of the
6777// types as they are written).
68- fn push_subtypes < ' tcx > ( stack : & mut TypeWalkerStack < ' tcx > , parent_ty : Ty < ' tcx > ) {
69- match parent_ty. kind {
70- ty:: Bool
71- | ty:: Char
72- | ty:: Int ( _)
73- | ty:: Uint ( _)
74- | ty:: Float ( _)
75- | ty:: Str
76- | ty:: Infer ( _)
77- | ty:: Param ( _)
78- | ty:: Never
79- | ty:: Error
80- | ty:: Placeholder ( ..)
81- | ty:: Bound ( ..)
82- | ty:: Foreign ( ..) => { }
83- ty:: Array ( ty, len) => {
84- if let ty:: ConstKind :: Unevaluated ( _, substs, promoted) = len. val {
85- assert ! ( promoted. is_none( ) ) ;
86- stack. extend ( substs. types ( ) . rev ( ) ) ;
78+ fn push_inner < ' tcx > ( stack : & mut TypeWalkerStack < ' tcx > , parent : GenericArg < ' tcx > ) {
79+ match parent. unpack ( ) {
80+ GenericArgKind :: Type ( parent_ty) => match parent_ty. kind {
81+ ty:: Bool
82+ | ty:: Char
83+ | ty:: Int ( _)
84+ | ty:: Uint ( _)
85+ | ty:: Float ( _)
86+ | ty:: Str
87+ | ty:: Infer ( _)
88+ | ty:: Param ( _)
89+ | ty:: Never
90+ | ty:: Error
91+ | ty:: Placeholder ( ..)
92+ | ty:: Bound ( ..)
93+ | ty:: Foreign ( ..) => { }
94+
95+ ty:: Array ( ty, len) => {
96+ stack. push ( len. into ( ) ) ;
97+ stack. push ( ty. into ( ) ) ;
8798 }
88- stack. push ( len. ty ) ;
89- stack. push ( ty) ;
90- }
91- ty:: Slice ( ty) => {
92- stack. push ( ty) ;
93- }
94- ty:: RawPtr ( ref mt) => {
95- stack. push ( mt. ty ) ;
96- }
97- ty:: Ref ( _, ty, _) => {
98- stack. push ( ty) ;
99- }
100- ty:: Projection ( ref data) | ty:: UnnormalizedProjection ( ref data) => {
101- stack. extend ( data. substs . types ( ) . rev ( ) ) ;
102- }
103- ty:: Dynamic ( ref obj, ..) => {
104- stack. extend ( obj. iter ( ) . rev ( ) . flat_map ( |predicate| {
105- let ( substs, opt_ty) = match * predicate. skip_binder ( ) {
106- ty:: ExistentialPredicate :: Trait ( tr) => ( tr. substs , None ) ,
107- ty:: ExistentialPredicate :: Projection ( p) => ( p. substs , Some ( p. ty ) ) ,
108- ty:: ExistentialPredicate :: AutoTrait ( _) =>
109- // Empty iterator
110- {
111- ( ty:: InternalSubsts :: empty ( ) , None )
112- }
113- } ;
99+ ty:: Slice ( ty) => {
100+ stack. push ( ty. into ( ) ) ;
101+ }
102+ ty:: RawPtr ( mt) => {
103+ stack. push ( mt. ty . into ( ) ) ;
104+ }
105+ ty:: Ref ( lt, ty, _) => {
106+ stack. push ( ty. into ( ) ) ;
107+ stack. push ( lt. into ( ) ) ;
108+ }
109+ ty:: Projection ( data) | ty:: UnnormalizedProjection ( data) => {
110+ stack. extend ( data. substs . iter ( ) . copied ( ) . rev ( ) ) ;
111+ }
112+ ty:: Dynamic ( obj, lt) => {
113+ stack. push ( lt. into ( ) ) ;
114+ stack. extend ( obj. iter ( ) . rev ( ) . flat_map ( |predicate| {
115+ let ( substs, opt_ty) = match * predicate. skip_binder ( ) {
116+ ty:: ExistentialPredicate :: Trait ( tr) => ( tr. substs , None ) ,
117+ ty:: ExistentialPredicate :: Projection ( p) => ( p. substs , Some ( p. ty ) ) ,
118+ ty:: ExistentialPredicate :: AutoTrait ( _) =>
119+ // Empty iterator
120+ {
121+ ( ty:: InternalSubsts :: empty ( ) , None )
122+ }
123+ } ;
114124
115- substs. types ( ) . rev ( ) . chain ( opt_ty)
116- } ) ) ;
117- }
118- ty:: Adt ( _, substs) | ty:: Opaque ( _, substs) => {
119- stack. extend ( substs. types ( ) . rev ( ) ) ;
120- }
121- ty:: Closure ( _, ref substs) | ty:: Generator ( _, ref substs, _) => {
122- stack. extend ( substs. types ( ) . rev ( ) ) ;
123- }
124- ty:: GeneratorWitness ( ts) => {
125- stack. extend ( ts. skip_binder ( ) . iter ( ) . cloned ( ) . rev ( ) ) ;
126- }
127- ty:: Tuple ( ..) => {
128- stack. extend ( parent_ty. tuple_fields ( ) . rev ( ) ) ;
129- }
130- ty:: FnDef ( _, substs) => {
131- stack. extend ( substs. types ( ) . rev ( ) ) ;
132- }
133- ty:: FnPtr ( sig) => {
134- stack. push ( sig. skip_binder ( ) . output ( ) ) ;
135- stack. extend ( sig. skip_binder ( ) . inputs ( ) . iter ( ) . cloned ( ) . rev ( ) ) ;
125+ substs. iter ( ) . copied ( ) . rev ( ) . chain ( opt_ty. map ( |ty| ty. into ( ) ) )
126+ } ) ) ;
127+ }
128+ ty:: Adt ( _, substs)
129+ | ty:: Opaque ( _, substs)
130+ | ty:: Closure ( _, substs)
131+ | ty:: Generator ( _, substs, _)
132+ | ty:: Tuple ( substs)
133+ | ty:: FnDef ( _, substs) => {
134+ stack. extend ( substs. iter ( ) . copied ( ) . rev ( ) ) ;
135+ }
136+ ty:: GeneratorWitness ( ts) => {
137+ stack. extend ( ts. skip_binder ( ) . iter ( ) . cloned ( ) . rev ( ) . map ( |ty| ty. into ( ) ) ) ;
138+ }
139+ ty:: FnPtr ( sig) => {
140+ stack. push ( sig. skip_binder ( ) . output ( ) . into ( ) ) ;
141+ stack. extend ( sig. skip_binder ( ) . inputs ( ) . iter ( ) . cloned ( ) . rev ( ) . map ( |ty| ty. into ( ) ) ) ;
142+ }
143+ } ,
144+ GenericArgKind :: Lifetime ( _) => { }
145+ GenericArgKind :: Const ( parent_ct) => {
146+ stack. push ( parent_ct. ty . into ( ) ) ;
147+ match parent_ct. val {
148+ ty:: ConstKind :: Infer ( _)
149+ | ty:: ConstKind :: Param ( _)
150+ | ty:: ConstKind :: Placeholder ( _)
151+ | ty:: ConstKind :: Bound ( ..)
152+ | ty:: ConstKind :: Value ( _) => { }
153+
154+ ty:: ConstKind :: Unevaluated ( _, substs, _) => {
155+ stack. extend ( substs. iter ( ) . copied ( ) . rev ( ) ) ;
156+ }
157+ }
136158 }
137159 }
138160}
0 commit comments