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

Tracking Issue for result_ffi_guarantees (RFC 3391) #110503

Open
5 of 7 tasks
tmandry opened this issue Apr 18, 2023 · 45 comments · May be fixed by #130628
Open
5 of 7 tasks

Tracking Issue for result_ffi_guarantees (RFC 3391) #110503

tmandry opened this issue Apr 18, 2023 · 45 comments · May be fixed by #130628
Labels
B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@tmandry
Copy link
Member

tmandry commented Apr 18, 2023

This is a tracking issue for the RFC "result_ffi_guarantees" (rust-lang/rfcs#3391).

About tracking issues

Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.

Steps

Unresolved Questions

None

Implementation history

@tmandry tmandry added B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. T-lang Relevant to the language team, which will review and decide on the PR/issue. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. labels Apr 18, 2023
@RalfJung
Copy link
Member

I did a bunch of work on ABI tests for repr(transparent) that could also be useful for testing this RFC:

@RalfJung RalfJung changed the title Tracking Issue for result_ffi_guarantees Tracking Issue for result_ffi_guarantees (RFC 3391) Sep 2, 2023
@MasterAwesome
Copy link
Contributor

Is anyone still working on this? If not, I'd love to try my shot at it.

@Lokathor
Copy link
Contributor

Lokathor commented Mar 9, 2024

I have not heard word of anyone working on this in a very long time. It's probably a safe bet to begin a PR.

@RalfJung
Copy link
Member

RalfJung commented Mar 12, 2024

Besides adjusting the improper-ctypes lint (which is happening in #122253), some other things that should be done:

  • For Option we have this documentation. I assume we want the same for Result? Is there some way to not repeat the table?
  • Miri has a test here that currently only checks Option, not Result.

@MasterAwesome
Copy link
Contributor

Should the documentation change be a separate PR?

@RalfJung
Copy link
Member

Yes, that probably makes review easier.

bors added a commit to rust-lang-ci/rust that referenced this issue May 1, 2024
Support Result<T, E> across FFI when niche optimization can be used

Allow allow enums like `Result<T, E>` to be used across FFI if the T/E can be niche optimized and the non-niche-optimized type is FFI safe.

Implementation of rust-lang/rfcs#3391
Tracking issue: rust-lang#110503

Additional ABI and codegen tests were added in rust-lang#115372
fmease added a commit to fmease/rust that referenced this issue May 5, 2024
Support Result<T, E> across FFI when niche optimization can be used

Allow allow enums like `Result<T, E>` to be used across FFI if the T/E can be niche optimized and the non-niche-optimized type is FFI safe.

Implementation of rust-lang/rfcs#3391
Tracking issue: rust-lang#110503

Additional ABI and codegen tests were added in rust-lang#115372
bors added a commit to rust-lang-ci/rust that referenced this issue May 5, 2024
Support Result<T, E> across FFI when niche optimization can be used

Allow allow enums like `Result<T, E>` to be used across FFI if the T/E can be niche optimized and the non-niche-optimized type is FFI safe.

Implementation of rust-lang/rfcs#3391
Tracking issue: rust-lang#110503

Additional ABI and codegen tests were added in rust-lang#115372
fmease added a commit to fmease/rust that referenced this issue May 5, 2024
Support Result<T, E> across FFI when niche optimization can be used (v2)

This PR is identical to rust-lang#122253, which was approved and merged but then removed from master by a force-push due to a [CI bug](https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra/topic/ci.20broken.3F).

r? ghost

Original PR description:

---

Allow allow enums like `Result<T, E>` to be used across FFI if the T/E can be niche optimized and the non-niche-optimized type is FFI safe.

Implementation of rust-lang/rfcs#3391
Tracking issue: rust-lang#110503

Additional ABI and codegen tests were added in rust-lang#115372
fmease added a commit to fmease/rust that referenced this issue May 5, 2024
Support Result<T, E> across FFI when niche optimization can be used (v2)

This PR is identical to rust-lang#122253, which was approved and merged but then removed from master by a force-push due to a [CI bug](https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra/topic/ci.20broken.3F).

r? ghost

Original PR description:

---

Allow allow enums like `Result<T, E>` to be used across FFI if the T/E can be niche optimized and the non-niche-optimized type is FFI safe.

Implementation of rust-lang/rfcs#3391
Tracking issue: rust-lang#110503

Additional ABI and codegen tests were added in rust-lang#115372
bors added a commit to rust-lang-ci/rust that referenced this issue May 6, 2024
Support Result<T, E> across FFI when niche optimization can be used (v2)

This PR is identical to rust-lang#122253, which was approved and merged but then removed from master by a force-push due to a [CI bug](https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra/topic/ci.20broken.3F).

r? ghost

Original PR description:

---

Allow allow enums like `Result<T, E>` to be used across FFI if the T/E can be niche optimized and the non-niche-optimized type is FFI safe.

Implementation of rust-lang/rfcs#3391
Tracking issue: rust-lang#110503

Additional ABI and codegen tests were added in rust-lang#115372
@Lokathor
Copy link
Contributor

Lokathor commented May 6, 2024

The lint update PR has merged.

@RalfJung
Copy link
Member

RalfJung commented May 6, 2024

I hope docs are next, then. :) We shouldn't go too long with such a gap between what we document and what we implement.

The Result type itself should get suitable documentation. And probably there's somewhere in the reference as well that needs updating?

@Lokathor
Copy link
Contributor

Lokathor commented May 6, 2024

philosophically speaking I'm not sure how much the reference needs to say in addition to what the standard library type docs say, but yeah docs on Option and Result are the next step. I will likely have time for a docs PR very soon if no one else does it first

github-actions bot pushed a commit to rust-lang/miri that referenced this issue May 11, 2024
Support Result<T, E> across FFI when niche optimization can be used (v2)

This PR is identical to #122253, which was approved and merged but then removed from master by a force-push due to a [CI bug](https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra/topic/ci.20broken.3F).

r? ghost

Original PR description:

---

Allow allow enums like `Result<T, E>` to be used across FFI if the T/E can be niche optimized and the non-niche-optimized type is FFI safe.

Implementation of rust-lang/rfcs#3391
Tracking issue: rust-lang/rust#110503

Additional ABI and codegen tests were added in rust-lang/rust#115372
lnicola pushed a commit to lnicola/rust-analyzer that referenced this issue May 18, 2024
Support Result<T, E> across FFI when niche optimization can be used (v2)

This PR is identical to #122253, which was approved and merged but then removed from master by a force-push due to a [CI bug](https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra/topic/ci.20broken.3F).

r? ghost

Original PR description:

---

Allow allow enums like `Result<T, E>` to be used across FFI if the T/E can be niche optimized and the non-niche-optimized type is FFI safe.

Implementation of rust-lang/rfcs#3391
Tracking issue: rust-lang/rust#110503

Additional ABI and codegen tests were added in rust-lang/rust#115372
flip1995 pushed a commit to flip1995/rust-clippy that referenced this issue May 24, 2024
Support Result<T, E> across FFI when niche optimization can be used (v2)

This PR is identical to #122253, which was approved and merged but then removed from master by a force-push due to a [CI bug](https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra/topic/ci.20broken.3F).

r? ghost

Original PR description:

---

Allow allow enums like `Result<T, E>` to be used across FFI if the T/E can be niche optimized and the non-niche-optimized type is FFI safe.

Implementation of rust-lang/rfcs#3391
Tracking issue: rust-lang/rust#110503

Additional ABI and codegen tests were added in rust-lang/rust#115372
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue May 27, 2024
…lnay

Update Result docs to the new guarantees

The `Option` docs already explain the guarantees given in [RFC 3391](https://github.com/rust-lang/rfcs/blob/master/text/3391-result_ffi_guarantees.md), so all that we need is a paragraph saying that some `Result` type combinations will also qualify.

Part of rust-lang#110503
rust-timer added a commit to rust-lang-ci/rust that referenced this issue May 27, 2024
Rollup merge of rust-lang#124870 - Lokathor:update-result-docs, r=dtolnay

Update Result docs to the new guarantees

The `Option` docs already explain the guarantees given in [RFC 3391](https://github.com/rust-lang/rfcs/blob/master/text/3391-result_ffi_guarantees.md), so all that we need is a paragraph saying that some `Result` type combinations will also qualify.

Part of rust-lang#110503
github-actions bot pushed a commit to rust-lang/miri that referenced this issue May 28, 2024
Update Result docs to the new guarantees

The `Option` docs already explain the guarantees given in [RFC 3391](https://github.com/rust-lang/rfcs/blob/master/text/3391-result_ffi_guarantees.md), so all that we need is a paragraph saying that some `Result` type combinations will also qualify.

Part of rust-lang/rust#110503
@Lokathor
Copy link
Contributor

that's just what @tmandry wrote in the start of the thread next to the checked box.

@RalfJung
Copy link
Member

Where is the reference PR they are mentioning there?

@Lokathor
Copy link
Contributor

I don't know, actually. I just saw a checked box and assumed the box wouldn't be checked if it wasn't completed yet.

@tmandry
Copy link
Member Author

tmandry commented Jul 11, 2024

I must have been under the impression that this was only a documentation change. It probably needs a lang team signoff since it's more than that.

@workingjubilee
Copy link
Member

Hm? Lang FCPed it? rust-lang/rfcs#3391 (comment)

@RalfJung
Copy link
Member

Indeed the change already landed and hit stable with Rust 1.80.

The only thing that's missing, AFAIK, is updating the Reference? Or maybe that has been done already but we forgot to close this issue?
Cc @ehuss

@cuviper
Copy link
Member

cuviper commented Sep 20, 2024

The feature gate is still unstable:

/// Allows enums like Result<T, E> to be used across FFI, if T's niche value can
/// be used to describe E or vise-versa.
(unstable, result_ffi_guarantees, "1.80.0", Some(110503)),

That needs to move to accepted in the neighboring module, and might need updates in places that use it too, like:

if !tcx.features().result_ffi_guarantees {
return None;
}

@workingjubilee
Copy link
Member

I have opened #130628 on the assumption that all necessary documentation changes have landed already. Please let me know if that is incorrect.

@ehuss
Copy link
Contributor

ehuss commented Sep 20, 2024

I do not believe this has been documented. I think that will be needed before stabilization should continue.

Also, it would be helpful to update the top comment with links to the implementation, since it's not really clear to me what was actually changed.

@workingjubilee
Copy link
Member

workingjubilee commented Sep 20, 2024

I believe it was documented on the Result type. Should we add it to the Reference?

@workingjubilee
Copy link
Member

workingjubilee commented Sep 20, 2024

Indeed the Result type was documented accordingly: https://doc.rust-lang.org/std/result/index.html#representation

Unfortunately some very peculiar events happened with CI around the time, so the history is somewhat harder to actually track.

@workingjubilee
Copy link
Member

I have lifted all PRs relevant to the implementation history to the top.

@workingjubilee
Copy link
Member

@ehuss It seems none of the ABI guarantees of Result or Option have been documented in the Reference that I can see, and I'm not sure where the other ABI guarantees that we offer are in the Reference either. So I think this is a larger concern than the matter of this feature and a separate issue should be opened for it. Type layout doesn't seem even close to exhaustive.

@workingjubilee
Copy link
Member

workingjubilee commented Sep 20, 2024

@ehuss I can post a bare-minimum PR to the reference regarding this specific guarantee, but it will mostly serve to make it more obvious that the work is direly unfinished w/r/t documenting ABI in the Reference.

@ehuss
Copy link
Contributor

ehuss commented Sep 20, 2024

Thanks @workingjubilee!

I am a bit confused, since I don't fully understand the connection between result_ffi_guarantees versus the already documented behavior in https://doc.rust-lang.org/std/result/index.html#representation. Is that current documentation making a stronger statement than what is actually true today? Or is there something missing?

I am also quite confused about what is being stabilized, or about the process being used. From the timeline I see:

  1. RFC: result_ffi_guarantees rfcs#3391 was merged to guarantee certain layouts for Result and Option used in FFI.
  2. Support Result<T, E> across FFI when niche optimization can be used (v2) #124747 implemented this for Result for FFI under the result_ffi_guarantees feature flag.
  3. Update Result docs to the new guarantees #124870 added documentation for Result, even though it is still behind a feature flag?

Some questions:

  • Does result_ffi_guarantees actually change the layout, or is it just related to squelching the improper-ctypes lint?
  • Why was the layout guarantee documented before it was stabilized? Is there some difference between repr-Rust (guaranteed on stable) and repr-C (not niche-optimized on stable)?
  • Where is the stabilization report, and the t-lang approval of that?
  • The RFC mentions Option, but the two PRs above seem to only be for Result. What happened with Option?

Sorry for all the dumb questions, but I am very confused as to what is being proposed.

As for layout guarantees, since the reference currently doesn't cover that, then I think it is fine to skip it for now. We are inching our way forward with rust-lang/reference#1545, and I think this might be included there (cc @chorman0773).

@chorman0773
Copy link
Contributor

As for layout guarantees, since the reference currently doesn't cover that, then I think it is fine to skip it for now. We are inching our way forward with rust-lang/reference#1545, and I think this might be included there (cc @chorman0773).

Will probably also want to go into the type-layout chapter as well. It can be added to abi as well once 1545 is merged.

@workingjubilee
Copy link
Member

workingjubilee commented Sep 20, 2024

I am a bit confused, since I don't fully understand the connection between result_ffi_guarantees versus the already documented behavior in https://doc.rust-lang.org/std/result/index.html#representation. Is that current documentation making a stronger statement than what is actually true today? Or is there something missing?

That IS the behavior with this feature.

The RFC mentions Option, but the two PRs above seem to only be for Result. What happened with Option?

Option already had such an ABI guarantee documented: https://doc.rust-lang.org/std/option/index.html#representation

Does result_ffi_guarantees actually change the layout, or is it just related to squelching the improper-ctypes lint?

My understanding is that it is not a functional behavioral change. It is a promise that the behavior will not change, and that if it varies from the documented behavior, it will be treated as a bug. To many developers, this is much more important than "how the compiler actually behaves".

Is there some difference between repr-Rust (guaranteed on stable) and repr-C (not niche-optimized on stable)?

I don't understand the question. Result is not a repr(C) type so this is irrelevant?

@workingjubilee
Copy link
Member

workingjubilee commented Sep 20, 2024

the RFC is not about:

  • Option, which already is in the desired state.
  • Other enums, which have no such guarantee.

the RFC is about:

  • Result<T, ()> and Result<(), T> where the T formed allows a niche optimization to track the Ok(()) or Err(()) tag, and other ZST types in lieu of (). In practice this means T is actually &T, &mut T, and the other NonWhatever types.

@chorman0773
Copy link
Contributor

FTR, I already have plans to redo the type-layout chapter, particularily the enum section. Option and Result will get their own few clauses in there.

@workingjubilee
Copy link
Member

Where is the stabilization report, and the t-lang approval of that?

gonna level with you here, this RFC was basically a stabilization report for a behavior we already implemented. 🙃

Why was the layout guarantee documented before it was stabilized?

I don't really know what to tell you here? This entire RFC arose because T-lang has such a crushingly low bandwidth that people have to use extremely high-volume signals (like RFCs) to get their attention for long. Then they have to make the RFC extremely conservative to avoid it being nitpicked to death. Then T-lang doesn't have sufficient bandwidth to properly shepherd something through its process so that missteps don't happen. So missteps happen.

I expect that can only realistically be solved by T-lang deciding to prioritize onboarding sufficient members in some capacity as to at least have a successorship. Perhaps they are actually doing that? But such would also consume their bandwidth, so either way, something like this was inevitable in some case.

I have no magical power to wave a wand and make them do that if they are not.

@chorman0773
Copy link
Contributor

Doing a stabilization report is probably a good idea nonetheless.

@workingjubilee
Copy link
Member

I suppose I will draft one, then! No promises it won't be very silly though.

@ehuss
Copy link
Contributor

ehuss commented Sep 20, 2024

I don't understand the question. Result is not a repr(C) type so this is irrelevant?

Oh, sorry, yea, that didn't make sense. My thinking was, do we have a stable guarantee such that let x: Result<NonZeroI32, ()> = unsafe { std::mem::transmute(12) }; is well-defined (all "Rust"-land), but extern "C" { fn f() -> Result<NonZeroI32, ()>; } is not (in "C" ABI land).

gonna level with you here, this RFC was basically a stabilization report for a behavior we already implemented. 🙃

That's what I'm trying to drill down to; is this just a documentation change, or is it a behavior change? If it was a documentation change, then I would not have expected #122253 to exist, unless the only goal there was to squelch improper-ctypes. The description of the PR doesn't really clarify what it does, and the RFC never mentions that lint.

For documentation-only changes, we have generally not required a stabilization report or separate FCP for an accepted RFC. Documentation-only RFCs normally get their doc changes merged almost right away, and there is no tracking issue. This seems slightly more than that, though.

I have no magical power to wave a wand and make them do that if they are not.

100% agree with you1, and I don't want to put up roadblocks where it's not appropriate. However, I do want to make sure that there is awareness and understanding of what is happening.

Footnotes

  1. You might be interested in https://github.com/rust-lang/lang-team/pull/290, which is a proposal to help scale some decision making.

@Lokathor
Copy link
Contributor

@ehuss I don't believe we have any guarantee that something is not defined.

In fact the entire point of the RFC is to make your example cose snippit be defined, as far as i can read it

@workingjubilee
Copy link
Member

workingjubilee commented Sep 20, 2024

@ehuss Of course! tbh I'm mostly just playing my occasional role of "clown that pratfalls into thing everyone is confused about, prompting everyone to laugh, cheer, boo, throw tomatoes, or buy popcorn". :^)

@workingjubilee
Copy link
Member

workingjubilee commented Sep 20, 2024

For documentation-only changes, we have generally not required a stabilization report or separate FCP for an accepted RFC. Documentation-only RFCs normally get their doc changes merged almost right away, and there is no tracking issue. This seems slightly more than that, though.

...speaking of documentation, is this written anywhere? I mean oral tradition is well and dandy but this actually seems worth formalizing because of the whole "T-lang has a tiny amount of bandwidth" 🫠 so it's good to note down when something only hard-requires one Formal Team Decision instead of two Formal Team Decisions.

I do think a tracking issue sometimes is warranted simply because "wait how many places do we have to update the documentation exactly...?" sometimes uhh needs a Formal Issue.

And there technically were related compiler changes in this re: the lint. I won't start an argument about whether lints are metaphysically also documentation, tho'. :^)

@workingjubilee
Copy link
Member

And yeah, with this feature, these are now both correct:

let x: Result<NonZeroI32, ()> = unsafe { std::mem::transmute(12) };
extern "C" {
    fn f() -> Result<NonZeroI32, ()>;
}

The latter even should, IIRC, be correct under the "integer normalization" CFI flag (which reduces entropy but enables certain ABI-compatible equivalencies). This is because the equivalence is sorta defined in terms of transmute:

If the declared signature and the signature of the function pointer are ABI-compatible, then the function call behaves as if every argument was transmuted from the type in the function pointer to the type at the function declaration, and the return value is transmuted from the type in the declaration to the type in the pointer. All the usual caveats and concerns around transmutation apply; for instance, if the function expects a NonZero<i32> and the function pointer uses the ABI-compatible type Option<NonZero<i32>>, and the value used for the argument is None, then this call is Undefined Behavior since transmuting None::<NonZero<i32>> to NonZero<i32> violates the non-zero requirement.

@workingjubilee
Copy link
Member

I have opened rust-lang/reference#1623 to track "documenting a complete explanation of our ABI rules, also what even is an ABI, huh? what?"

@RalfJung
Copy link
Member

RalfJung commented Sep 20, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants