about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-06-05 10:21:20 +0000
committerbors <bors@rust-lang.org>2025-06-05 10:21:20 +0000
commitc360e219f5a56631baa46065d28e9852ca7d4ce3 (patch)
tree7193d135b42af795cea72addaba2df1de3ca1b15 /library
parent425e142686242c7e73f5e32c79071ae266f0f355 (diff)
parentb541f93372c24bcbf036efc2b454cff6f6b8f8c5 (diff)
downloadrust-c360e219f5a56631baa46065d28e9852ca7d4ce3.tar.gz
rust-c360e219f5a56631baa46065d28e9852ca7d4ce3.zip
Auto merge of #135054 - cramertj:file-cstr, r=m-ou-se
Add Location::file_with_nul

This is useful for C/C++ APIs which expect the const char* returned from __FILE__ or std::source_location::file_name.

ACP: https://github.com/rust-lang/libs-team/issues/466
Tracking issue: https://github.com/rust-lang/rust/issues/141727
Diffstat (limited to 'library')
-rw-r--r--library/core/src/panic/location.rs41
1 files changed, 25 insertions, 16 deletions
diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs
index 1ad5c07d15c..94cfd667ffa 100644
--- a/library/core/src/panic/location.rs
+++ b/library/core/src/panic/location.rs
@@ -1,3 +1,4 @@
+use crate::ffi::CStr;
 use crate::fmt;
 
 /// A struct containing information about the location of a panic.
@@ -32,7 +33,12 @@ use crate::fmt;
 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
 #[stable(feature = "panic_hooks", since = "1.10.0")]
 pub struct Location<'a> {
-    file: &'a str,
+    // Note: this filename will have exactly one nul byte at its end, but otherwise
+    // it must never contain interior nul bytes. This is relied on for the conversion
+    // to `CStr` below.
+    //
+    // The prefix of the string without the trailing nul byte will be a regular UTF8 `str`.
+    file_bytes_with_nul: &'a [u8],
     line: u32,
     col: u32,
 }
@@ -125,9 +131,24 @@ impl<'a> Location<'a> {
     #[must_use]
     #[stable(feature = "panic_hooks", since = "1.10.0")]
     #[rustc_const_stable(feature = "const_location_fields", since = "1.79.0")]
-    #[inline]
     pub const fn file(&self) -> &str {
-        self.file
+        let str_len = self.file_bytes_with_nul.len() - 1;
+        // SAFETY: `file_bytes_with_nul` without the trailing nul byte is guaranteed to be
+        // valid UTF8.
+        unsafe { crate::str::from_raw_parts(self.file_bytes_with_nul.as_ptr(), str_len) }
+    }
+
+    /// Returns the name of the source file as a nul-terminated `CStr`.
+    ///
+    /// This is useful for interop with APIs that expect C/C++ `__FILE__` or
+    /// `std::source_location::file_name`, both of which return a nul-terminated `const char*`.
+    #[must_use]
+    #[unstable(feature = "file_with_nul", issue = "141727")]
+    #[inline]
+    pub const fn file_with_nul(&self) -> &CStr {
+        // SAFETY: `file_bytes_with_nul` is guaranteed to have a trailing nul byte and no
+        // interior nul bytes.
+        unsafe { CStr::from_bytes_with_nul_unchecked(self.file_bytes_with_nul) }
     }
 
     /// Returns the line number from which the panic originated.
@@ -181,22 +202,10 @@ impl<'a> Location<'a> {
     }
 }
 
-#[unstable(
-    feature = "panic_internals",
-    reason = "internal details of the implementation of the `panic!` and related macros",
-    issue = "none"
-)]
-impl<'a> Location<'a> {
-    #[doc(hidden)]
-    pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
-        Location { file, line, col }
-    }
-}
-
 #[stable(feature = "panic_hook_display", since = "1.26.0")]
 impl fmt::Display for Location<'_> {
     #[inline]
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(formatter, "{}:{}:{}", self.file, self.line, self.col)
+        write!(formatter, "{}:{}:{}", self.file(), self.line, self.col)
     }
 }