On Sat, Apr 17, 2021 at 01:46:35AM +0200, Miguel Ojeda wrote: > On Sat, Apr 17, 2021 at 12:04 AM Willy Tarreau <w@xxxxxx> wrote: > > > > But my point remains that the point of extreme care is at the interface > > with the rest of the kernel because there is a change of semantics > > there. > > > > Sure but as I said most often (due to API or ABI inheritance), both > > are already exclusive and stored as ranges. Returning 1..4095 for > > errno or a pointer including NULL for a success doesn't shock me at > > all. > > At the point of the interface we definitely need to take care of > converting properly, but for Rust-to-Rust code (i.e. the ones using > `Result` etc.), that would not be a concern. Sure. > Just to ensure I understood your concern, for instance, in this case > you mentioned: > > result.status = foo_alloc(); > if (!result.status) { > result.error = -ENOMEM; > return result; > } Yes I mentioned this when it was my understanding that the composite result returned was made both of a pointer and an error code, but Connor explained that it was in fact more of a selector and a union. > Is your concern is that the caller would mix up the `status` with the > `error`, basically bubbling up the `status` as an `int` and forgetting > about the `error`, and then someone else later understanding that > `int` as a non-error because it is non-negative? My concern was to know what field to look at to reliably detect an error from the C side after a sequence doing C -> Rust -> C when the inner C code uses NULL to mark an error and the upper C code uses NULL as a valid value and needs to look at an error code instead to rebuild a result. But if it's more: if (result.ok) return result.pointer; else return (void *)-result.error; then it shouldn't be an issue. Willy