sorbet-runtime 0.5.11266 → 0.5.11647
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 +0 -3
- data/lib/types/configuration.rb +2 -1
- data/lib/types/enum.rb +63 -39
- data/lib/types/non_forcing_constants.rb +4 -14
- data/lib/types/private/caller_utils.rb +6 -0
- data/lib/types/private/class_utils.rb +1 -1
- data/lib/types/private/methods/call_validation.rb +32 -14
- data/lib/types/private/methods/decl_builder.rb +3 -3
- data/lib/types/private/methods/signature_validation.rb +1 -1
- data/lib/types/private/runtime_levels.rb +0 -3
- data/lib/types/private/sealed.rb +6 -6
- data/lib/types/props/_props.rb +5 -5
- data/lib/types/props/decorator.rb +1 -1
- data/lib/types/props/has_lazily_specialized_methods.rb +3 -1
- data/lib/types/props/pretty_printable.rb +6 -6
- data/lib/types/props/serializable.rb +22 -7
- data/lib/types/struct.rb +1 -1
- data/lib/types/types/base.rb +3 -3
- data/lib/types/types/class_of.rb +2 -2
- data/lib/types/types/enum.rb +1 -1
- data/lib/types/types/proc.rb +1 -1
- data/lib/types/types/typed_array.rb +1 -1
- data/lib/types/types/typed_class.rb +1 -1
- data/lib/types/types/typed_enumerable.rb +5 -6
- data/lib/types/types/typed_enumerator.rb +1 -1
- data/lib/types/types/typed_enumerator_chain.rb +1 -1
- data/lib/types/types/typed_enumerator_lazy.rb +1 -1
- data/lib/types/types/typed_range.rb +1 -1
- data/lib/types/types/typed_set.rb +2 -2
- data/lib/types/utils.rb +1 -1
- metadata +16 -3
- data/lib/types/private/compiler.rb +0 -24
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cbc4c99744f25d0ec157e3a068f29bd639264546679e435c57324e6678d5b508
|
|
4
|
+
data.tar.gz: 48163adbeccaff12cac4aeabfef8613c327b93937a43d510d3d9db8b01c36eb4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 317425a0c17154e3f3cb3f850cc32317b63cb68898fe9f3c9c97f83a41432c0b3331936211241b25a4866a6f47ce037b20fdc54fd072d97d985ebfaded497b30
|
|
7
|
+
data.tar.gz: ab4e236b016f4e3c9f0123d1ee5b03b556f318755a483127facfad6d2247fac47ac4a83d90a168f68af94797a4b07d01efc12dc29c6e7841967528964512ddd5
|
data/lib/sorbet-runtime.rb
CHANGED
data/lib/types/configuration.rb
CHANGED
|
@@ -113,7 +113,7 @@ module T::Configuration
|
|
|
113
113
|
# statically, so that methods don't have to guard themselves from being
|
|
114
114
|
# called incorrectly by untyped code.
|
|
115
115
|
#
|
|
116
|
-
# @param [:never, :
|
|
116
|
+
# @param [:never, :tests, :always] default_checked_level
|
|
117
117
|
def self.default_checked_level=(default_checked_level)
|
|
118
118
|
T::Private::RuntimeLevels.default_checked_level = default_checked_level
|
|
119
119
|
end
|
|
@@ -536,6 +536,7 @@ module T::Configuration
|
|
|
536
536
|
|
|
537
537
|
@legacy_t_enum_migration_mode = false
|
|
538
538
|
def self.enable_legacy_t_enum_migration_mode
|
|
539
|
+
T::Enum.include(T::Enum::LegacyMigrationMode)
|
|
539
540
|
@legacy_t_enum_migration_mode = true
|
|
540
541
|
end
|
|
541
542
|
def self.disable_legacy_t_enum_migration_mode
|
data/lib/types/enum.rb
CHANGED
|
@@ -192,68 +192,92 @@ class T::Enum
|
|
|
192
192
|
# responds to the `to_str` method. It does not actually call `to_str` however.
|
|
193
193
|
#
|
|
194
194
|
# See https://ruby-doc.org/core-2.4.0/String.html#method-i-3D-3D
|
|
195
|
-
sig {returns(String)}
|
|
195
|
+
T::Sig::WithoutRuntime.sig {returns(String)}
|
|
196
196
|
def to_str
|
|
197
197
|
msg = 'Implicit conversion of Enum instances to strings is not allowed. Call #serialize instead.'
|
|
198
198
|
if T::Configuration.legacy_t_enum_migration_mode?
|
|
199
199
|
T::Configuration.soft_assert_handler(
|
|
200
200
|
msg,
|
|
201
|
-
storytime: {
|
|
201
|
+
storytime: {
|
|
202
|
+
class: self.class.name,
|
|
203
|
+
caller_location: Kernel.caller_locations(1..1)&.[](0)&.then {"#{_1.path}:#{_1.lineno}"},
|
|
204
|
+
},
|
|
202
205
|
)
|
|
203
206
|
serialize.to_s
|
|
204
207
|
else
|
|
205
|
-
raise NoMethodError.new(msg)
|
|
208
|
+
Kernel.raise NoMethodError.new(msg)
|
|
206
209
|
end
|
|
207
210
|
end
|
|
208
211
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
212
|
+
module LegacyMigrationMode
|
|
213
|
+
include Kernel
|
|
214
|
+
extend T::Helpers
|
|
215
|
+
abstract!
|
|
216
|
+
|
|
217
|
+
if T.unsafe(false)
|
|
218
|
+
# Declare to the type system that the `serialize` method for sure exists
|
|
219
|
+
# on whatever we mix this into.
|
|
220
|
+
T::Sig::WithoutRuntime.sig {abstract.returns(T.untyped)}
|
|
221
|
+
def serialize; end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# WithoutRuntime so that comparison_assertion_failed can assume a constant stack depth
|
|
225
|
+
T::Sig::WithoutRuntime.sig {params(other: BasicObject).returns(T::Boolean)}
|
|
226
|
+
def ==(other)
|
|
227
|
+
case other
|
|
228
|
+
when String
|
|
229
|
+
if T::Configuration.legacy_t_enum_migration_mode?
|
|
230
|
+
comparison_assertion_failed(:==, other)
|
|
231
|
+
self.serialize == other
|
|
232
|
+
else
|
|
233
|
+
false
|
|
234
|
+
end
|
|
216
235
|
else
|
|
217
|
-
|
|
236
|
+
super(other)
|
|
218
237
|
end
|
|
219
|
-
else
|
|
220
|
-
super(other)
|
|
221
238
|
end
|
|
222
|
-
end
|
|
223
239
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
240
|
+
# WithoutRuntime so that comparison_assertion_failed can assume a constant stack depth
|
|
241
|
+
T::Sig::WithoutRuntime.sig {params(other: BasicObject).returns(T::Boolean)}
|
|
242
|
+
def ===(other)
|
|
243
|
+
case other
|
|
244
|
+
when String
|
|
245
|
+
if T::Configuration.legacy_t_enum_migration_mode?
|
|
246
|
+
comparison_assertion_failed(:===, other)
|
|
247
|
+
self.serialize == other
|
|
248
|
+
else
|
|
249
|
+
false
|
|
250
|
+
end
|
|
231
251
|
else
|
|
232
|
-
|
|
252
|
+
super(other)
|
|
233
253
|
end
|
|
234
|
-
else
|
|
235
|
-
super(other)
|
|
236
254
|
end
|
|
237
|
-
end
|
|
238
255
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
T::
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
256
|
+
# WithoutRuntime so that caller_locations can assume a constant stack depth
|
|
257
|
+
# (Otherwise, the first call would be the method with the wrapping, which would have a different stack depth.)
|
|
258
|
+
T::Sig::WithoutRuntime.sig {params(method: Symbol, other: T.untyped).void}
|
|
259
|
+
private def comparison_assertion_failed(method, other)
|
|
260
|
+
T::Configuration.soft_assert_handler(
|
|
261
|
+
'Enum to string comparison not allowed. Compare to the Enum instance directly instead. See go/enum-migration',
|
|
262
|
+
storytime: {
|
|
263
|
+
class: self.class.name,
|
|
264
|
+
self: self.inspect,
|
|
265
|
+
other: other,
|
|
266
|
+
other_class: other.class.name,
|
|
267
|
+
method: method,
|
|
268
|
+
caller_location: Kernel.caller_locations(2..2)&.[](0)&.then {"#{_1.path}:#{_1.lineno}"},
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
end
|
|
251
272
|
end
|
|
252
273
|
|
|
253
274
|
### Private implementation ###
|
|
254
275
|
|
|
276
|
+
UNSET = T.let(Module.new.freeze, Module)
|
|
277
|
+
private_constant :UNSET
|
|
278
|
+
|
|
255
279
|
sig {params(serialized_val: SerializedVal).void}
|
|
256
|
-
def initialize(serialized_val=
|
|
280
|
+
def initialize(serialized_val=UNSET)
|
|
257
281
|
raise 'T::Enum is abstract' if self.class == T::Enum
|
|
258
282
|
if !self.class.started_initializing?
|
|
259
283
|
raise "Must instantiate all enum values of #{self.class} inside 'enums do'."
|
|
@@ -279,7 +303,7 @@ class T::Enum
|
|
|
279
303
|
sig {params(const_name: Symbol).void}
|
|
280
304
|
def _bind_name(const_name)
|
|
281
305
|
@const_name = const_name
|
|
282
|
-
@serialized_val = const_to_serialized_val(const_name) if @serialized_val.
|
|
306
|
+
@serialized_val = const_to_serialized_val(const_name) if @serialized_val.equal?(UNSET)
|
|
283
307
|
freeze
|
|
284
308
|
end
|
|
285
309
|
|
|
@@ -4,20 +4,13 @@
|
|
|
4
4
|
module T::NonForcingConstants
|
|
5
5
|
# NOTE: This method is documented on the RBI in Sorbet's payload, so that it
|
|
6
6
|
# shows up in the hover/completion documentation via LSP.
|
|
7
|
-
T::Sig::WithoutRuntime.sig {params(val: BasicObject, klass: String
|
|
8
|
-
def self.non_forcing_is_a?(val, klass
|
|
7
|
+
T::Sig::WithoutRuntime.sig {params(val: BasicObject, klass: String).returns(T::Boolean)}
|
|
8
|
+
def self.non_forcing_is_a?(val, klass)
|
|
9
9
|
method_name = "T::NonForcingConstants.non_forcing_is_a?"
|
|
10
10
|
if klass.empty?
|
|
11
11
|
raise ArgumentError.new("The string given to `#{method_name}` must not be empty")
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
# We don't treat packages differently at runtime, but the static
|
|
15
|
-
# type-checker still needs to have the package and constant
|
|
16
|
-
# separated out. This just re-assembles the string as needed
|
|
17
|
-
if !package.nil?
|
|
18
|
-
klass = "::#{package}::#{klass}"
|
|
19
|
-
end
|
|
20
|
-
|
|
21
14
|
current_klass = T.let(nil, T.nilable(Module))
|
|
22
15
|
current_prefix = T.let(nil, T.nilable(String))
|
|
23
16
|
|
|
@@ -25,10 +18,7 @@ module T::NonForcingConstants
|
|
|
25
18
|
parts.each do |part|
|
|
26
19
|
if current_klass.nil?
|
|
27
20
|
# First iteration
|
|
28
|
-
if part != ""
|
|
29
|
-
# if we've supplied a package, we're probably running in
|
|
30
|
-
# package mode, which means absolute references are
|
|
31
|
-
# meaningless
|
|
21
|
+
if part != ""
|
|
32
22
|
raise ArgumentError.new("The string given to `#{method_name}` must be an absolute constant reference that starts with `::`")
|
|
33
23
|
end
|
|
34
24
|
|
|
@@ -37,7 +27,7 @@ module T::NonForcingConstants
|
|
|
37
27
|
|
|
38
28
|
# if this had a :: prefix, then there's no more loading to
|
|
39
29
|
# do---skip to the next one
|
|
40
|
-
next
|
|
30
|
+
next
|
|
41
31
|
end
|
|
42
32
|
|
|
43
33
|
if current_klass.autoload?(part)
|
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
module T::Private::CallerUtils
|
|
5
5
|
if Thread.respond_to?(:each_caller_location) # RUBY_VERSION >= "3.2"
|
|
6
6
|
def self.find_caller
|
|
7
|
+
skipped_first = false
|
|
7
8
|
Thread.each_caller_location do |loc|
|
|
9
|
+
unless skipped_first
|
|
10
|
+
skipped_first = true
|
|
11
|
+
next
|
|
12
|
+
end
|
|
13
|
+
|
|
8
14
|
next if loc.path&.start_with?("<internal:")
|
|
9
15
|
|
|
10
16
|
return loc if yield(loc)
|
|
@@ -14,17 +14,7 @@ module T::Private::Methods::CallValidation
|
|
|
14
14
|
def self.wrap_method_if_needed(mod, method_sig, original_method)
|
|
15
15
|
original_visibility = visibility_method_name(mod, method_sig.method_name)
|
|
16
16
|
if method_sig.mode == T::Private::Methods::Modes.abstract
|
|
17
|
-
|
|
18
|
-
# We allow abstract methods to be implemented by things further down the ancestor chain.
|
|
19
|
-
# So, if a super method exists, call it.
|
|
20
|
-
if defined?(super)
|
|
21
|
-
super(*args, &blk)
|
|
22
|
-
else
|
|
23
|
-
raise NotImplementedError.new(
|
|
24
|
-
"The method `#{method_sig.method_name}` on #{mod} is declared as `abstract`. It does not have an implementation."
|
|
25
|
-
)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
17
|
+
create_abstract_wrapper(mod, method_sig, original_method, original_visibility)
|
|
28
18
|
# Do nothing in this case; this method was not wrapped in _on_method_added.
|
|
29
19
|
elsif method_sig.defined_raw
|
|
30
20
|
# Note, this logic is duplicated (intentionally, for micro-perf) at `Methods._on_method_added`,
|
|
@@ -55,6 +45,24 @@ module T::Private::Methods::CallValidation
|
|
|
55
45
|
@is_allowed_to_have_fast_path = false
|
|
56
46
|
end
|
|
57
47
|
|
|
48
|
+
def self.create_abstract_wrapper(mod, method_sig, original_method, original_visibility)
|
|
49
|
+
mod.module_eval(<<~METHOD, __FILE__, __LINE__ + 1)
|
|
50
|
+
#{original_visibility}
|
|
51
|
+
|
|
52
|
+
def #{method_sig.method_name}(...)
|
|
53
|
+
# We allow abstract methods to be implemented by things further down the ancestor chain.
|
|
54
|
+
# So, if a super method exists, call it.
|
|
55
|
+
if defined?(super)
|
|
56
|
+
super
|
|
57
|
+
else
|
|
58
|
+
raise NotImplementedError.new(
|
|
59
|
+
"The method `#{method_sig.method_name}` on #{mod} is declared as `abstract`. It does not have an implementation."
|
|
60
|
+
)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
METHOD
|
|
64
|
+
end
|
|
65
|
+
|
|
58
66
|
def self.create_validator_method(mod, original_method, method_sig, original_visibility)
|
|
59
67
|
has_fixed_arity = method_sig.kwarg_types.empty? && !method_sig.has_rest && !method_sig.has_keyrest &&
|
|
60
68
|
original_method.parameters.all? {|(kind, _name)| kind == :req || kind == :block}
|
|
@@ -291,11 +299,21 @@ module T::Private::Methods::CallValidation
|
|
|
291
299
|
|
|
292
300
|
def self.report_error(method_sig, error_message, kind, name, type, value, caller_offset: 0)
|
|
293
301
|
caller_loc = T.must(caller_locations(3 + caller_offset, 1))[0]
|
|
294
|
-
|
|
302
|
+
method = method_sig.method
|
|
303
|
+
definition_file, definition_line = method.source_location
|
|
304
|
+
|
|
305
|
+
owner = method.owner
|
|
306
|
+
pretty_method_name =
|
|
307
|
+
if owner.singleton_class? && owner.respond_to?(:attached_object)
|
|
308
|
+
# attached_object is new in Ruby 3.2
|
|
309
|
+
"#{owner.attached_object}.#{method.name}"
|
|
310
|
+
else
|
|
311
|
+
"#{owner}##{method.name}"
|
|
312
|
+
end
|
|
295
313
|
|
|
296
314
|
pretty_message = "#{kind}#{name ? " '#{name}'" : ''}: #{error_message}\n" \
|
|
297
315
|
"Caller: #{caller_loc.path}:#{caller_loc.lineno}\n" \
|
|
298
|
-
"Definition: #{definition_file}:#{definition_line}"
|
|
316
|
+
"Definition: #{definition_file}:#{definition_line} (#{pretty_method_name})"
|
|
299
317
|
|
|
300
318
|
T::Configuration.call_validation_error_handler(
|
|
301
319
|
method_sig,
|
|
@@ -318,7 +336,7 @@ module T::Private::Methods::CallValidation
|
|
|
318
336
|
elsif mod.private_method_defined?(name)
|
|
319
337
|
:private
|
|
320
338
|
else
|
|
321
|
-
|
|
339
|
+
mod.method(name) # Raises
|
|
322
340
|
end
|
|
323
341
|
end
|
|
324
342
|
end
|
|
@@ -101,7 +101,7 @@ module T::Private::Methods
|
|
|
101
101
|
if !decl.checked.equal?(ARG_NOT_PROVIDED)
|
|
102
102
|
raise BuilderError.new("You can't call .checked multiple times in a signature.")
|
|
103
103
|
end
|
|
104
|
-
if
|
|
104
|
+
if level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
105
105
|
raise BuilderError.new("You can't use .checked(:#{level}) with .on_failure because .on_failure will have no effect.")
|
|
106
106
|
end
|
|
107
107
|
if !T::Private::RuntimeLevels::LEVELS.include?(level)
|
|
@@ -119,7 +119,7 @@ module T::Private::Methods
|
|
|
119
119
|
if !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
120
120
|
raise BuilderError.new("You can't call .on_failure multiple times in a signature.")
|
|
121
121
|
end
|
|
122
|
-
if decl.checked == :never
|
|
122
|
+
if decl.checked == :never
|
|
123
123
|
raise BuilderError.new("You can't use .on_failure with .checked(:#{decl.checked}) because .on_failure will have no effect.")
|
|
124
124
|
end
|
|
125
125
|
|
|
@@ -222,7 +222,7 @@ module T::Private::Methods
|
|
|
222
222
|
end
|
|
223
223
|
if decl.checked.equal?(ARG_NOT_PROVIDED)
|
|
224
224
|
default_checked_level = T::Private::RuntimeLevels.default_checked_level
|
|
225
|
-
if
|
|
225
|
+
if default_checked_level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
226
226
|
raise BuilderError.new("To use .on_failure you must additionally call .checked(:tests) or .checked(:always), otherwise, the .on_failure has no effect.")
|
|
227
227
|
end
|
|
228
228
|
decl.checked = default_checked_level
|
|
@@ -234,7 +234,7 @@ module T::Private::Methods::SignatureValidation
|
|
|
234
234
|
return if signature.override_allow_incompatible
|
|
235
235
|
return if super_signature.mode == Modes.untyped
|
|
236
236
|
return unless [signature, super_signature].all? do |sig|
|
|
237
|
-
sig.check_level == :always ||
|
|
237
|
+
sig.check_level == :always || (sig.check_level == :tests && T::Private::RuntimeLevels.check_tests?)
|
|
238
238
|
end
|
|
239
239
|
mode_noun = super_signature.mode == Modes.abstract ? 'implementation' : 'override'
|
|
240
240
|
|
|
@@ -12,9 +12,6 @@ module T::Private::RuntimeLevels
|
|
|
12
12
|
# Don't even validate in tests, b/c too expensive,
|
|
13
13
|
# or b/c we fully trust the static typing
|
|
14
14
|
:never,
|
|
15
|
-
# Validate the sig when the file is using the Sorbet Compiler.
|
|
16
|
-
# Behaves like :never when interpreted.
|
|
17
|
-
:compiled,
|
|
18
15
|
].freeze
|
|
19
16
|
|
|
20
17
|
@check_tests = false
|
data/lib/types/private/sealed.rb
CHANGED
|
@@ -5,8 +5,8 @@ module T::Private::Sealed
|
|
|
5
5
|
module NoInherit
|
|
6
6
|
def inherited(child)
|
|
7
7
|
super
|
|
8
|
-
caller_loc = T::Private::CallerUtils.find_caller {|loc|
|
|
9
|
-
T::Private::Sealed.validate_inheritance(caller_loc
|
|
8
|
+
caller_loc = T::Private::CallerUtils.find_caller {|loc| loc.base_label != 'inherited'}
|
|
9
|
+
T::Private::Sealed.validate_inheritance(caller_loc, self, child, 'inherited')
|
|
10
10
|
@sorbet_sealed_module_all_subclasses << child
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -23,14 +23,14 @@ module T::Private::Sealed
|
|
|
23
23
|
def included(child)
|
|
24
24
|
super
|
|
25
25
|
caller_loc = T::Private::CallerUtils.find_caller {|loc| !loc.to_s.match(/in `included'$/)}
|
|
26
|
-
T::Private::Sealed.validate_inheritance(caller_loc
|
|
26
|
+
T::Private::Sealed.validate_inheritance(caller_loc, self, child, 'included')
|
|
27
27
|
@sorbet_sealed_module_all_subclasses << child
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def extended(child)
|
|
31
31
|
super
|
|
32
32
|
caller_loc = T::Private::CallerUtils.find_caller {|loc| !loc.to_s.match(/in `extended'$/)}
|
|
33
|
-
T::Private::Sealed.validate_inheritance(caller_loc
|
|
33
|
+
T::Private::Sealed.validate_inheritance(caller_loc, self, child, 'extended')
|
|
34
34
|
@sorbet_sealed_module_all_subclasses << child
|
|
35
35
|
end
|
|
36
36
|
|
|
@@ -68,8 +68,8 @@ module T::Private::Sealed
|
|
|
68
68
|
mod.instance_variable_defined?(:@sorbet_sealed_module_decl_file)
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
def self.validate_inheritance(
|
|
72
|
-
this_file =
|
|
71
|
+
def self.validate_inheritance(caller_loc, parent, child, verb)
|
|
72
|
+
this_file = caller_loc&.path
|
|
73
73
|
decl_file = parent.instance_variable_get(:@sorbet_sealed_module_decl_file) if sealed_module?(parent)
|
|
74
74
|
|
|
75
75
|
if !this_file
|
data/lib/types/props/_props.rb
CHANGED
|
@@ -110,7 +110,7 @@ module T::Props
|
|
|
110
110
|
#
|
|
111
111
|
# @return [void]
|
|
112
112
|
sig {params(name: Symbol, cls: T.untyped, rules: T.untyped).void}
|
|
113
|
-
def prop(name, cls, rules
|
|
113
|
+
def prop(name, cls, **rules)
|
|
114
114
|
cls = T::Utils.coerce(cls) if !cls.is_a?(Module)
|
|
115
115
|
decorator.prop_defined(name, cls, rules)
|
|
116
116
|
end
|
|
@@ -132,16 +132,16 @@ module T::Props
|
|
|
132
132
|
end
|
|
133
133
|
|
|
134
134
|
# Shorthand helper to define a `prop` with `immutable => true`
|
|
135
|
-
sig {params(name: Symbol, cls_or_args: T.untyped, args: T
|
|
136
|
-
def const(name, cls_or_args, args
|
|
135
|
+
sig {params(name: Symbol, cls_or_args: T.untyped, args: T.untyped).void}
|
|
136
|
+
def const(name, cls_or_args, **args)
|
|
137
137
|
if (cls_or_args.is_a?(Hash) && cls_or_args.key?(:immutable)) || args.key?(:immutable)
|
|
138
138
|
Kernel.raise ArgumentError.new("Cannot pass 'immutable' argument when using 'const' keyword to define a prop")
|
|
139
139
|
end
|
|
140
140
|
|
|
141
141
|
if cls_or_args.is_a?(Hash)
|
|
142
|
-
self.prop(name, cls_or_args.merge(immutable: true))
|
|
142
|
+
self.prop(name, **cls_or_args.merge(immutable: true))
|
|
143
143
|
else
|
|
144
|
-
self.prop(name, cls_or_args, args.merge(immutable: true))
|
|
144
|
+
self.prop(name, cls_or_args, **args.merge(immutable: true))
|
|
145
145
|
end
|
|
146
146
|
end
|
|
147
147
|
|
|
@@ -430,7 +430,7 @@ class T::Props::Decorator
|
|
|
430
430
|
else
|
|
431
431
|
nonnil_type = T::Utils.unwrap_nilable(type)
|
|
432
432
|
if nonnil_type
|
|
433
|
-
T.unsafe(T.nilable(T.all(nonnil_type, T.deprecated_enum(enum))))
|
|
433
|
+
T.unsafe(T.nilable(T.all(T.unsafe(nonnil_type), T.deprecated_enum(enum))))
|
|
434
434
|
else
|
|
435
435
|
T.unsafe(T.all(T.unsafe(type), T.deprecated_enum(enum)))
|
|
436
436
|
end
|
|
@@ -7,13 +7,13 @@ module T::Props::PrettyPrintable
|
|
|
7
7
|
|
|
8
8
|
# Override the PP gem with something that's similar, but gives us a hook to do redaction and customization
|
|
9
9
|
def pretty_print(pp)
|
|
10
|
-
|
|
10
|
+
klass = T.unsafe(T.cast(self, Object).class).decorator
|
|
11
11
|
multiline = pp.is_a?(PP)
|
|
12
|
-
pp.group(1, "<#{
|
|
13
|
-
|
|
12
|
+
pp.group(1, "<#{klass.inspect_class_with_decoration(self)}", ">") do
|
|
13
|
+
klass.all_props.sort.each do |prop|
|
|
14
14
|
pp.breakable
|
|
15
|
-
val =
|
|
16
|
-
rules =
|
|
15
|
+
val = klass.get(self, prop)
|
|
16
|
+
rules = klass.prop_rules(prop)
|
|
17
17
|
pp.text("#{prop}=")
|
|
18
18
|
if (custom_inspect = rules[:inspect])
|
|
19
19
|
inspected = if T::Utils.arity(custom_inspect) == 1
|
|
@@ -28,7 +28,7 @@ module T::Props::PrettyPrintable
|
|
|
28
28
|
val.pretty_print(pp)
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
|
-
|
|
31
|
+
klass.pretty_print_extra(self, pp)
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -261,15 +261,30 @@ module T::Props::Serializable::DecoratorMethods
|
|
|
261
261
|
end
|
|
262
262
|
|
|
263
263
|
def message_with_generated_source_context(error, generated_method, generate_source_method)
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
generated_method = generated_method.to_s
|
|
265
|
+
if error.backtrace_locations
|
|
266
|
+
line_loc = error.backtrace_locations.find {|l| l.base_label == generated_method}
|
|
267
|
+
return unless line_loc
|
|
266
268
|
|
|
267
|
-
|
|
268
|
-
# (eval):13:in `__t_props_generated_serialize'
|
|
269
|
-
line_label.split(':')[1]&.to_i
|
|
269
|
+
line_num = line_loc.lineno
|
|
270
270
|
else
|
|
271
|
-
|
|
272
|
-
|
|
271
|
+
label = if RUBY_VERSION >= "3.4"
|
|
272
|
+
# in 'ClassName#__t_props_generated_serialize'"
|
|
273
|
+
"##{generated_method}'"
|
|
274
|
+
else
|
|
275
|
+
# in `__t_props_generated_serialize'"
|
|
276
|
+
"in `#{generated_method}'"
|
|
277
|
+
end
|
|
278
|
+
line_label = error.backtrace.find {|l| l.end_with?(label)}
|
|
279
|
+
return unless line_label
|
|
280
|
+
|
|
281
|
+
line_num = if line_label.start_with?("(eval)")
|
|
282
|
+
# (eval):13:in ...
|
|
283
|
+
line_label.split(':')[1]&.to_i
|
|
284
|
+
else
|
|
285
|
+
# (eval at /Users/jez/stripe/sorbet/gems/sorbet-runtime/lib/types/props/has_lazily_specialized_methods.rb:65):13:in ...
|
|
286
|
+
line_label.split(':')[2]&.to_i
|
|
287
|
+
end
|
|
273
288
|
end
|
|
274
289
|
return unless line_num
|
|
275
290
|
|
data/lib/types/struct.rb
CHANGED
|
@@ -39,7 +39,7 @@ class T::ImmutableStruct < T::InexactStruct
|
|
|
39
39
|
|
|
40
40
|
# Matches the signature in Props, but raises since this is an immutable struct and only const is allowed
|
|
41
41
|
sig {params(name: Symbol, cls: T.untyped, rules: T.untyped).void}
|
|
42
|
-
def self.prop(name, cls, rules
|
|
42
|
+
def self.prop(name, cls, **rules)
|
|
43
43
|
return super if (cls.is_a?(Hash) && cls[:immutable]) || rules[:immutable]
|
|
44
44
|
|
|
45
45
|
raise "Cannot use `prop` in #{self.name} because it is an immutable struct. Use `const` instead"
|
data/lib/types/types/base.rb
CHANGED
|
@@ -21,7 +21,7 @@ module T::Types
|
|
|
21
21
|
valid?(obj)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
define_method(:valid?) do |_obj|
|
|
25
25
|
raise NotImplementedError
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -35,12 +35,12 @@ module T::Types
|
|
|
35
35
|
|
|
36
36
|
# Force any lazy initialization that this type might need to do
|
|
37
37
|
# It's unusual to call this directly; you probably want to call it indirectly via `T::Utils.run_all_sig_blocks`.
|
|
38
|
-
|
|
38
|
+
define_method(:build_type) do
|
|
39
39
|
raise NotImplementedError
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
# Equality is based on name, so be sure the name reflects all relevant state when implementing.
|
|
43
|
-
|
|
43
|
+
define_method(:name) do
|
|
44
44
|
raise NotImplementedError
|
|
45
45
|
end
|
|
46
46
|
|
data/lib/types/types/class_of.rb
CHANGED
|
@@ -21,7 +21,7 @@ module T::Types
|
|
|
21
21
|
|
|
22
22
|
# overrides Base
|
|
23
23
|
def valid?(obj)
|
|
24
|
-
obj.is_a?(Module) && obj <= @type
|
|
24
|
+
obj.is_a?(Module) && (obj <= @type || false)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
# overrides Base
|
|
@@ -32,7 +32,7 @@ module T::Types
|
|
|
32
32
|
when Simple
|
|
33
33
|
@type.is_a?(other.raw_type)
|
|
34
34
|
when TypedClass
|
|
35
|
-
|
|
35
|
+
@type.is_a?(other.underlying_class)
|
|
36
36
|
else
|
|
37
37
|
false
|
|
38
38
|
end
|
data/lib/types/types/enum.rb
CHANGED
data/lib/types/types/proc.rb
CHANGED
|
@@ -47,11 +47,10 @@ module T::Types
|
|
|
47
47
|
true
|
|
48
48
|
end
|
|
49
49
|
when Hash
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
key_type
|
|
54
|
-
value_type = types[1]
|
|
50
|
+
type_ = self.type
|
|
51
|
+
return false unless type_.is_a?(FixedArray)
|
|
52
|
+
key_type, value_type = type_.types
|
|
53
|
+
return false if key_type.nil? || value_type.nil? || type_.types.size > 2
|
|
55
54
|
obj.each_pair do |key, val|
|
|
56
55
|
# Some objects (I'm looking at you Rack::Utils::HeaderHash) don't
|
|
57
56
|
# iterate over a [key, value] array, so we can't just use the type.recursively_valid?(v)
|
|
@@ -179,7 +178,7 @@ module T::Types
|
|
|
179
178
|
|
|
180
179
|
class Untyped < TypedEnumerable
|
|
181
180
|
def initialize
|
|
182
|
-
super(T
|
|
181
|
+
super(T::Types::Untyped::Private::INSTANCE)
|
|
183
182
|
end
|
|
184
183
|
|
|
185
184
|
def valid?(obj)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
module T::Types
|
|
5
5
|
class TypedSet < TypedEnumerable
|
|
6
6
|
def underlying_class
|
|
7
|
-
|
|
7
|
+
Set
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
# overrides Base
|
|
@@ -37,7 +37,7 @@ module T::Types
|
|
|
37
37
|
|
|
38
38
|
class Untyped < TypedSet
|
|
39
39
|
def initialize
|
|
40
|
-
super(T
|
|
40
|
+
super(T::Types::Untyped::Private::INSTANCE)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def valid?(obj)
|
data/lib/types/utils.rb
CHANGED
|
@@ -155,7 +155,7 @@ module T::Utils
|
|
|
155
155
|
raise ArgumentError.new("#{enum.inspect} is not a T.deprecated_enum")
|
|
156
156
|
end
|
|
157
157
|
|
|
158
|
-
classes = enum.values.map(&:class).uniq
|
|
158
|
+
classes = T.unsafe(enum.values).map(&:class).uniq
|
|
159
159
|
if classes.empty?
|
|
160
160
|
T.untyped
|
|
161
161
|
elsif classes.length > 1
|
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.5.
|
|
4
|
+
version: 0.5.11647
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stripe
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-
|
|
11
|
+
date: 2024-11-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|
|
@@ -94,6 +94,20 @@ dependencies:
|
|
|
94
94
|
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
96
|
version: 1.1.5
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: debug
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
97
111
|
- !ruby/object:Gem::Dependency
|
|
98
112
|
name: pry
|
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -159,7 +173,6 @@ files:
|
|
|
159
173
|
- lib/types/private/caller_utils.rb
|
|
160
174
|
- lib/types/private/casts.rb
|
|
161
175
|
- lib/types/private/class_utils.rb
|
|
162
|
-
- lib/types/private/compiler.rb
|
|
163
176
|
- lib/types/private/decl_state.rb
|
|
164
177
|
- lib/types/private/final.rb
|
|
165
178
|
- lib/types/private/methods/_methods.rb
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
# typed: true
|
|
3
|
-
|
|
4
|
-
module T::Private
|
|
5
|
-
module Compiler
|
|
6
|
-
# If this code ever runs, the caller is running interpreted (or the
|
|
7
|
-
# compiler didn't see the call to `running_compiled?` statically.)
|
|
8
|
-
#
|
|
9
|
-
# The Sorbet Compiler replaces calls to this method unconditionally (no
|
|
10
|
-
# runtime guards) to return `true` when compiling a file.
|
|
11
|
-
def self.running_compiled?
|
|
12
|
-
false
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
# Returns `nil` because the compiler isn't running.
|
|
16
|
-
#
|
|
17
|
-
# The Sorbet Compiler replaces calls to this method unconditionally (no
|
|
18
|
-
# runtime guards) to return a String showing the Sorbet Compiler's version
|
|
19
|
-
# string.
|
|
20
|
-
def self.compiler_version
|
|
21
|
-
nil
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|