11use crate :: ffi:: CStr ;
22use crate :: fmt;
3+ use crate :: marker:: PhantomData ;
4+ use crate :: ptr:: NonNull ;
35
46/// A struct containing information about the location of a panic.
57///
@@ -33,14 +35,13 @@ use crate::fmt;
3335#[ derive( Copy , Clone , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
3436#[ stable( feature = "panic_hooks" , since = "1.10.0" ) ]
3537pub 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 ] ,
38+ // A raw pointer is used rather than a reference because the pointer is valid for one more byte
39+ // than the length stored in this pointer; the additional byte is the NUL-terminator used by
40+ // `Location::file_with_nul`.
41+ filename : NonNull < str > ,
4242 line : u32 ,
4343 col : u32 ,
44+ _filename : PhantomData < & ' a str > ,
4445}
4546
4647#[ stable( feature = "panic_hooks" , since = "1.10.0" ) ]
@@ -143,10 +144,8 @@ impl<'a> Location<'a> {
143144 #[ stable( feature = "panic_hooks" , since = "1.10.0" ) ]
144145 #[ rustc_const_stable( feature = "const_location_fields" , since = "1.79.0" ) ]
145146 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) }
147+ // SAFETY: The filename is valid.
148+ unsafe { self . filename . as_ref ( ) }
150149 }
151150
152151 /// Returns the name of the source file as a nul-terminated `CStr`.
@@ -157,9 +156,17 @@ impl<'a> Location<'a> {
157156 #[ unstable( feature = "file_with_nul" , issue = "141727" ) ]
158157 #[ inline]
159158 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 ) }
159+ let filename = self . filename . as_ptr ( ) ;
160+
161+ // SAFETY: The filename is valid for `filename_len+1` bytes, so this addition can't
162+ // overflow.
163+ let cstr_len = unsafe { crate :: mem:: size_of_val_raw ( filename) . unchecked_add ( 1 ) } ;
164+
165+ // SAFETY: The filename is valid for `filename_len+1` bytes.
166+ let slice = unsafe { crate :: slice:: from_raw_parts ( filename. cast ( ) , cstr_len) } ;
167+
168+ // SAFETY: The filename is guaranteed to have a trailing nul byte and no interior nul bytes.
169+ unsafe { CStr :: from_bytes_with_nul_unchecked ( slice) }
163170 }
164171
165172 /// Returns the line number from which the panic originated.
@@ -220,3 +227,8 @@ impl fmt::Display for Location<'_> {
220227 write ! ( formatter, "{}:{}:{}" , self . file( ) , self . line, self . col)
221228 }
222229}
230+
231+ #[ stable( feature = "panic_hooks" , since = "1.10.0" ) ]
232+ unsafe impl Send for Location < ' _ > { }
233+ #[ stable( feature = "panic_hooks" , since = "1.10.0" ) ]
234+ unsafe impl Sync for Location < ' _ > { }
0 commit comments