Description
In our project, we need to control which exceptions get thrown into C++ code from our Rust callbacks (i.e., it can't be rust::Error
, not even std::exception
, it has to be one of the project-specific exception types).
The PR #1180 already provides some basics to be able to handle custom errors using a callback into C++ to construct the exception (via ToCxxException
trait). However, this is not sufficient, since we need to handle also "standard" exceptions like AllocError
or std::io::Error
to throw respective C++ exceptions.
One possible way would be to add ToCxxException
for some standard Rust errors (which is probably desirable on its own), but due to the Rust type system, such implementations must reside in cxx
crate. Adding the possibility to register callbacks to generate different exceptions for all these types would bloat the cxx
crate unnecessarily.
The proposal is thus to simply leave this to the implementor of the higher layer functionality (i.e., our team in this case) to actually convert errors to C++ exceptions in an application-specific way.
In #1180, the default mapping is done using cxx::map_rust_error_to_cxx_exception
macro. This currently only handles CxxException
specially to allow for transparent passing of C++ exceptions through Rust frames. As mentioned, this could be extended for some standard exceptions.
However, to make this fully flexible, we can simply add an attribute with the path to the macro on the bridge/extern block/function (typically only on the bridge) to specify this mapping macro explicitly. Then, the bridge will generate the code to map the error to the exception in a user-specific way, avoiding bloat in the cxx
crate.
The current working proposal is:
#[cxx::bridge(namespace = "my_crate")]
#[error_mapper = ::my_crate::map_rust_error_to_cxx_exception]
pub mod ffi {
...
}
where my_crate::map_rust_error_to_cxx_exception
is a macro taking one ident
or expr
with the value of the Rust error and returning a cxx::CxxException
object built for it. Since it's a macro, it can implement the semi-specialization trick via multiple trait impls shadowing each other in a deterministic way to handle some errors explicitly and some by a common fallback path, much like already done in the cxx
crate.
We have the implementation already done in mere ~60 LOCs on top of #1180, but cannot publish it yet, since that PR is still pending.
Any further ideas/opinions/suggestions for the attribute name?
Thanks.