-
Notifications
You must be signed in to change notification settings - Fork 230
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
Add name mangling for method and type names to fit foreign language naming conventions #2
Conversation
Great, thanks for diving in!! I had I think it makes sense to pursue the " rust devs are delivering generated APIs to App developers" philosophy, at least to start. So being able to generate bindings that feel like they fit in the target language will be important. I'll try to carve out some time to take a detailed look later today. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all looks pretty reasonable to me! Some thoughts below that it would be good to get your take on, but if you think it's useful and ready to merge, I'd be happy to take it 👍
|
||
namespace naming_conventions { | ||
snake_case_object snake_case_method(u32 id); | ||
CamelCaseObject camelCaseMethod(u32 id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting philosophical point here about what to allow in the IDL, and I'm kind of in two minds about it. On one hand, it seems wrong to outright error out if something declared in this file does not match a particular naming convention, but on the other hand, allowing mixing conventions like this might lead to confusion. Perhaps it's the sort of thing that might one day be a candidate for a warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See discussion below. I think the chance of collision is too high here.
src/bindings/kotlin/gen_kotlin.rs
Outdated
@@ -283,13 +284,13 @@ internal interface _UniFFILib : Library { | |||
// Public interface members begin here. | |||
|
|||
{% for e in ci.iter_enum_definitions() %} | |||
enum class {{ e.name() }} { | |||
enum class {{ e.name()|decl_name_kt }} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably not clear from the code, but in my head I'd originally intended the "decl" prefix on these filter function to be read as "declare type". Something like "class_name_kt" might be a clearer name for this filter (and the existing "decl_kt" might be better as something like "type_kt" for clarity).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll change functions as you suggest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
src/scaffolding.rs
Outdated
@@ -34,7 +35,7 @@ ffi_support::define_bytebuffer_destructor!({{ ci.ffi_bytebuffer_free().name() }} | |||
// of items as declared in the rust code, but no harm will come from it. | |||
|
|||
{% for e in ci.iter_enum_definitions() %} | |||
unsafe impl uniffi::support::ViaFfi for {{ e.name() }} { | |||
unsafe impl uniffi::support::ViaFfi for {{ e.name()|decl_name_rs }} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than doing this conversion when generating the Rust scaffolding, what do you think about the following approach:
- Decree that the naming convention in the IDL should be the same as the naming convention in the Rust code (but allow users to write it differently if they want, maybe with a warning in future).
- When parsing the IDL, canonicalize all names to the rust convention as part of building the
ComponentInterface
struct (this would be the place where we warn about it in future). - Allow each foreign language binding to choose whether and how it wants to deviate from that convention to fit in with the norms of that language.
Alternately, we could just insist that the names in Rust and IDL must match exactly, however you've written them, and not try to do any conversion.
Keeping the IDL and the Rust more tightly bound makes sense to me in a vague kind of way, especially if we imagine that one day we might general definitions using inline rust macros rather than a separate IDL file. It would also mean there are no "control knobs" for callers to fiddle with when interfacing between the IDL and the Rust code, while allowing the possibility of such knobs when generating the bindings (which there is also a placeholder Config
class for in the kotlin and python bindings generators).
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, I agree with your:
insist that the names in Rust and IDL must match
while allowing the possibility of such knobs when generating the bindings
There will be some back pressure from the hand written rust from the linter or rustc so that the rust and WebIDL will naturally tend to conform to a rust naming convention— because the rust compiler will insist, rather than uniffi
. If users really want to have funky rust identifiers, they'll have to add their own annotations in rust.
The foreign language bindings are a view onto the WebIDL, so I think they should have a little bit of leeway to convert/mangle names to suite the language/project. I don't think we should do it without configuration in the long run because:
- collisions are still possible, (the webIDL could define
foo_bar
andfooBar
, which would both convert to the same methods). This might correspond to a normalize + check step before generating any bindings. - generating source-backward-compatible bindings for existing projects may still be an aim for the project.
If all this is desirable, then we should also consider doing the same for the property names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
collisions are still possible, (the webIDL could define foo_bar and fooBar, which would both convert to the same methods).
This might correspond to a normalize + check step before generating any bindings.
This is a good point; I think I'd be interested in trying out a normalize+check step when processing the IDL. In the same way that we'd error out if you tried to define two methods with exactly the same name, we could error out if you try to define two methods that would be ambiguous under common case conversions. (And it seems easier to error out now and loosen the rules later, than to start with loose rules and try to tighten them up later).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed name mangling in scaffolding.rs
and filed #13.
What I also need to do, is figure out some basic test infrastructure here. I'd like to be able to turn the existing |
(heads-up that I edited this PR to target the new |
Thanks for pushing on this! Just wanted to comment to set expectations, I should be able to find time to look at it by end-of-week. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming cleanups/consistency really made a difference here, I like the way this reads. Thanks!
throw RuntimeException("invalid enum value, something is very wrong!!") | ||
} | ||
internal fun lift(n: Int) = | ||
try { values()[n - 1] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, neat!
proc-macro: Silence UnwindSafe error without Mutex
This PR may not be useful, but starts as a way of exploring the codebase. Absenting some issues ;)
Is this useful?
This should probably be a candidate for project specific/language specific
uniffi
config.