-
Notifications
You must be signed in to change notification settings - Fork 183
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 icu4x_shared with some helpers #5101
base: main
Are you sure you want to change the base?
Conversation
where | ||
S: serde::ser::Serializer, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: This impl is not bound on Transparent
because (1) it isn't needed for safety reasons, (2) Transparent is a private trait, and (3) the generated functions use cast_ref_unchecked
which in effect enforces transparency since those functions require transparency
I'm not really in favor of introducing a Transparent trait, but I'll have a closer look later. I don't think such a trait is necessary to achieve what we need here. |
I introduced it as a crate-private trait in order to make the macros safe. Happy for suggestions on how to do this better. |
Ah, I see what you've done here. I think what I was envisioning was a way to not have any crate-specific unsafe code at use sites. A macro that can be invoked as impl_helpers!(
/// some docs
#[derive(...)]
#[repr(transparent)]
pub struct Foo(Bar);
) Thinking about it more it probably could still a trait so that it can be split into different cfg()able macros. I'm fine with that. But ideally the actual transparent impl can be done without writing Also FWIW while I don't consider it a blocking opinion, if we're putting unsafe stuff in |
Actually, no, thinking about it more, I do kind of consider this somewhat blocking. This goes back to the point I made about being very careful what we sacrifice in favor of the goals of serving cases like that of rust-url: I don't think "a lot more ICU4X crates contain unsafe code" is an acceptable cost. I'd rather this just lived in |
I would use the Adding yet another crate to do this, in addition to the docs macros noted in #4467, has downsides:
Some options:
|
I think this specific API is fine to put in a core crate, for two reasons:
I was extremely in favor of copy-pasting for the docs macros, because there is almost zero cost to that. Making every ICU4X crate (or even "every ICU4X crate using these macros") contain unsafe code is a major cost and affects ecosystem perception as well as the practicalities of unsafe review. Put differently: doc macros copy pasted across crates are effectively one bit of code that is seen in multiple places. The only impact "duplicate code" has is on maintainers, and we'll have tooling making it transparent. unsafe macros copy pasted across crates are not effectively the same bit of code seen in multiple places, each copy adds a cost, and it has impacts outside of maintainers, including in ways that affect the perception of our project. Personally, I am in favor of option 4: these macros (and only these macros) live in Preferences are |
Actually, hold on, I'm also comfortable with the unsafe macros living inside the varule crate. That would work just fine, and they could be public if we want, they're clearly useful. Happy to write them in a way that doesn't involve Transparent if desired. |
This functionality is sufficiently similar to what's in zerovec that I'd be okay adding them there In case it got lost, I want to point out that these are not only VarULE helper macros. They also encapsulate functionality from ref-cast, which is code we are already currently required to have sprinkled in various places. This particular crate already has unsafe code; the PR at hand does not change that. We're not regressing. We're not "sacrificing" anything in the more narrow context of this PR; that's only a hypothetical situation if a future migration changes a safe crate to an unsafe create. If we can move this crate's unsafe code elsewhere, that's a win. |
Okay, but the "narrow context of the PR" is not the context in which we were planning this change: we were planning to use these helpers to clean up a large chunk of our I also do think that from a reviewability perspective, this PR in its narrow context still makes things worse: it moves a single callsite over to a more indirect macro situation. The |
I haven't done a full audit but I would make the claim that most variable length repr(transparent) things need both ref-cast and VarULE impls, and since all ref-cast impls currently involve unsafe, there might not be many cases where we would be turning a safe crate to an unsafe crate (which I agree is a big cost). This PR definitely introduces indirection; my position is that it is an overall improvement, but it's a reasonable debate and one I was hoping to have. I think it is clearer and safer for the safety invariants to live as trait bounds in macros that all live in one file whose only job is to make it exceedingly obvious that the safety invariants are upheld rather than having random unsafe blocks sprinkled around the crate. |
Can you explain or demonstrate or cite how to do this safely without the trait bound? That might help move the conversation forward. Ultimately I'm mostly onboard with putting this in the zerovec crate. |
operative term here, I think we'll be applying these to most fixed length ones too and I'm not opposed to the VarULE macros exposing these methods too, it's not a hard toggle to add |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why wouldn't Transparent
live in zerovec
? There doesn't seem to be a use for it outside of an easier VarULE
implementation.
Can the invariant be enforced without the trait by generating a static assertion that the sizes are equal? |
@sffc I don't think we need to test the invariant at all, as long as the macro controls generating the struct. |
I would be quite sad but not block if the solution is wrapping the struct definition in a macro. I prefer standalone macros with traits or assertions |
Going to move discussion to #5127 |
Converting to draft pending discussions |
Relates to numerous issues:
syn
deps #5127