1
1
use crate :: ffi:: CStr ;
2
2
use crate :: fmt;
3
+ use crate :: marker:: PhantomData ;
3
4
4
5
/// A struct containing information about the location of a panic.
5
6
///
@@ -33,14 +34,13 @@ use crate::fmt;
33
34
#[ derive( Copy , Clone , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
34
35
#[ stable( feature = "panic_hooks" , since = "1.10.0" ) ]
35
36
pub struct Location < ' a > {
36
- // Note: this filename will have exactly one nul byte at its end, but otherwise
37
- // it must never contain interior nul bytes. This is relied on for the conversion
38
- // to `CStr` below.
39
- //
40
- // The prefix of the string without the trailing nul byte will be a regular UTF8 `str`.
41
- file_bytes_with_nul : & ' a [ u8 ] ,
37
+ // A raw pointer is used rather than a reference because the pointer is valid for one more byte
38
+ // than the length stored in this pointer; the additional byte is the NUL-terminator used by
39
+ // `Location::file_with_nul`.
40
+ filename : * const str ,
42
41
line : u32 ,
43
42
col : u32 ,
43
+ _filename : PhantomData < & ' a str > ,
44
44
}
45
45
46
46
#[ stable( feature = "panic_hooks" , since = "1.10.0" ) ]
@@ -143,10 +143,8 @@ impl<'a> Location<'a> {
143
143
#[ stable( feature = "panic_hooks" , since = "1.10.0" ) ]
144
144
#[ rustc_const_stable( feature = "const_location_fields" , since = "1.79.0" ) ]
145
145
pub const fn file ( & self ) -> & str {
146
- let str_len = self . file_bytes_with_nul . len ( ) - 1 ;
147
- // SAFETY: `file_bytes_with_nul` without the trailing nul byte is guaranteed to be
148
- // valid UTF8.
149
- unsafe { crate :: str:: from_raw_parts ( self . file_bytes_with_nul . as_ptr ( ) , str_len) }
146
+ // SAFETY: The filename is valid.
147
+ unsafe { & * self . filename }
150
148
}
151
149
152
150
/// Returns the name of the source file as a nul-terminated `CStr`.
@@ -157,9 +155,15 @@ impl<'a> Location<'a> {
157
155
#[ unstable( feature = "file_with_nul" , issue = "141727" ) ]
158
156
#[ inline]
159
157
pub const fn file_with_nul ( & self ) -> & CStr {
160
- // SAFETY: `file_bytes_with_nul` is guaranteed to have a trailing nul byte and no
161
- // interior nul bytes.
162
- unsafe { CStr :: from_bytes_with_nul_unchecked ( self . file_bytes_with_nul ) }
158
+ // SAFETY: The filename is valid for `filename_len+1` bytes, so this addition can't
159
+ // overflow.
160
+ let cstr_len = unsafe { crate :: mem:: size_of_val_raw ( self . filename ) . unchecked_add ( 1 ) } ;
161
+
162
+ // SAFETY: The filename is valid for `filename_len+1` bytes.
163
+ let slice = unsafe { crate :: slice:: from_raw_parts ( self . filename as * const _ , cstr_len) } ;
164
+
165
+ // SAFETY: The filename is guaranteed to have a trailing nul byte and no interior nul bytes.
166
+ unsafe { CStr :: from_bytes_with_nul_unchecked ( slice) }
163
167
}
164
168
165
169
/// Returns the line number from which the panic originated.
@@ -220,3 +224,8 @@ impl fmt::Display for Location<'_> {
220
224
write ! ( formatter, "{}:{}:{}" , self . file( ) , self . line, self . col)
221
225
}
222
226
}
227
+
228
+ #[ stable( feature = "panic_hooks" , since = "1.10.0" ) ]
229
+ unsafe impl Send for Location < ' _ > { }
230
+ #[ stable( feature = "panic_hooks" , since = "1.10.0" ) ]
231
+ unsafe impl Sync for Location < ' _ > { }
0 commit comments