diff --git a/lib/tapioca/internal.rb b/lib/tapioca/internal.rb index 1df72fb4f..ac8f8e592 100644 --- a/lib/tapioca/internal.rb +++ b/lib/tapioca/internal.rb @@ -13,6 +13,7 @@ require "tapioca/sorbet_ext/name_patch" require "tapioca/sorbet_ext/generic_name_patch" require "tapioca/sorbet_ext/proc_bind_patch" +require "tapioca/sorbet_ext/void_patch" require "tapioca/runtime/generic_type_registry" # The rewriter needs to be loaded very early so RBS comments within Tapioca itself are rewritten diff --git a/lib/tapioca/sorbet_ext/void_patch.rb b/lib/tapioca/sorbet_ext/void_patch.rb new file mode 100644 index 000000000..db6305b06 --- /dev/null +++ b/lib/tapioca/sorbet_ext/void_patch.rb @@ -0,0 +1,29 @@ +# typed: true +# frozen_string_literal: true + +# If Signature has `effective_return_type`, then `return_type` always returns the correct type. +# Ref: https://github.com/sorbet/sorbet/pull/10121 +return if T::Private::Methods::Signature.method_defined?(:effective_return_type) + +module T + module Private + module Methods + module DeclBuilderPatch + def void + super.tap do + @_real_returns_is_void = true + end + end + + def finalize! + super.tap do + #: self as untyped + decl.returns = T::Private::Types::Void::Private::INSTANCE if @_real_returns_is_void + end + end + end + + DeclBuilder.prepend(DeclBuilderPatch) + end + end +end diff --git a/sorbet/rbi/shims/sorbet.rbi b/sorbet/rbi/shims/sorbet.rbi index 318cdb7ad..e8c2bf6c0 100644 --- a/sorbet/rbi/shims/sorbet.rbi +++ b/sorbet/rbi/shims/sorbet.rbi @@ -14,7 +14,13 @@ module T::Private def self.sealed_module?(mod); end end - class Types::NotTyped < T::Types::Base; end + module Types + class NotTyped < T::Types::Base; end + + module Void::Private + INSTANCE = T.let(T.unsafe(nil), T::Private::Types::Void) + end + end module Methods ARG_NOT_PROVIDED = T.let(T.unsafe(nil), Object) @@ -53,6 +59,8 @@ module T::Private def finalized; end def finalized=(finalized); end end + + class Signature; end end module DeclState diff --git a/spec/tapioca/gem/pipeline_spec.rb b/spec/tapioca/gem/pipeline_spec.rb index 997ff982e..d9354b4fe 100644 --- a/spec/tapioca/gem/pipeline_spec.rb +++ b/spec/tapioca/gem/pipeline_spec.rb @@ -4627,6 +4627,32 @@ def foo; end assert_equal(output, compiled) end + it "compiles methods with .void.checked(:tests) properly" do + add_ruby_file("bar.rb", <<~RUBY) + class Bar + extend T::Sig + + sig { params(x: Integer).void.checked(:tests) } + def initialize(x); end + + sig { void.checked(:tests) } + def foo; end + end + RUBY + + output = template(<<~RBI) + class Bar + sig { params(x: ::Integer).void } + def initialize(x); end + + sig { void } + def foo; end + end + RBI + + assert_equal(output, compile) + end + it "compiles constants with nil values" do add_ruby_file("foo.rb", <<~RUBY) class Foo