Description
openedon Sep 1, 2023
Issue
Referencing a generic class inside of the sig
of its own .inherited
method will cause infinite recursion:
tapioca dsl --verify
crashes with a SystemStackError
Sample abridged backtrace
stack level too deep (SystemStackError)
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:177:in `rescue in block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:186:in `initialize'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:186:in `new'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:186:in `create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:120:in `create_generic_type'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:76:in `register_type'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/sorbet_ext/generic_name_patch.rb:18:in `[]'
from /Users/alex/my_app/app/my_generic_type.rb:70:in `block in <class:MyGenericType>' # sig block on `.inherited`
# ... This whole song-dance repeats a bunch of times, with a longer chain of intercepted method calls each time.
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:358:in `instance_exec'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:358:in `run_builder'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:336:in `run_sig'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:246:in `block in _on_method_added'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:447:in `run_sig_block_for_key'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:427:in `maybe_run_sig_block_for_key'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:256:in `block in _on_method_added'
# `.inherited` intercepted 3 times:
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:185:in `initialize'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:185:in `new'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:185:in `create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:120:in `create_generic_type'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:76:in `register_type'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/sorbet_ext/generic_name_patch.rb:18:in `[]'
from /Users/alex/my_app/app/my_generic_type.rb:70:in `block in <class:MyGenericType>' # sig block on `.inherited`
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:358:in `instance_exec'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:358:in `run_builder'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:336:in `run_sig'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:246:in `block in _on_method_added'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:447:in `run_sig_block_for_key'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:427:in `maybe_run_sig_block_for_key'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:256:in `block in _on_method_added'
# `.inherited` intercepted 2 times:
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:185:in `initialize'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:185:in `new'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:185:in `create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:120:in `create_generic_type'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:76:in `register_type'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/sorbet_ext/generic_name_patch.rb:18:in `[]'
from /Users/alex/my_app/app/my_generic_type.rb:70:in `block in <class:MyGenericType>' # sig block on `.inherited`
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:358:in `instance_exec'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:358:in `run_builder'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:336:in `run_sig'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:246:in `block in _on_method_added'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:447:in `run_sig_block_for_key'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:427:in `maybe_run_sig_block_for_key'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:256:in `block in _on_method_added'
# `.inherited` intercepted 1 time:
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `call'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:176:in `block in create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:185:in `initialize'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:185:in `new'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:185:in `create_safe_subclass'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:120:in `create_generic_type'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/runtime/generic_type_registry.rb:76:in `register_type'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/sorbet_ext/generic_name_patch.rb:18:in `[]'
from /Users/alex/my_app/app/my_generic_type.rb:70:in `block in <class:MyGenericType>' # sig block on `.inherited`
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:358:in `instance_exec'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:358:in `run_builder'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:336:in `run_sig'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:246:in `block in _on_method_added'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:447:in `run_sig_block_for_key'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:427:in `maybe_run_sig_block_for_key'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:256:in `block in _on_method_added'
from /Users/alex/my_app/app/class_that_uses_my_generic_type.rb:4:in `<main>'
from /Users/alex/.gem/ruby/3.2.2/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
from /Users/alex/.gem/ruby/3.2.2/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/kernel.rb:30:in `require'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader/helpers.rb:135:in `const_get'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader/helpers.rb:135:in `cget'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader/eager_load.rb:175:in `block in actual_eager_load_dir'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader/helpers.rb:40:in `block in ls'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader/helpers.rb:25:in `each'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader/helpers.rb:25:in `ls'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader/eager_load.rb:170:in `actual_eager_load_dir'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader/eager_load.rb:17:in `block (2 levels) in eager_load'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader/eager_load.rb:16:in `each'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader/eager_load.rb:16:in `block in eager_load'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader/eager_load.rb:10:in `synchronize'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader/eager_load.rb:10:in `eager_load'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader.rb:379:in `block in eager_load_all'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader.rb:377:in `each'
from /Users/alex/.gem/ruby/3.2.2/gems/zeitwerk-2.6.11/lib/zeitwerk/loader.rb:377:in `eager_load_all'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/loaders/loader.rb:206:in `eager_load_rails_app'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `bind_call'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/loaders/loader.rb:60:in `load_rails_application'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `bind_call'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/loaders/dsl.rb:74:in `load_application'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `bind_call'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/loaders/dsl.rb:29:in `load'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `bind_call'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/loaders/dsl.rb:22:in `load_application'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `bind_call'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/commands/dsl.rb:98:in `execute'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `bind_call'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/cli.rb:164:in `block in dsl'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca.rb:23:in `block in silence_warnings'
/opt/rubies/3.2.2/lib/ruby/3.2.0/rubygems/user_interaction.rb:46:in `use_ui'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca.rb:22:in `silence_warnings'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `bind_call'
from /Users/alex/.gem/ruby/3.2.2/gems/sorbet-runtime-0.5.10991/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/lib/tapioca/cli.rb:160:in `dsl'
from /Users/alex/.gem/ruby/3.2.2/gems/thor-1.2.2/lib/thor/command.rb:27:in `run'
from /Users/alex/.gem/ruby/3.2.2/gems/thor-1.2.2/lib/thor/invocation.rb:127:in `invoke_command'
from /Users/alex/.gem/ruby/3.2.2/gems/thor-1.2.2/lib/thor.rb:392:in `dispatch'
from /Users/alex/.gem/ruby/3.2.2/gems/thor-1.2.2/lib/thor/base.rb:485:in `start'
from /Users/alex/.gem/ruby/3.2.2/gems/tapioca-0.11.8/exe/tapioca:25:in `<top (required)>'
from bin/tapioca:31:in `load'
from bin/tapioca:31:in `<main>'
Example
Now that T::Class
is generic over its attached class (see sorbet/sorbet#6781), this code isn't valid:
class MyGenericClass
extend T::Sig
extend T::Generic
Element = type_member
# ❌ Malformed type declaration. Generic class without type arguments Class
sig { params(subclass: Class).void }
# ^^^^^
def self.inherited(subclass)
# ...
end
end
The developer might then try to use a specific class type to fix it:
- sig { params(subclass: Class).void }
+ sig { params(subclass: T::Class[MyGenericClass[T.anything]]).void } 🧨
This will cause the issue. A workaround would be to use a non-specific class type:
- sig { params(subclass: Class).void }
+ sig { params(subclass: T::Class[T.anything]).void } ✅
Here's a unit test that reproduces the issue:
392fbf6#diff-5a7c31a7504b1e445b8c319f9d3fcde2966c06f2f50bc66fd3d38605a565e02aR137-R140
Further details
At the time MyGenericClass[T.anything]
is referenced from the sig, MyGenericClass
doesn't exist in the GenericTypeRegistry
yet. The []
will try to look up the class in the registry, see that it's not there, and start the create_generic_type
. In doing so, it'll attempt to evaluate the sig, which recurses infinitely.
I'm not sure what the right way to handle this is, but I see a few possibilities, most of which are pretty complicated.
- We could just ignore the sigs on
.inherited
. - We could give special treatment to the sigs on
.inherited
, which evaluates them in a way that doesn't hit the recursion. I'm not sure what that might look like. - We could separate class construction from sig validation. If we construct all the classes first, then run the sigs in a second step, that might prevent this.
I welcome any other suggestions!