@@ -107,12 +107,12 @@ use std::rc::Rc;
107
107
/// Either a sequence of token trees or a single one. This is used as the representation of the
108
108
/// sequence of tokens that make up a matcher.
109
109
#[ derive( Clone ) ]
110
- enum TokenTreeOrTokenTreeSlice < ' a > {
110
+ enum TokenTreeOrTokenTreeSlice < ' tt > {
111
111
Tt ( TokenTree ) ,
112
- TtSeq ( & ' a [ TokenTree ] ) ,
112
+ TtSeq ( & ' tt [ TokenTree ] ) ,
113
113
}
114
114
115
- impl < ' a > TokenTreeOrTokenTreeSlice < ' a > {
115
+ impl < ' tt > TokenTreeOrTokenTreeSlice < ' tt > {
116
116
/// Returns the number of constituent top-level token trees of `self` (top-level in that it
117
117
/// will not recursively descend into subtrees).
118
118
fn len ( & self ) -> usize {
@@ -136,23 +136,41 @@ impl<'a> TokenTreeOrTokenTreeSlice<'a> {
136
136
/// This is used by `inner_parse_loop` to keep track of delimited submatchers that we have
137
137
/// descended into.
138
138
#[ derive( Clone ) ]
139
- struct MatcherTtFrame < ' a > {
139
+ struct MatcherTtFrame < ' tt > {
140
140
/// The "parent" matcher that we are descending into.
141
- elts : TokenTreeOrTokenTreeSlice < ' a > ,
141
+ elts : TokenTreeOrTokenTreeSlice < ' tt > ,
142
142
/// The position of the "dot" in `elts` at the time we descended.
143
143
idx : usize ,
144
144
}
145
145
146
146
type NamedMatchVec = SmallVec < [ NamedMatch ; 4 ] > ;
147
147
148
- /// Represents a single "position" (aka "matcher position", aka "item"), as described in the module
149
- /// documentation.
148
+ /// Represents a single "position" (aka "matcher position", aka "item"), as
149
+ /// described in the module documentation.
150
+ ///
151
+ /// Here:
152
+ ///
153
+ /// - `'root` represents the lifetime of the stack slot that holds the root
154
+ /// `MatcherPos`. As described in `MatcherPosHandle`, the root `MatcherPos`
155
+ /// structure is stored on the stack, but subsequent instances are put into
156
+ /// the heap.
157
+ /// - `'tt` represents the lifetime of the token trees that this matcher
158
+ /// position refers to.
159
+ ///
160
+ /// It is important to distinguish these two lifetimes because we have a
161
+ /// `SmallVec<TokenTreeOrTokenTreeSlice<'tt>>` below, and the destructor of
162
+ /// that is considered to possibly access the data from its elements (it lacks
163
+ /// a `#[may_dangle]` attribute). As a result, the compiler needs to know that
164
+ /// all the elements in that `SmallVec` strictly outlive the root stack slot
165
+ /// lifetime. By separating `'tt` from `'root`, we can show that.
150
166
#[ derive( Clone ) ]
151
- struct MatcherPos < ' a > {
167
+ struct MatcherPos < ' root , ' tt : ' root > {
152
168
/// The token or sequence of tokens that make up the matcher
153
- top_elts : TokenTreeOrTokenTreeSlice < ' a > ,
169
+ top_elts : TokenTreeOrTokenTreeSlice < ' tt > ,
170
+
154
171
/// The position of the "dot" in this matcher
155
172
idx : usize ,
173
+
156
174
/// The first span of source source that the beginning of this matcher corresponds to. In other
157
175
/// words, the token in the source whose span is `sp_open` is matched against the first token of
158
176
/// the matcher.
@@ -182,26 +200,31 @@ struct MatcherPos<'a> {
182
200
/// in this matcher.
183
201
match_hi : usize ,
184
202
185
- // Specifically used if we are matching a repetition. If we aren't both should be `None`.
203
+ // The following fields are used if we are matching a repetition. If we aren't, they should be
204
+ // `None`.
205
+
186
206
/// The KleeneOp of this sequence if we are in a repetition.
187
207
seq_op : Option < quoted:: KleeneOp > ,
188
- /// The separator if we are in a repetition
208
+
209
+ /// The separator if we are in a repetition.
189
210
sep : Option < Token > ,
211
+
190
212
/// The "parent" matcher position if we are in a repetition. That is, the matcher position just
191
213
/// before we enter the sequence.
192
- up : Option < MatcherPosHandle < ' a > > ,
214
+ up : Option < MatcherPosHandle < ' root , ' tt > > ,
193
215
194
- // Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from
195
- // a delimited token tree (e.g. something wrapped in `(` `)`) or to get the contents of a doc
196
- // comment...
216
+ /// Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from
217
+ /// a delimited token tree (e.g. something wrapped in `(` `)`) or to get the contents of a doc
218
+ /// comment...
219
+ ///
197
220
/// When matching against matchers with nested delimited submatchers (e.g. `pat ( pat ( .. )
198
221
/// pat ) pat`), we need to keep track of the matchers we are descending into. This stack does
199
222
/// that where the bottom of the stack is the outermost matcher.
200
- // Also, throughout the comments, this "descent" is often referred to as "unzipping"...
201
- stack : Vec < MatcherTtFrame < ' a > > ,
223
+ /// Also, throughout the comments, this "descent" is often referred to as "unzipping"...
224
+ stack : SmallVec < [ MatcherTtFrame < ' tt > ; 1 ] > ,
202
225
}
203
226
204
- impl < ' a > MatcherPos < ' a > {
227
+ impl < ' root , ' tt > MatcherPos < ' root , ' tt > {
205
228
/// Add `m` as a named match for the `idx`-th metavar.
206
229
fn push_match ( & mut self , idx : usize , m : NamedMatch ) {
207
230
let matches = Rc :: make_mut ( & mut self . matches [ idx] ) ;
@@ -218,12 +241,12 @@ impl<'a> MatcherPos<'a> {
218
241
// Therefore, the initial MatcherPos is always allocated on the stack,
219
242
// subsequent ones (of which there aren't that many) are allocated on the heap,
220
243
// and this type is used to encapsulate both cases.
221
- enum MatcherPosHandle < ' a > {
222
- Ref ( & ' a mut MatcherPos < ' a > ) ,
223
- Box ( Box < MatcherPos < ' a > > ) ,
244
+ enum MatcherPosHandle < ' root , ' tt : ' root > {
245
+ Ref ( & ' root mut MatcherPos < ' root , ' tt > ) ,
246
+ Box ( Box < MatcherPos < ' root , ' tt > > ) ,
224
247
}
225
248
226
- impl < ' a > Clone for MatcherPosHandle < ' a > {
249
+ impl < ' root , ' tt > Clone for MatcherPosHandle < ' root , ' tt > {
227
250
// This always produces a new Box.
228
251
fn clone ( & self ) -> Self {
229
252
MatcherPosHandle :: Box ( match * self {
@@ -233,8 +256,8 @@ impl<'a> Clone for MatcherPosHandle<'a> {
233
256
}
234
257
}
235
258
236
- impl < ' a > Deref for MatcherPosHandle < ' a > {
237
- type Target = MatcherPos < ' a > ;
259
+ impl < ' root , ' tt > Deref for MatcherPosHandle < ' root , ' tt > {
260
+ type Target = MatcherPos < ' root , ' tt > ;
238
261
fn deref ( & self ) -> & Self :: Target {
239
262
match * self {
240
263
MatcherPosHandle :: Ref ( ref r) => r,
@@ -243,8 +266,8 @@ impl<'a> Deref for MatcherPosHandle<'a> {
243
266
}
244
267
}
245
268
246
- impl < ' a > DerefMut for MatcherPosHandle < ' a > {
247
- fn deref_mut ( & mut self ) -> & mut MatcherPos < ' a > {
269
+ impl < ' root , ' tt > DerefMut for MatcherPosHandle < ' root , ' tt > {
270
+ fn deref_mut ( & mut self ) -> & mut MatcherPos < ' root , ' tt > {
248
271
match * self {
249
272
MatcherPosHandle :: Ref ( ref mut r) => r,
250
273
MatcherPosHandle :: Box ( ref mut b) => b,
@@ -292,7 +315,7 @@ fn create_matches(len: usize) -> Box<[Rc<NamedMatchVec>]> {
292
315
293
316
/// Generate the top-level matcher position in which the "dot" is before the first token of the
294
317
/// matcher `ms` and we are going to start matching at the span `open` in the source.
295
- fn initial_matcher_pos ( ms : & [ TokenTree ] , open : Span ) -> MatcherPos {
318
+ fn initial_matcher_pos < ' root , ' tt > ( ms : & ' tt [ TokenTree ] , open : Span ) -> MatcherPos < ' root , ' tt > {
296
319
let match_idx_hi = count_names ( ms) ;
297
320
let matches = create_matches ( match_idx_hi) ;
298
321
MatcherPos {
@@ -312,7 +335,7 @@ fn initial_matcher_pos(ms: &[TokenTree], open: Span) -> MatcherPos {
312
335
match_hi : match_idx_hi,
313
336
314
337
// Haven't descended into any delimiters, so empty stack
315
- stack : vec ! [ ] ,
338
+ stack : smallvec ! [ ] ,
316
339
317
340
// Haven't descended into any sequences, so both of these are `None`.
318
341
seq_op : None ,
@@ -445,12 +468,12 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
445
468
/// # Returns
446
469
///
447
470
/// A `ParseResult`. Note that matches are kept track of through the items generated.
448
- fn inner_parse_loop < ' a > (
471
+ fn inner_parse_loop < ' root , ' tt > (
449
472
sess : & ParseSess ,
450
- cur_items : & mut SmallVec < [ MatcherPosHandle < ' a > ; 1 ] > ,
451
- next_items : & mut Vec < MatcherPosHandle < ' a > > ,
452
- eof_items : & mut SmallVec < [ MatcherPosHandle < ' a > ; 1 ] > ,
453
- bb_items : & mut SmallVec < [ MatcherPosHandle < ' a > ; 1 ] > ,
473
+ cur_items : & mut SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
474
+ next_items : & mut Vec < MatcherPosHandle < ' root , ' tt > > ,
475
+ eof_items : & mut SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
476
+ bb_items : & mut SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
454
477
token : & Token ,
455
478
span : syntax_pos:: Span ,
456
479
) -> ParseResult < ( ) > {
@@ -554,7 +577,7 @@ fn inner_parse_loop<'a>(
554
577
555
578
let matches = create_matches ( item. matches . len ( ) ) ;
556
579
cur_items. push ( MatcherPosHandle :: Box ( Box :: new ( MatcherPos {
557
- stack : vec ! [ ] ,
580
+ stack : smallvec ! [ ] ,
558
581
sep : seq. separator . clone ( ) ,
559
582
seq_op : Some ( seq. op ) ,
560
583
idx : 0 ,
0 commit comments