12
12
13
13
use middle:: ty;
14
14
use middle:: ty_fold;
15
- use middle:: ty_fold:: TypeFolder ;
15
+ use middle:: ty_fold:: { TypeFoldable , TypeFolder } ;
16
16
use util:: ppaux:: Repr ;
17
17
18
- use std:: rc:: Rc ;
19
18
use syntax:: codemap:: Span ;
20
- use syntax:: owned_slice:: OwnedSlice ;
21
19
22
20
///////////////////////////////////////////////////////////////////////////
23
21
// Public trait `Subst`
24
22
//
25
23
// Just call `foo.subst(tcx, substs)` to perform a substitution across
26
- // `foo`.
27
- // Or use `foo.subst_spanned(tcx, substs, Some(span))` when there is more
28
- // information available (for better errors).
24
+ // `foo`. Or use `foo.subst_spanned(tcx, substs, Some(span))` when
25
+ // there is more information available (for better errors).
29
26
30
27
pub trait Subst {
31
28
fn subst ( & self , tcx : & ty:: ctxt , substs : & ty:: substs ) -> Self {
32
29
self . subst_spanned ( tcx, substs, None )
33
30
}
31
+
34
32
fn subst_spanned ( & self , tcx : & ty:: ctxt ,
35
33
substs : & ty:: substs ,
36
- span : Option < Span > ) -> Self ;
34
+ span : Option < Span > )
35
+ -> Self ;
37
36
}
38
37
39
- ///////////////////////////////////////////////////////////////////////////
40
- // Substitution over types
41
- //
42
- // Because this is so common, we make a special optimization to avoid
43
- // doing anything if `substs` is a no-op. I tried to generalize these
44
- // to all subst methods but ran into trouble due to the limitations of
45
- // our current method/trait matching algorithm. - Niko
46
-
47
- impl Subst for ty:: t {
48
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
38
+ impl < T : TypeFoldable > Subst for T {
39
+ fn subst_spanned ( & self ,
40
+ tcx : & ty:: ctxt ,
49
41
substs : & ty:: substs ,
50
- span : Option < Span > ) -> ty:: t {
51
- if ty:: substs_is_noop ( substs) && !ty:: type_has_params ( * self ) {
52
- * self
53
- } else {
54
- let mut folder = SubstFolder {
55
- tcx : tcx,
56
- substs : substs,
57
- span : span,
58
- root_ty : Some ( * self )
59
- } ;
60
- folder. fold_ty ( * self )
61
- }
42
+ span : Option < Span > )
43
+ -> T
44
+ {
45
+ let mut folder = SubstFolder { tcx : tcx,
46
+ substs : substs,
47
+ span : span,
48
+ root_ty : None ,
49
+ ty_stack_depth : 0 } ;
50
+ ( * self ) . fold_with ( & mut folder)
62
51
}
63
52
}
64
53
54
+ ///////////////////////////////////////////////////////////////////////////
55
+ // The actual substitution engine itself is a type folder.
56
+
65
57
struct SubstFolder < ' a > {
66
58
tcx : & ' a ty:: ctxt ,
67
59
substs : & ' a ty:: substs ,
@@ -70,23 +62,50 @@ struct SubstFolder<'a> {
70
62
span : Option < Span > ,
71
63
72
64
// The root type that is being substituted, if available.
73
- root_ty : Option < ty:: t >
65
+ root_ty : Option < ty:: t > ,
66
+
67
+ // Depth of type stack
68
+ ty_stack_depth : uint ,
74
69
}
75
70
76
71
impl < ' a > TypeFolder for SubstFolder < ' a > {
77
72
fn tcx < ' a > ( & ' a self ) -> & ' a ty:: ctxt { self . tcx }
78
73
79
74
fn fold_region ( & mut self , r : ty:: Region ) -> ty:: Region {
80
- r. subst ( self . tcx , self . substs )
75
+ // Note: This routine only handles regions that are bound on
76
+ // type declarations and other outer declarations, not those
77
+ // bound in *fn types*. Region substitution of the bound
78
+ // regions that appear in a function signature is done using
79
+ // the specialized routine
80
+ // `middle::typeck::check::regionmanip::replace_late_regions_in_fn_sig()`.
81
+ match r {
82
+ ty:: ReEarlyBound ( _, i, _) => {
83
+ match self . substs . regions {
84
+ ty:: ErasedRegions => ty:: ReStatic ,
85
+ ty:: NonerasedRegions ( ref regions) => * regions. get ( i) ,
86
+ }
87
+ }
88
+ _ => r
89
+ }
81
90
}
82
91
83
92
fn fold_ty ( & mut self , t : ty:: t ) -> ty:: t {
84
93
if !ty:: type_needs_subst ( t) {
85
94
return t;
86
95
}
87
96
88
- match ty:: get ( t) . sty {
97
+ // track the root type we were asked to substitute
98
+ let depth = self . ty_stack_depth ;
99
+ if depth == 0 {
100
+ self . root_ty = Some ( t) ;
101
+ }
102
+ self . ty_stack_depth += 1 ;
103
+
104
+ let t1 = match ty:: get ( t) . sty {
89
105
ty:: ty_param( p) => {
106
+ // FIXME -- This...really shouldn't happen. We should
107
+ // never be substituting without knowing what's in
108
+ // scope and knowing that the indices will line up!
90
109
if p. idx < self . substs . tps . len ( ) {
91
110
* self . substs . tps . get ( p. idx )
92
111
} else {
@@ -124,189 +143,14 @@ impl<'a> TypeFolder for SubstFolder<'a> {
124
143
}
125
144
}
126
145
_ => ty_fold:: super_fold_ty ( self , t)
127
- }
128
- }
129
- }
130
-
131
- ///////////////////////////////////////////////////////////////////////////
132
- // Other types
133
-
134
- impl < T : Subst > Subst for Vec < T > {
135
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
136
- substs : & ty:: substs ,
137
- span : Option < Span > ) -> Vec < T > {
138
- self . iter ( ) . map ( |t| t. subst_spanned ( tcx, substs, span) ) . collect ( )
139
- }
140
- }
141
- impl < T : Subst > Subst for Rc < T > {
142
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
143
- substs : & ty:: substs ,
144
- span : Option < Span > ) -> Rc < T > {
145
- Rc :: new ( ( * * self ) . subst_spanned ( tcx, substs, span) )
146
- }
147
- }
148
-
149
- impl < T : Subst > Subst for OwnedSlice < T > {
150
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
151
- substs : & ty:: substs ,
152
- span : Option < Span > ) -> OwnedSlice < T > {
153
- self . map ( |t| t. subst_spanned ( tcx, substs, span) )
154
- }
155
- }
156
-
157
- impl < T : Subst + ' static > Subst for @T {
158
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
159
- substs : & ty:: substs ,
160
- span : Option < Span > ) -> @T {
161
- match self {
162
- t => @( * * t) . subst_spanned ( tcx, substs, span)
163
- }
164
- }
165
- }
166
-
167
- impl < T : Subst > Subst for Option < T > {
168
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
169
- substs : & ty:: substs ,
170
- span : Option < Span > ) -> Option < T > {
171
- self . as_ref ( ) . map ( |t| t. subst_spanned ( tcx, substs, span) )
172
- }
173
- }
174
-
175
- impl Subst for ty:: TraitRef {
176
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
177
- substs : & ty:: substs ,
178
- span : Option < Span > ) -> ty:: TraitRef {
179
- ty:: TraitRef {
180
- def_id : self . def_id ,
181
- substs : self . substs . subst_spanned ( tcx, substs, span)
182
- }
183
- }
184
- }
185
-
186
- impl Subst for ty:: substs {
187
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
188
- substs : & ty:: substs ,
189
- span : Option < Span > ) -> ty:: substs {
190
- ty:: substs {
191
- regions : self . regions . subst_spanned ( tcx, substs, span) ,
192
- self_ty : self . self_ty . map ( |typ| typ. subst_spanned ( tcx, substs, span) ) ,
193
- tps : self . tps . iter ( ) . map ( |typ| typ. subst_spanned ( tcx, substs, span) ) . collect ( )
194
- }
195
- }
196
- }
197
-
198
- impl Subst for ty:: ItemSubsts {
199
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
200
- substs : & ty:: substs ,
201
- span : Option < Span > )
202
- -> ty:: ItemSubsts {
203
- ty:: ItemSubsts {
204
- substs : self . substs . subst_spanned ( tcx, substs, span)
205
- }
206
- }
207
- }
208
-
209
- impl Subst for ty:: RegionSubsts {
210
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
211
- substs : & ty:: substs ,
212
- span : Option < Span > ) -> ty:: RegionSubsts {
213
- match * self {
214
- ty:: ErasedRegions => {
215
- ty:: ErasedRegions
216
- }
217
- ty:: NonerasedRegions ( ref regions) => {
218
- ty:: NonerasedRegions ( regions. subst_spanned ( tcx, substs, span) )
219
- }
220
- }
221
- }
222
- }
223
-
224
- impl Subst for ty:: BareFnTy {
225
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
226
- substs : & ty:: substs ,
227
- span : Option < Span > ) -> ty:: BareFnTy {
228
- let mut folder = SubstFolder {
229
- tcx : tcx,
230
- substs : substs,
231
- span : span,
232
- root_ty : None
233
146
} ;
234
- folder. fold_bare_fn_ty ( self )
235
- }
236
- }
237
147
238
- impl Subst for ty:: ParamBounds {
239
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
240
- substs : & ty:: substs ,
241
- span : Option < Span > ) -> ty:: ParamBounds {
242
- ty:: ParamBounds {
243
- builtin_bounds : self . builtin_bounds ,
244
- trait_bounds : self . trait_bounds . subst_spanned ( tcx, substs, span)
148
+ assert_eq ! ( depth + 1 , self . ty_stack_depth) ;
149
+ self . ty_stack_depth -= 1 ;
150
+ if depth == 0 {
151
+ self . root_ty = None ;
245
152
}
246
- }
247
- }
248
153
249
- impl Subst for ty:: TypeParameterDef {
250
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
251
- substs : & ty:: substs ,
252
- span : Option < Span > ) -> ty:: TypeParameterDef {
253
- ty:: TypeParameterDef {
254
- ident : self . ident ,
255
- def_id : self . def_id ,
256
- bounds : self . bounds . subst_spanned ( tcx, substs, span) ,
257
- default : self . default . map ( |x| x. subst_spanned ( tcx, substs, span) )
258
- }
259
- }
260
- }
261
-
262
- impl Subst for ty:: Generics {
263
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
264
- substs : & ty:: substs ,
265
- span : Option < Span > ) -> ty:: Generics {
266
- ty:: Generics {
267
- type_param_defs : self . type_param_defs . subst_spanned ( tcx, substs, span) ,
268
- region_param_defs : self . region_param_defs . subst_spanned ( tcx, substs, span) ,
269
- }
270
- }
271
- }
272
-
273
- impl Subst for ty:: RegionParameterDef {
274
- fn subst_spanned ( & self , _: & ty:: ctxt ,
275
- _: & ty:: substs ,
276
- _: Option < Span > ) -> ty:: RegionParameterDef {
277
- * self
278
- }
279
- }
280
-
281
- impl Subst for ty:: Region {
282
- fn subst_spanned ( & self , _tcx : & ty:: ctxt ,
283
- substs : & ty:: substs ,
284
- _: Option < Span > ) -> ty:: Region {
285
- // Note: This routine only handles regions that are bound on
286
- // type declarations and other outer declarations, not those
287
- // bound in *fn types*. Region substitution of the bound
288
- // regions that appear in a function signature is done using
289
- // the specialized routine
290
- // `middle::typeck::check::regionmanip::replace_late_regions_in_fn_sig()`.
291
- match self {
292
- & ty:: ReEarlyBound ( _, i, _) => {
293
- match substs. regions {
294
- ty:: ErasedRegions => ty:: ReStatic ,
295
- ty:: NonerasedRegions ( ref regions) => * regions. get ( i) ,
296
- }
297
- }
298
- _ => * self
299
- }
300
- }
301
- }
302
-
303
- impl Subst for ty:: ty_param_bounds_and_ty {
304
- fn subst_spanned ( & self , tcx : & ty:: ctxt ,
305
- substs : & ty:: substs ,
306
- span : Option < Span > ) -> ty:: ty_param_bounds_and_ty {
307
- ty:: ty_param_bounds_and_ty {
308
- generics : self . generics . subst_spanned ( tcx, substs, span) ,
309
- ty : self . ty . subst_spanned ( tcx, substs, span)
310
- }
154
+ t1
311
155
}
312
156
}
0 commit comments