|
| 1 | +#[cfg(not(bootstrap))] |
| 2 | +use crate::ffi::CStr; |
1 | 3 | use crate::fmt;
|
2 | 4 |
|
3 | 5 | /// A struct containing information about the location of a panic.
|
@@ -32,7 +34,16 @@ use crate::fmt;
|
32 | 34 | #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
33 | 35 | #[stable(feature = "panic_hooks", since = "1.10.0")]
|
34 | 36 | pub struct Location<'a> {
|
| 37 | + #[cfg(bootstrap)] |
35 | 38 | file: &'a str,
|
| 39 | + |
| 40 | + // Note: this filename will have exactly one nul byte at its end, but otherwise |
| 41 | + // it must never contain interior nul bytes. This is relied on for the conversion |
| 42 | + // to `CStr` below. |
| 43 | + // |
| 44 | + // The prefix of the string without the trailing nul byte will be a regular UTF8 `str`. |
| 45 | + #[cfg(not(bootstrap))] |
| 46 | + file_bytes_with_nul: &'a [u8], |
36 | 47 | line: u32,
|
37 | 48 | col: u32,
|
38 | 49 | }
|
@@ -125,9 +136,33 @@ impl<'a> Location<'a> {
|
125 | 136 | #[must_use]
|
126 | 137 | #[stable(feature = "panic_hooks", since = "1.10.0")]
|
127 | 138 | #[rustc_const_stable(feature = "const_location_fields", since = "1.79.0")]
|
128 |
| - #[inline] |
129 | 139 | pub const fn file(&self) -> &str {
|
130 |
| - self.file |
| 140 | + #[cfg(bootstrap)] |
| 141 | + { |
| 142 | + self.file |
| 143 | + } |
| 144 | + |
| 145 | + #[cfg(not(bootstrap))] |
| 146 | + { |
| 147 | + let str_len = self.file_bytes_with_nul.len() - 1; |
| 148 | + // SAFETY: `file_bytes_with_nul` without the trailing nul byte is guaranteed to be |
| 149 | + // valid UTF8. |
| 150 | + unsafe { crate::str::from_raw_parts(self.file_bytes_with_nul.as_ptr(), str_len) } |
| 151 | + } |
| 152 | + } |
| 153 | + |
| 154 | + /// Returns the name of the source file as a nul-terminated `CStr`. |
| 155 | + /// |
| 156 | + /// This is useful for interop with APIs that expect C/C++ `__FILE__` or |
| 157 | + /// `std::source_location::file_name`, both of which return a nul-terminated `const char*`. |
| 158 | + #[cfg(not(bootstrap))] |
| 159 | + #[must_use] |
| 160 | + #[unstable(feature = "file_with_nul", issue = "none")] |
| 161 | + #[inline] |
| 162 | + pub const fn file_with_nul(&self) -> &CStr { |
| 163 | + // SAFETY: `file_bytes_with_nul` is guaranteed to have a trailing nul byte and no |
| 164 | + // interior nul bytes. |
| 165 | + unsafe { CStr::from_bytes_with_nul_unchecked(self.file_bytes_with_nul) } |
131 | 166 | }
|
132 | 167 |
|
133 | 168 | /// Returns the line number from which the panic originated.
|
@@ -181,22 +216,10 @@ impl<'a> Location<'a> {
|
181 | 216 | }
|
182 | 217 | }
|
183 | 218 |
|
184 |
| -#[unstable( |
185 |
| - feature = "panic_internals", |
186 |
| - reason = "internal details of the implementation of the `panic!` and related macros", |
187 |
| - issue = "none" |
188 |
| -)] |
189 |
| -impl<'a> Location<'a> { |
190 |
| - #[doc(hidden)] |
191 |
| - pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self { |
192 |
| - Location { file, line, col } |
193 |
| - } |
194 |
| -} |
195 |
| - |
196 | 219 | #[stable(feature = "panic_hook_display", since = "1.26.0")]
|
197 | 220 | impl fmt::Display for Location<'_> {
|
198 | 221 | #[inline]
|
199 | 222 | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
200 |
| - write!(formatter, "{}:{}:{}", self.file, self.line, self.col) |
| 223 | + write!(formatter, "{}:{}:{}", self.file(), self.line, self.col) |
201 | 224 | }
|
202 | 225 | }
|
0 commit comments