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 explicit nil to be serialized by enums #7896

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

Conversation

thomasmarshall
Copy link
Contributor

This commit uses an UNSET constant as the default serialized_val on T::Enum. This allows the runtime to understand the difference between an explicit nil and an unset default when serializing enum values. Sorbet already understands statically that a serialized value can be of type NilClass, but the runtime was serializing as a string representation based on the constant name instead.

Motivation

Fixes #7702.

Test plan

See included automated tests.

@thomasmarshall thomasmarshall requested a review from a team as a code owner May 19, 2024 09:40
@thomasmarshall thomasmarshall requested review from froydnj and removed request for a team May 19, 2024 09:40
serialized_vals = orphaned_instances.map do |instance|
serialized_val = instance.instance_variable_get('@serialized_val')
serialized_val.equal?(UNSET) ? 'unset' : serialized_val.inspect
end.join(', ')
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a bit awkward, but otherwise unset values will appear in the error message like [#<Object:0x0000000101376e08>]. That's because the @serialized_val instance variable hasn't yet been reassigned to a string representation of the constant name (which doesn't exist).

Copy link
Collaborator

@jez jez May 20, 2024

Choose a reason for hiding this comment

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

You can fix this by declaring UNSET as

UNSET = Module.new.freeze

instead of Object.new.freeze. This way, the to_s method of the UNSET object will be implemented by way of forwarding onto UNSET.name, which because the module has been assigned to a constant, will use that constant's name.

If you make that change, you can put these lines back to what they were.

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's much nicer, thanks for the suggestion.

@thomasmarshall thomasmarshall force-pushed the enum-serialize-nil branch 2 times, most recently from 0ee960e to 7696007 Compare May 21, 2024 08:10
This commit uses an `UNSET` constant as the default `serialized_val` on
`T::Enum`. This allows the runtime to understand the difference between
an explicit `nil` and an unset default when serializing enum values.
Sorbet already understands statically that a serialized value can be of
type `NilClass`, but the runtime was serializing as a string
representation based on the constant name instead.
@thomasmarshall
Copy link
Contributor Author

I force pushed to add a T.let assertion to the constant.

@jez
Copy link
Collaborator

jez commented Jun 3, 2024

We have a policy of testing changes to Sorbet against Stripe's codebase before
merging them. I've kicked off a test run for the current PR. When the build
finishes, I'll share with you whether or how it failed. Thanks!

Stripe employees can see the build results here:

https://go/builds/bui_QEA383HgWOiZxN
https://go/builds/bui_QEA3SqkRcBJQUU
https://go/builds/bui_QEA46Ym7IFXFCm

This change also has sorbet-runtime changes. Those tests:

https://go/builds/bui_QEAFIajEdYgPBd

@aisamanra
Copy link
Contributor

We have a policy of testing changes to Sorbet against Stripe's codebase before
merging them. I've kicked off a test run for the current PR. When the build
finishes, I'll share with you whether or how it failed. Thanks!

Stripe employees can see the build results here:

https://go/builds/bui_QFglIv5MWbPctA
https://go/builds/bui_QFglJaJcfYuote
https://go/builds/bui_QFglY0Q3aZCMJW

This change also has sorbet-runtime changes. Those tests:

https://go/builds/bui_QFguYxWm5ErH7e

@thomasmarshall
Copy link
Contributor Author

Is there anything else I should do for this PR? No rush, I actually don't need this fix, I just picked it up as a small and simple task to get more familiar with the Sorbet codebase 🙂

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.

Explicitly passing nil does not set serialized value to nil
3 participants