Module: T::Types::Union::Private::Pool

Defined in:
lib/types/types/union.rb

Class Method Summary collapse

Class Method Details

.union_of_types(type_a, type_b, types = EMPTY_ARRAY) ⇒ Object

Try to use to_nilable on a type to get memoization, or failing that try to at least use SimplePairUnion to get faster init and typechecking.

We aren't guaranteed to detect a simple T.nilable(<Module>) type here in cases where there are duplicate types, nested unions, etc.

That's ok, because returning is SimplePairUnion an optimization which isn't necessary for correctness.

Parameters:



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/types/types/union.rb', line 157

def self.union_of_types(type_a, type_b, types=EMPTY_ARRAY)
  if !types.empty?
    # Slow path
    return Union.new([type_a, type_b] + types)
  elsif !type_a.is_a?(T::Types::Simple) || !type_b.is_a?(T::Types::Simple)
    # Slow path
    return Union.new([type_a, type_b])
  end

  begin
    # The `equal?` checks are an identity fast path: NIL_TYPE is the pooled
    # `coerce(NilClass)` instance, so it hits on every normal `T.nilable` call.
    # The `==` fallbacks preserve semantics for hand-constructed
    # `Simple.new(NilClass)` instances that bypass the pool.
    if type_b.equal?(T::Utils::Nilable::NIL_TYPE) || type_b == T::Utils::Nilable::NIL_TYPE
      type_a.to_nilable
    elsif type_a.equal?(T::Utils::Nilable::NIL_TYPE) || type_a == T::Utils::Nilable::NIL_TYPE
      type_b.to_nilable
    else
      T::Private::Types::SimplePairUnion.new(type_a, type_b)
    end
  rescue T::Private::Types::SimplePairUnion::DuplicateType
    # Slow path
    #
    # This shouldn't normally be possible due to static checks,
    # but we can get here if we're constructing a type dynamically.
    #
    # Relying on the duplicate check in the constructor has the
    # advantage that we avoid it when we hit the memoized case
    # of `to_nilable`.
    type_a
  end
end