Skip to content

General pipeline updates #2536

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

bendk
Copy link
Contributor

@bendk bendk commented May 13, 2025

This were the result of me implementing the Python bindings using the new pipeline system. There were a handful of things I realized I needed/wanted there that didn't come up when I was implementing the JS bindings.

Add FfiTypeNode. I didn't originally have this as part of the general pipeline, since it wasn't needed there. However, virtually all language pipelines are going to want to add it so we may as well do it in shared code.

Determine enum discriminants for the bindings. This uses basically the same algorithm as from ComponentInterface. The one difference is that for enums without a specified repr, this calculates the smallest integer width needed to store the variants.

I used a new pipeline technique for the enum discriminents: the old/optional discr field gets renamed to meta_discr so that we can create a new/non-optional discr field.

Adding the Node::has_descendant method. I've noticed I'm implementing this code again and again, so it feels a good time to generalize.

Several other smaller changes/fixes.

@bendk bendk requested a review from a team as a code owner May 13, 2025 13:36
@bendk bendk requested review from gruberb and removed request for a team May 13, 2025 13:36
@bendk bendk force-pushed the push-uslvmlqkwwkx branch from 843e25c to 5ca7fa5 Compare May 13, 2025 13:43
..
} => {
match generate_ffi_type(builtin, current_module_name) {
// Fixup `module_name` for primitive types that lower to `RustBuffer`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this and the module/crate name confusion from the CI makes me sad. Isn't the module name the crate name transformed by the bindings config?

Can the bindings somehow fix this in a later stage? I don't quite get the new module node in the same way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's definitely sad. The corner case here is something like:

  • Crate A defines a custom URL type that lowers to a string
  • Crate B uses URL as an external type
  • When determining the FFI type, we start by getting the FFI type for the builtin. In this case the builtin type is string, so the FfiType is FfiType::RustBuffer(None).
  • However, since it's an external type used in crate B, we need to change that to FfiType::RustBuffer(Some("A"))

The core of this issue is the fact that we're creating multiple RustBuffer types, which means the custom URL type has 2 different ffi types, depending on the module FfiType::RustBuffer(None) vs FfiType::RustBuffer(Some("A")). Part of this is that FfiTypeRustBuffer(None) is special cased to mean "the RustBuffer from current module", which doesn't work well with external types.

Maybe it would be slightly cleaner to make the module name non-optional for RustBuffer. However, that's still pretty confusing. It means that when we're determining FFI types, we always need to know the "current module" and that module will change once you recurse inside an external type.

I think the real solution to this is having a single RustBuffer type that all modules share. At this point I'm very confident we can do that with this pipeline code.

@bendk bendk force-pushed the push-uslvmlqkwwkx branch from 5ca7fa5 to 0ac8418 Compare May 20, 2025 15:00
### Field Conversion order

Fields are converted in declaration order.
This matters when a field one uses `#[node(from(<name_of_the_another_field>)]`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is much clearer, thanks!

Maybe "This matters when a field is listed twice with one of them using #[node(from(<name_of_the_another_field>)]"?

(I'm still not quite sure what the semantics would be of the #[node(from(<name_of_the_another_field>)] field was listed second and the non-option item was listed first - how does the option get converted to the non-option there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That wording sounds good, thanks.

(I'm still not quite sure what the semantics would be of the #[node(from(<name_of_the_another_field>)] field was listed second and the non-option item was listed first - how does the option get converted to the non-option there?

That would be the same as the general case of converting an optional value into a non-option. It will always fail -- even if there were no None values (I'm not 100% sure on that, but I'm pretty sure that's how it should work).

@bendk bendk force-pushed the push-uslvmlqkwwkx branch from 0ac8418 to 6cddd0d Compare May 21, 2025 19:50
This were the result of me implementing the Python bindings using the
new pipeline system.  There were a handful of things I realized I
needed/wanted there that didn't come up when I was implementing the JS
bindings.

Add `FfiTypeNode`. I didn't originally have this as part of the general
pipeline, since it wasn't needed there.  However, virtually all language
pipelines are going to want to add it so we may as well do it in shared
code.

Determine enum discriminants for the bindings. This uses basically the
same algorithm as from `ComponentInterface`. The one difference is that
for enums without a specified `repr`, this calculates the smallest
integer width needed to store the variants.

I used a new pipeline technique for the enum discriminents: the
old/optional `discr` field gets renamed to `meta_discr` so that we can
create a new/non-optional `discr` field.

Adding the `Node::has_descendant` method. I've noticed I'm implementing
this code again and again, so it feels a good time to generalize.

Several other smaller changes/fixes.
@bendk bendk force-pushed the push-uslvmlqkwwkx branch 2 times, most recently from 0944997 to 89db902 Compare May 22, 2025 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants