module T::Private::Methods::CallValidation

def self.create_validator_method(mod, original_method, method_sig, original_visibility)

def self.create_validator_method(mod, original_method, method_sig, original_visibility)
  has_fixed_arity = method_sig.kwarg_types.empty? && !method_sig.has_rest && !method_sig.has_keyrest &&
    original_method.parameters.all? { |(kind, _name)| kind == :req || kind == :block }
  can_skip_block_type = method_sig.block_type.nil? || method_sig.block_type.valid?(nil)
  ok_for_fast_path = has_fixed_arity && can_skip_block_type && !method_sig.bind && method_sig.arg_types.length < 5 && is_allowed_to_have_fast_path
  all_args_are_simple = ok_for_fast_path && method_sig.arg_types.all? { |_name, type| type.is_a?(T::Types::Simple) }
  simple_method = all_args_are_simple && method_sig.effective_return_type.is_a?(T::Types::Simple)
  simple_procedure = all_args_are_simple && method_sig.effective_return_type.is_a?(T::Private::Types::Void)
  # All the types for which valid? unconditionally returns `true`
  return_is_ignorable =
    method_sig.effective_return_type.equal?(T::Types::Untyped::Private::INSTANCE) ||
    method_sig.effective_return_type.equal?(T::Types::Anything::Private::INSTANCE) ||
    method_sig.effective_return_type.equal?(T::Types::AttachedClassType::Private::INSTANCE) ||
    method_sig.effective_return_type.equal?(T::Types::SelfType::Private::INSTANCE) ||
    method_sig.effective_return_type.is_a?(T::Types::TypeParameter) ||
    method_sig.effective_return_type.is_a?(T::Types::TypeVariable) ||
    (method_sig.effective_return_type.is_a?(T::Types::Simple) && method_sig.effective_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.effective_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
        # The Ruby VM already validates that any block passed to a method
        # must be either `nil` or a `Proc` object, so there's no need to also
        # have sorbet-runtime check that.
        create_validator_slow_skip_block_type(mod, original_method, method_sig, original_visibility)
      else
        create_validator_slow(mod, original_method, method_sig, original_visibility)
      end
    end
    mod.send(original_visibility, method_sig.method_name)
  end
end