diff --git a/lib/tapioca/runtime/generic_type_registry.rb b/lib/tapioca/runtime/generic_type_registry.rb index 1bc1c6a8a..98828a597 100644 --- a/lib/tapioca/runtime/generic_type_registry.rb +++ b/lib/tapioca/runtime/generic_type_registry.rb @@ -111,8 +111,10 @@ def create_generic_type(constant, name) constant.clone end - # Let's set the `name` method to return the proper generic name - generic_type.define_singleton_method(:name) { name } + # Let's set the `name` and `to_s` methods to return the proper generic name + name_proc = -> { name } + generic_type.define_singleton_method(:name, name_proc) + generic_type.define_singleton_method(:to_s, name_proc) # We need to define a `<=` method on the cloned constant, so that Sorbet # can do covariance/contravariance checks on the type variables. diff --git a/spec/tapioca/gem/pipeline_spec.rb b/spec/tapioca/gem/pipeline_spec.rb index af0cc38e0..e41e3617c 100644 --- a/spec/tapioca/gem/pipeline_spec.rb +++ b/spec/tapioca/gem/pipeline_spec.rb @@ -2819,6 +2819,44 @@ class Foo assert_equal(output, compile) end + it "can compile generics in type variable arguments" do + add_ruby_file("service.rb", <<~RUBY) + class Result + extend T::Generic + + OkType = type_member + ErrType = type_member + end + + class Service + extend T::Generic + + InputType = type_member(upper: Result[Integer, String]) + ReturnType = type_member(fixed: Result[Integer, String]) + TempType = type_member(lower: Result[Integer, String]) + end + RUBY + + output = template(<<~RBI) + class Result + extend T::Generic + + OkType = type_member + ErrType = type_member + end + + class Service + extend T::Generic + + InputType = type_member(upper: Result[::Integer, ::String]) + ReturnType = type_member(fixed: Result[::Integer, ::String]) + TempType = type_member(lower: Result[::Integer, ::String]) + end + RBI + + assert_equal(output, compile) + end + it "can compile typed struct generics" do add_ruby_file("tstruct_generic.rb", <<~RUBY) class Foo < T::Struct