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 Extern Blocks #3484
base: master
Are you sure you want to change the base?
Unsafe Extern Blocks #3484
Conversation
Co-authored-by: Jacob Lifshay <programmerjake@gmail.com>
Perhaps non- This would minimize churn in the language definition if any such targets appear in the future. (But maybe that's an insignificant concern since support for previous editions is still required.) |
a future RFC can always relax required keywords in certain situations, it wouldn't even be an edition-break issue at that point. but let's save that for a future RFC when we actually have a clear and specific fully working case. |
One concern about making the functions inside the For example, I could imagine people updating their projects, solving issues one by one, and resolving this issue by just changing an (Keep in mind that not every project uses |
maybe have a weak keyword unsafe extern "C" {
safe fn sqrtf(v: f32) -> f32;
unsafe fn printf(s: *const c_char, ...);
} |
I'm frustrated by this RFC because the overall direction is obviously right to me, but the overloading of |
One specific concern I have:
i.e., we have to weigh the risk of people accidentally writing |
Hey I'm all for a |
The T-lang team met to discuss this RFC today. We bikeshed'ed a bit and probably covered the same ground that was already covered in this comment thread above (e.g. the suggestion above of a weak In the end, we have the following proposal for how you might adjust this RFC to meet some broader goals that we identified. Proposal:(In this text, let the term "unadorned
Here are the various motivations/assumptions that led us to the proposal above:
|
text/0000-unsafe-extern-blocks.md
Outdated
`extern` blocks are `unsafe` because if the declaration doesn't match the actual external function, or the actual external data, then it causes compile time Undefined Behavior (UB). | ||
|
||
Once they are unsafely declared, a `safe` item can be used outside the `extern` block as if it were any other safe function or static value declared within rust. | ||
The unsafe obligation of ensuring that the correct items are being linked to is performed by the crate making the declaration, not the crate using of that declaration. |
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.
The unsafe obligation of ensuring that the correct items are being linked to is performed by the crate making the declaration, not the crate using of that declaration. | |
The unsafe obligation of ensuring that the correct items are being linked to is performed by the crate making the declaration, not the crate using that declaration. |
@rustbot labels +I-lang-nominated +A-edition-2024 We met back on 2023-10-11 to discuss this RFC, and in that meeting, we hammered out a consensus for how to move forward on this as articulated by pnkfelix above. We've just been waiting for the RFC to be updated according to that consensus, and it now has been ( Let's nominate to discuss potentially moving forward on this for Rust 2024. |
Updates here look good! I this this is a good path forward and this version addresses the previous worries about changing something to be the opposite over an edition boundary. @rfcbot merge |
Team member @scottmcm 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. |
|
||
* On editions >= 2024, you *must* write all `extern` blocks as `unsafe extern`. | ||
* On editions < 2024, you *may* write `unsafe extern`, or you can write an `extern` block without the `unsafe` keyword. Writing an `extern` block without the `unsafe` keyword is provided for compatibility only, and will generate a warning. | ||
* `unsafe extern` interacts with the `unsafe_code` lint, and a `deny` or `forbid` with that lint will deny or forbid the unsafe external block. |
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.
Will an extern
(no unsafe
, edition < 2024
) block trip the lint? I'd argue it's as unsafe (if not more dangerous) with unsafe
token...
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.
for compatibility reasons I'd expect to warn at most, even if you use deny/forbid unsafe_code.
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.
My intent is that you get a forward compatibility warning if you write extern
without unsafe
.
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
||
* It is very unfortunate to have to essentially reverse the status quo. |
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.
This seems to mention a drawback of a previous version? (where no qualifier in unsafe extern {}
meant "safe")
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.
Uh, yeah, maybe, i dunno, i mean we're still swapping around how things work, maybe not "reversing" maybe some other verb.
I don't know how precisely to describe the motion happening, but also I don't wanna say that "there's no drawbacks at all!". it's definitely some motion.
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.
Hm. How about something like this?
- It is very unfortunate to change the syntax of
extern
blocks and require changes to all of them.
- Hopefully, allowing people to safely call some foreign functions will make up for the churn caused by this change.
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.
Yeah I agree "reverse" is confusing, I don't know what is being reverse here. 👍 for something like Waffle's proposal. Basically the drawback is "churn".
🔔 This is now entering its final comment period, as per the review above. 🔔 |
Excited about this RFC, particularly the ability to declare extern fn's and static's as safe, but also because it puts the "burden of proof" where it belongs, on the declaration of the extern. @rfcbot reviewed |
I think the consensus in the T-lang meeting today in response to @RalfJung's concern (hm, re-reading the comment now I'm not sure it's actually a concern, it actually looks more just a response to the other comment...) was that even if the "merge definitions" is an LLVM/rustc bug we still want to make |
@rfcbot reviewed I don't love the |
@rfcbot concern choice-of-keyword I guess, to @rust-lang/lang, I'd like to ask: Should we opt for |
Both the In contrast, the It seems unfortunate that we are introducing a new keyword to distinguish "create obligation" from "discharge obligation" but the same RFC also uses |
@rustbot labels +I-lang-nominated Let's nominate this to discuss the concern that nikomatsakis has raised above. |
I'm not against a discussion, but I'll note that "a safe function" is already what the Rust documentation/community calls a function that doesn't require an |
OK sorry maybe I'm confused about the current proposal. In the RFC's original version there was no unsafe extern "C" {
unsafe fn a(); // yes it's unsafe
fn b(); // unsafe by default, same as current situation, maybe linted to require unsafe/safe annotation
bikeshed_safe fn c(); // explicitly marked safe
unsafe static X: [u8; 1024]; // unsafe
static Y: [u8; 1024]; //unsafe by default
bikeshed_trusted static Z: [u8; 1024]; // explicitly safe
} That extern "C" { // <-- no unsafe keyword, still triggers unsafe_code lint
unsafe fn a();
fn b();
bikeshed_harmless fn c();
unsafe static X: [u8; 1024];
static Y: [u8; 1024];
bikeshed_good_boi static Z: [u8; 1024];
} |
My understanding is that the difference is primarily because of the history. I absolutely don't think it's good design on its own. EDIT: and some people just want the ascii string |
@kennytm I think the point of the
|
|
# Reference-level explanation | ||
[reference-level-explanation]: #reference-level-explanation | ||
|
||
The grammar of the langauge is updated so that: |
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.
The grammar of the langauge is updated so that: | |
The grammar of the language is updated so that: |
@rfcbot resolve choice-of-keyword We discussed this in the @rust-lang/lang meeting and @pnkfelix convinced me that the contextual keyword The question I was posing, effectively, is "if we DID distinguish trusted extern {
/*safe*/ fn foo();
} but we are including an explicit |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
I agree that that's where we want to end up. But I'll still argue that you do not need to worry about the // Edition 2015-2021
extern "C" {
fn a_safe_function(); // `unsafe`, even though that function itself is safe
fn an_unsafe_function();
}
// Edition 2024
unsafe extern "C" {
unsafe fn a_safe_function(); // Still forced to be `unsafe`, if we try to remove `unsafe` we get a compilation error
unsafe fn an_unsafe_function();
}
// Edition 2024+N, when enough people have migrated to `unsafe extern "C" { ... }`
unsafe extern "C" {
fn a_safe_function(); // Allow marking as safe by just not including `unsafe`
unsafe fn an_unsafe_function();
} |
sorry absolutely -1 if you want us to pepper
so this RFC should be changed to say (and I'm still not convinced that the keyword |
no, that is not our intention for this RFC. I took it as more of a general statement about where the language might try to go, in the very long term, but only as part of a more holistic revisiting of our story regarding of how one writes introduces and discharges proof obligations. |
Correct @pnkfelix --
...I was not attempting to suggest that we adopt the |
Rendered
Continuation of #3439, very sorry for the mix up, but when I went to make #3477 I deleted my
rfcs
repo fork and re-forked. I had forgotten that there was an open PR at the time.