From 2747c7e9fcb4472314d99fcc2beb92374d9066a4 Mon Sep 17 00:00:00 2001
From: Tamir Duberstein <tamird@gmail.com>
Date: Fri, 14 Mar 2025 10:04:02 -0400
Subject: [PATCH] Implement Deref<Target=ByteStr> for CStr

This produces a deref chain of `CStr` -> `BStr` -> `[u8]` which is
present in the Rust-for-Linux analogues of these types.

Add `AsRef<ByteStr>` as well.

Link: https://github.com/rust-lang/rust/issues/134915
Link: https://github.com/Rust-for-Linux/linux/issues/1075
Link: https://lore.kernel.org/all/20250221142816.0c015e9f@eugeo/
Link: https://github.com/Rust-for-Linux/linux/issues/1146
---
 library/core/src/ffi/c_str.rs                 | 22 +++++++++++++++++++
 src/tools/linkchecker/main.rs                 | 12 ++++++++++
 ...sociated-types-in-ambiguous-context.stderr |  4 ++--
 3 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 080c0cef53304..4e440b3edb3fe 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -25,6 +25,10 @@ use crate::{fmt, ops, slice, str};
 /// The `CStr` can then be converted to a Rust <code>&[str]</code> by performing
 /// UTF-8 validation, or into an owned `CString`.
 ///
+/// The `CStr` [`Deref`] implementation has the same semantics as
+/// [`CStr::to_bytes`]; the trailing nul terminator is **omitted** from
+/// [`Deref::Target`].
+///
 /// `&CStr` is to `CString` as <code>&[str]</code> is to `String`: the former
 /// in each pair are borrowed references; the latter are owned
 /// strings.
@@ -87,6 +91,8 @@ use crate::{fmt, ops, slice, str};
 /// ```
 ///
 /// [str]: prim@str "str"
+/// [`Deref`]: crate::ops::Deref
+/// [`Deref::Target`]: crate::ops::Deref::Target
 #[derive(PartialEq, Eq, Hash)]
 #[stable(feature = "core_c_str", since = "1.64.0")]
 #[rustc_diagnostic_item = "cstr_type"]
@@ -710,6 +716,22 @@ impl AsRef<CStr> for CStr {
     }
 }
 
+#[unstable(feature = "bstr", issue = "134915")]
+impl AsRef<crate::bstr::ByteStr> for CStr {
+    #[inline]
+    fn as_ref(&self) -> &crate::bstr::ByteStr {
+        crate::bstr::ByteStr::from_bytes(self.to_bytes())
+    }
+}
+
+impl ops::Deref for CStr {
+    type Target = crate::bstr::ByteStr;
+
+    fn deref(&self) -> &Self::Target {
+        self.as_ref()
+    }
+}
+
 /// Calculate the length of a nul-terminated string. Defers to C's `strlen` when possible.
 ///
 /// # Safety
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 19340b5d07a11..6fbc24dee5f3e 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -46,6 +46,8 @@ const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[
     // The docs in std::primitive use proper intra-doc links, so these seem fine to special-case.
     // Most these are broken because liballoc uses `#[lang_item]` magic to define things on
     // primitives that aren't available in core.
+    ("alloc/ffi/c_str/struct.CString.html", &["#method.sort_by_key"]),
+    ("alloc/ffi/struct.CString.html", &["#method.sort_by_key"]),
     ("alloc/slice/trait.Join.html", &["#method.join"]),
     ("alloc/slice/trait.Concat.html", &["#method.concat"]),
     ("alloc/slice/index.html", &["#method.concat", "#method.join"]),
@@ -73,6 +75,16 @@ const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[
         "core\\bstr\\slice::sort_by_key",
         "#method.sort_by_cached_key"
     ]),
+    ("core/ffi/c_str/struct.CStr.html", &[
+        "#method.to_ascii_uppercase",
+        "#method.to_ascii_lowercase",
+        "core/ffi/c_str/slice::sort_by_key",
+    ]),
+    ("core/ffi/struct.CStr.html", &[
+        "#method.to_ascii_uppercase",
+        "#method.to_ascii_lowercase",
+        "core/ffi/slice::sort_by_key",
+    ]),
     ("core/primitive.str.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase"]),
     ("core/primitive.slice.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase",
                                     "core/slice::sort_by_key", "core\\slice::sort_by_key",
diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
index d7d2161e7ad97..ce4f65b7e3eac 100644
--- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
+++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
@@ -49,10 +49,10 @@ LL - type X = std::ops::Deref::Target;
 LL + type X = <ByteString as Deref>::Target;
    |
 LL - type X = std::ops::Deref::Target;
-LL + type X = <CString as Deref>::Target;
+LL + type X = <CStr as Deref>::Target;
    |
 LL - type X = std::ops::Deref::Target;
-LL + type X = <IoSlice<'_> as Deref>::Target;
+LL + type X = <CString as Deref>::Target;
    |
      and N other candidates