1
1
//! An iterator over the type substructure.
2
2
//! WARNING: this does not keep track of the region depth.
3
3
4
+ use crate :: ty:: subst:: { GenericArg , GenericArgKind } ;
4
5
use crate :: ty:: { self , Ty } ;
5
6
use smallvec:: { self , SmallVec } ;
6
7
7
8
// The TypeWalker's stack is hot enough that it's worth going to some effort to
8
9
// 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 ] > ;
11
11
12
12
pub struct TypeWalker < ' tcx > {
13
13
stack : TypeWalkerStack < ' tcx > ,
14
14
last_subtree : usize ,
15
15
}
16
16
17
17
impl < ' 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 }
20
20
}
21
21
22
- /// Skips the subtree of types corresponding to the last type
22
+ /// Skips the subtree corresponding to the last type
23
23
/// returned by `next()`.
24
24
///
25
25
/// Example: Imagine you are walking `Foo<Bar<int>, usize>`.
@@ -41,98 +41,120 @@ impl<'tcx> Iterator for TypeWalker<'tcx> {
41
41
42
42
fn next ( & mut self ) -> Option < Ty < ' tcx > > {
43
43
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 ( _) => { }
51
53
}
52
54
}
55
+
56
+ None
53
57
}
54
58
}
55
59
56
- pub fn walk_shallow ( ty : Ty < ' _ > ) -> smallvec :: IntoIter < TypeWalkerArray < ' _ > > {
60
+ pub fn walk_shallow ( parent : GenericArg < ' tcx > ) -> impl Iterator < Item = Ty < ' tcx > > {
57
61
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
+ } )
60
70
}
61
71
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
63
73
// maintain a pre-order traversal. As of the time of this
64
74
// writing, the fact that the traversal is pre-order is not
65
75
// known to be significant to any code, but it seems like the
66
76
// natural order one would expect (basically, the order of the
67
77
// 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 ( ) ) ;
87
98
}
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
+ } ;
114
124
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
+ }
136
158
}
137
159
}
138
160
}
0 commit comments