@@ -89,7 +89,6 @@ use rustc_span::symbol::Ident;
89
89
use std:: borrow:: Cow ;
90
90
use std:: collections:: hash_map:: Entry :: { Occupied , Vacant } ;
91
91
use std:: mem;
92
- use std:: ops:: { Deref , DerefMut } ;
93
92
94
93
// To avoid costly uniqueness checks, we require that `MatchSeq` always has a nonempty body.
95
94
@@ -136,24 +135,8 @@ type NamedMatchVec = SmallVec<[NamedMatch; 4]>;
136
135
137
136
/// Represents a single "position" (aka "matcher position", aka "item"), as
138
137
/// described in the module documentation.
139
- ///
140
- /// Here:
141
- ///
142
- /// - `'root` represents the lifetime of the stack slot that holds the root
143
- /// `MatcherPos`. As described in `MatcherPosHandle`, the root `MatcherPos`
144
- /// structure is stored on the stack, but subsequent instances are put into
145
- /// the heap.
146
- /// - `'tt` represents the lifetime of the token trees that this matcher
147
- /// position refers to.
148
- ///
149
- /// It is important to distinguish these two lifetimes because we have a
150
- /// `SmallVec<TokenTreeOrTokenTreeSlice<'tt>>` below, and the destructor of
151
- /// that is considered to possibly access the data from its elements (it lacks
152
- /// a `#[may_dangle]` attribute). As a result, the compiler needs to know that
153
- /// all the elements in that `SmallVec` strictly outlive the root stack slot
154
- /// lifetime. By separating `'tt` from `'root`, we can show that.
155
138
#[ derive( Clone ) ]
156
- struct MatcherPos < ' root , ' tt > {
139
+ struct MatcherPos < ' tt > {
157
140
/// The token or slice of tokens that make up the matcher. `elts` is short for "elements".
158
141
top_elts : TokenTreeOrTokenTreeSlice < ' tt > ,
159
142
@@ -185,7 +168,7 @@ struct MatcherPos<'root, 'tt> {
185
168
match_hi : usize ,
186
169
187
170
/// This field is only used if we are matching a repetition.
188
- repetition : Option < MatcherPosRepetition < ' root , ' tt > > ,
171
+ repetition : Option < MatcherPosRepetition < ' tt > > ,
189
172
190
173
/// Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from
191
174
/// a delimited token tree (e.g., something wrapped in `(` `)`) or to get the contents of a doc
@@ -200,9 +183,9 @@ struct MatcherPos<'root, 'tt> {
200
183
201
184
// This type is used a lot. Make sure it doesn't unintentionally get bigger.
202
185
#[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
203
- rustc_data_structures:: static_assert_size!( MatcherPos <' _, ' _ >, 240 ) ;
186
+ rustc_data_structures:: static_assert_size!( MatcherPos <' _>, 232 ) ;
204
187
205
- impl < ' root , ' tt > MatcherPos < ' root , ' tt > {
188
+ impl < ' tt > MatcherPos < ' tt > {
206
189
/// `len` `Vec`s (initially shared and empty) that will store matches of metavars.
207
190
fn create_matches ( len : usize ) -> Box < [ Lrc < NamedMatchVec > ] > {
208
191
if len == 0 {
@@ -241,11 +224,7 @@ impl<'root, 'tt> MatcherPos<'root, 'tt> {
241
224
}
242
225
}
243
226
244
- fn repetition (
245
- up : MatcherPosHandle < ' root , ' tt > ,
246
- sp : DelimSpan ,
247
- seq : Lrc < SequenceRepetition > ,
248
- ) -> Self {
227
+ fn repetition ( up : Box < MatcherPos < ' tt > > , sp : DelimSpan , seq : Lrc < SequenceRepetition > ) -> Self {
249
228
MatcherPos {
250
229
stack : smallvec ! [ ] ,
251
230
idx : 0 ,
@@ -270,7 +249,7 @@ impl<'root, 'tt> MatcherPos<'root, 'tt> {
270
249
}
271
250
272
251
#[ derive( Clone ) ]
273
- struct MatcherPosRepetition < ' root , ' tt > {
252
+ struct MatcherPosRepetition < ' tt > {
274
253
/// The KleeneOp of this sequence.
275
254
seq_op : mbe:: KleeneOp ,
276
255
@@ -279,55 +258,12 @@ struct MatcherPosRepetition<'root, 'tt> {
279
258
280
259
/// The "parent" matcher position. That is, the matcher position just before we enter the
281
260
/// sequence.
282
- up : MatcherPosHandle < ' root , ' tt > ,
283
- }
284
-
285
- // Lots of MatcherPos instances are created at runtime. Allocating them on the
286
- // heap is slow. Furthermore, using SmallVec<MatcherPos> to allocate them all
287
- // on the stack is also slow, because MatcherPos is quite a large type and
288
- // instances get moved around a lot between vectors, which requires lots of
289
- // slow memcpy calls.
290
- //
291
- // Therefore, the initial MatcherPos is always allocated on the stack,
292
- // subsequent ones (of which there aren't that many) are allocated on the heap,
293
- // and this type is used to encapsulate both cases.
294
- enum MatcherPosHandle < ' root , ' tt > {
295
- Ref ( & ' root mut MatcherPos < ' root , ' tt > ) ,
296
- Box ( Box < MatcherPos < ' root , ' tt > > ) ,
261
+ up : Box < MatcherPos < ' tt > > ,
297
262
}
298
263
299
- impl < ' root , ' tt > Clone for MatcherPosHandle < ' root , ' tt > {
300
- // This always produces a new Box.
301
- fn clone ( & self ) -> Self {
302
- MatcherPosHandle :: Box ( match * self {
303
- MatcherPosHandle :: Ref ( ref r) => Box :: new ( ( * * r) . clone ( ) ) ,
304
- MatcherPosHandle :: Box ( ref b) => b. clone ( ) ,
305
- } )
306
- }
307
- }
308
-
309
- impl < ' root , ' tt > Deref for MatcherPosHandle < ' root , ' tt > {
310
- type Target = MatcherPos < ' root , ' tt > ;
311
- fn deref ( & self ) -> & Self :: Target {
312
- match * self {
313
- MatcherPosHandle :: Ref ( ref r) => r,
314
- MatcherPosHandle :: Box ( ref b) => b,
315
- }
316
- }
317
- }
318
-
319
- impl < ' root , ' tt > DerefMut for MatcherPosHandle < ' root , ' tt > {
320
- fn deref_mut ( & mut self ) -> & mut MatcherPos < ' root , ' tt > {
321
- match * self {
322
- MatcherPosHandle :: Ref ( ref mut r) => r,
323
- MatcherPosHandle :: Box ( ref mut b) => b,
324
- }
325
- }
326
- }
327
-
328
- enum EofItems < ' root , ' tt > {
264
+ enum EofItems < ' tt > {
329
265
None ,
330
- One ( MatcherPosHandle < ' root , ' tt > ) ,
266
+ One ( Box < MatcherPos < ' tt > > ) ,
331
267
Multiple ,
332
268
}
333
269
@@ -494,6 +430,10 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
494
430
495
431
pub struct TtParser {
496
432
macro_name : Ident ,
433
+
434
+ cur_items : Vec < Box < MatcherPos < ' tt > > > ,
435
+ next_items : Vec < Box < MatcherPos < ' tt > > > ,
436
+ bb_items : Vec < Box < MatcherPos < ' tt > > > ,
497
437
}
498
438
499
439
impl TtParser {
@@ -520,13 +460,13 @@ impl TtParser {
520
460
///
521
461
/// `Some(result)` if everything is finished, `None` otherwise. Note that matches are kept
522
462
/// track of through the items generated.
523
- fn parse_tt_inner < ' root , ' tt > (
463
+ fn parse_tt_inner < ' tt > (
524
464
& self ,
525
465
sess : & ParseSess ,
526
466
ms : & [ TokenTree ] ,
527
- cur_items : & mut SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
528
- next_items : & mut SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
529
- bb_items : & mut SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
467
+ cur_items : & mut SmallVec < [ Box < MatcherPos < ' tt > > ; 1 ] > ,
468
+ next_items : & mut SmallVec < [ Box < MatcherPos < ' tt > > ; 1 ] > ,
469
+ bb_items : & mut SmallVec < [ Box < MatcherPos < ' tt > > ; 1 ] > ,
530
470
token : & Token ,
531
471
) -> Option < NamedParseResult > {
532
472
// Matcher positions that would be valid if the macro invocation was over now. Only
@@ -570,9 +510,7 @@ impl TtParser {
570
510
}
571
511
572
512
// Allow for the possibility of one or more matches of this sequence.
573
- cur_items. push ( MatcherPosHandle :: Box ( Box :: new ( MatcherPos :: repetition (
574
- item, sp, seq,
575
- ) ) ) ) ;
513
+ cur_items. push ( box MatcherPos :: repetition ( item, sp, seq) ) ;
576
514
}
577
515
578
516
TokenTree :: MetaVarDecl ( span, _, None ) => {
@@ -706,11 +644,7 @@ impl TtParser {
706
644
// `parse_tt_inner` then processes all of these possible matcher positions and produces
707
645
// possible next positions into `next_items`. After some post-processing, the contents of
708
646
// `next_items` replenish `cur_items` and we start over again.
709
- //
710
- // This MatcherPos instance is allocated on the stack. All others -- and there are
711
- // frequently *no* others! -- are allocated on the heap.
712
- let mut initial = MatcherPos :: new ( ms) ;
713
- let mut cur_items = smallvec ! [ MatcherPosHandle :: Ref ( & mut initial) ] ;
647
+ let mut cur_items = smallvec ! [ box MatcherPos :: new( ms) ] ;
714
648
715
649
loop {
716
650
let mut next_items = SmallVec :: new ( ) ;
@@ -793,10 +727,10 @@ impl TtParser {
793
727
}
794
728
}
795
729
796
- fn ambiguity_error < ' root , ' tt > (
730
+ fn ambiguity_error < ' tt > (
797
731
& self ,
798
- next_items : SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
799
- bb_items : SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
732
+ next_items : SmallVec < [ Box < MatcherPos < ' tt > > ; 1 ] > ,
733
+ bb_items : SmallVec < [ Box < MatcherPos < ' tt > > ; 1 ] > ,
800
734
token_span : rustc_span:: Span ,
801
735
) -> NamedParseResult {
802
736
let nts = bb_items
0 commit comments