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

Simplify implementation of Serializable#initialize #13433

Conversation

straight-shoota
Copy link
Member

@straight-shoota straight-shoota commented May 5, 2023

The deserialization logic in JSON::Serializable and YAML::Serializable is unnecessarily complex. This patch is a refactor for simplicity.

The code for handling whether a value was (not) found and the different conditions (nilable, default) was a major jumble.
The special handling for nilable types is completely unnecessary. If we remove that special case, it all becomes much more straightforward. It also gets rid of duplications. This is the main point of this PR, addressed in the second commit.

The first commit adds specs for #13431 to avoid breaking that in the refactor.

The third commit doesn't change anything structurally, it just simplifies the macro code with a different mechanism. The conditional nesting of read_null_or/parse_null_or adds unnecessary complexity. We can omit that by just asking the parser for a null value and acting accordingly.

{% else %}
uninitialized ::Union({{value[:type]}})
{% end %}
%var{name} = uninitialized ::Union({{value[:type]}})
Copy link
Contributor

Choose a reason for hiding this comment

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

interesting why this condition was needed?

Copy link
Member Author

Choose a reason for hiding this comment

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

The convoluted implementation of the finalizing steps (where the ivar is assigned) always assigned @{{name}} = %var{name} if value[:nilable]. So it needed a value and could not be uninitialized.

Copy link
Member Author

Choose a reason for hiding this comment

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

With this patch, it only assigns if %found{name} so there's no need for a default initialization.

Copy link
Member Author

Choose a reason for hiding this comment

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

Before #13238 %var{name} was always initialized to nil and then that nil type was filtered out later when the ivar was not nilable. uninitialized is a much better tool, though. It doesn't add Nil to the type.

@straight-shoota straight-shoota added this to the 1.9.0 milestone May 5, 2023
@straight-shoota straight-shoota changed the title Simplify implementation of Serializable.new Simplify implementation of Serializable#initialize May 5, 2023
@straight-shoota straight-shoota merged commit 3610f8c into crystal-lang:master May 6, 2023
45 checks passed
@straight-shoota straight-shoota deleted the refactor/simplify-serializable branch May 6, 2023 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants