-
Notifications
You must be signed in to change notification settings - Fork 32
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
Implement more ergonomic rustls_result? #513
Comments
@jsha I would be curious to hear your thoughts on this as the originator of |
I think the key change that made this viable was RFC 3391: rust-lang/rfcs#3391 It's not clear to me yet if this is limited to specific Rust versions+ |
I did a bit of experimentation and the results (so far) are not super promising. I'm not sure yet if the root cause is my own misunderstanding or a limitation of Based on the discussion above I'd expect this function to be FFI-safe (and indeed it produces no "not FFI-safe" warning, as expected): pub const MAY_FAIL_ARG_ZERO_ERR: u32 = 99;
#[no_mangle]
extern "C" fn may_fail(arg: u32) -> Result<(), NonZeroU32> {
match arg == 0 {
true => Err(NonZeroU32::new(MAY_FAIL_ARG_ZERO_ERR).unwrap()),
false => Ok(()),
}
} However, when run through #define MAY_FAIL_ARG_ZERO_ERR 99
typedef struct Result_u32 Result_u32;
struct Result_u32 may_fail(uint32_t arg); Changing #define MAY_FAIL_ARG_ZERO_ERR 99
uint32_t may_fail(uint32_t arg); Edit: opened mozilla/cbindgen#1035 with |
This does have some significant advantages! My original thoughts in defining RUSTLS_RESULT_OK == 7000 was that some C APIs return 0 for success; others return non-zero for success; and in my unscientific observations of bug histories, it seems like confusion between the two is a moderately common source of bugs. The fact that it enables shorthand like However, I don't feel strongly enough about the decision to say we shouldn't change it if we can reap some ergonomic benefits.
My guess here is that (a) cbindgen may not have code to take advantage of the representation guarantees you mention, and (b) it would probably require some opt-in since not all Option/Result returns necessarily want to export the details of their representation. |
Thanks for your input!
Agreed - this is a nice property. Maybe for a crate like this it makes more sense to prioritize the C API user experience (especially given the danger that misuse presents in that context) as opposed to the Rust developer experience.
That's my intuition too. The guarantee for the I think considering: how much time I have to invest in this particular task, the state of It might be worth revisiting in the future but I'd consider |
In error.rs we define a
repr(u32)
enum,rustls_result
, and use it throughout the API as an ABI-stable, FFI-friendly way of representing what a Rustacean would probably write asResult<(), NonZero<u32>>
. This is mechanically safe, but also makes the Rust code awkward, in particular precluding use of?
. It also reduces type-safety by using the same type for both success and error (rustls_result::OK
&rustls_result::*
vsOk(())
&Err(_)
variants).It was pointed out to me a while ago by @complexspaces that
Result
is documented to have the same stable ABI/repr asOption<T>
, subject to some caveats. The docs say:I think changing our API to use
Result<(), NonZeroU32>
would be an ergonomics/safety improvement for the Rust code assuming there aren't any additional "gotchas" lurking here. My thinking is we would renamerustls_result
torustls_error
and remove therustls_result::Ok
value.From an API compatibility standpoint my main concern is how invasive this will be due to
rustls_result::Ok
being defined as7000
presently. AIUI a caller that got anOk(())
from anextern "C" fn rustls_foo() -> Result<(), NonZeroU32>
would now have0
in hand, as opposed to7000
. This is mainly a concern if someone wasn't using the.h
constants (e.g.if(rr == 7000)
vsif(rr == RUSTLS_RESULT_OK)
) - it seems to me it's fair to say those people (if they exist) are already begging for bugs?We have a sem-ver incompatible 0.15.0 release coming up Soon ™️ so maybe we should do this?
The text was updated successfully, but these errors were encountered: