Skip to content

Commit

Permalink
Merge pull request #944 from Shopify/uk-fix-type-variable-patch
Browse files Browse the repository at this point in the history
Fix type variable patch to respect references to late defined types
  • Loading branch information
paracycle committed May 27, 2022
2 parents 6d5298f + 7d2b602 commit dc87f12
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 32 deletions.
77 changes: 45 additions & 32 deletions lib/tapioca/sorbet_ext/generic_name_patch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,47 +21,33 @@ def [](*types)
Tapioca::Runtime::GenericTypeRegistry.register_type(constant, types)
end

def type_member(variance = :invariant, fixed: nil, lower: nil, upper: nil, &blk)
def type_member(variance = :invariant, fixed: nil, lower: nil, upper: nil, &bounds_proc)
# `T::Generic#type_member` just instantiates a `T::Type::TypeMember` instance and returns it.
# We use that when registering the type member and then later return it from this method.
hash = if blk
blk.call
else
{
fixed: fixed,
lower: lower,
upper: upper,
}
end

Tapioca::TypeVariableModule.new(
T.cast(self, Module),
Tapioca::TypeVariableModule::Type::Member,
variance,
**hash,
fixed,
lower,
upper,
bounds_proc
).tap do |type_variable|
Tapioca::Runtime::GenericTypeRegistry.register_type_variable(self, type_variable)
end
end

def type_template(variance = :invariant, fixed: nil, lower: nil, upper: nil, &blk)
def type_template(variance = :invariant, fixed: nil, lower: nil, upper: nil, &bounds_proc)
# `T::Generic#type_template` just instantiates a `T::Type::TypeTemplate` instance and returns it.
# We use that when registering the type template and then later return it from this method.
hash = if blk
blk.call
else
{
fixed: fixed,
lower: lower,
upper: upper,
}
end

Tapioca::TypeVariableModule.new(
T.cast(self, Module),
Tapioca::TypeVariableModule::Type::Template,
variance,
**hash,
fixed,
lower,
upper,
bounds_proc
).tap do |type_variable|
Tapioca::Runtime::GenericTypeRegistry.register_type_variable(self, type_variable)
end
Expand Down Expand Up @@ -136,18 +122,31 @@ class Type < T::Enum
end
end

# rubocop:disable Metrics/ParameterLists
sig do
params(context: Module, type: Type, variance: Symbol, fixed: T.untyped, lower: T.untyped, upper: T.untyped).void
params(
context: Module,
type: Type,
variance: Symbol,
fixed: T.untyped,
lower: T.untyped,
upper: T.untyped,
bounds_proc: T.nilable(T.proc.returns(T::Hash[Symbol, T.untyped]))
).void
end
def initialize(context, type, variance, fixed: nil, lower: nil, upper: nil)
def initialize(context, type, variance, fixed, lower, upper, bounds_proc)
@context = context
@type = type
@variance = variance
@fixed = fixed
@lower = lower
@upper = upper
@bounds_proc = if bounds_proc
bounds_proc
else
build_bounds_proc(fixed, lower, upper)
end

super()
end
# rubocop:enable Metrics/ParameterLists

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

sig { returns(String) }
def serialize
fixed = @fixed.to_s if @fixed
upper = @upper.to_s if @upper
lower = @lower.to_s if @lower
bounds = @bounds_proc.call
fixed = bounds[:fixed].to_s if bounds.key?(:fixed)
lower = bounds[:lower].to_s if bounds.key?(:lower)
upper = bounds[:upper].to_s if bounds.key?(:upper)

TypeVariableHelper.serialize_type_variable(
@type.serialize,
Expand All @@ -190,6 +190,19 @@ def coerce_to_type_variable

private

sig do
params(fixed: T.untyped, lower: T.untyped, upper: T.untyped)
.returns(T.proc.returns(T::Hash[Symbol, T.untyped]))
end
def build_bounds_proc(fixed, lower, upper)
bounds = {}
bounds[:fixed] = fixed unless fixed.nil?
bounds[:lower] = lower unless lower.nil?
bounds[:upper] = upper unless upper.nil?

-> { bounds }
end

sig do
type_parameters(:Result)
.params(block: T.proc.returns(T.type_parameter(:Result)))
Expand Down
18 changes: 18 additions & 0 deletions spec/tapioca/gem/pipeline_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2663,6 +2663,16 @@ def complex(foo); end
NullGenericType = SimpleGenericType[Integer].new(0)
end
module ForwardDeclaration
extend T::Sig
extend T::Generic
Elem = type_member { { fixed: LateDeclaredModule }}
module LateDeclaredModule
end
end
end
RUBY

Expand Down Expand Up @@ -2771,6 +2781,14 @@ class << self
end
end
module Generics::ForwardDeclaration
extend T::Generic
Elem = type_member { { fixed: Generics::ForwardDeclaration::LateDeclaredModule } }
end
module Generics::ForwardDeclaration::LateDeclaredModule; end
class Generics::SimpleGenericType
extend T::Generic
Expand Down

0 comments on commit dc87f12

Please sign in to comment.