From 233578e6767f7a9263bcab58d9d24d058d0d2b18 Mon Sep 17 00:00:00 2001 From: "Adam C. Foltzer" Date: Tue, 10 Sep 2019 12:23:37 -0700 Subject: [PATCH 1/5] switch from annotation approach to new ABI string approach --- text/0000-simple_unwind_annotation.md | 42 ++++++++++++++++++--------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/text/0000-simple_unwind_annotation.md b/text/0000-simple_unwind_annotation.md index ec91d0b4..29433591 100644 --- a/text/0000-simple_unwind_annotation.md +++ b/text/0000-simple_unwind_annotation.md @@ -1,4 +1,4 @@ -- Feature Name: `simple_unwind_attribute` +- Feature Name: `simple_c_panic_abi` - Start Date: 2019-08-29 - RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) - Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) @@ -6,8 +6,8 @@ # Summary [summary]: #summary -Provides an annotation to permit functions with explicit ABI specifications -(such as `extern "C"`) to unwind, and affirms that calls to function pointers with explicit ABI specifications may unwind. +Provides a new ABI string `extern "C+panic"` to denote functions that use the C ABI, but may also +unwind with a Rust panic. # Motivation [motivation]: #motivation @@ -50,21 +50,23 @@ compatible with the unspecified Rust unwinding mechanism. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation -When used on Rust functions with non-Rust ABIs (e.g. `extern "C" fn`), the `#[unwind(allowed)]` attribute permits unwinding out of the annotated function; without the attribute, the process will automatically be terminated at the function boundary. +Rust function definitions with the `"C+panic"` ABI string (e.g., `extern "C+panic" fn`) are +permitted to unwind with a panic, as opposed to `extern "C" fn` functions which will abort the +process if a panic reaches the function boundary. -When used on declarations of imported functions (e.g. `extern "C" { fn ... }`), the `#[unwind(allowed)]` attribute ensures that if the function unwinds, the unwind will be propagated though any calling code; without the attribute, the behavior is undefined. - -Calls to function pointers with non-Rust ABIs, as opposed to declared or defined functions, -currently are permitted to unwind. This RFC does not change this behavior. +When used on declarations of imported functions (e.g., `extern "C+panic" { fn ... }`), or function +pointers (e.g., `extern "C+panic" fn()`) the `"C+panic"` ABI string means that if the function +unwinds, the unwind will be propagated though any calling code. If an `extern "C"` imported function +or function pointer unwinds, the behavior is undefined. # Reference-level explanation [reference-level-explanation]: #reference-level-explanation -By default, Rust assumes that an external function imported with `extern "C" { +Currently, Rust assumes that an external function imported with `extern "C" { ... }` (or another ABI other than `"Rust"`) cannot unwind, and Rust will abort if a panic would propagate out of a -Rust function with a non-"Rust" ABI ("`extern "ABI" fn`") specification. If you specify -the `#[unwind(allowed)]` attribute on a function with a non-"Rust" ABI, Rust -will instead allow an unwind (such as a panic) to proceed through that function +Rust function with a non-"Rust" ABI ("`extern "ABI" fn`") specification. Under this RFC, +functions with the `"C+panic"` ABI string +instead allows an unwind (such as a panic) to proceed through that function boundary using Rust's normal unwind mechanism. This may potentially allow Rust code to call non-Rust code that calls back into Rust code, and then allow a panic to propagate from Rust to Rust across the non-Rust code. @@ -77,11 +79,16 @@ unwinds. Propagating a Rust panic through non-Rust code is unspecified; implementations that define the behavior may require target-specific options for the non-Rust code, or this feature may not be supported at all. +For the purposes of the type system, `"C+panic"` is considered a totally distinct ABI string from +`"C"`. While there may be some circumstances where it is sensible to use an `extern "C" fn` in place +of an `extern "C+panic" fn`, and vice-versa, this introduces questions of subtyping and variance +that are beyond the scope of this RFC. This restrictive approach is forwards-compatible with more +permissive typing in future work like #2699. + # Drawbacks [drawbacks]: #drawbacks - Only works as long as the foreign code supports the same unwinding mechanism as Rust. (Currently, Rust and C++ code compiled for ABI-compatible backends use the same mechanism.) -- Does not allow external library bindings to specify whether callbacks they accept are expected to unwind. # Rationale and alternatives [rationale-and-alternatives]: #rationale-and-alternatives @@ -127,6 +134,15 @@ The alternatives considered are: attribute means that we can address those current needs right away, and then transition to #2699's eventual solution by converting the attribute into a deprecated proc-macro. +3. Using an attribute on function definitions and declarations to indicate that unwinding should be + allowed, regardless of the ABI string. This would be easy to implement, as there is currently + such an attribute in unstable Rust. An attribute is not a complete solution, though, as there is + no current way to syntactically attach an attribute to a function pointer type. We considered + making all function pointers unwindable without changing the existing syntax (see #2602), because + Rust currently does not emit `nounwind` for calls to function pointers, however this would + require changes to the language reference that would codify inconsistency between function + pointers and definitions/declarations. + # Prior art [prior-art]: #prior-art From 85944045cdc1357d7af55f4c4b41c5f22e368338 Mon Sep 17 00:00:00 2001 From: "Adam C. Foltzer" Date: Tue, 10 Sep 2019 12:27:46 -0700 Subject: [PATCH 2/5] fix link to related RFC PR --- text/0000-simple_unwind_annotation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/text/0000-simple_unwind_annotation.md b/text/0000-simple_unwind_annotation.md index 29433591..c7a023f3 100644 --- a/text/0000-simple_unwind_annotation.md +++ b/text/0000-simple_unwind_annotation.md @@ -137,11 +137,11 @@ The alternatives considered are: 3. Using an attribute on function definitions and declarations to indicate that unwinding should be allowed, regardless of the ABI string. This would be easy to implement, as there is currently such an attribute in unstable Rust. An attribute is not a complete solution, though, as there is - no current way to syntactically attach an attribute to a function pointer type. We considered - making all function pointers unwindable without changing the existing syntax (see #2602), because - Rust currently does not emit `nounwind` for calls to function pointers, however this would - require changes to the language reference that would codify inconsistency between function - pointers and definitions/declarations. + no current way to syntactically attach an attribute to a function pointer type (see + https://github.com/rust-lang/rfcs/pull/2602). We considered making all function pointers + unwindable without changing the existing syntax, because Rust currently does not emit `nounwind` + for calls to function pointers, however this would require changes to the language reference that + would codify inconsistency between function pointers and definitions/declarations. # Prior art [prior-art]: #prior-art From 8c78012d264e46ccfad58fccca810c6b7ea156fb Mon Sep 17 00:00:00 2001 From: "Adam C. Foltzer" Date: Tue, 10 Sep 2019 12:34:09 -0700 Subject: [PATCH 3/5] `"C+panic"` -> `"C panic"` per current discussion --- text/0000-simple_unwind_annotation.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/text/0000-simple_unwind_annotation.md b/text/0000-simple_unwind_annotation.md index c7a023f3..6509c65e 100644 --- a/text/0000-simple_unwind_annotation.md +++ b/text/0000-simple_unwind_annotation.md @@ -6,7 +6,7 @@ # Summary [summary]: #summary -Provides a new ABI string `extern "C+panic"` to denote functions that use the C ABI, but may also +Provides a new ABI string `extern "C panic"` to denote functions that use the C ABI, but may also unwind with a Rust panic. # Motivation @@ -50,12 +50,12 @@ compatible with the unspecified Rust unwinding mechanism. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation -Rust function definitions with the `"C+panic"` ABI string (e.g., `extern "C+panic" fn`) are +Rust function definitions with the `"C panic"` ABI string (e.g., `extern "C panic" fn`) are permitted to unwind with a panic, as opposed to `extern "C" fn` functions which will abort the process if a panic reaches the function boundary. -When used on declarations of imported functions (e.g., `extern "C+panic" { fn ... }`), or function -pointers (e.g., `extern "C+panic" fn()`) the `"C+panic"` ABI string means that if the function +When used on declarations of imported functions (e.g., `extern "C panic" { fn ... }`), or function +pointers (e.g., `extern "C panic" fn()`) the `"C panic"` ABI string means that if the function unwinds, the unwind will be propagated though any calling code. If an `extern "C"` imported function or function pointer unwinds, the behavior is undefined. @@ -65,7 +65,7 @@ or function pointer unwinds, the behavior is undefined. Currently, Rust assumes that an external function imported with `extern "C" { ... }` (or another ABI other than `"Rust"`) cannot unwind, and Rust will abort if a panic would propagate out of a Rust function with a non-"Rust" ABI ("`extern "ABI" fn`") specification. Under this RFC, -functions with the `"C+panic"` ABI string +functions with the `"C panic"` ABI string instead allows an unwind (such as a panic) to proceed through that function boundary using Rust's normal unwind mechanism. This may potentially allow Rust code to call non-Rust code that calls back into Rust code, and then allow a @@ -79,9 +79,9 @@ unwinds. Propagating a Rust panic through non-Rust code is unspecified; implementations that define the behavior may require target-specific options for the non-Rust code, or this feature may not be supported at all. -For the purposes of the type system, `"C+panic"` is considered a totally distinct ABI string from +For the purposes of the type system, `"C panic"` is considered a totally distinct ABI string from `"C"`. While there may be some circumstances where it is sensible to use an `extern "C" fn` in place -of an `extern "C+panic" fn`, and vice-versa, this introduces questions of subtyping and variance +of an `extern "C panic" fn`, and vice-versa, this introduces questions of subtyping and variance that are beyond the scope of this RFC. This restrictive approach is forwards-compatible with more permissive typing in future work like #2699. From cdd2ab11627c0f82bd434bf89d22ed958ebdbb7f Mon Sep 17 00:00:00 2001 From: "Adam C. Foltzer" Date: Tue, 10 Sep 2019 12:42:14 -0700 Subject: [PATCH 4/5] Apply suggestions from code review Co-Authored-By: Kyle J Strand --- text/0000-simple_unwind_annotation.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0000-simple_unwind_annotation.md b/text/0000-simple_unwind_annotation.md index 6509c65e..9126f8c0 100644 --- a/text/0000-simple_unwind_annotation.md +++ b/text/0000-simple_unwind_annotation.md @@ -54,8 +54,8 @@ Rust function definitions with the `"C panic"` ABI string (e.g., `extern "C pani permitted to unwind with a panic, as opposed to `extern "C" fn` functions which will abort the process if a panic reaches the function boundary. -When used on declarations of imported functions (e.g., `extern "C panic" { fn ... }`), or function -pointers (e.g., `extern "C panic" fn()`) the `"C panic"` ABI string means that if the function +When used on declarations of imported functions (e.g., `extern "C panic" { fn ... }`) or function +pointers (e.g., `extern "C panic" fn()`), the `"C panic"` ABI string means that if the function unwinds, the unwind will be propagated though any calling code. If an `extern "C"` imported function or function pointer unwinds, the behavior is undefined. @@ -80,8 +80,8 @@ implementations that define the behavior may require target-specific options for the non-Rust code, or this feature may not be supported at all. For the purposes of the type system, `"C panic"` is considered a totally distinct ABI string from -`"C"`. While there may be some circumstances where it is sensible to use an `extern "C" fn` in place -of an `extern "C panic" fn`, and vice-versa, this introduces questions of subtyping and variance +`"C"`. While there may be some circumstances for which an `extern "C" fn` in place +of an `extern "C panic" fn` (or vice-versa) would be useful, this introduces questions of subtyping and variance that are beyond the scope of this RFC. This restrictive approach is forwards-compatible with more permissive typing in future work like #2699. From 090838351107d85e6f121fba42925de0df9bac22 Mon Sep 17 00:00:00 2001 From: "Adam C. Foltzer" Date: Tue, 10 Sep 2019 12:43:53 -0700 Subject: [PATCH 5/5] fix up grammar --- text/0000-simple_unwind_annotation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-simple_unwind_annotation.md b/text/0000-simple_unwind_annotation.md index 9126f8c0..1abef470 100644 --- a/text/0000-simple_unwind_annotation.md +++ b/text/0000-simple_unwind_annotation.md @@ -66,7 +66,7 @@ Currently, Rust assumes that an external function imported with `extern "C" { ... }` (or another ABI other than `"Rust"`) cannot unwind, and Rust will abort if a panic would propagate out of a Rust function with a non-"Rust" ABI ("`extern "ABI" fn`") specification. Under this RFC, functions with the `"C panic"` ABI string -instead allows an unwind (such as a panic) to proceed through that function +instead allow Rust panic unwinding to proceed through that function boundary using Rust's normal unwind mechanism. This may potentially allow Rust code to call non-Rust code that calls back into Rust code, and then allow a panic to propagate from Rust to Rust across the non-Rust code.