Use static assertions to check uniffi/uniffi-bindgen version compatibility. (#414)
Fixes #413.
Prior to this commit, the `uniffi-bindgen` command would use `cargo metadata`
to discover the version of uniffi being used by the target crate, and would
error out if did not match the version of uniffi-bindgen itself.
Unfortunately, this approach is not reliable when the target crate is being
compiled as a dependency rather than as the primary crate. The build process
may pick a version of uniffi based on the `Cargo.lock` of the primary crate
or based on resolving compatible versions with other dependencies, while
while `cargo metadata` will report the verison of uniffi that would be used
if you built the target crate in isolation.
To avoid these potential sources of error, this commit switches to an approach
based on static assertions, in two halves:
* When generating the Rust scaffolding, we emit a call to a new
macro `uniffi::assert_compatible_version!(v)` and pass it a static
string constant representing the version of uniffi_bindgen that
generated the code.
* When compiling the resulting code as part of a uniffied crate, the
`assert_compatible_version!` macro will check the static string against
the version of uniffi being used in the build, producing a compile-time
failure if they do not match.
This is a slightly worse consumer experience because the error message
isn't as good, but it's more reliable, so I think it's a win overall.
Be warned, I had to do some terrible things to perform this check in
a compile-time const context on stable Rust :-/
I've also taken the opportunity to try out the `trybuild` crate to
write a testcase for the actual compiler error message generated
by the macro. As we come to iterate more on the developer experience,
I expect `trybuild` or something like it will become pretty important.