Skip to content

Commit 6cff515

Browse files
committed
Merge pull request #944 from Shopify/uk-fix-type-variable-patch
Fix type variable patch to respect references to late defined types
1 parent 25f138c commit 6cff515

File tree

2 files changed

+63
-32
lines changed

2 files changed

+63
-32
lines changed

lib/tapioca/sorbet_ext/generic_name_patch.rb

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,47 +21,33 @@ def [](*types)
2121
Tapioca::Runtime::GenericTypeRegistry.register_type(constant, types)
2222
end
2323

24-
def type_member(variance = :invariant, fixed: nil, lower: nil, upper: nil, &blk)
24+
def type_member(variance = :invariant, fixed: nil, lower: nil, upper: nil, &bounds_proc)
2525
# `T::Generic#type_member` just instantiates a `T::Type::TypeMember` instance and returns it.
2626
# We use that when registering the type member and then later return it from this method.
27-
hash = if blk
28-
blk.call
29-
else
30-
{
31-
fixed: fixed,
32-
lower: lower,
33-
upper: upper,
34-
}
35-
end
36-
3727
Tapioca::TypeVariableModule.new(
3828
T.cast(self, Module),
3929
Tapioca::TypeVariableModule::Type::Member,
4030
variance,
41-
**hash,
31+
fixed,
32+
lower,
33+
upper,
34+
bounds_proc
4235
).tap do |type_variable|
4336
Tapioca::Runtime::GenericTypeRegistry.register_type_variable(self, type_variable)
4437
end
4538
end
4639

47-
def type_template(variance = :invariant, fixed: nil, lower: nil, upper: nil, &blk)
40+
def type_template(variance = :invariant, fixed: nil, lower: nil, upper: nil, &bounds_proc)
4841
# `T::Generic#type_template` just instantiates a `T::Type::TypeTemplate` instance and returns it.
4942
# We use that when registering the type template and then later return it from this method.
50-
hash = if blk
51-
blk.call
52-
else
53-
{
54-
fixed: fixed,
55-
lower: lower,
56-
upper: upper,
57-
}
58-
end
59-
6043
Tapioca::TypeVariableModule.new(
6144
T.cast(self, Module),
6245
Tapioca::TypeVariableModule::Type::Template,
6346
variance,
64-
**hash,
47+
fixed,
48+
lower,
49+
upper,
50+
bounds_proc
6551
).tap do |type_variable|
6652
Tapioca::Runtime::GenericTypeRegistry.register_type_variable(self, type_variable)
6753
end
@@ -136,18 +122,31 @@ class Type < T::Enum
136122
end
137123
end
138124

125+
# rubocop:disable Metrics/ParameterLists
139126
sig do
140-
params(context: Module, type: Type, variance: Symbol, fixed: T.untyped, lower: T.untyped, upper: T.untyped).void
127+
params(
128+
context: Module,
129+
type: Type,
130+
variance: Symbol,
131+
fixed: T.untyped,
132+
lower: T.untyped,
133+
upper: T.untyped,
134+
bounds_proc: T.nilable(T.proc.returns(T::Hash[Symbol, T.untyped]))
135+
).void
141136
end
142-
def initialize(context, type, variance, fixed: nil, lower: nil, upper: nil)
137+
def initialize(context, type, variance, fixed, lower, upper, bounds_proc)
143138
@context = context
144139
@type = type
145140
@variance = variance
146-
@fixed = fixed
147-
@lower = lower
148-
@upper = upper
141+
@bounds_proc = if bounds_proc
142+
bounds_proc
143+
else
144+
build_bounds_proc(fixed, lower, upper)
145+
end
146+
149147
super()
150148
end
149+
# rubocop:enable Metrics/ParameterLists
151150

152151
sig { returns(T.nilable(String)) }
153152
def name
@@ -170,9 +169,10 @@ def name
170169

171170
sig { returns(String) }
172171
def serialize
173-
fixed = @fixed.to_s if @fixed
174-
upper = @upper.to_s if @upper
175-
lower = @lower.to_s if @lower
172+
bounds = @bounds_proc.call
173+
fixed = bounds[:fixed].to_s if bounds.key?(:fixed)
174+
lower = bounds[:lower].to_s if bounds.key?(:lower)
175+
upper = bounds[:upper].to_s if bounds.key?(:upper)
176176

177177
TypeVariableHelper.serialize_type_variable(
178178
@type.serialize,
@@ -190,6 +190,19 @@ def coerce_to_type_variable
190190

191191
private
192192

193+
sig do
194+
params(fixed: T.untyped, lower: T.untyped, upper: T.untyped)
195+
.returns(T.proc.returns(T::Hash[Symbol, T.untyped]))
196+
end
197+
def build_bounds_proc(fixed, lower, upper)
198+
bounds = {}
199+
bounds[:fixed] = fixed unless fixed.nil?
200+
bounds[:lower] = lower unless lower.nil?
201+
bounds[:upper] = upper unless upper.nil?
202+
203+
-> { bounds }
204+
end
205+
193206
sig do
194207
type_parameters(:Result)
195208
.params(block: T.proc.returns(T.type_parameter(:Result)))

spec/tapioca/gem/pipeline_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,6 +2588,16 @@ def complex(foo); end
25882588
25892589
NullGenericType = SimpleGenericType[Integer].new(0)
25902590
end
2591+
2592+
module ForwardDeclaration
2593+
extend T::Sig
2594+
extend T::Generic
2595+
2596+
Elem = type_member { { fixed: LateDeclaredModule }}
2597+
2598+
module LateDeclaredModule
2599+
end
2600+
end
25912601
end
25922602
RUBY
25932603

@@ -2695,6 +2705,14 @@ class << self
26952705
end
26962706
end
26972707
2708+
module Generics::ForwardDeclaration
2709+
extend T::Generic
2710+
2711+
Elem = type_member { { fixed: Generics::ForwardDeclaration::LateDeclaredModule } }
2712+
end
2713+
2714+
module Generics::ForwardDeclaration::LateDeclaredModule; end
2715+
26982716
class Generics::SimpleGenericType
26992717
extend T::Generic
27002718

0 commit comments

Comments
 (0)