From edb3a686cad56a73f74af1e3e94a1fca7a12a160 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 8 Feb 2019 18:29:45 +0100 Subject: [PATCH 1/5] Add an attribute to indicate that a function might return multiple times --- text/0000-returns-twice.md | 106 +++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 text/0000-returns-twice.md diff --git a/text/0000-returns-twice.md b/text/0000-returns-twice.md new file mode 100644 index 00000000000..5b1a678d896 --- /dev/null +++ b/text/0000-returns-twice.md @@ -0,0 +1,106 @@ +- Feature Name: ffi-returns-twice +- Start Date: 2019.02.08 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary +[summary]: #summary + +This RFC adds a new function attribute, `#[ffi_returns_twice]`, which indicates +that an `extern` function can return multiple times. + +# Motivation +[motivation]: #motivation + +Rust assumes that function calls like: + +```rust +let x = foo(); +``` + +return only once. That is, when the execution arrives at the function call, the +function is called, it returns a single value, and that's it. This assumption +allows Rust to perform many optimizations. + +However, some `extern` functions like [`setjmp`] and [`vfork`] can return +multiple times. + +The `#[ffi_returns_twice]` attribute specifies that an `extern` function might +returns multiple times, inhibiting optimizations that assume that this is never +the case. + +[`setjmp`]: https://en.cppreference.com/w/cpp/utility/program/setjmp +[`longjmp`]: https://en.cppreference.com/w/cpp/utility/program/longjmp +[`vfork`]: http://man7.org/linux/man-pages/man2/vfork.2.html + +# Guide-level and reference-level explanation +[guide-level-explanation]: #guide-level-explanation + +The `#[ffi_returns_twice]` function attribute specifies that an `extern` function +might return multiple times, disabling optimizations that are incorrect for such +functions. Two examples of such functions are [`setjmp`] and [`vfork`]. + +# Drawbacks +[drawbacks]: #drawbacks + +This complicates the language creating a new kind of functions. + +# Prior art +[prior-art]: #prior-art + +This attribute is provided in both [LLVM] and [GCC]. + +[LLVM]: https://llvm.org/docs/LangRef.html#id979 +[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html + +# Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + +In some platforms, efficient implementations of standard library APIs have to +call low-level platform APIs that return multiple times. For example, the +widely-used [`musl`] library implements [`posix_spawn`] on Linux by calling +[`vfork`] (see: [`musl` blog post]). Rust implementations of such libraries (for +example, see: [`steed`]) should be able to call these platform interfaces +without invoking undefined behavior. + +This RFC introduces a function attribute that disables incorrect optimizations +only for those functions for which they would be incorrect. + +One alternative could be to remove the assumption that Rust functions return at +most once, eliminating the need for this attribute. This would have negative +performance implications for most Rust functions, which do not return multiple +times, making Rust functions a non-zero-cost abstraction. + +Another alternative could be to not support interfacing with this type of +platform APIs, requiring users to use a different programming language (C, +Assembly, etc.) to do so. + +[`posix_spawn`]: http://man7.org/linux/man-pages/man3/posix_spawn.3.html +[`musl`]: https://www.musl-libc.org/ +[`musl` blog post]: https://ewontfix.com/7/ +[`steed`]: https://github.com/japaric/steed + +# Unresolved questions +[unresolved-questions]: #unresolved-questions + +Is this attribute sufficient to make write programs with functions that return +multiple times possible? + +# Future possibilities +[future-possibilities]: #future-possibilities + +This RFC attempts to make writing programs that interface with extern functions +that return multiple times possible, but doing so is very challenging because it +is trivial to introduce undefined behavior in those programs. + +Future RFCs could try to make it easier to avoid certain types of undefined +behavior. For example, we could extend the borrow checker to take +`#[ffi_returns_twice]` into account and reject programs that would have +undefined behavior of the type "use-after-move". + +In the presence of types that implement `Drop`, usage of APIs that return +multiple times requires extreme care to avoid deallocating memory without +invoking constructors. We could also explore diagnosing these cases. + +[`Drop`]: https://doc.rust-lang.org/std/ops/trait.Drop.html +[`Pin`]: https://doc.rust-lang.org/std/pin/struct.Pin.html From c33392c9865d3e886abca19c26e7257d1ef1be76 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 9 Feb 2019 20:38:42 +0100 Subject: [PATCH 2/5] Replace extern functions with foreign functions --- text/0000-returns-twice.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/text/0000-returns-twice.md b/text/0000-returns-twice.md index 5b1a678d896..1c78a854454 100644 --- a/text/0000-returns-twice.md +++ b/text/0000-returns-twice.md @@ -7,7 +7,7 @@ [summary]: #summary This RFC adds a new function attribute, `#[ffi_returns_twice]`, which indicates -that an `extern` function can return multiple times. +that an foreign function can return multiple times. # Motivation [motivation]: #motivation @@ -22,10 +22,10 @@ return only once. That is, when the execution arrives at the function call, the function is called, it returns a single value, and that's it. This assumption allows Rust to perform many optimizations. -However, some `extern` functions like [`setjmp`] and [`vfork`] can return +However, some foreign functions like [`setjmp`] and [`vfork`] can return multiple times. -The `#[ffi_returns_twice]` attribute specifies that an `extern` function might +The `#[ffi_returns_twice]` attribute specifies that a foreign function might returns multiple times, inhibiting optimizations that assume that this is never the case. @@ -36,7 +36,7 @@ the case. # Guide-level and reference-level explanation [guide-level-explanation]: #guide-level-explanation -The `#[ffi_returns_twice]` function attribute specifies that an `extern` function +The `#[ffi_returns_twice]` function attribute specifies that a foreign function might return multiple times, disabling optimizations that are incorrect for such functions. Two examples of such functions are [`setjmp`] and [`vfork`]. @@ -89,7 +89,7 @@ multiple times possible? # Future possibilities [future-possibilities]: #future-possibilities -This RFC attempts to make writing programs that interface with extern functions +This RFC attempts to make writing programs that interface with foreign functions that return multiple times possible, but doing so is very challenging because it is trivial to introduce undefined behavior in those programs. From 2f31cb86ba181e50fb786575db33b3e4e178239f Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Mon, 18 Feb 2019 14:27:47 +0100 Subject: [PATCH 3/5] Add using a different name and namingspacing the attribute as an unresolved question --- text/0000-returns-twice.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/text/0000-returns-twice.md b/text/0000-returns-twice.md index 1c78a854454..e381a0e844d 100644 --- a/text/0000-returns-twice.md +++ b/text/0000-returns-twice.md @@ -83,9 +83,17 @@ Assembly, etc.) to do so. # Unresolved questions [unresolved-questions]: #unresolved-questions -Is this attribute sufficient to make write programs with functions that return +* Is this attribute sufficient to make write programs with functions that return multiple times possible? +* Should we give this attribute a different name, e.g., + `#[might_return_multiple_times]` or similar? Currently, this attribute is + called `returns_twice` because that's how the C attribute is called. Using the + same name as C here makes life easier for them. + +* Should we namespace `ffi`-only attributes somehow (e.g. `#[ffi(returns_twice, + foo, bar)]` ? See: https://github.com/rust-lang/rfcs/issues/2637 + # Future possibilities [future-possibilities]: #future-possibilities From fcc83bba58d219101d4f979ccb811615fbd11db1 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Mon, 18 Feb 2019 14:29:19 +0100 Subject: [PATCH 4/5] Mention Pin's safety --- text/0000-returns-twice.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/text/0000-returns-twice.md b/text/0000-returns-twice.md index e381a0e844d..e58a2835d2c 100644 --- a/text/0000-returns-twice.md +++ b/text/0000-returns-twice.md @@ -108,7 +108,8 @@ undefined behavior of the type "use-after-move". In the presence of types that implement `Drop`, usage of APIs that return multiple times requires extreme care to avoid deallocating memory without -invoking constructors. We could also explore diagnosing these cases. +invoking destructors - this is critical for using [`Pin`] safely. We could also +explore diagnosing these cases. [`Drop`]: https://doc.rust-lang.org/std/ops/trait.Drop.html [`Pin`]: https://doc.rust-lang.org/std/pin/struct.Pin.html From e63371676761655f55de7b432bb783d77332a8a5 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Mon, 18 Feb 2019 14:29:53 +0100 Subject: [PATCH 5/5] Fix typo --- text/0000-returns-twice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-returns-twice.md b/text/0000-returns-twice.md index e58a2835d2c..11cc677a9b4 100644 --- a/text/0000-returns-twice.md +++ b/text/0000-returns-twice.md @@ -7,7 +7,7 @@ [summary]: #summary This RFC adds a new function attribute, `#[ffi_returns_twice]`, which indicates -that an foreign function can return multiple times. +that a foreign function can return multiple times. # Motivation [motivation]: #motivation