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

add c_str! macro to create &'static CStr #4255

Merged
merged 12 commits into from
Jun 18, 2024
Merged

Conversation

davidhewitt
Copy link
Member

@davidhewitt davidhewitt commented Jun 15, 2024

With Rust 1.77 finally stabilising c"" c-string literals, I've wanted for a little while to be able to make better use of &'static CStr inside PyO3.

This PR proposes a pathway to doing that, by adding a c_str!("foo") macro to create a static c-string safely. With MSRV 1.63 we're able to support this on all versions.

This has the nice effect of moving work from runtime to compile time, because at the moment we have a lot of &str which need to be converted to &CStr using runtime checks. In the future when MSRV passes 1.77 we have a trivial cleanup to swap everything to c"" literals.

The only user-facing changes:

  • Add pyo3_ffi::c_str macro (also accessible as pyo3::ffi::c_str).
  • The PyCFunction constructors now take &'static CStr where they previously took &'static str.

Copy link
Member

@mejrs mejrs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a big fan of this :)

examples/sequential/src/id.rs Show resolved Hide resolved
pyo3-macros-backend/src/method.rs Show resolved Hide resolved
@@ -870,7 +870,8 @@ pub enum PropertyType<'a> {
}

impl PropertyType<'_> {
fn null_terminated_python_name(&self) -> Result<syn::LitStr> {
fn null_terminated_python_name(&self, ctx: &Ctx) -> Result<TokenStream> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than using TokenStream I'd prefer we make our own type for this and switch to syn::LitCStr when it becomes available.

Then we can also change

pub struct PythonDoc(TokenStream);

to

pub struct LitCStr { .. };
pub struct PythonDoc(LitCStr);

Copy link
Member Author

@davidhewitt davidhewitt Jun 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to go with that; I might also see how painful it is to use conditional code to emit c"" directly from macros on new enough versions. I think it'd be much more efficient codegen and makes it easier for us to clean up later.

... but maybe in the interest of not blocking the 0.22 release too much, would you be ok if I punt doing this into a follow-up internal refactoring PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure 👍

@@ -284,22 +272,6 @@ where
retval
}

pub(crate) struct PyMethodDefDestructor {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to get rid of this :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me too! It felt so awkward before to have to do the dance with &'static str in a bunch of places. In some we created these destructors and in others we made an unsafe requirement of no interior nulls. This end state is much more satisfying.

@davidhewitt davidhewitt mentioned this pull request Jun 15, 2024
5 tasks
davidhewitt and others added 2 commits June 15, 2024 22:50
@Icxolu
Copy link
Contributor

Icxolu commented Jun 15, 2024

Big 👍 for this from me as well! This is a lot nicer and safer than having to remember to add the \0 and it also gets rid of a lot of casting which is nice to see.

@davidhewitt
Copy link
Member Author

Given the two broadly positive sentiments, I think I'm going to merge this once I get CI passing. It'll make #4254 easier to finish implementing, which I want to complete ASAP with a view to then shipping 0.22.

If there are changes which are wanted (like the PythonDoc changes proposed above) let's put them into follow-up PRs or issues to land after we've shipped and unblocked everyone downstream from 3.13 testing.

@davidhewitt davidhewitt enabled auto-merge June 18, 2024 06:05
@davidhewitt davidhewitt added this pull request to the merge queue Jun 18, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jun 18, 2024
@davidhewitt davidhewitt enabled auto-merge June 18, 2024 06:54
@davidhewitt davidhewitt added this pull request to the merge queue Jun 18, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jun 18, 2024
@davidhewitt davidhewitt enabled auto-merge June 18, 2024 07:51
@davidhewitt davidhewitt added this pull request to the merge queue Jun 18, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jun 18, 2024
@davidhewitt davidhewitt enabled auto-merge June 18, 2024 17:49
@davidhewitt davidhewitt added this pull request to the merge queue Jun 18, 2024
Merged via the queue into PyO3:main with commit 0e142f0 Jun 18, 2024
40 of 41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants