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

Tapioca DSL crashes when using T::Struct containing generic members #2130

Open
amanda-mitchell opened this issue Dec 20, 2024 · 0 comments
Open

Comments

@amanda-mitchell
Copy link
Contributor

amanda-mitchell commented Dec 20, 2024

Summary

When running tapioca dsl in a Rails app that

  • Overrides T::Configuration.call_validation_error_handler during application load with a handler that raises errors
  • Contains a T::Struct with a member whose type is a generic interface
  • Instantiates that struct during app startup with a concrete implementation of the generic interface

Tapioca will crash while trying to create the struct because of a type mismatch error between the interface and the implementation.

I created a repository containing what seems to be the absolute minimum configuration necessary to activate this bug. You can find it here: https://github.com/amanda-mitchell/tapioca-bug-repro

The short version of my analysis is that while most type checks are suppressed by Tapioca setting the default check level to :never, members declared on T::Struct don't respect this setting, so they still produce type errors.

Workarounds

Although I'd love to see this get a long term fix, I'd also like to document some potential workarounds for folks who might run across this in the meantime.

Use setter_validate

T::Struct contains an undocumented option for member declarations called setter_validate, and this is expected to a proc that performs validation side effects. Providing an empty (no-op) lambda will force the implementation of T::Struct onto an alternate code path that does not activate the bug.

Wrap the type in an intersection with Kernel

Simply switching the type from MyInterface[TypeArgument] to T.all(MyInterface[TypeArgument], Kernel) is also enough to nudge T::Struct onto the code path listed above.

Disable runtime checks while running Tapioca

If you have some code that can detect when Tapioca is running and set your implementation of T::Configuration.call_validation_error_handler to something that no-ops, you won't encounter the crash.

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

No branches or pull requests

1 participant