From 44c8664da064741e9ab7e7d934752e15c4bcd725 Mon Sep 17 00:00:00 2001 From: Ufuk Kayserilioglu Date: Tue, 1 Mar 2022 21:08:25 +0200 Subject: [PATCH 1/2] Add failing test --- spec/tapioca/gem/pipeline_spec.rb | 38 +++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) 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 From 4e648253a9c06e0986cc0e810442848517b03ed8 Mon Sep 17 00:00:00 2001 From: Ufuk Kayserilioglu Date: Tue, 1 Mar 2022 21:15:45 +0200 Subject: [PATCH 2/2] Override `to_s` on generic clones as well --- lib/tapioca/runtime/generic_type_registry.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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.