I think this is infeasible and also the wrong way of thinking about FFI.
For something like #[repr(C++)] to be feasible, Rustās type system would have to be able to represent every detail of C++'s type system. That is not only not a reasonable design goal for the language, itās not even a desirable design goal; we actively want to be able to look at a C++ type-system feature and say āno, that is a bad feature and we are not copying it.ā
#[repr(C)] is feasible only because Cās type system is simple enough that it does make sense to clone every detail of it, and youāll note that there are still lacunae, e.g. last I checked transparent unions of structures were still not available, making it impossible to work with certain system APIs in Rust.
ABI-level annotations like the proposed #[pass_by(invisible_reference)] are feasible for the same reason #[repr(C)] is feasible: the possibility space is simple and orthogonal. There are only so many ways to pass arguments around, and only so many ways to lay out aggregate types in memory. (I would like to see Rust grow something like Adaās representation clauses, in the long term.) But theyāre also the right way to think about FFI, because they give you direct control over the properties that actually matter for interop. If you observe that
struct Bar {
size_t data;
~Bar() { data = 0; }
};
needs to be passed by invisible reference, you can just toggle that property on the Rust shim structure; you donāt have to know why pass-by-value is unwanted.
Itās true that low-level annotations donāt directly solve the problem of FFI interaction with C++. Something, or someone, has to track all the details of the C++ ABI and work out which annotations to apply to which shim structures. To some extent my strategy just moves the complexity from rustc to bindgen, but Iād argue that bindgen is the right place for it.