Skip to content
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

Use DiplomatSlice/etc instead of splitting params into data/len pairs #615

Merged
merged 15 commits into from
Aug 6, 2024

Conversation

Manishearth
Copy link
Contributor

@Manishearth Manishearth commented Aug 1, 2024

Fixes #613

Things this does not do that it should, but I might do in a followup:

  • Potentially get rid of DiplomatStr in favor of the new types. It's not really worth it to allow people to specify &[&DiplomatStr], they should just go all the way IMO.
  • Add checks so that the shortcuts are only allowed in params, not struct fields
  • Clean up the tests: Macro tests should also ensure stuff compiles #617
  • Use a StdlibOrRuntime enum instead of a boolean

@Manishearth Manishearth force-pushed the DiplomatSlice branch 2 times, most recently from 01c58b5 to 1ccf792 Compare August 1, 2024 12:13
@Manishearth Manishearth marked this pull request as ready for review August 1, 2024 12:13
@Manishearth Manishearth requested a review from sffc August 1, 2024 12:15
@Manishearth
Copy link
Contributor Author

@ambiguousname I'd like some help making the relevant changes here for JS.

The change made here is that basically until now slices in structs and params were handled differently: in a struct a slice becomes a DiplomatFooView C type, whereas in params it gets split into a foo_data and foo_len pair of parameters on the FFI function, which complicates conversion code (since now you need to branch on struct-vs-params, and you need to deal with the fact that some params end up becoming multiple params on the FFI function.

However I'm not super familiar with slice handling in your backend.

It appears to be the case that the Kotlin backend already handles things correctly (previously it was incorrect), where it didn't know about this issue with slice params. Fortunately, now that things are uniform, Kotlin is automagically correct already. cc @jcrist1 just so you're aware

I managed to make it work for Dart.

@Manishearth Manishearth marked this pull request as draft August 1, 2024 12:34
Copy link
Collaborator

@robertbastian robertbastian left a comment

Choose a reason for hiding this comment

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

not an in-depth review

runtime/src/slices.rs Outdated Show resolved Hide resolved
runtime/src/slices.rs Outdated Show resolved Hide resolved
runtime/src/slices.rs Outdated Show resolved Hide resolved
runtime/src/slices.rs Outdated Show resolved Hide resolved
Comment on lines 50 to 51
final (utf8StrData, utf8StrLength) = utf8Str._utf8AllocIn(utf8StrArena.arena);
final utf8Str = ffi.Struct.create<_SliceUtf8>();
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd push the struct creation into allocIn, but I can follow up

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd love that yeah.

@@ -75,6 +81,6 @@ final class BorrowedFields {
}

@meta.ResourceIdentifier('BorrowedFields_from_bar_and_strings')
@ffi.Native<_BorrowedFieldsFfi Function(ffi.Pointer<ffi.Opaque>, ffi.Pointer<ffi.Uint16>, ffi.Size, ffi.Pointer<ffi.Uint8>, ffi.Size)>(isLeaf: true, symbol: 'BorrowedFields_from_bar_and_strings')
@ffi.Native<_BorrowedFieldsFfi Function(ffi.Pointer<ffi.Opaque>)>(isLeaf: true, symbol: 'BorrowedFields_from_bar_and_strings')
Copy link
Collaborator

Choose a reason for hiding this comment

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

issue: the arguments disappeared

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. The param_types_ffi_cast etc stuff is kinda confusing, we generate a lot of different things in one function. I didn't bother to try and understand it too deeply but we should document this better if we get the chance.

(Also now that this is no longer doing two-parameter stuff we probably can clean things up)

feature_tests/dart/lib/src/BorrowedFields.g.dart Outdated Show resolved Hide resolved
@Manishearth
Copy link
Contributor Author

I'm signing off soon, but @robertbastian please do feel free to polish up the Dart section and push, I did a quick-and-dirty fix which still appears to be broken.

(let me know if you've pushed though, so I don't overwrite)

@Manishearth Manishearth force-pushed the DiplomatSlice branch 2 times, most recently from 7b9435a to cfa3d00 Compare August 1, 2024 13:27
@Manishearth
Copy link
Contributor Author

I tried to fix some things but Dart's still broken

@ambiguousname
Copy link
Member

ambiguousname commented Aug 1, 2024

I'll take a look and adjust the JS backend. We have a few open issues with how JS handles slices anyways (I believe to do with cleanup in particular), so maybe I can re-write the JS slices system to account for those issues in addition to your changes. I'll ping you before EOD today when I've got something.

@Manishearth
Copy link
Contributor Author

found a double free and also fixed the dart issues, but won't be able to push for another hour I think

@ambiguousname
Copy link
Member

ambiguousname commented Aug 1, 2024

@Manishearth I did some review of the updated .wasm output and how JS handles slices; I believe JS handles slices the same whether they're being used as struct fields or function parameters.

WASM output still requires a pointer and size, the new types are ignored: (func $icu4x_Locale_new_mv1 (type 3) (param i32 i32) (result i32)

As for backend logic, JS uses the same DiplomatBuf type for slices regardless of conversion context.

For clarity, struct field conversion is done in js/type_generation/mod.rs, line 165 and parameter conversion is done js/type_generation/mod.rs, line 307. Both use the same gen_js_to_c_for_type function.

The only change I can think of is renaming DiplomatBuf to DiplomatSliceBuf for clarity?

As a caveat, I can't seem to find tests in feature_tests that handle cases where a struct has a DiplomatSlice as a member, so I can't verify JS behavior. JS does pass all tests (including the one slice test that's in its suite) with the new changes.

TL;DR JS already handles slices for structs and function parameters in the same way. If I'm missing something or you'd like additional changes, let me know.

@Manishearth Manishearth force-pushed the DiplomatSlice branch 2 times, most recently from bf2a12a to 44a2547 Compare August 1, 2024 15:42
@Manishearth Manishearth marked this pull request as ready for review August 1, 2024 15:43
@Manishearth
Copy link
Contributor Author

Oh yeah, that makes sense, the WASM abi hates structs so everything is done splatted out anyway. Nice to not have to worry about this!

@Manishearth Manishearth force-pushed the DiplomatSlice branch 3 times, most recently from b14c6d2 to cf81dc3 Compare August 1, 2024 16:55
@Manishearth Manishearth mentioned this pull request Aug 1, 2024
@Manishearth
Copy link
Contributor Author

And CI passes!

@Manishearth
Copy link
Contributor Author

That took less time than I expected.

As a bonus, this simplifies the macro code so a lot of the gnarly DiplomatOption handling I wanted to do becomes really straightforward, and that reduces the amount of macro mess that was going to be in #558 ! (I never pushed the macro mess code because I was annoyed with it)

Copy link
Collaborator

@robertbastian robertbastian left a comment

Choose a reason for hiding this comment

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

LG overall. Will work on the Dart simplifications so please no more force pushes.

core/src/ast/types.rs Show resolved Hide resolved
example/c/main.c Outdated Show resolved Hide resolved
@Manishearth
Copy link
Contributor Author

Sounds good. I'll try to merge as soon as possible to avoid you needing to patch stack

@Manishearth Manishearth merged commit 2754a5f into rust-diplomat:main Aug 6, 2024
15 checks passed
@Manishearth Manishearth deleted the DiplomatSlice branch August 6, 2024 08:52
DiplomatStringView bn = {"bn", 2};

Locale* locale = icu4x_Locale_new_mv1(bn);
Locale* locale = icu4x_Locale_new_mv1((DiplomatStringView){.data = "bn", .len = 2});
Copy link
Collaborator

Choose a reason for hiding this comment

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

does this really need the cast? 😕

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 fails to parse without the cast. I don't understand it either.

C is weird and has terrible errors, if you can figure out how to avoid the cast be my guest 🙃🙃

Copy link
Collaborator

Choose a reason for hiding this comment

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

ew. in that case I'm not sure if the inline is actually nicer 🤷

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah feel free to change it back if you'd like. I'm very ambivalent here

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.

Should we stop splitting out data,len pairs when slices show up in FFI params?
3 participants