sorbet-runtime 0.4.4398 → 0.4.4451
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/sorbet-runtime.rb +1 -0
- data/lib/types/configuration.rb +45 -0
- data/lib/types/generic.rb +2 -2
- data/lib/types/helpers.rb +4 -0
- data/lib/types/private/abstract/declare.rb +6 -0
- data/lib/types/private/class_utils.rb +7 -3
- data/lib/types/private/decl_state.rb +1 -0
- data/lib/types/private/final.rb +48 -0
- data/lib/types/private/methods/_methods.rb +118 -14
- data/lib/types/private/methods/call_validation.rb +14 -9
- data/lib/types/props/decorator.rb +12 -10
- data/lib/types/sig.rb +11 -6
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dce4a30b82fe35c4a1e14c4b9e4215daed0a9d87
|
|
4
|
+
data.tar.gz: 45ffa6a922ea6cf8779952b1157026a8a27d0d4e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f1d21c72d44210d9c3885a6ff6cbd2ad9d43e5822e5690e61deacf8e68833df6b10a3678ca52581ff5d3fac2f9500f7cc683e750c0ea3caa382a0709093d17e3
|
|
7
|
+
data.tar.gz: 8a4c58f165eaf65718e5b4adf08c92576503dcd641409ebae59af0e918bc764964210294d329b26f6e37a8f5466e05f2b2a1dc251a43fe743af4790246759e7c
|
data/lib/sorbet-runtime.rb
CHANGED
|
@@ -29,6 +29,7 @@ require_relative 'types/private/runtime_levels'
|
|
|
29
29
|
require_relative 'types/private/methods/_methods'
|
|
30
30
|
require_relative 'types/sig'
|
|
31
31
|
require_relative 'types/helpers'
|
|
32
|
+
require_relative 'types/private/final'
|
|
32
33
|
|
|
33
34
|
# The types themselves. First base classes
|
|
34
35
|
require_relative 'types/types/base'
|
data/lib/types/configuration.rb
CHANGED
|
@@ -17,6 +17,31 @@ module T::Configuration
|
|
|
17
17
|
T::Private::RuntimeLevels.enable_checking_in_tests
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
# Announce to Sorbet that we would like the final checks to be enabled when
|
|
21
|
+
# including and extending modules. Iff this is not called, then the following
|
|
22
|
+
# example will not raise an error.
|
|
23
|
+
#
|
|
24
|
+
# ```ruby
|
|
25
|
+
# module M
|
|
26
|
+
# extend T::Sig
|
|
27
|
+
# sig(:final) {void}
|
|
28
|
+
# def foo; end
|
|
29
|
+
# end
|
|
30
|
+
# class C
|
|
31
|
+
# include M
|
|
32
|
+
# def foo; end
|
|
33
|
+
# end
|
|
34
|
+
# ```
|
|
35
|
+
def self.enable_final_checks_for_include_extend
|
|
36
|
+
T::Private::Methods.set_final_checks_for_include_extend(true)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Undo the effects of a previous call to
|
|
40
|
+
# `enable_final_checks_for_include_extend`.
|
|
41
|
+
def self.reset_final_checks_for_include_extend
|
|
42
|
+
T::Private::Methods.set_final_checks_for_include_extend(false)
|
|
43
|
+
end
|
|
44
|
+
|
|
20
45
|
# Configure the default checked level for a sig with no explicit `.checked`
|
|
21
46
|
# builder. When unset, the default checked level is `:always`.
|
|
22
47
|
#
|
|
@@ -333,6 +358,26 @@ module T::Configuration
|
|
|
333
358
|
@scalar_types || @default_scalar_types
|
|
334
359
|
end
|
|
335
360
|
|
|
361
|
+
# Temporarily disable ruby warnings while executing the given block. This is
|
|
362
|
+
# useful when doing something that would normally cause a warning to be
|
|
363
|
+
# emitted in Ruby verbose mode ($VERBOSE = true).
|
|
364
|
+
#
|
|
365
|
+
# @yield
|
|
366
|
+
#
|
|
367
|
+
def self.without_ruby_warnings
|
|
368
|
+
if $VERBOSE
|
|
369
|
+
begin
|
|
370
|
+
original_verbose = $VERBOSE
|
|
371
|
+
$VERBOSE = false
|
|
372
|
+
yield
|
|
373
|
+
ensure
|
|
374
|
+
$VERBOSE = original_verbose
|
|
375
|
+
end
|
|
376
|
+
else
|
|
377
|
+
yield
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
336
381
|
|
|
337
382
|
private_class_method def self.validate_lambda_given!(value)
|
|
338
383
|
if !value.nil? && !value.respond_to?(:call)
|
data/lib/types/generic.rb
CHANGED
|
@@ -13,11 +13,11 @@ module T::Generic
|
|
|
13
13
|
self
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def type_member(variance=:invariant, fixed: nil)
|
|
16
|
+
def type_member(variance=:invariant, fixed: nil, lower: T.untyped, upper: BasicObject)
|
|
17
17
|
T::Types::TypeMember.new(variance) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def type_template(variance=:invariant, fixed: nil)
|
|
20
|
+
def type_template(variance=:invariant, fixed: nil, lower: T.untyped, upper: BasicObject)
|
|
21
21
|
T::Types::TypeTemplate.new(variance) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
|
|
22
22
|
end
|
|
23
23
|
end
|
data/lib/types/helpers.rb
CHANGED
|
@@ -16,6 +16,10 @@ module T::Helpers
|
|
|
16
16
|
Private::Abstract::Declare.declare_abstract(self, type: :interface)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
def final!
|
|
20
|
+
Private::Final.declare(self)
|
|
21
|
+
end
|
|
22
|
+
|
|
19
23
|
# Causes a mixin to also mix in class methods from the named module.
|
|
20
24
|
#
|
|
21
25
|
# Nearly equivalent to
|
|
@@ -9,6 +9,9 @@ module T::Private::Abstract::Declare
|
|
|
9
9
|
if AbstractUtils.abstract_module?(mod)
|
|
10
10
|
raise "#{mod.name} is already declared as abstract"
|
|
11
11
|
end
|
|
12
|
+
if T::Private::Final.final_module?(mod)
|
|
13
|
+
raise "#{mod.name} was already declared as final and cannot be declared as abstract"
|
|
14
|
+
end
|
|
12
15
|
|
|
13
16
|
Abstract::Data.set(mod, :can_have_abstract_methods, true)
|
|
14
17
|
Abstract::Data.set(mod.singleton_class, :can_have_abstract_methods, true)
|
|
@@ -28,6 +31,9 @@ module T::Private::Abstract::Declare
|
|
|
28
31
|
raise "You must call `abstract!` *before* defining an initialize method"
|
|
29
32
|
end
|
|
30
33
|
|
|
34
|
+
# Don't need to silence warnings via without_ruby_warnings when calling
|
|
35
|
+
# define_method because of the guard above
|
|
36
|
+
|
|
31
37
|
mod.send(:define_method, :initialize) do |*args, &blk|
|
|
32
38
|
if self.class == mod
|
|
33
39
|
raise "#{mod} is declared as abstract; it cannot be instantiated"
|
|
@@ -32,7 +32,9 @@ module T::Private::ClassUtils
|
|
|
32
32
|
|
|
33
33
|
if @overwritten
|
|
34
34
|
# The original method was overwritten. Overwrite again to restore it.
|
|
35
|
-
|
|
35
|
+
T::Configuration.without_ruby_warnings do
|
|
36
|
+
@mod.send(:define_method, @old_method.name, @old_method) # rubocop:disable PrisonGuard/UsePublicSend
|
|
37
|
+
end
|
|
36
38
|
else
|
|
37
39
|
# The original method was in an ancestor. Restore it by removing the overriding method.
|
|
38
40
|
@mod.send(:remove_method, @old_method.name) # rubocop:disable PrisonGuard/UsePublicSend
|
|
@@ -93,8 +95,10 @@ module T::Private::ClassUtils
|
|
|
93
95
|
end
|
|
94
96
|
|
|
95
97
|
overwritten = original_owner == mod
|
|
96
|
-
|
|
97
|
-
|
|
98
|
+
T::Configuration.without_ruby_warnings do
|
|
99
|
+
mod.send(:define_method, name, &blk) # rubocop:disable PrisonGuard/UsePublicSend
|
|
100
|
+
mod.send(original_visibility, name) # rubocop:disable PrisonGuard/UsePublicSend
|
|
101
|
+
end
|
|
98
102
|
new_method = mod.instance_method(name)
|
|
99
103
|
|
|
100
104
|
ReplacedMethod.new(mod, original_method, new_method, overwritten, original_visibility)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: false
|
|
3
|
+
|
|
4
|
+
module T::Private::Final
|
|
5
|
+
module NoInherit
|
|
6
|
+
def inherited(arg)
|
|
7
|
+
super(arg)
|
|
8
|
+
raise "#{self.name} was declared as final and cannot be inherited"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module NoIncludeExtend
|
|
13
|
+
def included(arg)
|
|
14
|
+
super(arg)
|
|
15
|
+
raise "#{self.name} was declared as final and cannot be included"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def extended(arg)
|
|
19
|
+
super(arg)
|
|
20
|
+
raise "#{self.name} was declared as final and cannot be extended"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.declare(mod)
|
|
25
|
+
if !mod.is_a?(Module)
|
|
26
|
+
raise "#{mod.name} is not a class or module and cannot be declared as final with `final!`"
|
|
27
|
+
end
|
|
28
|
+
if final_module?(mod)
|
|
29
|
+
raise "#{mod.name} was already declared as final and cannot be re-declared as final"
|
|
30
|
+
end
|
|
31
|
+
if T::AbstractUtils.abstract_module?(mod)
|
|
32
|
+
raise "#{mod.name} was already declared as abstract and cannot be declared as final"
|
|
33
|
+
end
|
|
34
|
+
mod.extend(mod.is_a?(Class) ? NoInherit : NoIncludeExtend)
|
|
35
|
+
mark_as_final_module(mod)
|
|
36
|
+
mark_as_final_module(mod.singleton_class)
|
|
37
|
+
T::Private::Methods.install_hooks(mod)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.final_module?(mod)
|
|
41
|
+
mod.instance_variable_defined?(:@sorbet_final_module)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private_class_method def self.mark_as_final_module(mod)
|
|
45
|
+
mod.instance_variable_set(:@sorbet_final_module, true)
|
|
46
|
+
T::Private::Methods.add_module_with_final(mod)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -6,23 +6,36 @@ module T::Private::Methods
|
|
|
6
6
|
@signatures_by_method = {}
|
|
7
7
|
@sig_wrappers = {}
|
|
8
8
|
@sigs_that_raised = {}
|
|
9
|
+
# the info about whether a method is final is not stored in a DeclBuilder nor a Signature, but instead right here.
|
|
10
|
+
# this is because final checks are special:
|
|
11
|
+
# - they are done possibly before any sig block has run.
|
|
12
|
+
# - they are done even if the method being defined doesn't have a sig.
|
|
13
|
+
@final_methods = Set.new
|
|
14
|
+
# if a module directly defines a final method, or includes, extends, or inherits from a module which does so, then it
|
|
15
|
+
# should be in this set.
|
|
16
|
+
@modules_with_final = Set.new
|
|
17
|
+
@old_included_extended = nil
|
|
9
18
|
|
|
10
19
|
ARG_NOT_PROVIDED = Object.new
|
|
11
20
|
PROC_TYPE = Object.new
|
|
12
21
|
|
|
13
|
-
DeclarationBlock = Struct.new(:mod, :loc, :blk)
|
|
22
|
+
DeclarationBlock = Struct.new(:mod, :loc, :blk, :final)
|
|
14
23
|
|
|
15
|
-
def self.declare_sig(mod, &blk)
|
|
24
|
+
def self.declare_sig(mod, arg, &blk)
|
|
16
25
|
install_hooks(mod)
|
|
17
26
|
|
|
18
27
|
if T::Private::DeclState.current.active_declaration
|
|
19
|
-
T::Private::DeclState.current.
|
|
28
|
+
T::Private::DeclState.current.reset!
|
|
20
29
|
raise "You called sig twice without declaring a method inbetween"
|
|
21
30
|
end
|
|
22
31
|
|
|
32
|
+
if !arg.nil? && arg != :final
|
|
33
|
+
raise "Invalid argument to `sig`: #{arg}"
|
|
34
|
+
end
|
|
35
|
+
|
|
23
36
|
loc = caller_locations(2, 1).first
|
|
24
37
|
|
|
25
|
-
T::Private::DeclState.current.active_declaration = DeclarationBlock.new(mod, loc, blk)
|
|
38
|
+
T::Private::DeclState.current.active_declaration = DeclarationBlock.new(mod, loc, blk, arg == :final)
|
|
26
39
|
|
|
27
40
|
nil
|
|
28
41
|
end
|
|
@@ -106,15 +119,63 @@ module T::Private::Methods
|
|
|
106
119
|
@signatures_by_method[key]
|
|
107
120
|
end
|
|
108
121
|
|
|
122
|
+
# when target includes a module with instance methods source_method_names, ensure there is zero intersection between
|
|
123
|
+
# the final instance methods of target and source_method_names. so, for every m in source_method_names, check if there
|
|
124
|
+
# is already a method defined on one of target_ancestors with the same name that is final.
|
|
125
|
+
def self._check_final_ancestors(target, target_ancestors, source_method_names)
|
|
126
|
+
# use reverse_each to check farther-up ancestors first, for better error messages. we could avoid this if we were on
|
|
127
|
+
# the version of ruby that adds the optional argument to method_defined? that allows you to exclude ancestors.
|
|
128
|
+
target_ancestors.reverse_each do |ancestor|
|
|
129
|
+
source_method_names.each do |method_name|
|
|
130
|
+
# the usage of method_owner_and_name_to_key(ancestor, method_name) instead of
|
|
131
|
+
# method_to_key(ancestor.instance_method(method_name)) is not (just) an optimization, but also required for
|
|
132
|
+
# correctness, since ancestor.method_defined?(method_name) may return true even if method_name is not defined
|
|
133
|
+
# directly on ancestor but instead an ancestor of ancestor.
|
|
134
|
+
if ancestor.method_defined?(method_name) && final_method?(method_owner_and_name_to_key(ancestor, method_name))
|
|
135
|
+
raise(
|
|
136
|
+
"`#{ancestor.name}##{method_name}` was declared as final and cannot be " +
|
|
137
|
+
(target == ancestor ? "redefined" : "overridden in `#{target.name}`")
|
|
138
|
+
)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
private_class_method def self.add_final_method(method_key)
|
|
145
|
+
@final_methods.add(method_key)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
private_class_method def self.final_method?(method_key)
|
|
149
|
+
@final_methods.include?(method_key)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def self.add_module_with_final(mod)
|
|
153
|
+
@modules_with_final.add(mod)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
private_class_method def self.module_with_final?(mod)
|
|
157
|
+
@modules_with_final.include?(mod)
|
|
158
|
+
end
|
|
159
|
+
|
|
109
160
|
# Only public because it needs to get called below inside the replace_method blocks below.
|
|
110
161
|
def self._on_method_added(hook_mod, method_name, is_singleton_method: false)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
162
|
+
if T::Private::DeclState.current.skip_next_on_method_added
|
|
163
|
+
T::Private::DeclState.current.skip_next_on_method_added = false
|
|
164
|
+
return
|
|
165
|
+
end
|
|
114
166
|
|
|
167
|
+
current_declaration = T::Private::DeclState.current.active_declaration
|
|
115
168
|
mod = is_singleton_method ? hook_mod.singleton_class : hook_mod
|
|
116
169
|
original_method = mod.instance_method(method_name)
|
|
117
170
|
|
|
171
|
+
if T::Private::Final.final_module?(mod) && (current_declaration.nil? || !current_declaration.final)
|
|
172
|
+
raise "`#{mod.name}` was declared as final but its method `#{method_name}` was not declared as final"
|
|
173
|
+
end
|
|
174
|
+
_check_final_ancestors(mod, mod.ancestors, [method_name])
|
|
175
|
+
|
|
176
|
+
return if current_declaration.nil?
|
|
177
|
+
T::Private::DeclState.current.reset!
|
|
178
|
+
|
|
118
179
|
sig_block = lambda do
|
|
119
180
|
T::Private::Methods.run_sig(hook_mod, method_name, original_method, current_declaration)
|
|
120
181
|
end
|
|
@@ -124,6 +185,8 @@ module T::Private::Methods
|
|
|
124
185
|
# This wrapper is very slow, so it will subsequently re-wrap with a much faster wrapper
|
|
125
186
|
# (or unwrap back to the original method).
|
|
126
187
|
new_method = nil
|
|
188
|
+
# this prevents us from running the final checks twice for every method def.
|
|
189
|
+
T::Private::DeclState.current.skip_next_on_method_added = true
|
|
127
190
|
T::Private::ClassUtils.replace_method(mod, method_name) do |*args, &blk|
|
|
128
191
|
if !T::Private::Methods.has_sig_block_for_method(new_method)
|
|
129
192
|
# This should only happen if the user used alias_method to grab a handle
|
|
@@ -161,15 +224,16 @@ module T::Private::Methods
|
|
|
161
224
|
end
|
|
162
225
|
|
|
163
226
|
new_method = mod.instance_method(method_name)
|
|
164
|
-
|
|
227
|
+
key = method_to_key(new_method)
|
|
228
|
+
@sig_wrappers[key] = sig_block
|
|
229
|
+
if current_declaration.final
|
|
230
|
+
add_final_method(key)
|
|
231
|
+
add_module_with_final(mod)
|
|
232
|
+
end
|
|
165
233
|
end
|
|
166
234
|
|
|
167
235
|
def self.sig_error(loc, message)
|
|
168
|
-
raise(
|
|
169
|
-
ArgumentError.new(
|
|
170
|
-
"#{loc.path}:#{loc.lineno}: Error interpreting `sig`:\n #{message}\n\n"
|
|
171
|
-
)
|
|
172
|
-
)
|
|
236
|
+
raise(ArgumentError.new("#{loc.path}:#{loc.lineno}: Error interpreting `sig`:\n #{message}\n\n"))
|
|
173
237
|
end
|
|
174
238
|
|
|
175
239
|
# Executes the `sig` block, and converts the resulting Declaration
|
|
@@ -300,6 +364,38 @@ module T::Private::Methods
|
|
|
300
364
|
end
|
|
301
365
|
end
|
|
302
366
|
|
|
367
|
+
# the module target is adding the methods from the module source to itself. we need to check that for all instance
|
|
368
|
+
# methods M on source, M is not defined on any of target's ancestors.
|
|
369
|
+
def self._included_extended_impl(target, target_ancestors, source)
|
|
370
|
+
if !module_with_final?(target) && !module_with_final?(source)
|
|
371
|
+
return
|
|
372
|
+
end
|
|
373
|
+
add_module_with_final(target)
|
|
374
|
+
install_hooks(target)
|
|
375
|
+
_check_final_ancestors(target, target_ancestors - source.ancestors, source.instance_methods)
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def self.set_final_checks_for_include_extend(enable)
|
|
379
|
+
is_enabled = @old_included_extended != nil
|
|
380
|
+
if enable == is_enabled
|
|
381
|
+
return
|
|
382
|
+
end
|
|
383
|
+
if is_enabled
|
|
384
|
+
@old_included_extended.each(&:restore)
|
|
385
|
+
@old_included_extended = nil
|
|
386
|
+
else
|
|
387
|
+
old_included = T::Private::ClassUtils.replace_method(Module, :included) do |arg|
|
|
388
|
+
old_included.bind(self).call(arg)
|
|
389
|
+
::T::Private::Methods._included_extended_impl(arg, arg.ancestors, self)
|
|
390
|
+
end
|
|
391
|
+
old_extended = T::Private::ClassUtils.replace_method(Module, :extended) do |arg|
|
|
392
|
+
old_extended.bind(self).call(arg)
|
|
393
|
+
::T::Private::Methods._included_extended_impl(arg, arg.singleton_class.ancestors, self)
|
|
394
|
+
end
|
|
395
|
+
@old_included_extended = [old_included, old_extended]
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
303
399
|
def self.install_hooks(mod)
|
|
304
400
|
return if @installed_hooks.include?(mod)
|
|
305
401
|
@installed_hooks << mod
|
|
@@ -317,6 +413,9 @@ module T::Private::Methods
|
|
|
317
413
|
|
|
318
414
|
private_class_method def self.install_singleton_method_added_hook(singleton_klass)
|
|
319
415
|
attached = nil
|
|
416
|
+
# this prevents the final checks from triggering about singleton_method_added not being a final method even if the
|
|
417
|
+
# module is final.
|
|
418
|
+
T::Private::DeclState.current.skip_next_on_method_added = true
|
|
320
419
|
original_singleton_method = T::Private::ClassUtils.replace_method(singleton_klass, :singleton_method_added) do |name|
|
|
321
420
|
attached = self
|
|
322
421
|
T::Private::Methods._on_method_added(self, name, is_singleton_method: true)
|
|
@@ -330,8 +429,13 @@ module T::Private::Methods
|
|
|
330
429
|
original_singleton_method.bind(attached).call(:singleton_method_added)
|
|
331
430
|
end
|
|
332
431
|
|
|
432
|
+
# use this directly if you don't want/need to box up the method into an object to pass to method_to_key.
|
|
433
|
+
private_class_method def self.method_owner_and_name_to_key(owner, name)
|
|
434
|
+
"#{owner.object_id}##{name}"
|
|
435
|
+
end
|
|
436
|
+
|
|
333
437
|
private_class_method def self.method_to_key(method)
|
|
334
|
-
|
|
438
|
+
method_owner_and_name_to_key(method.owner, method.name)
|
|
335
439
|
end
|
|
336
440
|
|
|
337
441
|
private_class_method def self.key_to_method(key)
|
|
@@ -35,9 +35,11 @@ module T::Private::Methods::CallValidation
|
|
|
35
35
|
elsif method_sig.check_level == :always || (method_sig.check_level == :tests && T::Private::RuntimeLevels.check_tests?)
|
|
36
36
|
create_validator_method(mod, original_method, method_sig, original_visibility)
|
|
37
37
|
else
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
T::Configuration.without_ruby_warnings do
|
|
39
|
+
# get all the shims out of the way and put back the original method
|
|
40
|
+
mod.send(:define_method, method_sig.method_name, original_method)
|
|
41
|
+
mod.send(original_visibility, method_sig.method_name)
|
|
42
|
+
end
|
|
41
43
|
end
|
|
42
44
|
# Return the newly created method (or the original one if we didn't replace it)
|
|
43
45
|
mod.instance_method(method_sig.method_name)
|
|
@@ -161,18 +163,21 @@ module T::Private::Methods::CallValidation
|
|
|
161
163
|
end
|
|
162
164
|
|
|
163
165
|
def self.create_validator_method(mod, original_method, method_sig, original_visibility)
|
|
166
|
+
T::Private::DeclState.current.skip_next_on_method_added = true
|
|
164
167
|
has_fixed_arity = method_sig.kwarg_types.empty? && !method_sig.has_rest && !method_sig.has_keyrest &&
|
|
165
168
|
original_method.parameters.all? {|(kind, _name)| kind == :req}
|
|
166
169
|
all_args_are_simple = method_sig.arg_types.all? {|_name, type| type.is_a?(T::Types::Simple)}
|
|
167
170
|
has_simple_method_types = all_args_are_simple && method_sig.return_type.is_a?(T::Types::Simple)
|
|
168
171
|
has_simple_procedure_types = all_args_are_simple && method_sig.return_type.is_a?(T::Private::Types::Void)
|
|
169
172
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
T::Configuration.without_ruby_warnings do
|
|
174
|
+
if has_fixed_arity && has_simple_method_types && method_sig.arg_types.length < 5 && is_allowed_to_have_fast_path
|
|
175
|
+
create_validator_method_fast(mod, original_method, method_sig)
|
|
176
|
+
elsif has_fixed_arity && has_simple_procedure_types && method_sig.arg_types.length < 5 && is_allowed_to_have_fast_path
|
|
177
|
+
create_validator_procedure_fast(mod, original_method, method_sig)
|
|
178
|
+
else
|
|
179
|
+
create_validator_slow(mod, original_method, method_sig)
|
|
180
|
+
end
|
|
176
181
|
end
|
|
177
182
|
mod.send(original_visibility, method_sig.method_name)
|
|
178
183
|
end
|
|
@@ -485,18 +485,20 @@ class T::Props::Decorator
|
|
|
485
485
|
|
|
486
486
|
sig {params(name: Symbol, rules: Rules).void}
|
|
487
487
|
private def define_getter_and_setter(name, rules)
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
488
|
+
T::Configuration.without_ruby_warnings do
|
|
489
|
+
if rules[:immutable]
|
|
490
|
+
@class.send(:define_method, "#{name}=") do |_x|
|
|
491
|
+
raise T::Props::ImmutableProp.new("#{self.class}##{name} cannot be modified after creation.")
|
|
492
|
+
end
|
|
493
|
+
else
|
|
494
|
+
@class.send(:define_method, "#{name}=") do |x|
|
|
495
|
+
self.class.decorator.prop_set(self, name, x, rules)
|
|
496
|
+
end
|
|
495
497
|
end
|
|
496
|
-
end
|
|
497
498
|
|
|
498
|
-
|
|
499
|
-
|
|
499
|
+
@class.send(:define_method, name) do
|
|
500
|
+
self.class.decorator.prop_get(self, name, rules)
|
|
501
|
+
end
|
|
500
502
|
end
|
|
501
503
|
end
|
|
502
504
|
|
data/lib/types/sig.rb
CHANGED
|
@@ -7,19 +7,24 @@ module T::Sig
|
|
|
7
7
|
module WithoutRuntime
|
|
8
8
|
# At runtime, does nothing, but statically it is treated exactly the same
|
|
9
9
|
# as T::Sig#sig. Only use it in cases where you can't use T::Sig#sig.
|
|
10
|
-
def self.sig(&blk); end # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
|
10
|
+
def self.sig(arg=nil, &blk); end # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
|
11
|
+
|
|
12
|
+
original_verbose = $VERBOSE
|
|
13
|
+
$VERBOSE = false
|
|
11
14
|
|
|
12
15
|
# At runtime, does nothing, but statically it is treated exactly the same
|
|
13
16
|
# as T::Sig#sig. Only use it in cases where you can't use T::Sig#sig.
|
|
14
|
-
T::Sig::WithoutRuntime.sig {params(blk: T.proc.bind(T::Private::Methods::DeclBuilder).void).void}
|
|
15
|
-
def self.sig(&blk); end # rubocop:disable PrisonGuard/BanBuiltinMethodOverride, Lint/DuplicateMethods
|
|
17
|
+
T::Sig::WithoutRuntime.sig {params(arg: T.nilable(Symbol), blk: T.proc.bind(T::Private::Methods::DeclBuilder).void).void}
|
|
18
|
+
def self.sig(arg=nil, &blk); end # rubocop:disable PrisonGuard/BanBuiltinMethodOverride, Lint/DuplicateMethods
|
|
19
|
+
|
|
20
|
+
$VERBOSE = original_verbose
|
|
16
21
|
end
|
|
17
22
|
|
|
18
23
|
# Declares a method with type signatures and/or
|
|
19
24
|
# abstract/override/... helpers. See the documentation URL on
|
|
20
25
|
# {T::Helpers}
|
|
21
|
-
T::Sig::WithoutRuntime.sig {params(blk: T.proc.bind(T::Private::Methods::DeclBuilder).void).void}
|
|
22
|
-
def sig(&blk) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
|
23
|
-
T::Private::Methods.declare_sig(self, &blk)
|
|
26
|
+
T::Sig::WithoutRuntime.sig {params(arg: T.nilable(Symbol), blk: T.proc.bind(T::Private::Methods::DeclBuilder).void).void}
|
|
27
|
+
def sig(arg=nil, &blk) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
|
28
|
+
T::Private::Methods.declare_sig(self, arg, &blk)
|
|
24
29
|
end
|
|
25
30
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sorbet-runtime
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.4451
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stripe
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-07-
|
|
11
|
+
date: 2019-07-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|
|
@@ -75,6 +75,7 @@ files:
|
|
|
75
75
|
- lib/types/private/class_utils.rb
|
|
76
76
|
- lib/types/private/decl_state.rb
|
|
77
77
|
- lib/types/private/error_handler.rb
|
|
78
|
+
- lib/types/private/final.rb
|
|
78
79
|
- lib/types/private/methods/_methods.rb
|
|
79
80
|
- lib/types/private/methods/call_validation.rb
|
|
80
81
|
- lib/types/private/methods/decl_builder.rb
|