Merge pull request #16505 from Homebrew/dependabot/bundler/Library/Homebrew/sorbet-static-and-runtime-and-sorbet-runtime-0.5.11212

build(deps): bump sorbet-static-and-runtime and sorbet-runtime in /Library/Homebrew
This commit is contained in:
Mike McQuaid 2024-01-19 09:00:43 +00:00 committed by GitHub
commit 1976ead217
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
92 changed files with 1577 additions and 506 deletions

View File

@ -141,14 +141,14 @@ GEM
simplecov_json_formatter (0.1.4)
simpleidn (0.2.1)
unf (~> 0.1.4)
sorbet (0.5.11155)
sorbet-static (= 0.5.11155)
sorbet-runtime (0.5.11155)
sorbet-static (0.5.11155-universal-darwin)
sorbet-static (0.5.11155-x86_64-linux)
sorbet-static-and-runtime (0.5.11155)
sorbet (= 0.5.11155)
sorbet-runtime (= 0.5.11155)
sorbet (0.5.11212)
sorbet-static (= 0.5.11212)
sorbet-runtime (0.5.11212)
sorbet-static (0.5.11212-universal-darwin)
sorbet-static (0.5.11212-x86_64-linux)
sorbet-static-and-runtime (0.5.11212)
sorbet (= 0.5.11212)
sorbet-runtime (= 0.5.11212)
spoom (1.2.4)
erubi (>= 1.10.0)
sorbet-static-and-runtime (>= 0.5.10187)

View File

@ -5,7 +5,6 @@
class AbstractCoreTap
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
class AbstractDownloadStrategy
@ -3209,7 +3208,6 @@ end
class Cask::Artifact::AbstractArtifact
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
module Cask::Cache
@ -3219,12 +3217,10 @@ end
class Cask::CaskLoader::AbstractContentLoader
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
module Cask::CaskLoader::ILoader
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
extend ::T::Private::Methods::MethodHooks
extend ::T::Private::Methods::SingletonMethodHooks
end
@ -3718,7 +3714,6 @@ end
class Downloadable
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
class ELFTools::LazyArray
@ -6324,6 +6319,8 @@ class Net::HTTP
VERSION = ::T.let(nil, ::T.untyped)
end
Net::HTTP::ProxyMod = Net::HTTP::ProxyDelta
class Net::HTTPAlreadyReported
HAS_BODY = ::T.let(nil, ::T.untyped)
end
@ -6501,7 +6498,6 @@ end
class OS::Mac::BaseSDKLocator
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
module OS::Mac::CLT
@ -7300,7 +7296,6 @@ end
class Parlour::Conversion::Converter
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
module Parlour::Debugging
@ -7310,7 +7305,6 @@ end
module Parlour::Mixin::Searchable
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
extend ::T::Private::Methods::MethodHooks
extend ::T::Private::Methods::SingletonMethodHooks
end
@ -7318,7 +7312,6 @@ end
class Parlour::Plugin
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
module Parlour::TypeLoader
@ -7329,13 +7322,11 @@ end
class Parlour::TypedObject
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
class Parlour::Types::Type
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
class Proc
@ -7423,7 +7414,6 @@ end
module RBI::Indexable
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
extend ::T::Private::Methods::MethodHooks
extend ::T::Private::Methods::SingletonMethodHooks
end
@ -7431,13 +7421,11 @@ end
class RBI::Node
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
class RBI::Visitor
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
class RDoc::Alias
@ -9362,7 +9350,6 @@ end
class RuboCop::Cop::FormulaCop
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
module RuboCop::Cop::HelperFunctions
@ -9825,7 +9812,6 @@ end
class Spoom::Coverage::D3::Base
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
module Spoom::Coverage::D3
@ -9835,7 +9821,6 @@ end
class Spoom::Coverage::Template
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
module Spoom::Coverage
@ -9845,13 +9830,11 @@ end
class Spoom::Deadcode::Error
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
class Spoom::Deadcode::Plugins::Base
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
module Spoom::Deadcode
@ -9861,13 +9844,11 @@ end
class Spoom::FileTree::Visitor
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
module Spoom::LSP::PrintableSymbol
extend ::T::Helpers
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
extend ::T::Private::Methods::MethodHooks
extend ::T::Private::Methods::SingletonMethodHooks
end
@ -9979,10 +9960,6 @@ class Test::Helper::OutputAsTTY::Output
RUBYGEMS_ACTIVATION_MONITOR = ::T.let(nil, ::T.untyped)
end
class Thread
def native_thread_id(); end
end
class Thread::Backtrace
def self.limit(); end
end
@ -10182,7 +10159,6 @@ end
module UnpackStrategy
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
extend ::T::Private::Methods::MethodHooks
extend ::T::Private::Methods::SingletonMethodHooks
end
@ -10256,12 +10232,10 @@ end
class Version::Parser
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
class Version::Token
extend ::T::Private::Abstract::Hooks
extend ::T::InterfaceWrapper::Helpers
end
class WeakRef

View File

@ -71,7 +71,7 @@ $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/racc-1.7.3/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/parser-3.3.0.4/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/rainbow-3.1.1/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-runtime-0.5.11155/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-runtime-0.5.11212/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/parlour-8.1.0/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/patchelf-1.4.0/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/plist-3.7.1/lib")
@ -112,9 +112,9 @@ $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/simplecov_json_formatter-0.1.4/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/simplecov-0.22.0/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/simplecov-cobertura-2.1.0/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-static-0.5.11155-universal-darwin/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-0.5.11155/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-static-and-runtime-0.5.11155/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-static-0.5.11212-universal-darwin/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-0.5.11212/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-static-and-runtime-0.5.11212/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/syntax_tree-6.2.0/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/thor-1.3.0/lib")
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/spoom-1.2.4/lib")

View File

@ -1,162 +0,0 @@
# frozen_string_literal: true
# typed: false
# Wraps an object, exposing only the methods defined on a given class/module. The idea is that, in
# the absence of a static type checker that would prevent you from calling non-Bar methods on a
# variable of type Bar, we can use these wrappers as a way of enforcing it at runtime.
#
# Once we ship static type checking, we should get rid of this entirely.
class T::InterfaceWrapper
extend T::Sig
module Helpers
def wrap_instance(obj)
T::InterfaceWrapper.wrap_instance(obj, self)
end
def wrap_instances(arr)
T::InterfaceWrapper.wrap_instances(arr, self)
end
end
private_class_method :new # use `wrap_instance`
def self.wrap_instance(obj, interface_mod)
wrapper = wrapped_dynamic_cast(obj, interface_mod)
if wrapper.nil?
raise "#{obj.class} cannot be cast to #{interface_mod}"
end
wrapper
end
sig do
params(
arr: Array,
interface_mod: T.untyped
)
.returns(Array)
end
def self.wrap_instances(arr, interface_mod)
arr.map {|instance| self.wrap_instance(instance, interface_mod)}
end
def initialize(target_obj, interface_mod)
if target_obj.is_a?(T::InterfaceWrapper)
# wrapped_dynamic_cast should guarantee this never happens.
raise "Unexpected: wrapping a wrapper. Please report this bug at https://github.com/sorbet/sorbet/issues"
end
if !target_obj.is_a?(interface_mod)
# wrapped_dynamic_cast should guarantee this never happens.
raise "Unexpected: `is_a?` failed. Please report this bug at https://github.com/sorbet/sorbet/issues"
end
if target_obj.class == interface_mod
# wrapped_dynamic_cast should guarantee this never happens.
raise "Unexpected: exact class match. Please report this bug at https://github.com/sorbet/sorbet/issues"
end
@target_obj = target_obj
@interface_mod = interface_mod
self_methods = self.class.self_methods
# If perf becomes an issue, we can define these on an anonymous subclass, and keep a cache
# so we only need to do it once per unique `interface_mod`
T::Utils.methods_excluding_object(interface_mod).each do |method_name|
if self_methods.include?(method_name)
raise "interface_mod has a method that conflicts with #{self.class}: #{method_name}"
end
define_singleton_method(method_name) do |*args, &blk|
target_obj.send(method_name, *args, &blk)
end
if singleton_class.respond_to?(:ruby2_keywords, true)
singleton_class.send(:ruby2_keywords, method_name)
end
if target_obj.singleton_class.public_method_defined?(method_name)
# no-op, it's already public
elsif target_obj.singleton_class.protected_method_defined?(method_name)
singleton_class.send(:protected, method_name)
elsif target_obj.singleton_class.private_method_defined?(method_name)
singleton_class.send(:private, method_name)
else
raise "This should never happen. Report this bug at https://github.com/sorbet/sorbet/issues"
end
end
end
def kind_of?(other)
is_a?(other)
end
def is_a?(other)
if !other.is_a?(Module)
raise TypeError.new("class or module required")
end
# This makes is_a? return true for T::InterfaceWrapper (and its ancestors),
# as well as for @interface_mod and its ancestors.
self.class <= other || @interface_mod <= other
end
# Prefixed because we're polluting the namespace of the interface we're wrapping, and we don't
# want anyone else (besides dynamic_cast) calling it.
def __target_obj_DO_NOT_USE # rubocop:disable Naming/MethodName
@target_obj
end
# Prefixed because we're polluting the namespace of the interface we're wrapping, and we don't
# want anyone else (besides wrapped_dynamic_cast) calling it.
def __interface_mod_DO_NOT_USE # rubocop:disable Naming/MethodName
@interface_mod
end
# "Cast" an object to another type. If `obj` is an InterfaceWrapper, returns the the wrapped
# object if that matches `type`. Otherwise, returns `obj` if it matches `type`. Otherwise,
# returns nil.
#
# @param obj [Object] object to cast
# @param mod [Module] type to cast `obj` to
#
# @example
# if (impl = T::InterfaceWrapper.dynamic_cast(iface, MyImplementation))
# impl.do_things
# end
def self.dynamic_cast(obj, mod)
if obj.is_a?(T::InterfaceWrapper)
target_obj = obj.__target_obj_DO_NOT_USE
target_obj.is_a?(mod) ? target_obj : nil
elsif obj.is_a?(mod)
obj
else
nil
end
end
# Like dynamic_cast, but puts the result in its own wrapper if necessary.
#
# @param obj [Object] object to cast
# @param mod [Module] type to cast `obj` to
def self.wrapped_dynamic_cast(obj, mod)
# Avoid unwrapping and creating an equivalent wrapper.
if obj.is_a?(T::InterfaceWrapper) && obj.__interface_mod_DO_NOT_USE == mod
return obj
end
cast_obj = dynamic_cast(obj, mod)
if cast_obj.nil?
nil
elsif cast_obj.class == mod
# Nothing to wrap, they want the full class
cast_obj
else
new(cast_obj, mod)
end
end
def self.self_methods
@self_methods ||= self.instance_methods(false).to_set
end
end

View File

@ -1,197 +0,0 @@
# frozen_string_literal: true
# typed: strict
module T::Props
module Private
module SetterFactory
extend T::Sig
SetterProc = T.type_alias {T.proc.params(val: T.untyped).void}
ValidateProc = T.type_alias {T.proc.params(prop: Symbol, value: T.untyped).void}
sig do
params(
klass: T.all(Module, T::Props::ClassMethods),
prop: Symbol,
rules: T::Hash[Symbol, T.untyped]
)
.returns(SetterProc)
.checked(:never)
end
def self.build_setter_proc(klass, prop, rules)
# Our nil check works differently than a simple T.nilable for various
# reasons (including the `raise_on_nil_write` setting and the existence
# of defaults & factories), so unwrap any T.nilable and do a check
# manually.
non_nil_type = T::Utils::Nilable.get_underlying_type_object(rules.fetch(:type_object))
accessor_key = rules.fetch(:accessor_key)
validate = rules[:setter_validate]
# It seems like a bug that this affects the behavior of setters, but
# some existing code relies on this behavior
has_explicit_nil_default = rules.key?(:default) && rules.fetch(:default).nil?
# Use separate methods in order to ensure that we only close over necessary
# variables
if !T::Props::Utils.need_nil_write_check?(rules) || has_explicit_nil_default
if validate.nil? && non_nil_type.is_a?(T::Types::Simple)
simple_nilable_proc(prop, accessor_key, non_nil_type.raw_type, klass)
else
nilable_proc(prop, accessor_key, non_nil_type, klass, validate)
end
else
if validate.nil? && non_nil_type.is_a?(T::Types::Simple)
simple_non_nil_proc(prop, accessor_key, non_nil_type.raw_type, klass)
else
non_nil_proc(prop, accessor_key, non_nil_type, klass, validate)
end
end
end
sig do
params(
prop: Symbol,
accessor_key: Symbol,
non_nil_type: Module,
klass: T.all(Module, T::Props::ClassMethods),
)
.returns(SetterProc)
end
private_class_method def self.simple_non_nil_proc(prop, accessor_key, non_nil_type, klass)
proc do |val|
unless val.is_a?(non_nil_type)
T::Props::Private::SetterFactory.raise_pretty_error(
klass,
prop,
T::Utils.coerce(non_nil_type),
val,
)
end
instance_variable_set(accessor_key, val)
end
end
sig do
params(
prop: Symbol,
accessor_key: Symbol,
non_nil_type: T::Types::Base,
klass: T.all(Module, T::Props::ClassMethods),
validate: T.nilable(ValidateProc)
)
.returns(SetterProc)
end
private_class_method def self.non_nil_proc(prop, accessor_key, non_nil_type, klass, validate)
proc do |val|
# this use of recursively_valid? is intentional: unlike for
# methods, we want to make sure data at the 'edge'
# (e.g. models that go into databases or structs serialized
# from disk) are correct, so we use more thorough runtime
# checks there
if non_nil_type.recursively_valid?(val)
validate&.call(prop, val)
else
T::Props::Private::SetterFactory.raise_pretty_error(
klass,
prop,
non_nil_type,
val,
)
end
instance_variable_set(accessor_key, val)
end
end
sig do
params(
prop: Symbol,
accessor_key: Symbol,
non_nil_type: Module,
klass: T.all(Module, T::Props::ClassMethods),
)
.returns(SetterProc)
end
private_class_method def self.simple_nilable_proc(prop, accessor_key, non_nil_type, klass)
proc do |val|
if val.nil?
instance_variable_set(accessor_key, nil)
elsif val.is_a?(non_nil_type)
instance_variable_set(accessor_key, val)
else
T::Props::Private::SetterFactory.raise_pretty_error(
klass,
prop,
T::Utils.coerce(non_nil_type),
val,
)
instance_variable_set(accessor_key, val)
end
end
end
sig do
params(
prop: Symbol,
accessor_key: Symbol,
non_nil_type: T::Types::Base,
klass: T.all(Module, T::Props::ClassMethods),
validate: T.nilable(ValidateProc),
)
.returns(SetterProc)
end
private_class_method def self.nilable_proc(prop, accessor_key, non_nil_type, klass, validate)
proc do |val|
if val.nil?
instance_variable_set(accessor_key, nil)
# this use of recursively_valid? is intentional: unlike for
# methods, we want to make sure data at the 'edge'
# (e.g. models that go into databases or structs serialized
# from disk) are correct, so we use more thorough runtime
# checks there
elsif non_nil_type.recursively_valid?(val)
validate&.call(prop, val)
instance_variable_set(accessor_key, val)
else
T::Props::Private::SetterFactory.raise_pretty_error(
klass,
prop,
non_nil_type,
val,
)
instance_variable_set(accessor_key, val)
end
end
end
sig do
params(
klass: T.all(Module, T::Props::ClassMethods),
prop: Symbol,
type: T.any(T::Types::Base, Module),
val: T.untyped,
)
.void
end
def self.raise_pretty_error(klass, prop, type, val)
base_message = "Can't set #{klass.name}.#{prop} to #{val.inspect} (instance of #{val.class}) - need a #{type}"
pretty_message = "Parameter '#{prop}': #{base_message}\n"
caller_loc = caller_locations.find {|l| !l.to_s.include?('sorbet-runtime/lib/types/props')}
if caller_loc
pretty_message += "Caller: #{caller_loc.path}:#{caller_loc.lineno}\n"
end
T::Configuration.call_validation_error_handler(
nil,
message: base_message,
pretty_message: pretty_message,
kind: 'Parameter',
name: prop,
type: type,
value: val,
location: caller_loc,
)
end
end
end
end

View File

@ -73,7 +73,6 @@ require_relative 'types/private/abstract/validate'
# Catch all. Sort of built by `cd extn; find types -type f | grep -v test | sort`
require_relative 'types/generic'
require_relative 'types/interface_wrapper'
require_relative 'types/private/abstract/declare'
require_relative 'types/private/abstract/hooks'
require_relative 'types/private/casts'

View File

@ -18,7 +18,6 @@ module T::Private::Abstract::Declare
Abstract::Data.set(mod, :abstract_type, type)
mod.extend(Abstract::Hooks)
mod.extend(T::InterfaceWrapper::Helpers)
if mod.is_a?(Class)
if type == :interface

View File

@ -191,12 +191,11 @@ module T::Private::Methods
end
end
def self.add_module_with_final_method(mod, method_name, is_singleton_method)
m = is_singleton_method ? mod.singleton_class : mod
methods = @modules_with_final[m]
def self.add_module_with_final_method(mod, method_name)
methods = @modules_with_final[mod]
if methods.nil?
methods = {}
@modules_with_final[m] = methods
@modules_with_final[mod] = methods
end
methods[method_name] = true
nil
@ -209,13 +208,12 @@ module T::Private::Methods
end
# Only public because it needs to get called below inside the replace_method blocks below.
def self._on_method_added(hook_mod, method_name, is_singleton_method: false)
def self._on_method_added(hook_mod, mod, method_name)
if T::Private::DeclState.current.skip_on_method_added
return
end
current_declaration = T::Private::DeclState.current.active_declaration
mod = is_singleton_method ? hook_mod.singleton_class : hook_mod
if T::Private::Final.final_module?(mod) && (current_declaration.nil? || !current_declaration.final)
raise "#{mod} was declared as final but its method `#{method_name}` was not declared as final"
@ -286,7 +284,7 @@ module T::Private::Methods
# use hook_mod, not mod, because for example, we want class C to be marked as having final if we def C.foo as
# final. change this to mod to see some final_method tests fail.
note_module_deals_with_final(hook_mod)
add_module_with_final_method(hook_mod, method_name, is_singleton_method)
add_module_with_final_method(mod, method_name)
end
end
@ -430,7 +428,7 @@ module T::Private::Methods
run_sig_block_for_key(method_to_key(method))
end
private_class_method def self.run_sig_block_for_key(key)
private_class_method def self.run_sig_block_for_key(key, force_type_init: false)
blk = @sig_wrappers[key]
if !blk
sig = @signatures_by_method[key]
@ -453,14 +451,17 @@ module T::Private::Methods
end
@sig_wrappers.delete(key)
sig.force_type_init if force_type_init
sig
end
def self.run_all_sig_blocks
def self.run_all_sig_blocks(force_type_init: true)
loop do
break if @sig_wrappers.empty?
key, = @sig_wrappers.first
run_sig_block_for_key(key)
run_sig_block_for_key(key, force_type_init: force_type_init)
end
end
@ -540,14 +541,14 @@ module T::Private::Methods
module MethodHooks
def method_added(name)
super(name)
::T::Private::Methods._on_method_added(self, name, is_singleton_method: false)
::T::Private::Methods._on_method_added(self, self, name)
end
end
module SingletonMethodHooks
def singleton_method_added(name)
super(name)
::T::Private::Methods._on_method_added(self, name, is_singleton_method: true)
::T::Private::Methods._on_method_added(self, singleton_class, name)
end
end

View File

@ -15,8 +15,6 @@ module T::Private::Methods::CallValidation
original_visibility = visibility_method_name(mod, method_sig.method_name)
if method_sig.mode == T::Private::Methods::Modes.abstract
T::Private::ClassUtils.replace_method(mod, method_sig.method_name, true) do |*args, &blk|
# TODO: write a cop to ensure that abstract methods have an empty body
#
# We allow abstract methods to be implemented by things further down the ancestor chain.
# So, if a super method exists, call it.
if defined?(super)
@ -67,14 +65,30 @@ module T::Private::Methods::CallValidation
simple_method = all_args_are_simple && method_sig.return_type.is_a?(T::Types::Simple)
simple_procedure = all_args_are_simple && method_sig.return_type.is_a?(T::Private::Types::Void)
# All the types for which valid? unconditionally returns `true`
return_is_ignorable =
(method_sig.return_type.equal?(T::Types::Untyped::Private::INSTANCE) ||
method_sig.return_type.equal?(T::Types::Anything::Private::INSTANCE) ||
method_sig.return_type.equal?(T::Types::AttachedClassType::Private::INSTANCE) ||
method_sig.return_type.equal?(T::Types::SelfType::Private::INSTANCE) ||
method_sig.return_type.is_a?(T::Types::TypeParameter) ||
method_sig.return_type.is_a?(T::Types::TypeVariable) ||
(method_sig.return_type.is_a?(T::Types::Simple) && method_sig.return_type.raw_type.equal?(BasicObject)))
returns_anything_method = all_args_are_simple && return_is_ignorable
T::Configuration.without_ruby_warnings do
T::Private::DeclState.current.without_on_method_added do
if simple_method
create_validator_method_fast(mod, original_method, method_sig, original_visibility)
elsif returns_anything_method
create_validator_method_skip_return_fast(mod, original_method, method_sig, original_visibility)
elsif simple_procedure
create_validator_procedure_fast(mod, original_method, method_sig, original_visibility)
elsif ok_for_fast_path && method_sig.return_type.is_a?(T::Private::Types::Void)
create_validator_procedure_medium(mod, original_method, method_sig, original_visibility)
elsif ok_for_fast_path && return_is_ignorable
create_validator_method_skip_return_medium(mod, original_method, method_sig, original_visibility)
elsif ok_for_fast_path
create_validator_method_medium(mod, original_method, method_sig, original_visibility)
elsif can_skip_block_type

View File

@ -343,6 +343,265 @@ module T::Private::Methods::CallValidation
end
end
def self.create_validator_method_skip_return_fast(mod, original_method, method_sig, original_visibility)
# trampoline to reduce stack frame size
arg_types = method_sig.arg_types
case arg_types.length
when 0
create_validator_method_skip_return_fast0(mod, original_method, method_sig, original_visibility)
when 1
create_validator_method_skip_return_fast1(mod, original_method, method_sig, original_visibility,
arg_types[0][1].raw_type)
when 2
create_validator_method_skip_return_fast2(mod, original_method, method_sig, original_visibility,
arg_types[0][1].raw_type,
arg_types[1][1].raw_type)
when 3
create_validator_method_skip_return_fast3(mod, original_method, method_sig, original_visibility,
arg_types[0][1].raw_type,
arg_types[1][1].raw_type,
arg_types[2][1].raw_type)
when 4
create_validator_method_skip_return_fast4(mod, original_method, method_sig, original_visibility,
arg_types[0][1].raw_type,
arg_types[1][1].raw_type,
arg_types[2][1].raw_type,
arg_types[3][1].raw_type)
else
raise 'should not happen'
end
end
def self.create_validator_method_skip_return_fast0(mod, original_method, method_sig, original_visibility)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk|
# This method is a manually sped-up version of more general code in `validate_call`
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind(self).call(&blk)
end
end
def self.create_validator_method_skip_return_fast1(mod, original_method, method_sig, original_visibility, arg0_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0.is_a?(arg0_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind(self).call(arg0, &blk)
end
end
def self.create_validator_method_skip_return_fast2(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0.is_a?(arg0_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
unless arg1.is_a?(arg1_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[1][1].error_message_for_obj(arg1),
'Parameter',
method_sig.arg_types[1][0],
arg1_type,
arg1,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind(self).call(arg0, arg1, &blk)
end
end
def self.create_validator_method_skip_return_fast3(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0.is_a?(arg0_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
unless arg1.is_a?(arg1_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[1][1].error_message_for_obj(arg1),
'Parameter',
method_sig.arg_types[1][0],
arg1_type,
arg1,
caller_offset: -1
)
end
unless arg2.is_a?(arg2_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[2][1].error_message_for_obj(arg2),
'Parameter',
method_sig.arg_types[2][0],
arg2_type,
arg2,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind(self).call(arg0, arg1, arg2, &blk)
end
end
def self.create_validator_method_skip_return_fast4(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type, arg3_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0.is_a?(arg0_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
unless arg1.is_a?(arg1_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[1][1].error_message_for_obj(arg1),
'Parameter',
method_sig.arg_types[1][0],
arg1_type,
arg1,
caller_offset: -1
)
end
unless arg2.is_a?(arg2_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[2][1].error_message_for_obj(arg2),
'Parameter',
method_sig.arg_types[2][0],
arg2_type,
arg2,
caller_offset: -1
)
end
unless arg3.is_a?(arg3_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[3][1].error_message_for_obj(arg3),
'Parameter',
method_sig.arg_types[3][0],
arg3_type,
arg3,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind(self).call(arg0, arg1, arg2, arg3, &blk)
end
end
def self.create_validator_procedure_fast(mod, original_method, method_sig, original_visibility)
# trampoline to reduce stack frame size
arg_types = method_sig.arg_types
@ -944,6 +1203,265 @@ module T::Private::Methods::CallValidation
end
end
def self.create_validator_method_skip_return_medium(mod, original_method, method_sig, original_visibility)
# trampoline to reduce stack frame size
arg_types = method_sig.arg_types
case arg_types.length
when 0
create_validator_method_skip_return_medium0(mod, original_method, method_sig, original_visibility)
when 1
create_validator_method_skip_return_medium1(mod, original_method, method_sig, original_visibility,
arg_types[0][1])
when 2
create_validator_method_skip_return_medium2(mod, original_method, method_sig, original_visibility,
arg_types[0][1],
arg_types[1][1])
when 3
create_validator_method_skip_return_medium3(mod, original_method, method_sig, original_visibility,
arg_types[0][1],
arg_types[1][1],
arg_types[2][1])
when 4
create_validator_method_skip_return_medium4(mod, original_method, method_sig, original_visibility,
arg_types[0][1],
arg_types[1][1],
arg_types[2][1],
arg_types[3][1])
else
raise 'should not happen'
end
end
def self.create_validator_method_skip_return_medium0(mod, original_method, method_sig, original_visibility)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk|
# This method is a manually sped-up version of more general code in `validate_call`
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind(self).call(&blk)
end
end
def self.create_validator_method_skip_return_medium1(mod, original_method, method_sig, original_visibility, arg0_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0_type.valid?(arg0)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind(self).call(arg0, &blk)
end
end
def self.create_validator_method_skip_return_medium2(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0_type.valid?(arg0)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
unless arg1_type.valid?(arg1)
CallValidation.report_error(
method_sig,
method_sig.arg_types[1][1].error_message_for_obj(arg1),
'Parameter',
method_sig.arg_types[1][0],
arg1_type,
arg1,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind(self).call(arg0, arg1, &blk)
end
end
def self.create_validator_method_skip_return_medium3(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0_type.valid?(arg0)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
unless arg1_type.valid?(arg1)
CallValidation.report_error(
method_sig,
method_sig.arg_types[1][1].error_message_for_obj(arg1),
'Parameter',
method_sig.arg_types[1][0],
arg1_type,
arg1,
caller_offset: -1
)
end
unless arg2_type.valid?(arg2)
CallValidation.report_error(
method_sig,
method_sig.arg_types[2][1].error_message_for_obj(arg2),
'Parameter',
method_sig.arg_types[2][0],
arg2_type,
arg2,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind(self).call(arg0, arg1, arg2, &blk)
end
end
def self.create_validator_method_skip_return_medium4(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type, arg3_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0_type.valid?(arg0)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
unless arg1_type.valid?(arg1)
CallValidation.report_error(
method_sig,
method_sig.arg_types[1][1].error_message_for_obj(arg1),
'Parameter',
method_sig.arg_types[1][0],
arg1_type,
arg1,
caller_offset: -1
)
end
unless arg2_type.valid?(arg2)
CallValidation.report_error(
method_sig,
method_sig.arg_types[2][1].error_message_for_obj(arg2),
'Parameter',
method_sig.arg_types[2][0],
arg2_type,
arg2,
caller_offset: -1
)
end
unless arg3_type.valid?(arg3)
CallValidation.report_error(
method_sig,
method_sig.arg_types[3][1].error_message_for_obj(arg3),
'Parameter',
method_sig.arg_types[3][0],
arg3_type,
arg3,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind(self).call(arg0, arg1, arg2, arg3, &blk)
end
end
def self.create_validator_procedure_medium(mod, original_method, method_sig, original_visibility)
# trampoline to reduce stack frame size
arg_types = method_sig.arg_types

View File

@ -343,6 +343,265 @@ module T::Private::Methods::CallValidation
end
end
def self.create_validator_method_skip_return_fast(mod, original_method, method_sig, original_visibility)
# trampoline to reduce stack frame size
arg_types = method_sig.arg_types
case arg_types.length
when 0
create_validator_method_skip_return_fast0(mod, original_method, method_sig, original_visibility)
when 1
create_validator_method_skip_return_fast1(mod, original_method, method_sig, original_visibility,
arg_types[0][1].raw_type)
when 2
create_validator_method_skip_return_fast2(mod, original_method, method_sig, original_visibility,
arg_types[0][1].raw_type,
arg_types[1][1].raw_type)
when 3
create_validator_method_skip_return_fast3(mod, original_method, method_sig, original_visibility,
arg_types[0][1].raw_type,
arg_types[1][1].raw_type,
arg_types[2][1].raw_type)
when 4
create_validator_method_skip_return_fast4(mod, original_method, method_sig, original_visibility,
arg_types[0][1].raw_type,
arg_types[1][1].raw_type,
arg_types[2][1].raw_type,
arg_types[3][1].raw_type)
else
raise 'should not happen'
end
end
def self.create_validator_method_skip_return_fast0(mod, original_method, method_sig, original_visibility)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk|
# This method is a manually sped-up version of more general code in `validate_call`
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind_call(self, &blk)
end
end
def self.create_validator_method_skip_return_fast1(mod, original_method, method_sig, original_visibility, arg0_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0.is_a?(arg0_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind_call(self, arg0, &blk)
end
end
def self.create_validator_method_skip_return_fast2(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0.is_a?(arg0_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
unless arg1.is_a?(arg1_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[1][1].error_message_for_obj(arg1),
'Parameter',
method_sig.arg_types[1][0],
arg1_type,
arg1,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind_call(self, arg0, arg1, &blk)
end
end
def self.create_validator_method_skip_return_fast3(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0.is_a?(arg0_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
unless arg1.is_a?(arg1_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[1][1].error_message_for_obj(arg1),
'Parameter',
method_sig.arg_types[1][0],
arg1_type,
arg1,
caller_offset: -1
)
end
unless arg2.is_a?(arg2_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[2][1].error_message_for_obj(arg2),
'Parameter',
method_sig.arg_types[2][0],
arg2_type,
arg2,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind_call(self, arg0, arg1, arg2, &blk)
end
end
def self.create_validator_method_skip_return_fast4(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type, arg3_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0.is_a?(arg0_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
unless arg1.is_a?(arg1_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[1][1].error_message_for_obj(arg1),
'Parameter',
method_sig.arg_types[1][0],
arg1_type,
arg1,
caller_offset: -1
)
end
unless arg2.is_a?(arg2_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[2][1].error_message_for_obj(arg2),
'Parameter',
method_sig.arg_types[2][0],
arg2_type,
arg2,
caller_offset: -1
)
end
unless arg3.is_a?(arg3_type)
CallValidation.report_error(
method_sig,
method_sig.arg_types[3][1].error_message_for_obj(arg3),
'Parameter',
method_sig.arg_types[3][0],
arg3_type,
arg3,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind_call(self, arg0, arg1, arg2, arg3, &blk)
end
end
def self.create_validator_procedure_fast(mod, original_method, method_sig, original_visibility)
# trampoline to reduce stack frame size
arg_types = method_sig.arg_types
@ -944,6 +1203,265 @@ module T::Private::Methods::CallValidation
end
end
def self.create_validator_method_skip_return_medium(mod, original_method, method_sig, original_visibility)
# trampoline to reduce stack frame size
arg_types = method_sig.arg_types
case arg_types.length
when 0
create_validator_method_skip_return_medium0(mod, original_method, method_sig, original_visibility)
when 1
create_validator_method_skip_return_medium1(mod, original_method, method_sig, original_visibility,
arg_types[0][1])
when 2
create_validator_method_skip_return_medium2(mod, original_method, method_sig, original_visibility,
arg_types[0][1],
arg_types[1][1])
when 3
create_validator_method_skip_return_medium3(mod, original_method, method_sig, original_visibility,
arg_types[0][1],
arg_types[1][1],
arg_types[2][1])
when 4
create_validator_method_skip_return_medium4(mod, original_method, method_sig, original_visibility,
arg_types[0][1],
arg_types[1][1],
arg_types[2][1],
arg_types[3][1])
else
raise 'should not happen'
end
end
def self.create_validator_method_skip_return_medium0(mod, original_method, method_sig, original_visibility)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk|
# This method is a manually sped-up version of more general code in `validate_call`
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind_call(self, &blk)
end
end
def self.create_validator_method_skip_return_medium1(mod, original_method, method_sig, original_visibility, arg0_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0_type.valid?(arg0)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind_call(self, arg0, &blk)
end
end
def self.create_validator_method_skip_return_medium2(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0_type.valid?(arg0)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
unless arg1_type.valid?(arg1)
CallValidation.report_error(
method_sig,
method_sig.arg_types[1][1].error_message_for_obj(arg1),
'Parameter',
method_sig.arg_types[1][0],
arg1_type,
arg1,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind_call(self, arg0, arg1, &blk)
end
end
def self.create_validator_method_skip_return_medium3(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0_type.valid?(arg0)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
unless arg1_type.valid?(arg1)
CallValidation.report_error(
method_sig,
method_sig.arg_types[1][1].error_message_for_obj(arg1),
'Parameter',
method_sig.arg_types[1][0],
arg1_type,
arg1,
caller_offset: -1
)
end
unless arg2_type.valid?(arg2)
CallValidation.report_error(
method_sig,
method_sig.arg_types[2][1].error_message_for_obj(arg2),
'Parameter',
method_sig.arg_types[2][0],
arg2_type,
arg2,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind_call(self, arg0, arg1, arg2, &blk)
end
end
def self.create_validator_method_skip_return_medium4(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type, arg3_type)
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk|
# This method is a manually sped-up version of more general code in `validate_call`
unless arg0_type.valid?(arg0)
CallValidation.report_error(
method_sig,
method_sig.arg_types[0][1].error_message_for_obj(arg0),
'Parameter',
method_sig.arg_types[0][0],
arg0_type,
arg0,
caller_offset: -1
)
end
unless arg1_type.valid?(arg1)
CallValidation.report_error(
method_sig,
method_sig.arg_types[1][1].error_message_for_obj(arg1),
'Parameter',
method_sig.arg_types[1][0],
arg1_type,
arg1,
caller_offset: -1
)
end
unless arg2_type.valid?(arg2)
CallValidation.report_error(
method_sig,
method_sig.arg_types[2][1].error_message_for_obj(arg2),
'Parameter',
method_sig.arg_types[2][0],
arg2_type,
arg2,
caller_offset: -1
)
end
unless arg3_type.valid?(arg3)
CallValidation.report_error(
method_sig,
method_sig.arg_types[3][1].error_message_for_obj(arg3),
'Parameter',
method_sig.arg_types[3][0],
arg3_type,
arg3,
caller_offset: -1
)
end
# The following line breaks are intentional to show nice pry message
# PRY note:
# this code is sig validation code.
# Please issue `finish` to step out of it
original_method.bind_call(self, arg0, arg1, arg2, arg3, &blk)
end
end
def self.create_validator_procedure_medium(mod, original_method, method_sig, original_visibility)
# trampoline to reduce stack frame size
arg_types = method_sig.arg_types

View File

@ -183,7 +183,7 @@ module T::Private::Methods
self
end
# Declares valid type paramaters which can be used with `T.type_parameter` in
# Declares valid type parameters which can be used with `T.type_parameter` in
# this `sig`.
#
# This is used for generic methods. Example usage:

View File

@ -245,6 +245,15 @@ class T::Private::Methods::Signature
"#{@method} at #{loc}"
end
def force_type_init
@arg_types.each {|_, type| type.build_type}
@kwarg_types.each {|_, type| type.build_type}
@block_type&.build_type
@rest_type&.build_type
@keyrest_type&.build_type
@return_type.build_type
end
EMPTY_LIST = [].freeze
EMPTY_HASH = {}.freeze
end

View File

@ -262,7 +262,14 @@ module T::Private::Methods::SignatureValidation
end
# return types must be covariant
if !signature.return_type.subtype_of?(super_signature.return_type)
super_signature_return_type = super_signature.return_type
if super_signature_return_type == T::Private::Types::Void::Private::INSTANCE
# Treat `.void` as `T.anything` (see corresponding comment in definition_valitor for more)
super_signature_return_type = T::Types::Anything::Private::INSTANCE
end
if !signature.return_type.subtype_of?(super_signature_return_type)
raise "Incompatible return type in signature for #{mode_noun} of method `#{signature.method_name}`:\n" \
"* Base: `#{super_signature.return_type}` (in #{method_loc_str(super_signature.method)})\n" \
"* #{mode_noun.capitalize}: `#{signature.return_type}` (in #{method_loc_str(signature.method)})\n" \

View File

@ -6,6 +6,10 @@
class T::Private::Types::NotTyped < T::Types::Base
ERROR_MESSAGE = "Validation is being done on a `NotTyped`. Please report this bug at https://github.com/sorbet/sorbet/issues"
def build_type
nil
end
# overrides Base
def name
"<NOT-TYPED>"

View File

@ -9,6 +9,10 @@ class T::Private::Types::StringHolder < T::Types::Base
@string = string
end
def build_type
nil
end
# overrides Base
def name
string

View File

@ -9,6 +9,10 @@ module T::Private::Types
@callable = callable
end
def build_type
nil
end
def aliased_type
@aliased_type ||= T::Utils.coerce(@callable.call)
end

View File

@ -139,9 +139,9 @@ module T::Props
end
if cls_or_args.is_a?(Hash)
self.prop(name, **cls_or_args.merge(immutable: true))
self.prop(name, cls_or_args.merge(immutable: true))
else
self.prop(name, cls_or_args, **args.merge(immutable: true))
self.prop(name, cls_or_args, args.merge(immutable: true))
end
end

View File

@ -100,10 +100,7 @@ class T::Props::Decorator
# checked(:never) - potentially O(prop accesses) depending on usage pattern
sig {params(prop: Symbol, val: T.untyped).void.checked(:never)}
def validate_prop_value(prop, val)
# We call `setter_proc` here without binding to an instance, so it'll run
# `instance_variable_set` if validation passes, but nothing will care.
# We only care about the validation.
prop_rules(prop).fetch(:setter_proc).call(val)
prop_rules(prop).fetch(:value_validate_proc).call(val)
end
# For performance, don't use named params here.
@ -335,7 +332,7 @@ class T::Props::Decorator
prop_validate_definition!(name, cls, rules, type_object)
# Retrive the possible underlying object with T.nilable.
# Retrieve the possible underlying object with T.nilable.
type = T::Utils::Nilable.get_underlying_type(type)
rules_sensitivity = rules[:sensitivity]
@ -378,7 +375,11 @@ class T::Props::Decorator
end
end
rules[:setter_proc] = T::Props::Private::SetterFactory.build_setter_proc(@class, name, rules).freeze
setter_proc, value_validate_proc = T::Props::Private::SetterFactory.build_setter_proc(@class, name, rules)
setter_proc.freeze
value_validate_proc.freeze
rules[:setter_proc] = setter_proc
rules[:value_validate_proc] = value_validate_proc
add_prop_definition(name, rules)

View File

@ -0,0 +1,257 @@
# frozen_string_literal: true
# typed: strict
module T::Props
module Private
module SetterFactory
extend T::Sig
SetterProc = T.type_alias {T.proc.params(val: T.untyped).void}
ValueValidationProc = T.type_alias {T.proc.params(val: T.untyped).void}
ValidateProc = T.type_alias {T.proc.params(prop: Symbol, value: T.untyped).void}
sig do
params(
klass: T.all(Module, T::Props::ClassMethods),
prop: Symbol,
rules: T::Hash[Symbol, T.untyped]
)
.returns([SetterProc, ValueValidationProc])
.checked(:never)
end
def self.build_setter_proc(klass, prop, rules)
# Our nil check works differently than a simple T.nilable for various
# reasons (including the `raise_on_nil_write` setting and the existence
# of defaults & factories), so unwrap any T.nilable and do a check
# manually.
non_nil_type = T::Utils::Nilable.get_underlying_type_object(rules.fetch(:type_object))
accessor_key = rules.fetch(:accessor_key)
validate = rules[:setter_validate]
# It seems like a bug that this affects the behavior of setters, but
# some existing code relies on this behavior
has_explicit_nil_default = rules.key?(:default) && rules.fetch(:default).nil?
# Use separate methods in order to ensure that we only close over necessary
# variables
if !T::Props::Utils.need_nil_write_check?(rules) || has_explicit_nil_default
if validate.nil? && non_nil_type.is_a?(T::Types::Simple)
simple_nilable_proc(prop, accessor_key, non_nil_type.raw_type, klass)
else
nilable_proc(prop, accessor_key, non_nil_type, klass, validate)
end
else
if validate.nil? && non_nil_type.is_a?(T::Types::Simple)
simple_non_nil_proc(prop, accessor_key, non_nil_type.raw_type, klass)
else
non_nil_proc(prop, accessor_key, non_nil_type, klass, validate)
end
end
end
sig do
params(
prop: Symbol,
accessor_key: Symbol,
non_nil_type: Module,
klass: T.all(Module, T::Props::ClassMethods),
)
.returns([SetterProc, ValueValidationProc])
end
private_class_method def self.simple_non_nil_proc(prop, accessor_key, non_nil_type, klass)
[
proc do |val|
unless val.is_a?(non_nil_type)
T::Props::Private::SetterFactory.raise_pretty_error(
klass,
prop,
T::Utils.coerce(non_nil_type),
val,
)
end
instance_variable_set(accessor_key, val)
end,
proc do |val|
unless val.is_a?(non_nil_type)
T::Props::Private::SetterFactory.raise_pretty_error(
klass,
prop,
T::Utils.coerce(non_nil_type),
val,
)
end
end,
]
end
sig do
params(
prop: Symbol,
accessor_key: Symbol,
non_nil_type: T::Types::Base,
klass: T.all(Module, T::Props::ClassMethods),
validate: T.nilable(ValidateProc)
)
.returns([SetterProc, ValueValidationProc])
end
private_class_method def self.non_nil_proc(prop, accessor_key, non_nil_type, klass, validate)
[
proc do |val|
# this use of recursively_valid? is intentional: unlike for
# methods, we want to make sure data at the 'edge'
# (e.g. models that go into databases or structs serialized
# from disk) are correct, so we use more thorough runtime
# checks there
if non_nil_type.recursively_valid?(val)
validate&.call(prop, val)
else
T::Props::Private::SetterFactory.raise_pretty_error(
klass,
prop,
non_nil_type,
val,
)
end
instance_variable_set(accessor_key, val)
end,
proc do |val|
# this use of recursively_valid? is intentional: unlike for
# methods, we want to make sure data at the 'edge'
# (e.g. models that go into databases or structs serialized
# from disk) are correct, so we use more thorough runtime
# checks there
if non_nil_type.recursively_valid?(val)
validate&.call(prop, val)
else
T::Props::Private::SetterFactory.raise_pretty_error(
klass,
prop,
non_nil_type,
val,
)
end
end,
]
end
sig do
params(
prop: Symbol,
accessor_key: Symbol,
non_nil_type: Module,
klass: T.all(Module, T::Props::ClassMethods),
)
.returns([SetterProc, ValueValidationProc])
end
private_class_method def self.simple_nilable_proc(prop, accessor_key, non_nil_type, klass)
[
proc do |val|
unless val.nil? || val.is_a?(non_nil_type)
T::Props::Private::SetterFactory.raise_pretty_error(
klass,
prop,
T::Utils.coerce(non_nil_type),
val,
)
end
instance_variable_set(accessor_key, val)
end,
proc do |val|
unless val.nil? || val.is_a?(non_nil_type)
T::Props::Private::SetterFactory.raise_pretty_error(
klass,
prop,
T::Utils.coerce(non_nil_type),
val,
)
end
end,
]
end
sig do
params(
prop: Symbol,
accessor_key: Symbol,
non_nil_type: T::Types::Base,
klass: T.all(Module, T::Props::ClassMethods),
validate: T.nilable(ValidateProc),
)
.returns([SetterProc, ValueValidationProc])
end
private_class_method def self.nilable_proc(prop, accessor_key, non_nil_type, klass, validate)
[
proc do |val|
if val.nil?
instance_variable_set(accessor_key, nil)
# this use of recursively_valid? is intentional: unlike for
# methods, we want to make sure data at the 'edge'
# (e.g. models that go into databases or structs serialized
# from disk) are correct, so we use more thorough runtime
# checks there
elsif non_nil_type.recursively_valid?(val)
validate&.call(prop, val)
instance_variable_set(accessor_key, val)
else
T::Props::Private::SetterFactory.raise_pretty_error(
klass,
prop,
non_nil_type,
val,
)
instance_variable_set(accessor_key, val)
end
end,
proc do |val|
if val.nil?
# this use of recursively_valid? is intentional: unlike for
# methods, we want to make sure data at the 'edge'
# (e.g. models that go into databases or structs serialized
# from disk) are correct, so we use more thorough runtime
# checks there
elsif non_nil_type.recursively_valid?(val)
validate&.call(prop, val)
else
T::Props::Private::SetterFactory.raise_pretty_error(
klass,
prop,
non_nil_type,
val,
)
end
end,
]
end
sig do
params(
klass: T.all(Module, T::Props::ClassMethods),
prop: Symbol,
type: T.any(T::Types::Base, Module),
val: T.untyped,
)
.void
end
def self.raise_pretty_error(klass, prop, type, val)
base_message = "Can't set #{klass.name}.#{prop} to #{val.inspect} (instance of #{val.class}) - need a #{type}"
pretty_message = "Parameter '#{prop}': #{base_message}\n"
caller_loc = caller_locations.find {|l| !l.to_s.include?('sorbet-runtime/lib/types/props')}
if caller_loc
pretty_message += "Caller: #{caller_loc.path}:#{caller_loc.lineno}\n"
end
T::Configuration.call_validation_error_handler(
nil,
message: base_message,
pretty_message: pretty_message,
kind: 'Parameter',
name: prop,
type: type,
value: val,
location: caller_loc,
)
end
end
end
end

View File

@ -6,6 +6,10 @@ module T::Types
class Anything < Base
def initialize; end
def build_type
nil
end
# overrides Base
def name
"T.anything"

View File

@ -10,6 +10,10 @@ module T::Types
def initialize(); end
def build_type
nil
end
# overrides Base
def name
"T.attached_class"

View File

@ -33,6 +33,12 @@ module T::Types
raise NotImplementedError
end
# Force any lazy initialization that this type might need to do
# It's unusual to call this directly; you probably want to call it indirectly via `T::Utils.run_all_sig_blocks`.
def build_type
raise NotImplementedError
end
# Equality is based on name, so be sure the name reflects all relevant state when implementing.
def name
raise NotImplementedError

View File

@ -10,6 +10,10 @@ module T::Types
@type = type
end
def build_type
nil
end
# overrides Base
def name
"T.class_of(#{@type})"

View File

@ -12,6 +12,10 @@ module T::Types
@values = values
end
def build_type
nil
end
# overrides Base
def valid?(obj)
@values.member?(obj)

View File

@ -6,23 +6,30 @@ module T::Types
# Takes a list of types. Validates each item in an array using the type in the same position
# in the list.
class FixedArray < Base
attr_reader :types
def initialize(types)
@types = types.map {|type| T::Utils.coerce(type)}
@inner_types = types
end
def types
@types ||= @inner_types.map {|type| T::Utils.coerce(type)}
end
def build_type
types
nil
end
# overrides Base
def name
"[#{@types.join(', ')}]"
"[#{types.join(', ')}]"
end
# overrides Base
def recursively_valid?(obj)
if obj.is_a?(Array) && obj.length == @types.length
if obj.is_a?(Array) && obj.length == types.length
i = 0
while i < @types.length
if !@types[i].recursively_valid?(obj[i])
while i < types.length
if !types[i].recursively_valid?(obj[i])
return false
end
i += 1
@ -35,10 +42,10 @@ module T::Types
# overrides Base
def valid?(obj)
if obj.is_a?(Array) && obj.length == @types.length
if obj.is_a?(Array) && obj.length == types.length
i = 0
while i < @types.length
if !@types[i].valid?(obj[i])
while i < types.length
if !types[i].valid?(obj[i])
return false
end
i += 1
@ -56,7 +63,7 @@ module T::Types
# Properly speaking, covariance here is unsound since arrays
# can be mutated, but sorbet implements covariant tuples for
# ease of adoption.
@types.size == other.types.size && @types.zip(other.types).all? do |t1, t2|
types.size == other.types.size && types.zip(other.types).all? do |t1, t2|
t1.subtype_of?(t2)
end
when TypedArray
@ -85,7 +92,7 @@ module T::Types
# overrides Base
def describe_obj(obj)
if obj.is_a?(Array)
if obj.length == @types.length
if obj.length == types.length
item_classes = obj.map(&:class).join(', ')
"type [#{item_classes}]"
else

View File

@ -5,30 +5,37 @@ module T::Types
# Takes a hash of types. Validates each item in a hash using the type in the same position
# in the list.
class FixedHash < Base
attr_reader :types
def initialize(types)
@types = types.transform_values {|v| T::Utils.coerce(v)}
@inner_types = types
end
def types
@types ||= @inner_types.transform_values {|v| T::Utils.coerce(v)}
end
def build_type
types
nil
end
# overrides Base
def name
serialize_hash(@types)
serialize_hash(types)
end
# overrides Base
def recursively_valid?(obj)
return false unless obj.is_a?(Hash)
return false if @types.any? {|key, type| !type.recursively_valid?(obj[key])}
return false if obj.any? {|key, _| !@types[key]}
return false if types.any? {|key, type| !type.recursively_valid?(obj[key])}
return false if obj.any? {|key, _| !types[key]}
true
end
# overrides Base
def valid?(obj)
return false unless obj.is_a?(Hash)
return false if @types.any? {|key, type| !type.valid?(obj[key])}
return false if obj.any? {|key, _| !@types[key]}
return false if types.any? {|key, type| !type.valid?(obj[key])}
return false if obj.any? {|key, _| !types[key]}
true
end
@ -37,7 +44,7 @@ module T::Types
case other
when FixedHash
# Using `subtype_of?` here instead of == would be unsound
@types == other.types
types == other.types
when TypedHash
# warning: covariant hashes

View File

@ -4,10 +4,12 @@
module T::Types
# Takes a list of types. Validates that an object matches all of the types.
class Intersection < Base
attr_reader :types
def initialize(types)
@types = types.flat_map do |type|
@inner_types = types
end
def types
@types ||= @inner_types.flat_map do |type|
type = T::Utils.resolve_alias(type)
if type.is_a?(Intersection)
# Simplify nested intersections (mostly so `name` returns a nicer value)
@ -18,19 +20,24 @@ module T::Types
end.uniq
end
def build_type
types
nil
end
# overrides Base
def name
"T.all(#{@types.map(&:name).compact.sort.join(', ')})"
"T.all(#{types.map(&:name).compact.sort.join(', ')})"
end
# overrides Base
def recursively_valid?(obj)
@types.all? {|type| type.recursively_valid?(obj)}
types.all? {|type| type.recursively_valid?(obj)}
end
# overrides Base
def valid?(obj)
@types.all? {|type| type.valid?(obj)}
types.all? {|type| type.valid?(obj)}
end
# overrides Base

View File

@ -6,6 +6,10 @@ module T::Types
class NoReturn < Base
def initialize; end
def build_type
nil
end
# overrides Base
def name
"T.noreturn"

View File

@ -8,21 +8,31 @@ module T::Types
# At present, we only support fixed-arity procs with no optional or
# keyword arguments.
class Proc < Base
attr_reader :arg_types
attr_reader :returns
def initialize(arg_types, returns)
@arg_types = {}
arg_types.each do |key, raw_type|
@arg_types[key] = T::Utils.coerce(raw_type)
end
@returns = T::Utils.coerce(returns)
@inner_arg_types = arg_types
@inner_returns = returns
end
def arg_types
@arg_types ||= @inner_arg_types.map do |key, raw_type|
[key, T::Utils.coerce(raw_type)]
end.to_h
end
def returns
@returns ||= T::Utils.coerce(@inner_returns)
end
def build_type
arg_types
returns
nil
end
# overrides Base
def name
args = []
@arg_types.each do |k, v|
arg_types.each do |k, v|
args << "#{k}: #{v.name}"
end
"T.proc.params(#{args.join(', ')}).returns(#{returns})"

View File

@ -8,6 +8,10 @@ module T::Types
def initialize(); end
def build_type
nil
end
# overrides Base
def name
"T.self_type"

View File

@ -13,6 +13,10 @@ module T::Types
@raw_type = raw_type
end
def build_type
nil
end
# overrides Base
def name
# Memoize to mitigate pathological performance with anonymous modules (https://bugs.ruby-lang.org/issues/11119)

View File

@ -10,6 +10,10 @@ module T::Types
@val = val
end
def build_type
nil
end
# overrides Base
def name
# Strips the #<...> off, just leaving the ...

View File

@ -20,6 +20,10 @@ module T::Types
@name = name
end
def build_type
nil
end
def self.make(name)
cached = Private.cached_entry(name)
return cached if cached

View File

@ -5,7 +5,7 @@ module T::Types
class TypedArray < TypedEnumerable
# overrides Base
def name
"T::Array[#{@type.name}]"
"T::Array[#{type.name}]"
end
def underlying_class
@ -60,6 +60,11 @@ module T::Types
obj.is_a?(Array)
end
def freeze
build_type # force lazy initialization before freezing the object
super
end
module Private
INSTANCE = Untyped.new.freeze
end

View File

@ -3,15 +3,22 @@
module T::Types
class TypedClass < T::Types::Base
attr_reader :type
def initialize(type)
@type = T::Utils.coerce(type)
@inner_type = type
end
def type
@type ||= T::Utils.coerce(@inner_type)
end
def build_type
type
nil
end
# overrides Base
def name
"T::Class[#{@type.name}]"
"T::Class[#{type.name}]"
end
def underlying_class
@ -67,6 +74,11 @@ module T::Types
super(T.untyped)
end
def freeze
build_type # force lazy initialization before freezing the object
super
end
module Private
INSTANCE = Untyped.new.freeze
end
@ -77,6 +89,11 @@ module T::Types
super(T.anything)
end
def freeze
build_type # force lazy initialization before freezing the object
super
end
module Private
INSTANCE = Anything.new.freeze
end

View File

@ -6,10 +6,17 @@ module T::Types
# `case` statement below in `describe_obj` in order to get better
# error messages.
class TypedEnumerable < Base
attr_reader :type
def initialize(type)
@type = T::Utils.coerce(type)
@inner_type = type
end
def type
@type ||= T::Utils.coerce(@inner_type)
end
def build_type
type
nil
end
def underlying_class
@ -18,7 +25,7 @@ module T::Types
# overrides Base
def name
"T::Enumerable[#{@type.name}]"
"T::Enumerable[#{type.name}]"
end
# overrides Base
@ -34,20 +41,20 @@ module T::Types
begin
it = 0
while it < obj.count
return false unless @type.recursively_valid?(obj[it])
return false unless type.recursively_valid?(obj[it])
it += 1
end
true
end
when Hash
return false unless @type.is_a?(FixedArray)
types = @type.types
return false unless type.is_a?(FixedArray)
types = type.types
return false if types.count != 2
key_type = types[0]
value_type = types[1]
obj.each_pair do |key, val|
# Some objects (I'm looking at you Rack::Utils::HeaderHash) don't
# iterate over a [key, value] array, so we can't juse use the @type.recursively_valid?(v)
# iterate over a [key, value] array, so we can't just use the type.recursively_valid?(v)
return false if !key_type.recursively_valid?(key) || !value_type.recursively_valid?(val)
end
true
@ -65,10 +72,10 @@ module T::Types
# boundlessness, it does not express a type. For example `(nil...nil)` is not a T::Range[NilClass], its a range
# of unknown types (T::Range[T.untyped]).
# Similarly, `(nil...1)` is not a `T::Range[T.nilable(Integer)]`, it's a boundless range of Integer.
(obj.begin.nil? || @type.recursively_valid?(obj.begin)) && (obj.end.nil? || @type.recursively_valid?(obj.end))
(obj.begin.nil? || type.recursively_valid?(obj.begin)) && (obj.end.nil? || type.recursively_valid?(obj.end))
when Set
obj.each do |item|
return false unless @type.recursively_valid?(item)
return false unless type.recursively_valid?(item)
end
true
@ -90,7 +97,7 @@ module T::Types
# should be invariant because they are mutable and support
# both reading and writing. However, Sorbet treats *all*
# Enumerable subclasses as covariant for ease of adoption.
@type.subtype_of?(other.type)
type.subtype_of?(other.type)
elsif other.class <= Simple
underlying_class <= other.raw_type
else

View File

@ -3,15 +3,13 @@
module T::Types
class TypedEnumerator < TypedEnumerable
attr_reader :type
def underlying_class
Enumerator
end
# overrides Base
def name
"T::Enumerator[#{@type.name}]"
"T::Enumerator[#{type.name}]"
end
# overrides Base

View File

@ -3,15 +3,13 @@
module T::Types
class TypedEnumeratorChain < TypedEnumerable
attr_reader :type
def underlying_class
Enumerator::Chain
end
# overrides Base
def name
"T::Enumerator::Chain[#{@type.name}]"
"T::Enumerator::Chain[#{type.name}]"
end
# overrides Base

View File

@ -3,15 +3,13 @@
module T::Types
class TypedEnumeratorLazy < TypedEnumerable
attr_reader :type
def underlying_class
Enumerator::Lazy
end
# overrides Base
def name
"T::Enumerator::Lazy[#{@type.name}]"
"T::Enumerator::Lazy[#{type.name}]"
end
# overrides Base

View File

@ -3,22 +3,32 @@
module T::Types
class TypedHash < TypedEnumerable
# Technically we don't need these, but they are a nice api
attr_reader :keys, :values
def underlying_class
Hash
end
def initialize(keys:, values:)
@keys = T::Utils.coerce(keys)
@values = T::Utils.coerce(values)
@type = T::Utils.coerce([keys, values])
@inner_keys = keys
@inner_values = values
end
# Technically we don't need this, but it is a nice api
def keys
@keys ||= T::Utils.coerce(@inner_keys)
end
# Technically we don't need this, but it is a nice api
def values
@values ||= T::Utils.coerce(@inner_values)
end
def type
@type ||= T::Utils.coerce([keys, values])
end
# overrides Base
def name
"T::Hash[#{@keys.name}, #{@values.name}]"
"T::Hash[#{keys.name}, #{values.name}]"
end
# overrides Base

View File

@ -3,15 +3,13 @@
module T::Types
class TypedRange < TypedEnumerable
attr_reader :type
def underlying_class
Hash
end
# overrides Base
def name
"T::Range[#{@type.name}]"
"T::Range[#{type.name}]"
end
# overrides Base

View File

@ -3,15 +3,13 @@
module T::Types
class TypedSet < TypedEnumerable
attr_reader :type
def underlying_class
Hash
end
# overrides Base
def name
"T::Set[#{@type.name}]"
"T::Set[#{type.name}]"
end
# overrides Base

View File

@ -4,12 +4,14 @@
module T::Types
# Takes a list of types. Validates that an object matches at least one of the types.
class Union < Base
attr_reader :types
# Don't use Union.new directly, use `Private::Pool.union_of_types`
# inside sorbet-runtime and `T.any` elsewhere.
def initialize(types)
@types = types.flat_map do |type|
@inner_types = types
end
def types
@types ||= @inner_types.flat_map do |type|
type = T::Utils.coerce(type)
if type.is_a?(Union)
# Simplify nested unions (mostly so `name` returns a nicer value)
@ -20,6 +22,11 @@ module T::Types
end.uniq
end
def build_type
types
nil
end
# overrides Base
def name
# Use the attr_reader here so we can override it in SimplePairUnion
@ -51,12 +58,12 @@ module T::Types
# overrides Base
def recursively_valid?(obj)
@types.any? {|type| type.recursively_valid?(obj)}
types.any? {|type| type.recursively_valid?(obj)}
end
# overrides Base
def valid?(obj)
@types.any? {|type| type.valid?(obj)}
types.any? {|type| type.valid?(obj)}
end
# overrides Base

View File

@ -7,6 +7,10 @@ module T::Types
def initialize; end
def build_type
nil
end
# overrides Base
def name
"T.untyped"

View File

@ -79,8 +79,8 @@ module T::Utils
end
# Unwraps all the sigs.
def self.run_all_sig_blocks
T::Private::Methods.run_all_sig_blocks
def self.run_all_sig_blocks(force_type_init: true)
T::Private::Methods.run_all_sig_blocks(force_type_init: force_type_init)
end
# Return the underlying type for a type alias. Otherwise returns type.