@@ -97,7 +97,7 @@ impl SpanPos {
97
97
/// ex3b!(2);
98
98
/// ```
99
99
///
100
- /// In this example `ex3b!(2)` expands to `ex3a(2, 3)` which in turn expands to
100
+ /// In this example `ex3b!(2)` expands to `ex3a! (2, 3)` which in turn expands to
101
101
/// `2 + 3`. This expansion has three layers, first the root, which contains the
102
102
/// `ex3b!(2)` call. The next layer is the `ex3a!(2, 3)` call. The binary expression
103
103
/// comes from the third layer, the number 3 from the second, and the number 2 from
@@ -122,8 +122,8 @@ impl SpanPos {
122
122
///
123
123
/// This example expands `ex4a` into a new `ex4b` macro, which in turn expands
124
124
/// into a `4 + 4` expression. The [`Span`] of the binary expression has three
125
- /// layers. First the root layer calling the `ex4b` macro, this would then
126
- /// expand to the `4 + 4` expression, which actually comes from the `ex4a` expansion .
125
+ /// layers. First the root layer calling the `ex4b` macro, which calls the `ex4a`
126
+ /// macro, which inturn expands into the `4 + 4` expression.
127
127
///
128
128
/// ### Proc Macros
129
129
///
@@ -142,6 +142,7 @@ pub struct ExpnInfo<'ast> {
142
142
}
143
143
144
144
impl < ' ast > ExpnInfo < ' ast > {
145
+ /// This returns [`Some`] if this expansion comes from another expansion.
145
146
#[ must_use]
146
147
pub fn parent ( & self ) -> Option < & ExpnInfo < ' ast > > {
147
148
with_cx ( self , |cx| cx. span_expn_info ( self . parent ) )
@@ -204,7 +205,7 @@ pub struct Span<'ast> {
204
205
source_id : SpanSrcId ,
205
206
/// This information could also be retrieved, by requesting the [`ExpnInfo`]
206
207
/// of this span. However, from looking at Clippy and rustc lints, it looks
207
- /// like the main interested is, if this comes from a macro expansion, not from
208
+ /// like the main interest is, if this comes from a macro expansion, not from
208
209
/// which one. Having this boolean flag will be sufficient to answer this simple
209
210
/// question and will save on extra [`SpanSrcId`] mappings.
210
211
from_expansion : bool ,
@@ -226,8 +227,8 @@ impl<'ast> std::fmt::Debug for Span<'ast> {
226
227
SpanSource :: File ( file) => format ! (
227
228
"{}:{} - {}" ,
228
229
file. file( ) ,
229
- fmt_pos( file. to_file_pos ( self . start) ) ,
230
- fmt_pos( file. to_file_pos ( self . end) )
230
+ fmt_pos( file. try_to_file_pos ( self . start) ) ,
231
+ fmt_pos( file. try_to_file_pos ( self . end) )
231
232
) ,
232
233
SpanSource :: Macro ( expn) => format ! ( "[Inside Macro] {:#?}" , expn. call_site( ) ) ,
233
234
} ;
@@ -271,8 +272,12 @@ impl<'ast> Span<'ast> {
271
272
///
272
273
/// If you're planning to use this snippet in a suggestion, consider using
273
274
/// [`snippet_with_applicability`](Self::snippet_with_applicability) instead.
274
- pub fn snippet_or ( & self , default : & str ) -> String {
275
- self . snippet ( ) . unwrap_or ( default) . to_string ( )
275
+ pub fn snippet_or < ' a , ' b > ( & self , default : & ' a str ) -> & ' b str
276
+ where
277
+ ' a : ' b ,
278
+ ' ast : ' b ,
279
+ {
280
+ self . snippet ( ) . unwrap_or ( default)
276
281
}
277
282
278
283
/// Adjusts the given [`Applicability`] according to the context and returns the
@@ -288,26 +293,39 @@ impl<'ast> Span<'ast> {
288
293
/// your suggestion should have, and then use it with this snippet function
289
294
/// to adjust it accordingly. The applicability is then used to submit the
290
295
/// suggestion to the driver.
291
- pub fn snippet_with_applicability ( & self , placeholder : & str , applicability : & mut Applicability ) -> String {
296
+ ///
297
+ /// Here is an example, for constructing a string with two expressions `a` and `b`:
298
+ ///
299
+ /// ```rust,ignore
300
+ /// let mut app = Applicability::MachineApplicable;
301
+ /// let sugg = format!(
302
+ /// "{}..{}",
303
+ /// a.span().snippet_with_applicability("<expr-a>", &mut app),
304
+ /// b.span().snippet_with_applicability("<expr-b>", &mut app),
305
+ /// );
306
+ /// ```
307
+ pub fn snippet_with_applicability < ' a , ' b > ( & self , placeholder : & ' a str , applicability : & mut Applicability ) -> & ' b str
308
+ where
309
+ ' a : ' b ,
310
+ ' ast : ' b ,
311
+ {
292
312
if * applicability != Applicability :: Unspecified && self . is_from_expansion ( ) {
293
313
* applicability = Applicability :: MaybeIncorrect ;
294
314
}
295
- self . snippet ( )
296
- . unwrap_or_else ( || {
297
- if matches ! (
298
- * applicability,
299
- Applicability :: MachineApplicable | Applicability :: MaybeIncorrect
300
- ) {
301
- * applicability = Applicability :: HasPlaceholders ;
302
- }
303
- placeholder
304
- } )
305
- . to_string ( )
315
+ self . snippet ( ) . unwrap_or_else ( || {
316
+ if matches ! (
317
+ * applicability,
318
+ Applicability :: MachineApplicable | Applicability :: MaybeIncorrect
319
+ ) {
320
+ * applicability = Applicability :: HasPlaceholders ;
321
+ }
322
+ placeholder
323
+ } )
306
324
}
307
325
308
326
/// Returns the length of the this [`Span`] in bytes.
309
327
pub fn len ( & self ) -> usize {
310
- ( self . start . 0 - self . end . 0 )
328
+ ( self . end . 0 - self . start . 0 )
311
329
. try_into ( )
312
330
. expect ( "Marker is not compiled for usize::BITs < 32" )
313
331
}
@@ -388,7 +406,7 @@ impl<'ast> Span<'ast> {
388
406
389
407
#[ repr( C ) ]
390
408
#[ derive( Debug ) ]
391
- #[ allow ( clippy :: exhaustive_enums ) ]
409
+ #[ non_exhaustive ]
392
410
pub enum SpanSource < ' ast > {
393
411
File ( & ' ast FileInfo < ' ast > ) ,
394
412
Macro ( & ' ast ExpnInfo < ' ast > ) ,
@@ -406,11 +424,22 @@ impl<'ast> FileInfo<'ast> {
406
424
self . file . get ( )
407
425
}
408
426
409
- /// Maps the given [`SpanPos`] to a [`FilePos`]. The [`SpanPos`] has to correspond
410
- /// to a position that belongs to this [`FileInfo`].
411
- pub fn to_file_pos ( & self , span_pos : SpanPos ) -> Option < FilePos > {
427
+ /// Tries to map the given [`SpanPos`] to a [`FilePos`]. It will return [`None`]
428
+ /// if the given [`FilePos`] belongs to a different [`FileInfo`].
429
+ pub fn try_to_file_pos ( & self , span_pos : SpanPos ) -> Option < FilePos > {
412
430
with_cx ( self , |cx| cx. span_pos_to_file_loc ( self , span_pos) )
413
431
}
432
+
433
+ /// Map the given [`SpanPos`] to a [`FilePos`]. This will panic, if the
434
+ /// [`SpanPos`] doesn't belong to this [`FileInfo`]
435
+ pub fn to_file_pos ( & self , span_pos : SpanPos ) -> FilePos {
436
+ self . try_to_file_pos ( span_pos) . unwrap_or_else ( || {
437
+ panic ! (
438
+ "the given span position `{span_pos:#?}` is out of range of the file `{}`" ,
439
+ self . file. get( )
440
+ )
441
+ } )
442
+ }
414
443
}
415
444
416
445
#[ cfg( feature = "driver-api" ) ]
@@ -428,7 +457,7 @@ impl<'ast> FileInfo<'ast> {
428
457
}
429
458
}
430
459
431
- /// A locating inside a file.
460
+ /// A location inside a file.
432
461
///
433
462
/// [`SpanPos`] instances belonging to files can be mapped to [`FilePos`] with
434
463
/// the [`FileInfo`] from the [`SpanSource`] of the [`Span`] they belong to. See:
0 commit comments