sorbet-runtime 0.4.4446 → 0.4.4788
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 +5 -5
- data/lib/sorbet-runtime.rb +3 -0
- data/lib/types/_types.rb +44 -6
- data/lib/types/configuration.rb +13 -9
- data/lib/types/helpers.rb +8 -0
- data/lib/types/private/abstract/declare.rb +4 -1
- data/lib/types/private/abstract/validate.rb +1 -1
- data/lib/types/private/casts.rb +1 -1
- data/lib/types/private/class_utils.rb +4 -2
- data/lib/types/private/decl_state.rb +12 -1
- data/lib/types/private/error_handler.rb +0 -37
- data/lib/types/private/final.rb +51 -0
- data/lib/types/private/methods/_methods.rb +73 -50
- data/lib/types/private/methods/call_validation.rb +12 -9
- data/lib/types/private/methods/decl_builder.rb +18 -26
- data/lib/types/private/methods/modes.rb +5 -7
- data/lib/types/private/methods/signature_validation.rb +18 -17
- data/lib/types/private/sealed.rb +60 -0
- data/lib/types/props/decorator.rb +1 -5
- data/lib/types/types/base.rb +1 -0
- data/lib/types/types/opus_enum.rb +33 -0
- data/lib/types/types/typed_array.rb +14 -0
- data/lib/types/types/typed_enumerable.rb +16 -1
- data/lib/types/types/typed_enumerator.rb +14 -0
- data/lib/types/types/typed_hash.rb +14 -0
- data/lib/types/types/typed_range.rb +4 -0
- data/lib/types/types/typed_set.rb +14 -0
- data/lib/types/utils.rb +2 -0
- metadata +20 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 31271303dfeb98e19ae3042f9c577f080415b592e005a407be7dab657cae0f77
|
|
4
|
+
data.tar.gz: 10ebdce3b1e460c9a95b6144e0b0662f98eb77574eb586a1d248c38c91e01b73
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0027993a7fa1be8694fd2eb2b0b3c64978430bb6d44b91a54ebd8922cbab1a9b40b4ecab04f8d3331acfded84873e49926b6930be53acbd565f418c34e817484'
|
|
7
|
+
data.tar.gz: 89c69d15484d2f69df868ab465dc8085c1123adae026b1678c28b268211c0b2eb80ef991af6b930572a2c0113fc8bc165e3aba1138d7af187c1487aa79aa2632
|
data/lib/sorbet-runtime.rb
CHANGED
|
@@ -29,6 +29,8 @@ 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'
|
|
33
|
+
require_relative 'types/private/sealed'
|
|
32
34
|
|
|
33
35
|
# The types themselves. First base classes
|
|
34
36
|
require_relative 'types/types/base'
|
|
@@ -43,6 +45,7 @@ require_relative 'types/types/noreturn'
|
|
|
43
45
|
require_relative 'types/types/proc'
|
|
44
46
|
require_relative 'types/types/self_type'
|
|
45
47
|
require_relative 'types/types/simple'
|
|
48
|
+
require_relative 'types/types/opus_enum'
|
|
46
49
|
require_relative 'types/types/type_parameter'
|
|
47
50
|
require_relative 'types/types/typed_array'
|
|
48
51
|
require_relative 'types/types/typed_enumerator'
|
data/lib/types/_types.rb
CHANGED
|
@@ -184,7 +184,7 @@ module T
|
|
|
184
184
|
begin
|
|
185
185
|
raise TypeError.new("Passed `nil` into T.must")
|
|
186
186
|
rescue TypeError => e # raise into rescue to ensure e.backtrace is populated
|
|
187
|
-
T::
|
|
187
|
+
T::Configuration.inline_type_error_handler(e)
|
|
188
188
|
end
|
|
189
189
|
end
|
|
190
190
|
|
|
@@ -195,29 +195,63 @@ module T
|
|
|
195
195
|
value
|
|
196
196
|
end
|
|
197
197
|
|
|
198
|
+
# A way to ask Sorbet to prove that a certain branch of control flow never
|
|
199
|
+
# happens. Commonly used to assert that a case or if statement exhausts all
|
|
200
|
+
# possible cases.
|
|
201
|
+
def self.absurd(value)
|
|
202
|
+
msg = "Control flow reached T.absurd."
|
|
203
|
+
|
|
204
|
+
case value
|
|
205
|
+
when Kernel
|
|
206
|
+
msg += " Got value: #{value}"
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
begin
|
|
210
|
+
raise TypeError.new(msg)
|
|
211
|
+
rescue TypeError => e # raise into rescue to ensure e.backtrace is populated
|
|
212
|
+
T::Configuration.inline_type_error_handler(e)
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
198
216
|
### Generic classes ###
|
|
199
217
|
|
|
200
218
|
module Array
|
|
201
219
|
def self.[](type)
|
|
202
|
-
T::Types::
|
|
220
|
+
if type.is_a?(T::Types::Untyped)
|
|
221
|
+
T::Types::TypedArray::Untyped.new
|
|
222
|
+
else
|
|
223
|
+
T::Types::TypedArray.new(type)
|
|
224
|
+
end
|
|
203
225
|
end
|
|
204
226
|
end
|
|
205
227
|
|
|
206
228
|
module Hash
|
|
207
229
|
def self.[](keys, values)
|
|
208
|
-
T::Types::
|
|
230
|
+
if keys.is_a?(T::Types::Untyped) && values.is_a?(T::Types::Untyped)
|
|
231
|
+
T::Types::TypedHash::Untyped.new
|
|
232
|
+
else
|
|
233
|
+
T::Types::TypedHash.new(keys: keys, values: values)
|
|
234
|
+
end
|
|
209
235
|
end
|
|
210
236
|
end
|
|
211
237
|
|
|
212
238
|
module Enumerable
|
|
213
239
|
def self.[](type)
|
|
214
|
-
T::Types::
|
|
240
|
+
if type.is_a?(T::Types::Untyped)
|
|
241
|
+
T::Types::TypedEnumerable::Untyped.new
|
|
242
|
+
else
|
|
243
|
+
T::Types::TypedEnumerable.new(type)
|
|
244
|
+
end
|
|
215
245
|
end
|
|
216
246
|
end
|
|
217
247
|
|
|
218
248
|
module Enumerator
|
|
219
249
|
def self.[](type)
|
|
220
|
-
T::Types::
|
|
250
|
+
if type.is_a?(T::Types::Untyped)
|
|
251
|
+
T::Types::TypedEnumerator::Untyped.new
|
|
252
|
+
else
|
|
253
|
+
T::Types::TypedEnumerator.new(type)
|
|
254
|
+
end
|
|
221
255
|
end
|
|
222
256
|
end
|
|
223
257
|
|
|
@@ -229,7 +263,11 @@ module T
|
|
|
229
263
|
|
|
230
264
|
module Set
|
|
231
265
|
def self.[](type)
|
|
232
|
-
T::Types::
|
|
266
|
+
if type.is_a?(T::Types::Untyped)
|
|
267
|
+
T::Types::TypedSet::Untyped.new
|
|
268
|
+
else
|
|
269
|
+
T::Types::TypedSet.new(type)
|
|
270
|
+
end
|
|
233
271
|
end
|
|
234
272
|
end
|
|
235
273
|
|
data/lib/types/configuration.rb
CHANGED
|
@@ -32,14 +32,14 @@ module T::Configuration
|
|
|
32
32
|
# def foo; end
|
|
33
33
|
# end
|
|
34
34
|
# ```
|
|
35
|
-
def self.
|
|
36
|
-
T::Private::Methods.
|
|
35
|
+
def self.enable_final_checks_on_hooks
|
|
36
|
+
T::Private::Methods.set_final_checks_on_hooks(true)
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
# Undo the effects of a previous call to
|
|
40
|
-
# `
|
|
41
|
-
def self.
|
|
42
|
-
T::Private::Methods.
|
|
40
|
+
# `enable_final_checks_on_hooks`.
|
|
41
|
+
def self.reset_final_checks_on_hooks
|
|
42
|
+
T::Private::Methods.set_final_checks_on_hooks(false)
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
# Configure the default checked level for a sig with no explicit `.checked`
|
|
@@ -89,6 +89,7 @@ module T::Configuration
|
|
|
89
89
|
else
|
|
90
90
|
inline_type_error_handler_default(error)
|
|
91
91
|
end
|
|
92
|
+
nil
|
|
92
93
|
end
|
|
93
94
|
|
|
94
95
|
# Set a handler to handle errors that occur when the builder methods in the
|
|
@@ -119,7 +120,7 @@ module T::Configuration
|
|
|
119
120
|
end
|
|
120
121
|
|
|
121
122
|
private_class_method def self.sig_builder_error_handler_default(error, location)
|
|
122
|
-
|
|
123
|
+
raise ArgumentError.new("#{location.path}:#{location.lineno}: Error interpreting `sig`:\n #{error.message}\n\n")
|
|
123
124
|
end
|
|
124
125
|
|
|
125
126
|
def self.sig_builder_error_handler(error, location)
|
|
@@ -128,6 +129,7 @@ module T::Configuration
|
|
|
128
129
|
else
|
|
129
130
|
sig_builder_error_handler_default(error, location)
|
|
130
131
|
end
|
|
132
|
+
nil
|
|
131
133
|
end
|
|
132
134
|
|
|
133
135
|
# Set a handler to handle sig validation errors.
|
|
@@ -171,12 +173,13 @@ module T::Configuration
|
|
|
171
173
|
raise error
|
|
172
174
|
end
|
|
173
175
|
|
|
174
|
-
def self.sig_validation_error_handler(error, opts)
|
|
176
|
+
def self.sig_validation_error_handler(error, opts={})
|
|
175
177
|
if @sig_validation_error_handler
|
|
176
178
|
@sig_validation_error_handler.call(error, opts)
|
|
177
179
|
else
|
|
178
180
|
sig_validation_error_handler_default(error, opts)
|
|
179
181
|
end
|
|
182
|
+
nil
|
|
180
183
|
end
|
|
181
184
|
|
|
182
185
|
# Set a handler for type errors that result from calling a method.
|
|
@@ -216,12 +219,13 @@ module T::Configuration
|
|
|
216
219
|
raise TypeError.new(opts[:pretty_message])
|
|
217
220
|
end
|
|
218
221
|
|
|
219
|
-
def self.call_validation_error_handler(signature, opts)
|
|
222
|
+
def self.call_validation_error_handler(signature, opts={})
|
|
220
223
|
if @call_validation_error_handler
|
|
221
224
|
@call_validation_error_handler.call(signature, opts)
|
|
222
225
|
else
|
|
223
226
|
call_validation_error_handler_default(signature, opts)
|
|
224
227
|
end
|
|
228
|
+
nil
|
|
225
229
|
end
|
|
226
230
|
|
|
227
231
|
# Set a handler for logging
|
|
@@ -315,7 +319,7 @@ module T::Configuration
|
|
|
315
319
|
raise str
|
|
316
320
|
end
|
|
317
321
|
|
|
318
|
-
def self.hard_assert_handler(str, extra)
|
|
322
|
+
def self.hard_assert_handler(str, extra={})
|
|
319
323
|
if @hard_assert_handler
|
|
320
324
|
@hard_assert_handler.call(str, extra)
|
|
321
325
|
else
|
data/lib/types/helpers.rb
CHANGED
|
@@ -16,6 +16,14 @@ 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
|
+
|
|
23
|
+
def sealed!
|
|
24
|
+
Private::Sealed.declare(self, Kernel.caller(1..1)&.first&.split(':')&.first)
|
|
25
|
+
end
|
|
26
|
+
|
|
19
27
|
# Causes a mixin to also mix in class methods from the named module.
|
|
20
28
|
#
|
|
21
29
|
# Nearly equivalent to
|
|
@@ -7,7 +7,10 @@ module T::Private::Abstract::Declare
|
|
|
7
7
|
|
|
8
8
|
def self.declare_abstract(mod, type:)
|
|
9
9
|
if AbstractUtils.abstract_module?(mod)
|
|
10
|
-
raise "#{mod
|
|
10
|
+
raise "#{mod} is already declared as abstract"
|
|
11
|
+
end
|
|
12
|
+
if T::Private::Final.final_module?(mod)
|
|
13
|
+
raise "#{mod} was already declared as final and cannot be declared as abstract"
|
|
11
14
|
end
|
|
12
15
|
|
|
13
16
|
Abstract::Data.set(mod, :can_have_abstract_methods, true)
|
|
@@ -61,7 +61,7 @@ module T::Private::Abstract::Validate
|
|
|
61
61
|
# In that case, get its untyped signature.
|
|
62
62
|
implementation_signature ||= Methods::Signature.new_untyped(
|
|
63
63
|
method: implementation_method,
|
|
64
|
-
mode: Methods::Modes.
|
|
64
|
+
mode: Methods::Modes.override
|
|
65
65
|
)
|
|
66
66
|
SignatureValidation.validate_override_shape(implementation_signature, abstract_signature)
|
|
67
67
|
SignatureValidation.validate_override_types(implementation_signature, abstract_signature)
|
data/lib/types/private/casts.rb
CHANGED
|
@@ -14,7 +14,7 @@ module T::Private
|
|
|
14
14
|
|
|
15
15
|
raise TypeError.new("#{cast_method}: #{error}\n#{suffix}")
|
|
16
16
|
rescue TypeError => e # raise into rescue to ensure e.backtrace is populated
|
|
17
|
-
T::
|
|
17
|
+
T::Configuration.inline_type_error_handler(e)
|
|
18
18
|
value
|
|
19
19
|
end
|
|
20
20
|
end
|
|
@@ -96,9 +96,11 @@ module T::Private::ClassUtils
|
|
|
96
96
|
|
|
97
97
|
overwritten = original_owner == mod
|
|
98
98
|
T::Configuration.without_ruby_warnings do
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
T::Private::DeclState.current.without_on_method_added do
|
|
100
|
+
mod.send(:define_method, name, &blk) # rubocop:disable PrisonGuard/UsePublicSend
|
|
101
|
+
end
|
|
101
102
|
end
|
|
103
|
+
mod.send(original_visibility, name) # rubocop:disable PrisonGuard/UsePublicSend
|
|
102
104
|
new_method = mod.instance_method(name)
|
|
103
105
|
|
|
104
106
|
ReplacedMethod.new(mod, original_method, new_method, overwritten, original_visibility)
|
|
@@ -11,9 +11,20 @@ class T::Private::DeclState
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
attr_accessor :active_declaration
|
|
14
|
-
attr_accessor :
|
|
14
|
+
attr_accessor :skip_on_method_added
|
|
15
15
|
|
|
16
16
|
def reset!
|
|
17
17
|
self.active_declaration = nil
|
|
18
18
|
end
|
|
19
|
+
|
|
20
|
+
def without_on_method_added
|
|
21
|
+
begin
|
|
22
|
+
# explicit 'self' is needed here
|
|
23
|
+
old_value = self.skip_on_method_added
|
|
24
|
+
self.skip_on_method_added = true
|
|
25
|
+
yield
|
|
26
|
+
ensure
|
|
27
|
+
self.skip_on_method_added = old_value
|
|
28
|
+
end
|
|
29
|
+
end
|
|
19
30
|
end
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# typed: true
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
module T::Private::ErrorHandler
|
|
5
|
-
# Handle a rescued TypeError. This will pass the TypeError to the
|
|
6
|
-
# T::Configuration.inline_type_error_handler so that the user can override
|
|
7
|
-
# error handling if they wish. If no inline_type_error_handler is set, this
|
|
8
|
-
# method will call handle_inline_type_error_default, which raises the error.
|
|
9
|
-
def self.handle_inline_type_error(type_error)
|
|
10
|
-
T::Configuration.inline_type_error_handler(type_error)
|
|
11
|
-
nil
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Handle a sig declaration failure. This allows users to override the behavior
|
|
15
|
-
# when a sig decl fails. If T::Configuration.sig_builder_error_handler
|
|
16
|
-
# is unset, this method will call handle_sig_builder_error_default.
|
|
17
|
-
def self.handle_sig_builder_error(error, location)
|
|
18
|
-
T::Configuration.sig_builder_error_handler(error, location)
|
|
19
|
-
nil
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Handle a sig build validation failure. This allows users to override the
|
|
23
|
-
# behavior when a sig build fails. If T::Configuration.sig_validation_error_handler
|
|
24
|
-
# is unset, this method will call handle_sig_validation_error_default.
|
|
25
|
-
def self.handle_sig_validation_error(error, opts={})
|
|
26
|
-
T::Configuration.sig_validation_error_handler(error, opts)
|
|
27
|
-
nil
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Handle a sig call validation failure. This allows users to override the
|
|
31
|
-
# behavior when a sig call fails. If T::Configuration.call_validation_error_handler
|
|
32
|
-
# is unset, this method will call handle_call_validation_error_default.
|
|
33
|
-
def self.handle_call_validation_error(signature, opts={})
|
|
34
|
-
T::Configuration.call_validation_error_handler(signature, opts)
|
|
35
|
-
nil
|
|
36
|
-
end
|
|
37
|
-
end
|
|
@@ -0,0 +1,51 @@
|
|
|
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} 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} was declared as final and cannot be included"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def extended(arg)
|
|
19
|
+
super(arg)
|
|
20
|
+
raise "#{self} 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} is not a class or module and cannot be declared as final with `final!`"
|
|
27
|
+
end
|
|
28
|
+
if final_module?(mod)
|
|
29
|
+
raise "#{mod} was already declared as final and cannot be re-declared as final"
|
|
30
|
+
end
|
|
31
|
+
if T::AbstractUtils.abstract_module?(mod)
|
|
32
|
+
raise "#{mod} was already declared as abstract and cannot be declared as final"
|
|
33
|
+
end
|
|
34
|
+
if T::Private::Sealed.sealed_module?(mod)
|
|
35
|
+
raise "#{mod} was already declared as sealed and cannot be declared as final"
|
|
36
|
+
end
|
|
37
|
+
mod.extend(mod.is_a?(Class) ? NoInherit : NoIncludeExtend)
|
|
38
|
+
mark_as_final_module(mod)
|
|
39
|
+
mark_as_final_module(mod.singleton_class)
|
|
40
|
+
T::Private::Methods.add_module_with_final(mod)
|
|
41
|
+
T::Private::Methods.install_hooks(mod)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.final_module?(mod)
|
|
45
|
+
mod.instance_variable_defined?(:@sorbet_final_module)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private_class_method def self.mark_as_final_module(mod)
|
|
49
|
+
mod.instance_variable_set(:@sorbet_final_module, true)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -11,10 +11,18 @@ module T::Private::Methods
|
|
|
11
11
|
# - they are done possibly before any sig block has run.
|
|
12
12
|
# - they are done even if the method being defined doesn't have a sig.
|
|
13
13
|
@final_methods = Set.new
|
|
14
|
-
#
|
|
15
|
-
#
|
|
14
|
+
# a non-singleton is a module for which at least one of the following is true:
|
|
15
|
+
# - is declared final
|
|
16
|
+
# - defines a method that is declared final
|
|
17
|
+
# - includes an non-singleton
|
|
18
|
+
# - extends an non-singleton
|
|
19
|
+
# a singleton is the singleton_class of a non-singleton.
|
|
20
|
+
# modules_with_final is the set of singletons and non-singletons.
|
|
16
21
|
@modules_with_final = Set.new
|
|
17
|
-
|
|
22
|
+
# this stores the old [included, extended] hooks for Module and inherited hook for Class that we override when
|
|
23
|
+
# enabling final checks for when those hooks are called. the 'hooks' here don't have anything to do with the 'hooks'
|
|
24
|
+
# in installed_hooks.
|
|
25
|
+
@old_hooks = nil
|
|
18
26
|
|
|
19
27
|
ARG_NOT_PROVIDED = Object.new
|
|
20
28
|
PROC_TYPE = Object.new
|
|
@@ -123,6 +131,9 @@ module T::Private::Methods
|
|
|
123
131
|
# the final instance methods of target and source_method_names. so, for every m in source_method_names, check if there
|
|
124
132
|
# is already a method defined on one of target_ancestors with the same name that is final.
|
|
125
133
|
def self._check_final_ancestors(target, target_ancestors, source_method_names)
|
|
134
|
+
if !module_with_final?(target)
|
|
135
|
+
return
|
|
136
|
+
end
|
|
126
137
|
# use reverse_each to check farther-up ancestors first, for better error messages. we could avoid this if we were on
|
|
127
138
|
# the version of ruby that adds the optional argument to method_defined? that allows you to exclude ancestors.
|
|
128
139
|
target_ancestors.reverse_each do |ancestor|
|
|
@@ -133,8 +144,8 @@ module T::Private::Methods
|
|
|
133
144
|
# directly on ancestor but instead an ancestor of ancestor.
|
|
134
145
|
if ancestor.method_defined?(method_name) && final_method?(method_owner_and_name_to_key(ancestor, method_name))
|
|
135
146
|
raise(
|
|
136
|
-
"`#{
|
|
137
|
-
(target == ancestor ? "redefined" : "overridden in
|
|
147
|
+
"The method `#{method_name}` on #{ancestor} was declared as final and cannot be " +
|
|
148
|
+
(target == ancestor ? "redefined" : "overridden in #{target}")
|
|
138
149
|
)
|
|
139
150
|
end
|
|
140
151
|
end
|
|
@@ -151,6 +162,7 @@ module T::Private::Methods
|
|
|
151
162
|
|
|
152
163
|
def self.add_module_with_final(mod)
|
|
153
164
|
@modules_with_final.add(mod)
|
|
165
|
+
@modules_with_final.add(mod.singleton_class)
|
|
154
166
|
end
|
|
155
167
|
|
|
156
168
|
private_class_method def self.module_with_final?(mod)
|
|
@@ -159,20 +171,31 @@ module T::Private::Methods
|
|
|
159
171
|
|
|
160
172
|
# Only public because it needs to get called below inside the replace_method blocks below.
|
|
161
173
|
def self._on_method_added(hook_mod, method_name, is_singleton_method: false)
|
|
162
|
-
if T::Private::DeclState.current.
|
|
163
|
-
T::Private::DeclState.current.skip_next_on_method_added = false
|
|
174
|
+
if T::Private::DeclState.current.skip_on_method_added
|
|
164
175
|
return
|
|
165
176
|
end
|
|
166
177
|
|
|
167
178
|
current_declaration = T::Private::DeclState.current.active_declaration
|
|
168
179
|
mod = is_singleton_method ? hook_mod.singleton_class : hook_mod
|
|
169
|
-
original_method = mod.instance_method(method_name)
|
|
170
180
|
|
|
181
|
+
if T::Private::Final.final_module?(mod) && (current_declaration.nil? || !current_declaration.final)
|
|
182
|
+
raise "#{mod} was declared as final but its method `#{method_name}` was not declared as final"
|
|
183
|
+
end
|
|
171
184
|
_check_final_ancestors(mod, mod.ancestors, [method_name])
|
|
172
185
|
|
|
173
|
-
|
|
186
|
+
if current_declaration.nil?
|
|
187
|
+
return
|
|
188
|
+
end
|
|
174
189
|
T::Private::DeclState.current.reset!
|
|
175
190
|
|
|
191
|
+
if method_name == :method_added || method_name == :singleton_method_added
|
|
192
|
+
raise(
|
|
193
|
+
"Putting a `sig` on `#{method_name}` is not supported" +
|
|
194
|
+
" (sorbet-runtime uses this method internally to perform `sig` validation logic)"
|
|
195
|
+
)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
original_method = mod.instance_method(method_name)
|
|
176
199
|
sig_block = lambda do
|
|
177
200
|
T::Private::Methods.run_sig(hook_mod, method_name, original_method, current_declaration)
|
|
178
201
|
end
|
|
@@ -223,14 +246,12 @@ module T::Private::Methods
|
|
|
223
246
|
@sig_wrappers[key] = sig_block
|
|
224
247
|
if current_declaration.final
|
|
225
248
|
add_final_method(key)
|
|
226
|
-
|
|
249
|
+
# use hook_mod, not mod, because for example, we want class C to be marked as having final if we def C.foo as
|
|
250
|
+
# final. change this to mod to see some final_method tests fail.
|
|
251
|
+
add_module_with_final(hook_mod)
|
|
227
252
|
end
|
|
228
253
|
end
|
|
229
254
|
|
|
230
|
-
def self.sig_error(loc, message)
|
|
231
|
-
raise(ArgumentError.new("#{loc.path}:#{loc.lineno}: Error interpreting `sig`:\n #{message}\n\n"))
|
|
232
|
-
end
|
|
233
|
-
|
|
234
255
|
# Executes the `sig` block, and converts the resulting Declaration
|
|
235
256
|
# to a Signature.
|
|
236
257
|
def self.run_sig(hook_mod, method_name, original_method, declaration_block)
|
|
@@ -238,7 +259,7 @@ module T::Private::Methods
|
|
|
238
259
|
begin
|
|
239
260
|
run_builder(declaration_block)
|
|
240
261
|
rescue DeclBuilder::BuilderError => e
|
|
241
|
-
T::
|
|
262
|
+
T::Configuration.sig_builder_error_handler(e, declaration_block.loc)
|
|
242
263
|
nil
|
|
243
264
|
end
|
|
244
265
|
|
|
@@ -271,10 +292,6 @@ module T::Private::Methods
|
|
|
271
292
|
"class/module."
|
|
272
293
|
end
|
|
273
294
|
|
|
274
|
-
if current_declaration.returns.equal?(ARG_NOT_PROVIDED)
|
|
275
|
-
sig_error(loc, "You must provide a return type; use the `.returns` or `.void` builder methods. Method: #{original_method}")
|
|
276
|
-
end
|
|
277
|
-
|
|
278
295
|
signature = Signature.new(
|
|
279
296
|
method: original_method,
|
|
280
297
|
method_name: method_name,
|
|
@@ -294,7 +311,7 @@ module T::Private::Methods
|
|
|
294
311
|
super_method = original_method&.super_method
|
|
295
312
|
super_signature = signature_for_method(super_method) if super_method
|
|
296
313
|
|
|
297
|
-
T::
|
|
314
|
+
T::Configuration.sig_validation_error_handler(
|
|
298
315
|
e,
|
|
299
316
|
method: original_method,
|
|
300
317
|
declaration: current_declaration,
|
|
@@ -334,7 +351,13 @@ module T::Private::Methods
|
|
|
334
351
|
private_class_method def self.run_sig_block_for_key(key)
|
|
335
352
|
blk = @sig_wrappers[key]
|
|
336
353
|
if !blk
|
|
337
|
-
|
|
354
|
+
sig = @signatures_by_method[key]
|
|
355
|
+
if sig
|
|
356
|
+
# We already ran the sig block, perhaps in another thread.
|
|
357
|
+
return sig
|
|
358
|
+
else
|
|
359
|
+
raise "No `sig` wrapper for #{key_to_method(key)}"
|
|
360
|
+
end
|
|
338
361
|
end
|
|
339
362
|
|
|
340
363
|
begin
|
|
@@ -361,7 +384,7 @@ module T::Private::Methods
|
|
|
361
384
|
|
|
362
385
|
# the module target is adding the methods from the module source to itself. we need to check that for all instance
|
|
363
386
|
# methods M on source, M is not defined on any of target's ancestors.
|
|
364
|
-
def self.
|
|
387
|
+
def self._hook_impl(target, target_ancestors, source)
|
|
365
388
|
if !module_with_final?(target) && !module_with_final?(source)
|
|
366
389
|
return
|
|
367
390
|
end
|
|
@@ -370,24 +393,42 @@ module T::Private::Methods
|
|
|
370
393
|
_check_final_ancestors(target, target_ancestors - source.ancestors, source.instance_methods)
|
|
371
394
|
end
|
|
372
395
|
|
|
373
|
-
def self.
|
|
374
|
-
is_enabled = @
|
|
396
|
+
def self.set_final_checks_on_hooks(enable)
|
|
397
|
+
is_enabled = @old_hooks != nil
|
|
375
398
|
if enable == is_enabled
|
|
376
399
|
return
|
|
377
400
|
end
|
|
378
401
|
if is_enabled
|
|
379
|
-
@
|
|
380
|
-
@
|
|
402
|
+
@old_hooks.each(&:restore)
|
|
403
|
+
@old_hooks = nil
|
|
381
404
|
else
|
|
382
405
|
old_included = T::Private::ClassUtils.replace_method(Module, :included) do |arg|
|
|
383
406
|
old_included.bind(self).call(arg)
|
|
384
|
-
::T::Private::Methods.
|
|
407
|
+
::T::Private::Methods._hook_impl(arg, arg.ancestors, self)
|
|
385
408
|
end
|
|
386
409
|
old_extended = T::Private::ClassUtils.replace_method(Module, :extended) do |arg|
|
|
387
410
|
old_extended.bind(self).call(arg)
|
|
388
|
-
::T::Private::Methods.
|
|
411
|
+
::T::Private::Methods._hook_impl(arg, arg.singleton_class.ancestors, self)
|
|
389
412
|
end
|
|
390
|
-
|
|
413
|
+
old_inherited = T::Private::ClassUtils.replace_method(Class, :inherited) do |arg|
|
|
414
|
+
old_inherited.bind(self).call(arg)
|
|
415
|
+
::T::Private::Methods._hook_impl(arg, arg.ancestors, self)
|
|
416
|
+
end
|
|
417
|
+
@old_hooks = [old_included, old_extended, old_inherited]
|
|
418
|
+
end
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
module MethodHooks
|
|
422
|
+
def method_added(name)
|
|
423
|
+
super(name)
|
|
424
|
+
::T::Private::Methods._on_method_added(self, name, is_singleton_method: false)
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
module SingletonMethodHooks
|
|
429
|
+
def singleton_method_added(name)
|
|
430
|
+
super(name)
|
|
431
|
+
::T::Private::Methods._on_method_added(self, name, is_singleton_method: true)
|
|
391
432
|
end
|
|
392
433
|
end
|
|
393
434
|
|
|
@@ -396,29 +437,11 @@ module T::Private::Methods
|
|
|
396
437
|
@installed_hooks << mod
|
|
397
438
|
|
|
398
439
|
if mod.singleton_class?
|
|
399
|
-
|
|
440
|
+
mod.include(SingletonMethodHooks)
|
|
400
441
|
else
|
|
401
|
-
|
|
402
|
-
T::Private::Methods._on_method_added(self, name)
|
|
403
|
-
original_method.bind(self).call(name)
|
|
404
|
-
end
|
|
405
|
-
end
|
|
406
|
-
install_singleton_method_added_hook(mod.singleton_class)
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
private_class_method def self.install_singleton_method_added_hook(singleton_klass)
|
|
410
|
-
attached = nil
|
|
411
|
-
original_singleton_method = T::Private::ClassUtils.replace_method(singleton_klass, :singleton_method_added) do |name|
|
|
412
|
-
attached = self
|
|
413
|
-
T::Private::Methods._on_method_added(self, name, is_singleton_method: true)
|
|
414
|
-
# This will be nil when this gets called for the addition of this method itself. We
|
|
415
|
-
# call it below to compensate.
|
|
416
|
-
if original_singleton_method
|
|
417
|
-
original_singleton_method.bind(self).call(name)
|
|
418
|
-
end
|
|
442
|
+
mod.extend(MethodHooks)
|
|
419
443
|
end
|
|
420
|
-
|
|
421
|
-
original_singleton_method.bind(attached).call(:singleton_method_added)
|
|
444
|
+
mod.extend(SingletonMethodHooks)
|
|
422
445
|
end
|
|
423
446
|
|
|
424
447
|
# use this directly if you don't want/need to box up the method into an object to pass to method_to_key.
|
|
@@ -37,7 +37,9 @@ module T::Private::Methods::CallValidation
|
|
|
37
37
|
else
|
|
38
38
|
T::Configuration.without_ruby_warnings do
|
|
39
39
|
# get all the shims out of the way and put back the original method
|
|
40
|
-
|
|
40
|
+
T::Private::DeclState.current.without_on_method_added do
|
|
41
|
+
mod.send(:define_method, method_sig.method_name, original_method)
|
|
42
|
+
end
|
|
41
43
|
mod.send(original_visibility, method_sig.method_name)
|
|
42
44
|
end
|
|
43
45
|
end
|
|
@@ -163,7 +165,6 @@ module T::Private::Methods::CallValidation
|
|
|
163
165
|
end
|
|
164
166
|
|
|
165
167
|
def self.create_validator_method(mod, original_method, method_sig, original_visibility)
|
|
166
|
-
T::Private::DeclState.current.skip_next_on_method_added = true
|
|
167
168
|
has_fixed_arity = method_sig.kwarg_types.empty? && !method_sig.has_rest && !method_sig.has_keyrest &&
|
|
168
169
|
original_method.parameters.all? {|(kind, _name)| kind == :req}
|
|
169
170
|
all_args_are_simple = method_sig.arg_types.all? {|_name, type| type.is_a?(T::Types::Simple)}
|
|
@@ -171,12 +172,14 @@ module T::Private::Methods::CallValidation
|
|
|
171
172
|
has_simple_procedure_types = all_args_are_simple && method_sig.return_type.is_a?(T::Private::Types::Void)
|
|
172
173
|
|
|
173
174
|
T::Configuration.without_ruby_warnings do
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
175
|
+
T::Private::DeclState.current.without_on_method_added do
|
|
176
|
+
if has_fixed_arity && has_simple_method_types && method_sig.arg_types.length < 5 && is_allowed_to_have_fast_path
|
|
177
|
+
create_validator_method_fast(mod, original_method, method_sig)
|
|
178
|
+
elsif has_fixed_arity && has_simple_procedure_types && method_sig.arg_types.length < 5 && is_allowed_to_have_fast_path
|
|
179
|
+
create_validator_procedure_fast(mod, original_method, method_sig)
|
|
180
|
+
else
|
|
181
|
+
create_validator_slow(mod, original_method, method_sig)
|
|
182
|
+
end
|
|
180
183
|
end
|
|
181
184
|
end
|
|
182
185
|
mod.send(original_visibility, method_sig.method_name)
|
|
@@ -1161,7 +1164,7 @@ module T::Private::Methods::CallValidation
|
|
|
1161
1164
|
"Caller: #{caller_loc.path}:#{caller_loc.lineno}\n" \
|
|
1162
1165
|
"Definition: #{definition_file}:#{definition_line}"
|
|
1163
1166
|
|
|
1164
|
-
T::
|
|
1167
|
+
T::Configuration.call_validation_error_handler(
|
|
1165
1168
|
method_sig,
|
|
1166
1169
|
message: error_message,
|
|
1167
1170
|
pretty_message: pretty_message,
|
|
@@ -145,13 +145,17 @@ module T::Private::Methods
|
|
|
145
145
|
when Modes.abstract
|
|
146
146
|
raise BuilderError.new(".abstract cannot be repeated in a single signature")
|
|
147
147
|
else
|
|
148
|
-
raise BuilderError.new("`.abstract` cannot be combined with
|
|
149
|
-
"`.overridable`.")
|
|
148
|
+
raise BuilderError.new("`.abstract` cannot be combined with `.override` or `.overridable`.")
|
|
150
149
|
end
|
|
151
150
|
|
|
152
151
|
self
|
|
153
152
|
end
|
|
154
153
|
|
|
154
|
+
def final
|
|
155
|
+
check_live!
|
|
156
|
+
raise BuilderError.new("The syntax for declaring a method final is `sig(:final) {...}`, not `sig {final. ...}`")
|
|
157
|
+
end
|
|
158
|
+
|
|
155
159
|
def override(allow_incompatible: false)
|
|
156
160
|
check_live!
|
|
157
161
|
|
|
@@ -159,11 +163,12 @@ module T::Private::Methods
|
|
|
159
163
|
when Modes.standard
|
|
160
164
|
decl.mode = Modes.override
|
|
161
165
|
decl.override_allow_incompatible = allow_incompatible
|
|
162
|
-
when Modes.override
|
|
166
|
+
when Modes.override, Modes.overridable_override
|
|
163
167
|
raise BuilderError.new(".override cannot be repeated in a single signature")
|
|
168
|
+
when Modes.overridable
|
|
169
|
+
decl.mode = Modes.overridable_override
|
|
164
170
|
else
|
|
165
|
-
raise BuilderError.new("`.override` cannot be combined with
|
|
166
|
-
"`.overridable`.")
|
|
171
|
+
raise BuilderError.new("`.override` cannot be combined with `.abstract`.")
|
|
167
172
|
end
|
|
168
173
|
|
|
169
174
|
self
|
|
@@ -173,36 +178,19 @@ module T::Private::Methods
|
|
|
173
178
|
check_live!
|
|
174
179
|
|
|
175
180
|
case decl.mode
|
|
176
|
-
when Modes.abstract
|
|
181
|
+
when Modes.abstract
|
|
177
182
|
raise BuilderError.new("`.overridable` cannot be combined with `.#{decl.mode}`")
|
|
183
|
+
when Modes.override
|
|
184
|
+
decl.mode = Modes.overridable_override
|
|
178
185
|
when Modes.standard
|
|
179
186
|
decl.mode = Modes.overridable
|
|
180
|
-
when Modes.
|
|
181
|
-
decl.mode = Modes.overridable_implementation
|
|
182
|
-
when Modes.overridable, Modes.overridable_implementation
|
|
187
|
+
when Modes.overridable, Modes.overridable_override
|
|
183
188
|
raise BuilderError.new(".overridable cannot be repeated in a single signature")
|
|
184
189
|
end
|
|
185
190
|
|
|
186
191
|
self
|
|
187
192
|
end
|
|
188
193
|
|
|
189
|
-
def implementation
|
|
190
|
-
check_live!
|
|
191
|
-
|
|
192
|
-
case decl.mode
|
|
193
|
-
when Modes.abstract, Modes.override
|
|
194
|
-
raise BuilderError.new("`.implementation` cannot be combined with `.#{decl.mode}`")
|
|
195
|
-
when Modes.standard
|
|
196
|
-
decl.mode = Modes.implementation
|
|
197
|
-
when Modes.overridable
|
|
198
|
-
decl.mode = Modes.overridable_implementation
|
|
199
|
-
when Modes.implementation, Modes.overridable_implementation
|
|
200
|
-
raise BuilderError.new(".implementation cannot be repeated in a single signature")
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
self
|
|
204
|
-
end
|
|
205
|
-
|
|
206
194
|
# Declares valid type paramaters which can be used with `T.type_parameter` in
|
|
207
195
|
# this `sig`.
|
|
208
196
|
#
|
|
@@ -233,6 +221,10 @@ module T::Private::Methods
|
|
|
233
221
|
def finalize!
|
|
234
222
|
check_live!
|
|
235
223
|
|
|
224
|
+
if decl.returns.equal?(ARG_NOT_PROVIDED)
|
|
225
|
+
raise BuilderError.new("You must provide a return type; use the `.returns` or `.void` builder methods.")
|
|
226
|
+
end
|
|
227
|
+
|
|
236
228
|
if decl.bind.equal?(ARG_NOT_PROVIDED)
|
|
237
229
|
decl.bind = nil
|
|
238
230
|
end
|
|
@@ -5,14 +5,12 @@ module T::Private::Methods::Modes
|
|
|
5
5
|
def self.standard; 'standard'; end
|
|
6
6
|
def self.abstract; 'abstract'; end
|
|
7
7
|
def self.overridable; 'overridable'; end
|
|
8
|
-
def self.implementation; 'implementation'; end
|
|
9
8
|
def self.override; 'override'; end
|
|
10
|
-
def self.
|
|
9
|
+
def self.overridable_override; 'overridable_override'; end
|
|
11
10
|
def self.untyped; 'untyped'; end
|
|
12
|
-
MODES = [self.standard, self.abstract, self.overridable, self.
|
|
11
|
+
MODES = [self.standard, self.abstract, self.overridable, self.override, self.overridable_override, self.untyped]
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
NON_OVERRIDE_MODES = MODES - OVERRIDE_MODES - IMPLEMENT_MODES
|
|
13
|
+
OVERRIDABLE_MODES = [self.override, self.overridable, self.overridable_override, self.untyped, self.abstract]
|
|
14
|
+
OVERRIDE_MODES = [self.override, self.overridable_override]
|
|
15
|
+
NON_OVERRIDE_MODES = MODES - OVERRIDE_MODES
|
|
18
16
|
end
|
|
@@ -48,8 +48,8 @@ module T::Private::Methods::SignatureValidation
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
private_class_method def self.pretty_mode(signature)
|
|
51
|
-
if signature.mode == Modes.
|
|
52
|
-
'.overridable.
|
|
51
|
+
if signature.mode == Modes.overridable_override
|
|
52
|
+
'.overridable.override'
|
|
53
53
|
else
|
|
54
54
|
".#{signature.mode}"
|
|
55
55
|
end
|
|
@@ -59,21 +59,15 @@ module T::Private::Methods::SignatureValidation
|
|
|
59
59
|
case signature.mode
|
|
60
60
|
when *Modes::OVERRIDE_MODES
|
|
61
61
|
if !Modes::OVERRIDABLE_MODES.include?(super_signature.mode)
|
|
62
|
-
raise "You declared `#{signature.method_name}` as #{pretty_mode(signature)}, but the method it overrides is not declared as `overridable`.\n" \
|
|
62
|
+
raise "You declared `#{signature.method_name}` as #{pretty_mode(signature)}, but the method it overrides is not declared as `overridable` or `abstract`.\n" \
|
|
63
63
|
" Parent definition: #{method_loc_str(super_signature.method)}\n" \
|
|
64
64
|
" Child definition: #{method_loc_str(signature.method)}\n"
|
|
65
65
|
end
|
|
66
|
-
when *Modes::IMPLEMENT_MODES
|
|
67
|
-
if super_signature.mode != Modes.abstract
|
|
68
|
-
raise "You declared `#{signature.method_name}` as #{pretty_mode(signature)}, but the method it overrides is not declared as abstract.\n" \
|
|
69
|
-
" Either mark #{super_signature.method_name} as `abstract.` in the parent: #{method_loc_str(super_signature.method)}\n" \
|
|
70
|
-
" ... or mark #{signature.method_name} as `override.` in the child: #{method_loc_str(signature.method)}\n"
|
|
71
|
-
end
|
|
72
66
|
when *Modes::NON_OVERRIDE_MODES
|
|
73
67
|
if super_signature.mode == Modes.standard
|
|
74
68
|
# Peaceful
|
|
75
69
|
elsif super_signature.mode == Modes.abstract
|
|
76
|
-
raise "You must use `.
|
|
70
|
+
raise "You must use `.override` when overriding the abstract method `#{signature.method_name}`.\n" \
|
|
77
71
|
" Abstract definition: #{method_loc_str(super_signature.method)}\n" \
|
|
78
72
|
" Implementation definition: #{method_loc_str(signature.method)}\n"
|
|
79
73
|
elsif super_signature.mode != Modes.untyped
|
|
@@ -89,16 +83,23 @@ module T::Private::Methods::SignatureValidation
|
|
|
89
83
|
def self.validate_non_override_mode(signature)
|
|
90
84
|
case signature.mode
|
|
91
85
|
when Modes.override
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
86
|
+
if signature.method_name == :each && signature.method.owner < Enumerable
|
|
87
|
+
# Enumerable#each is the only method in Sorbet's RBI payload that defines an abstract method.
|
|
88
|
+
# Enumerable#each does not actually exist at runtime, but it is required to be implemented by
|
|
89
|
+
# any class which includes Enumerable. We want to declare Enumerable#each as abstract so that
|
|
90
|
+
# people can call it anything which implements the Enumerable interface, and so that it's a
|
|
91
|
+
# static error to forget to implement it.
|
|
92
|
+
#
|
|
93
|
+
# This is a one-off hack, and we should think carefully before adding more methods here.
|
|
94
|
+
nil
|
|
95
|
+
else
|
|
96
|
+
raise "You marked `#{signature.method_name}` as #{pretty_mode(signature)}, but that method doesn't already exist in this class/module to be overriden.\n" \
|
|
97
|
+
" Either check for typos and for missing includes or super classes to make the parent method shows up\n" \
|
|
98
|
+
" ... or remove #{pretty_mode(signature)} here: #{method_loc_str(signature.method)}\n"
|
|
99
|
+
end
|
|
95
100
|
when Modes.standard, *Modes::NON_OVERRIDE_MODES
|
|
96
101
|
# Peaceful
|
|
97
102
|
nil
|
|
98
|
-
when *Modes::IMPLEMENT_MODES
|
|
99
|
-
raise "You marked `#{signature.method_name}` as #{pretty_mode(signature)}, but it doesn't match up with a corresponding abstract method.\n" \
|
|
100
|
-
" Either check for typos and for missing includes or super classes to make the parent method shows up\n" \
|
|
101
|
-
" ... or remove #{pretty_mode(signature)} here: #{method_loc_str(signature.method)}\n"
|
|
102
103
|
else
|
|
103
104
|
raise "Unexpected mode: #{signature.mode}. Please report to #dev-productivity."
|
|
104
105
|
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: false
|
|
3
|
+
|
|
4
|
+
module T::Private::Sealed
|
|
5
|
+
module NoInherit
|
|
6
|
+
def inherited(other)
|
|
7
|
+
super
|
|
8
|
+
this_line = Kernel.caller.find {|line| !line.match(/in `inherited'$/)}
|
|
9
|
+
T::Private::Sealed.validate_inheritance(this_line, self, 'inherited')
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module NoIncludeExtend
|
|
14
|
+
def included(other)
|
|
15
|
+
super
|
|
16
|
+
this_line = Kernel.caller.find {|line| !line.match(/in `included'$/)}
|
|
17
|
+
T::Private::Sealed.validate_inheritance(this_line, self, 'included')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def extended(other)
|
|
21
|
+
super
|
|
22
|
+
this_line = Kernel.caller.find {|line| !line.match(/in `extended'$/)}
|
|
23
|
+
T::Private::Sealed.validate_inheritance(this_line, self, 'extended')
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.declare(mod, decl_file)
|
|
28
|
+
if !mod.is_a?(Module)
|
|
29
|
+
raise "#{mod} is not a class or module and cannot be declared `sealed!`"
|
|
30
|
+
end
|
|
31
|
+
if sealed_module?(mod)
|
|
32
|
+
raise "#{mod} was already declared `sealed!` and cannot be re-declared `sealed!`"
|
|
33
|
+
end
|
|
34
|
+
if T::Private::Final.final_module?(mod)
|
|
35
|
+
raise "#{mod} was already declared `final!` and cannot be declared `sealed!`"
|
|
36
|
+
end
|
|
37
|
+
mod.extend(mod.is_a?(Class) ? NoInherit : NoIncludeExtend)
|
|
38
|
+
if !decl_file
|
|
39
|
+
raise "Couldn't determine declaration file for sealed class."
|
|
40
|
+
end
|
|
41
|
+
mod.instance_variable_set(:@sorbet_sealed_module_decl_file, decl_file)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.sealed_module?(mod)
|
|
45
|
+
mod.instance_variable_defined?(:@sorbet_sealed_module_decl_file)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.validate_inheritance(this_line, parent, verb)
|
|
49
|
+
this_file = this_line&.split(':').first
|
|
50
|
+
decl_file = parent.instance_variable_get(:@sorbet_sealed_module_decl_file)
|
|
51
|
+
|
|
52
|
+
if !this_file || !decl_file
|
|
53
|
+
raise "Couldn't determine enough file information for checking sealed modules"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
if !this_file.start_with?(decl_file)
|
|
57
|
+
raise "#{parent} was declared sealed and can only be #{verb} in #{decl_file}, not #{this_file}"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -486,11 +486,7 @@ class T::Props::Decorator
|
|
|
486
486
|
sig {params(name: Symbol, rules: Rules).void}
|
|
487
487
|
private def define_getter_and_setter(name, rules)
|
|
488
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
|
|
489
|
+
if !rules[:immutable]
|
|
494
490
|
@class.send(:define_method, "#{name}=") do |x|
|
|
495
491
|
self.class.decorator.prop_set(self, name, x, rules)
|
|
496
492
|
end
|
data/lib/types/types/base.rb
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
3
|
+
|
|
4
|
+
module T::Types
|
|
5
|
+
# Validates that an object is equal to another Opus::Enum singleton value.
|
|
6
|
+
class OpusEnum < Base
|
|
7
|
+
attr_reader :val
|
|
8
|
+
|
|
9
|
+
def initialize(val)
|
|
10
|
+
@val = val
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @override Base
|
|
14
|
+
def name
|
|
15
|
+
@val.inspect
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @override Base
|
|
19
|
+
def valid?(obj)
|
|
20
|
+
@val == obj
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @override Base
|
|
24
|
+
private def subtype_of_single?(other)
|
|
25
|
+
case other
|
|
26
|
+
when OpusEnum
|
|
27
|
+
@val == other.val
|
|
28
|
+
else
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -8,6 +8,10 @@ module T::Types
|
|
|
8
8
|
"T::Array[#{@type.name}]"
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def underlying_class
|
|
12
|
+
Array
|
|
13
|
+
end
|
|
14
|
+
|
|
11
15
|
# @override Base
|
|
12
16
|
def valid?(obj)
|
|
13
17
|
obj.is_a?(Array) && super
|
|
@@ -16,5 +20,15 @@ module T::Types
|
|
|
16
20
|
def new(*args) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
|
17
21
|
Array.new(*T.unsafe(args))
|
|
18
22
|
end
|
|
23
|
+
|
|
24
|
+
class Untyped < TypedArray
|
|
25
|
+
def initialize
|
|
26
|
+
super(T.untyped)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def valid?(obj)
|
|
30
|
+
obj.is_a?(Array)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
19
33
|
end
|
|
20
34
|
end
|
|
@@ -12,6 +12,10 @@ module T::Types
|
|
|
12
12
|
@type = T::Utils.coerce(type)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
+
def underlying_class
|
|
16
|
+
Enumerable
|
|
17
|
+
end
|
|
18
|
+
|
|
15
19
|
# @override Base
|
|
16
20
|
def name
|
|
17
21
|
"T::Enumerable[#{@type.name}]"
|
|
@@ -68,7 +72,8 @@ module T::Types
|
|
|
68
72
|
|
|
69
73
|
# @override Base
|
|
70
74
|
private def subtype_of_single?(other)
|
|
71
|
-
if
|
|
75
|
+
if other.class <= TypedEnumerable &&
|
|
76
|
+
underlying_class <= other.underlying_class
|
|
72
77
|
# Enumerables are covariant because they are read only
|
|
73
78
|
#
|
|
74
79
|
# Properly speaking, many Enumerable subtypes (e.g. Set)
|
|
@@ -137,5 +142,15 @@ module T::Types
|
|
|
137
142
|
self.class.new(type_from_instances(obj))
|
|
138
143
|
end
|
|
139
144
|
end
|
|
145
|
+
|
|
146
|
+
class Untyped < TypedEnumerable
|
|
147
|
+
def initialize
|
|
148
|
+
super(T.untyped)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def valid?(obj)
|
|
152
|
+
obj.is_a?(Enumerable)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
140
155
|
end
|
|
141
156
|
end
|
|
@@ -5,6 +5,10 @@ module T::Types
|
|
|
5
5
|
class TypedEnumerator < TypedEnumerable
|
|
6
6
|
attr_reader :type
|
|
7
7
|
|
|
8
|
+
def underlying_class
|
|
9
|
+
Enumerator
|
|
10
|
+
end
|
|
11
|
+
|
|
8
12
|
# @override Base
|
|
9
13
|
def name
|
|
10
14
|
"T::Enumerator[#{@type.name}]"
|
|
@@ -18,5 +22,15 @@ module T::Types
|
|
|
18
22
|
def new(*args, &blk) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
|
19
23
|
T.unsafe(Enumerator).new(*args, &blk)
|
|
20
24
|
end
|
|
25
|
+
|
|
26
|
+
class Untyped < TypedEnumerator
|
|
27
|
+
def initialize
|
|
28
|
+
super(T.untyped)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def valid?(obj)
|
|
32
|
+
obj.is_a?(Enumerator)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
21
35
|
end
|
|
22
36
|
end
|
|
@@ -6,6 +6,10 @@ module T::Types
|
|
|
6
6
|
# Technically we don't need these, but they are a nice api
|
|
7
7
|
attr_reader :keys, :values
|
|
8
8
|
|
|
9
|
+
def underlying_class
|
|
10
|
+
Hash
|
|
11
|
+
end
|
|
12
|
+
|
|
9
13
|
def initialize(keys:, values:)
|
|
10
14
|
@keys = T::Utils.coerce(keys)
|
|
11
15
|
@values = T::Utils.coerce(values)
|
|
@@ -25,5 +29,15 @@ module T::Types
|
|
|
25
29
|
def new(*args, &blk) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
|
26
30
|
Hash.new(*T.unsafe(args), &blk) # rubocop:disable PrisonGuard/RestrictHashDefaults
|
|
27
31
|
end
|
|
32
|
+
|
|
33
|
+
class Untyped < TypedHash
|
|
34
|
+
def initialize
|
|
35
|
+
super(keys: T.untyped, values: T.untyped)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def valid?(obj)
|
|
39
|
+
obj.is_a?(Hash)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
28
42
|
end
|
|
29
43
|
end
|
|
@@ -5,6 +5,10 @@ module T::Types
|
|
|
5
5
|
class TypedSet < TypedEnumerable
|
|
6
6
|
attr_reader :type
|
|
7
7
|
|
|
8
|
+
def underlying_class
|
|
9
|
+
Hash
|
|
10
|
+
end
|
|
11
|
+
|
|
8
12
|
# @override Base
|
|
9
13
|
def name
|
|
10
14
|
"T::Set[#{@type.name}]"
|
|
@@ -18,5 +22,15 @@ module T::Types
|
|
|
18
22
|
def new(*args) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
|
19
23
|
Set.new(*T.unsafe(args))
|
|
20
24
|
end
|
|
25
|
+
|
|
26
|
+
class Untyped < TypedSet
|
|
27
|
+
def initialize
|
|
28
|
+
super(T.untyped)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def valid?(obj)
|
|
32
|
+
obj.is_a?(Set)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
21
35
|
end
|
|
22
36
|
end
|
data/lib/types/utils.rb
CHANGED
|
@@ -26,6 +26,8 @@ module T::Utils
|
|
|
26
26
|
T::Types::FixedHash.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
|
|
27
27
|
elsif val.is_a?(T::Private::Methods::DeclBuilder)
|
|
28
28
|
T::Private::Methods.finalize_proc(val.decl)
|
|
29
|
+
elsif defined?(::Opus) && defined?(::Opus::Enum) && val.is_a?(::Opus::Enum)
|
|
30
|
+
T::Types::OpusEnum.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
|
|
29
31
|
else
|
|
30
32
|
raise "Invalid value for type constraint. Must be an #{T::Types::Base}, a " \
|
|
31
33
|
"class/module, or an array. Got a `#{val.class}`."
|
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.4788
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stripe
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-
|
|
11
|
+
date: 2019-09-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|
|
@@ -52,6 +52,20 @@ dependencies:
|
|
|
52
52
|
- - ">="
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: concurrent-ruby
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 1.1.5
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 1.1.5
|
|
55
69
|
description: Sorbet's runtime type checking component
|
|
56
70
|
email:
|
|
57
71
|
executables: []
|
|
@@ -75,6 +89,7 @@ files:
|
|
|
75
89
|
- lib/types/private/class_utils.rb
|
|
76
90
|
- lib/types/private/decl_state.rb
|
|
77
91
|
- lib/types/private/error_handler.rb
|
|
92
|
+
- lib/types/private/final.rb
|
|
78
93
|
- lib/types/private/methods/_methods.rb
|
|
79
94
|
- lib/types/private/methods/call_validation.rb
|
|
80
95
|
- lib/types/private/methods/decl_builder.rb
|
|
@@ -83,6 +98,7 @@ files:
|
|
|
83
98
|
- lib/types/private/methods/signature_validation.rb
|
|
84
99
|
- lib/types/private/mixins/mixins.rb
|
|
85
100
|
- lib/types/private/runtime_levels.rb
|
|
101
|
+
- lib/types/private/sealed.rb
|
|
86
102
|
- lib/types/private/types/not_typed.rb
|
|
87
103
|
- lib/types/private/types/string_holder.rb
|
|
88
104
|
- lib/types/private/types/void.rb
|
|
@@ -109,6 +125,7 @@ files:
|
|
|
109
125
|
- lib/types/types/fixed_hash.rb
|
|
110
126
|
- lib/types/types/intersection.rb
|
|
111
127
|
- lib/types/types/noreturn.rb
|
|
128
|
+
- lib/types/types/opus_enum.rb
|
|
112
129
|
- lib/types/types/proc.rb
|
|
113
130
|
- lib/types/types/self_type.rb
|
|
114
131
|
- lib/types/types/simple.rb
|
|
@@ -147,8 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
147
164
|
- !ruby/object:Gem::Version
|
|
148
165
|
version: '0'
|
|
149
166
|
requirements: []
|
|
150
|
-
|
|
151
|
-
rubygems_version: 2.6.14
|
|
167
|
+
rubygems_version: 3.0.3
|
|
152
168
|
signing_key:
|
|
153
169
|
specification_version: 4
|
|
154
170
|
summary: Sorbet runtime
|