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

Allow coercing unboxed with payload to primitive when applicable #6441

Merged
merged 5 commits into from
Oct 19, 2023

Conversation

zth
Copy link
Collaborator

@zth zth commented Oct 18, 2023

Allows:

@unboxed
type someType = One | Two | Other(string)

let v = Other("Hello")
let v2 = One

Console.log((v :> string))
Console.log((v2 :> string))

Coercing from a variant to a string is OK when the variant only has cases that are represented as strings at runtime. This happens when all constructors in the variant conforms to the following:

  • It has no payload and no @as attribute. The default runtime representation of a variant constructor is a string since v11
  • It has an @as attribute and that attribute has a string payload
  • The variant is @unboxed and the constructor has a single payload that's a string

All of the cases above means that the variant will be represented as a string at runtime, and that means coercion to a string is safe.

Allowing going the "other way" is explored here: #6443

@zth zth force-pushed the coerce-untagged-variants-with-payload-to-primitive branch from 3c8cd67 to e737fab Compare October 18, 2023 20:03
@zth zth requested a review from cristianoc October 18, 2023 20:04
@zth zth marked this pull request as ready for review October 18, 2023 20:04
@cristianoc
Copy link
Collaborator

Could you write in words the conditions under which this coercion is OK? I think the conditions need to imply that every value represented in the variant is string.

Generally speaking this seems fine, if only a bit niche.

@zth
Copy link
Collaborator Author

zth commented Oct 19, 2023

@cristianoc I updated the OP with a list of conditions. Maybe I should also add them as an explicit comment in the code.

let check_paths_same p1 p2 target_path =
Path.same p1 target_path && Path.same p2 target_path

let can_coerce_variant ~(path : Path.t) ~unboxed
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the function's name should indicate that this function is for coercing a variant to a type.
And the for_all commented or refactored so the high-level algorithm is clear:

  • every case of the variant has the same runtime representation as the target type.

This allows to treat string and float at the same time as both conform to that algorithm.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, good catch! I'll clean these things up a bit.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Merge away when done.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@cristianoc please look at 95be068 to see if the refactor is clear enough.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Looks great

@unboxed type strings = String(string) | First | Second | Third
let a: strings = String("hello")
let aa: strings = First
let b: string = (a :> string)
Copy link
Collaborator

Choose a reason for hiding this comment

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

These 2 lines test the same thing. Does not hurt, but it's not helpful either.
Coercion works on types and does not depend on the specific instance.

Copy link
Collaborator

Choose a reason for hiding this comment

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

That said, it's kind of nice as documentation of the intentions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah that was my intention, to illustrate that it works for both the catch all case and the regular cases. But yes, it's not actually useful as a test, just illustrating for documentation purposes.

@zth zth merged commit 761adc2 into master Oct 19, 2023
@zth zth deleted the coerce-untagged-variants-with-payload-to-primitive branch October 19, 2023 12:35
@zth zth restored the coerce-untagged-variants-with-payload-to-primitive branch December 27, 2023 08:22
@zth zth deleted the coerce-untagged-variants-with-payload-to-primitive branch December 27, 2023 08:27
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.

2 participants