Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Deref<Target=ByteStr> for CStr #138498

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

tamird
Copy link
Contributor

@tamird tamird commented Mar 14, 2025

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

Link: #134915
Link: Rust-for-Linux/linux#1075
Link: https://lore.kernel.org/all/20250221142816.0c015e9f@eugeo/
Link: Rust-for-Linux/linux#1146

r? @joshtriplett
cc @nbdd0121

I'm not entirely sure what it means for a stable type to deref to an unstable one - hopefully the compiler does the right thing and gates this impl on all the items being available.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Mar 14, 2025
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@joshtriplett
Copy link
Member

This is a really interesting idea. One potential point of concern: the deref to ByteStr uses to_bytes (rather than to_bytes_with_nul), which somewhat makes sense, but with the further deref to &[u8], is there any chance that someone will end up with a &[u8] that lacks the NUL when they expected a &[u8] that has the NUL?

This is probably fine, and I would hope that any FFI cases that require the NUL use CStr (or to_bytes_with_nul). However, I wanted to call it out as a potential hazard. If we do this, I think this deserves a mention in the documentation at least.

@tamird
Copy link
Contributor Author

tamird commented Mar 15, 2025

@joshtriplett sounds reasonable, except I'm not sure where to document this. I can't document it on the trait impl. Would it go in the CStr documentation? The documentation would in effect be insta-stable, which would be odd. What did you have in mind?

@joshtriplett
Copy link
Member

I think it would go on CStr. Even before BStr is stable, the resulting transitive Deref to a slice will work, and that merits the documentation.

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: rust-lang#134915
Link: Rust-for-Linux/linux#1075
Link: https://lore.kernel.org/all/20250221142816.0c015e9f@eugeo/
Link: Rust-for-Linux/linux#1146
@tamird
Copy link
Contributor Author

tamird commented Mar 16, 2025

@joshtriplett done.

@joshtriplett joshtriplett added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. and removed T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Mar 20, 2025
@joshtriplett
Copy link
Member

Looks reasonable. Since trait impls are insta-stable, starting an FCP on this:

@rfcbot merge

@rfcbot
Copy link
Collaborator

rfcbot commented Mar 20, 2025

Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members:

Concerns:

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Mar 20, 2025
@m-ou-se
Copy link
Member

m-ou-se commented Mar 20, 2025

@rfcbot concern &cstr as thin ptr

Afaik, there is still a plan to make &CStr a thin pointer in the future. If we do that, then a deref to [u8] would mean counting the length (strlen) every time.

@joshtriplett
Copy link
Member

@m-ou-se That's a really good point. That is enough overhead that we shouldn't have this Deref at all if we're going to change CStr to a thin pointer.

@tamird
Copy link
Contributor Author

tamird commented Mar 25, 2025

@m-ou-se @joshtriplett that overhead is probably significant enough that even AsRef backed by that implementation would be inappropriate. Right?

@m-ou-se
Copy link
Member

m-ou-se commented Mar 25, 2025

Yes. That's why CStr::to_bytes() is called "to" not "as".

@joshtriplett
Copy link
Member

This isn't the first case where we've had interesting work gated on whether we're actually going to make CStr a thin pointer. It seems like we need to evaluate the decision about whether we're ever going to do that and want to reserve the ability to do so.

(Other alternatives include making a separate type for a CThinStr, for instance.)

We should talk about that at a future libs-api meeting.

@lukas-code
Copy link
Member

I'm not entirely sure what it means for a stable type to deref to an unstable one - hopefully the compiler does the right thing and gates this impl on all the items being available.

The compiler does not gate this correctly: Trait impls are currently not checked for stability and this impl will allow access to ByteStr values and trait impls of ByteStr without a feature gate:

use std::ffi::CStr;

fn foo(s: &CStr) {
    let bstr = &**s;
    println!("{bstr}"); // accesses `ByteStr as Display` without a feature gate!
}

fn main() {
    foo(c"cstr");
}

@joshtriplett
Copy link
Member

@lukas-code Trait impls aren't able to be feature-gated in general, and it's already established that feature-gating a type doesn't prevent you from getting a value of that type if a function returns it, it just prevents you from naming the type (e.g. to construct it).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants