-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Unsafe derives and attributes #3715
base: master
Are you sure you want to change the base?
Conversation
2339301
to
0530e44
Compare
Just my 2¢, but I think that the shorthand for You have to separate out derive traits any time there's some different requirement, e.g. Sure, it's likely it won't make a difference, but I think that only having to check attributes at the top level for unsafe to verify safety is best. |
The greppability is already broken by things like |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
I feel kind of silly for literally alluding to this point in my post and missing it somehow. You're right and I retract my original claim. |
We had a @rust-lang/lang design meeting today on the set of macro RFCs. I've updated the RFC to incorporate the feedback from that design meeting. Per the feedback in that meeting, I'm starting an FCP to start letting people register consensus for this RFC. @rfcbot merge |
Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. 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! cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns. |
@rust-lang/lang I've updated this to match the consensus syntax of |
One thing I thought of was that it might make sense to make a derive maybe-unsafe and branch between whether |
I think that would be a big mistake. The presence or absence of |
In terms of the mental model I find OTOH, the RFC does make some good points in favor of "inner |
That distinction is tied exactly to:
That is, I agree that if Putting that all together, we could say that, within attributes, we have to be in a |
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.
While to the proc_macro author in #[derive(Clone, Copy)] struct Foo { ... }
it may be understood as invoking the "macros" Clone
and Copy
on struct Foo { ... }
, to an average user it is highly unintuitive to think like that.
We would think
#[derive(Clone, Copy)]
is just a short hand for#[derive(Clone)] #[derive(Copy)]
and- the
derive
and the trait (ok, macro) name is a single unit to drive the code generation.
So #[unsafe(derive(UnsafeTrait))]
makes more sense to me, which the unsafe
is applied the entirety of derive(UnsafeTrait)
, not the word derive
alone.
If writing code that enforces `SAFETY` comments for every use of `unsafe`, you | ||
can write the `SAFETY` comment immediately prior to the attribute: |
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.
If writing code that enforces `SAFETY` comments for every use of `unsafe`, you | |
can write the `SAFETY` comment immediately prior to the attribute: | |
You can write the `SAFETY` comment immediately prior to the attribute: |
"What, you mean there's code somewhere that doesn't require that?" I'd prefer to not hint that this expectation is somehow not the default. Probably we can just leave this predicate out entirely.
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.
@traviscross It is, in a very practical sense, not currently the default: there's no warn-by-default lint for it. I'm all for changing that, but meanwhile, it'd be inaccurate to imply that it is currently required everywhere.
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.
Josh and I talked, but for others here, by wanting to remove the predicate, I don't mean to suggest by this language that it is the default or is required.
If we say, "you can write X here," I don't think that implies that you must write "X" at all. I read it instead as, "if you're going to write an X, which is entirely your option as far as we're concerned, you can write it here."
What I don't want to suggest is that writing such safety comments is unusual, and the fussy language referencing extrinsic requirements for doing this makes it feel that way to me.
I proposed wording along the lines of "when adding a safety comment, you can write it here" that both Josh and I liked, and that I think he's planning to update the text to reflect.
Let's cancel the stale FCP and restart... @rfcbot fcp cancel |
@traviscross proposal cancelled. |
This all looks correct and desirable to me with one amendment, which I'm including in this proposed FCP, which is that we change the def site for derive macros to match the use site, and write the #[proc_macro_derive(unsafe(DangerousDeriveMacro))]
pub fn derive_helper_attr(_item: TokenStream) -> TokenStream {
TokenStream::new()
} (For me, that the use site syntax we chose allows for this symmetry is yet another reason to prefer it.) @rfcbot fcp merge |
Team member @traviscross 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! cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns. |
@traviscross As mentioned by @carbotaniuman and myself in response to that suggestion: that makes it look like something that's unsafe to define rather than unsafe to use. For that reason, I don't think that syntax is an improvement. We've already set the precedent, with unsafe attributes, that I could imagine making the case that this should be written I've listed an alternative for this, along with rationale for why we shouldn't go with that alternative. |
Co-authored-by: Travis Cross <tc@traviscross.com>
6e3b06d
to
962e17c
Compare
Let's use a concern to mark the discussion we need to have on def-site syntax. @rfcbot concern pick-def-site-name (Edit: I meant to type |
We'll need to discuss it on a lang call regardless, and I'm rather curious to hear what others on the team think. While I'm thinking about it, though, here are my notes on the case for symmetry between the def site and the use site. (@joshtriplett and I talked these points over, and our interesting and fruitful discussion helped to sharpen them for this quick write-up. These are my views only though.) First off, I agree that it's a bit of a pun, but I think it's a kind of attractive pun in this case. What pushes me over the line is that I just can't imagine that, having picked Broadly, I think it's fine, given how things are today, if I'm reminded here too about our recent syntax discussions for const trait impls. We may not end up marking them at all -- that's what the current RFC draft says -- but when we were thinking of doing that, we had to pick between (The parity we try to maintain between our type syntax and constructor expression syntax is maybe also a place where we could say that it's a bit of a pun between two distinct things, but that we like it.) Another angle is to imagine what we'd do if we didn't have this feature. Probably we'd still mark these unsafe derive macros by naming them things like (Here and throughout, I'm using Regarding the fact that One reason that I proposed this change is that putting the |
We're already using |
it just occurred to me that we may want to mark derive macro helper attributes #[proc_macro_derive(MyDebug, attributes(unsafe(debug_deref)))]
fn my_debug ... // no `unsafe(MyDebug)` here since it's only unsafe
// when you need to deref pointers, which not all structs have.
#[derive(MyDebug)]
pub struct FooPtr<T> {
// SAFETY: ptr points to a valid memory chunk allocated with `malloc`
#[unsafe(debug_deref)]
ptr: NonNull<T>,
bar: usize,
} |
Excellent point. We'll take that up with the nomination as well. |
`#[derive(...)]`, if desired. Putting the `unsafe` on the outside requires | ||
separate `derive`s for safe and unsafe derives, and potentially multiple in | ||
the (unusual) case where the derives care about ordering. | ||
- This makes it easy to attach `SAFETY` comments to each individual derive | ||
macro. |
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 that as of 1.87 as long as you insert a single comment between any item, rustfmt
will automatically convert to the style to put everything in a single line.
#[derive(
Copy, Clone, Eq, Hash, PartialEq, Ord, PartialOrd, Debug,
// SAFETY: demo
unsafe(FromRawFd),
)]
struct Foo(RawFd);
// ↓ after rustfmt ↓
#[derive(
Copy,
Clone,
Eq,
Hash,
PartialEq,
Ord,
PartialOrd,
Debug,
// SAFETY: demo
unsafe(FromRawFd),
)]
struct Foo(RawFd);
if you want to keep this within 3~5 lines and rustfmt-stable you need to split the safe and unsafe parts anyway.
#[derive(Copy, Clone, Eq, Hash, PartialEq, Ord, PartialOrd, Debug)]
// SAFETY: demo
#[derive(unsafe(FromRawFd))]
struct Foo(RawFd);
The motivation section is really short. Even though this seems like an "obvious" extension, I would appreciate it if @joshtriplett and others could add concrete examples of derives that would use this. Until then further bikeshedding on the spelling seems premature. |
Allow declaring proc macro attributes and derive macros as unsafe, and
requiring
unsafe
to invoke them.Rendered