sorbet-runtime 0.6.12872 → 0.6.13192
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/types/helpers.rb +0 -2
- data/lib/types/private/abstract/hooks.rb +1 -1
- data/lib/types/private/class_utils.rb +22 -69
- data/lib/types/private/methods/_methods.rb +38 -34
- data/lib/types/private/methods/call_validation.rb +43 -21
- data/lib/types/private/methods/call_validation_2_7.rb +32 -32
- data/lib/types/private/methods/decl_builder.rb +11 -13
- data/lib/types/private/methods/signature.rb +18 -19
- data/lib/types/private/methods/signature_validation.rb +22 -31
- data/lib/types/struct.rb +4 -2
- metadata +16 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf43d3cf4e297c8c2c814618b558777e99dad15ee9fdedaf1275adac6303b1ab
|
|
4
|
+
data.tar.gz: 9b454b18a90066a60aef190a683699dae158bf6e0d42be29b4314e3e5a28a072
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b5e5e921d5a506dabd5fe96e434a73723ec8105ac8f4d554379f2e82f265e965dfbeed04b04b1875f8f35520467bb35d41f8baf8dc6558d07068e1ece3f55af6
|
|
7
|
+
data.tar.gz: 145f14e022976650ccbed8a8abe9398970d687759833650185156e4e4156d91b7fd7b54ade90a86c7be2a916b608880ae739d1d8473e629c29714c1330a33b6b
|
data/lib/types/helpers.rb
CHANGED
|
@@ -27,7 +27,7 @@ module T::Private::Abstract::Hooks
|
|
|
27
27
|
# `self` may not actually be abstract -- it could be a concrete class that inherited from an
|
|
28
28
|
# abstract class. We only need to check this in `inherited` because, for modules being included
|
|
29
29
|
# or extended, the concrete ones won't have these hooks at all. This is just an optimization.
|
|
30
|
-
return if !T::AbstractUtils.abstract_module?(self)
|
|
30
|
+
return if !T::AbstractUtils.abstract_module?(T.unsafe(self))
|
|
31
31
|
|
|
32
32
|
T::Private::Abstract::Data.set(self, :last_used_by, other)
|
|
33
33
|
end
|
|
@@ -3,61 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
# Cut down version of Chalk::Tools::ClassUtils with only :replace_method functionality.
|
|
5
5
|
# Extracted to a separate namespace so the type system can be used standalone.
|
|
6
|
+
#
|
|
7
|
+
# Note: the functionality to "restore" a method was removed, because it is no
|
|
8
|
+
# longer being used by sorbet-runtime. Restoring a method requires care--if you
|
|
9
|
+
# need to reintroduce this functionality, consult the git history for how to do
|
|
10
|
+
# it safely.
|
|
6
11
|
module T::Private::ClassUtils
|
|
7
|
-
class ReplacedMethod
|
|
8
|
-
def initialize(mod, old_method, new_method, overwritten, visibility)
|
|
9
|
-
if old_method.name != new_method.name
|
|
10
|
-
raise "Method names must match. old=#{old_method.name} new=#{new_method.name}"
|
|
11
|
-
end
|
|
12
|
-
@mod = mod
|
|
13
|
-
@old_method = old_method
|
|
14
|
-
@new_method = new_method
|
|
15
|
-
@overwritten = overwritten
|
|
16
|
-
@name = old_method.name
|
|
17
|
-
@visibility = visibility
|
|
18
|
-
@restored = false
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def restore
|
|
22
|
-
# The check below would also catch this, but this makes the failure mode much clearer
|
|
23
|
-
if @restored
|
|
24
|
-
raise "Method '#{@name}' on '#{@mod}' was already restored"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
if @mod.instance_method(@name) != @new_method
|
|
28
|
-
raise "Trying to restore #{@mod}##{@name} but the method has changed since the call to replace_method"
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
@restored = true
|
|
32
|
-
|
|
33
|
-
if @overwritten
|
|
34
|
-
# The original method was overwritten. Overwrite again to restore it.
|
|
35
|
-
T::Configuration.without_ruby_warnings do
|
|
36
|
-
@mod.send(:define_method, @old_method.name, @old_method)
|
|
37
|
-
end
|
|
38
|
-
else
|
|
39
|
-
# The original method was in an ancestor. Restore it by removing the overriding method.
|
|
40
|
-
@mod.send(:remove_method, @old_method.name)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Restore the visibility. Note that we need to do this even when we call remove_method
|
|
44
|
-
# above, because the module may have set custom visibility for a method it inherited.
|
|
45
|
-
@mod.send(@visibility, @old_method.name)
|
|
46
|
-
|
|
47
|
-
nil
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def bind(obj)
|
|
51
|
-
@old_method.bind(obj)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def to_s
|
|
55
|
-
@old_method.to_s
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
12
|
# `name` must be an instance method (for class methods, pass in mod.singleton_class)
|
|
60
|
-
|
|
13
|
+
def self.visibility_method_name(mod, name)
|
|
61
14
|
if mod.public_method_defined?(name)
|
|
62
15
|
:public
|
|
63
16
|
elsif mod.protected_method_defined?(name)
|
|
@@ -65,7 +18,10 @@ module T::Private::ClassUtils
|
|
|
65
18
|
elsif mod.private_method_defined?(name)
|
|
66
19
|
:private
|
|
67
20
|
else
|
|
68
|
-
|
|
21
|
+
# Raises a NameError formatted like the Ruby VM would (the exact text formatting
|
|
22
|
+
# of these errors changed across Ruby VM versions, in ways that would sometimes
|
|
23
|
+
# cause tests to fail if they were dependent on hard coding errors).
|
|
24
|
+
mod.method(name)
|
|
69
25
|
end
|
|
70
26
|
end
|
|
71
27
|
|
|
@@ -90,15 +46,18 @@ module T::Private::ClassUtils
|
|
|
90
46
|
end
|
|
91
47
|
end
|
|
92
48
|
|
|
93
|
-
# Replaces a method, either by overwriting it (if it is defined directly on
|
|
94
|
-
# overriding it (if it is defined by one of mod's ancestors).
|
|
95
|
-
#
|
|
96
|
-
#
|
|
97
|
-
#
|
|
49
|
+
# Replaces a method, either by overwriting it (if it is defined directly on
|
|
50
|
+
# `mod`) or by overriding it (if it is defined by one of mod's ancestors).
|
|
51
|
+
#
|
|
52
|
+
# Takes the `original_method` as a parameter, so it does not return anything.
|
|
53
|
+
#
|
|
54
|
+
# Can also avoid `T.let` pinning errors by letting the caller pre-compute the
|
|
55
|
+
# `original_method`, so it knows that it will always be defined (because it
|
|
56
|
+
# doesn't know that the block will always run once)
|
|
98
57
|
#
|
|
99
|
-
#
|
|
100
|
-
|
|
101
|
-
|
|
58
|
+
# Does not share code with `replace_method_with_handle`, for performance (do
|
|
59
|
+
# not want to increase the call stack, as this is a very sensitive code path).
|
|
60
|
+
def self.replace_method(original_method, mod, name, &blk)
|
|
102
61
|
original_visibility = visibility_method_name(mod, name)
|
|
103
62
|
original_owner = original_method.owner
|
|
104
63
|
|
|
@@ -117,18 +76,12 @@ module T::Private::ClassUtils
|
|
|
117
76
|
end
|
|
118
77
|
end
|
|
119
78
|
|
|
120
|
-
overwritten = original_owner == mod
|
|
121
79
|
T::Configuration.without_ruby_warnings do
|
|
122
80
|
T::Private::DeclState.current.without_on_method_added do
|
|
123
81
|
def_with_visibility(mod, name, original_visibility, &blk)
|
|
124
82
|
end
|
|
125
83
|
end
|
|
126
84
|
|
|
127
|
-
|
|
128
|
-
original_method
|
|
129
|
-
else
|
|
130
|
-
new_method = mod.instance_method(name)
|
|
131
|
-
ReplacedMethod.new(mod, original_method, new_method, overwritten, original_visibility)
|
|
132
|
-
end
|
|
85
|
+
nil
|
|
133
86
|
end
|
|
134
87
|
end
|
|
@@ -34,7 +34,13 @@ module T::Private::Methods
|
|
|
34
34
|
ARG_NOT_PROVIDED = Object.new
|
|
35
35
|
PROC_TYPE = Object.new
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
# blk_or_decl:
|
|
38
|
+
# - It's a `Proc` if we haven't forced the thunk yet.
|
|
39
|
+
# - It's a `Declaration` if we have, but we haven't finished building the sig
|
|
40
|
+
# (This can matter for circular load-time behavior, where a method is
|
|
41
|
+
# called while its Signature is being built)
|
|
42
|
+
# - It's `nil` if we've finished building the sig
|
|
43
|
+
DeclarationBlock = Struct.new(:mod, :loc, :blk_or_decl, :final, :raw)
|
|
38
44
|
|
|
39
45
|
def self.declare_sig(mod, loc, arg, &blk)
|
|
40
46
|
T::Private::DeclState.current.active_declaration = _declare_sig_internal(mod, loc, arg, &blk)
|
|
@@ -236,7 +242,7 @@ module T::Private::Methods
|
|
|
236
242
|
# (or unwrap back to the original method).
|
|
237
243
|
key = method_owner_and_name_to_key(mod, method_name)
|
|
238
244
|
unless current_declaration.raw
|
|
239
|
-
T::Private::ClassUtils.replace_method(mod, method_name
|
|
245
|
+
T::Private::ClassUtils.replace_method(original_method, mod, method_name) do |*args, &blk|
|
|
240
246
|
method_sig = T::Private::Methods.maybe_run_sig_block_for_key(key)
|
|
241
247
|
method_sig ||= T::Private::Methods._handle_missing_method_signature(
|
|
242
248
|
self,
|
|
@@ -321,6 +327,7 @@ module T::Private::Methods
|
|
|
321
327
|
nil
|
|
322
328
|
end
|
|
323
329
|
|
|
330
|
+
# Release location information sooner
|
|
324
331
|
declaration_block.loc = nil
|
|
325
332
|
|
|
326
333
|
signature =
|
|
@@ -331,15 +338,28 @@ module T::Private::Methods
|
|
|
331
338
|
end
|
|
332
339
|
|
|
333
340
|
unwrap_method(signature.method.owner, signature, original_method)
|
|
341
|
+
|
|
342
|
+
# Drop this declaration. Only drop it after we've actually wrapped the
|
|
343
|
+
# method and recorded the signature, because that might raise an exception,
|
|
344
|
+
# leaving the declaration in a weird state if the program rescues that
|
|
345
|
+
# exception and continues.
|
|
346
|
+
declaration_block.blk_or_decl = nil
|
|
347
|
+
|
|
334
348
|
signature
|
|
335
349
|
end
|
|
336
350
|
|
|
337
351
|
def self.run_builder(declaration_block)
|
|
352
|
+
blk_or_decl = declaration_block.blk_or_decl
|
|
353
|
+
return blk_or_decl if blk_or_decl.is_a?(Declaration)
|
|
354
|
+
if blk_or_decl.nil?
|
|
355
|
+
raise "DeclarationBlock for #{declaration_block.mod} at #{declaration_block.loc} should have already been unwrapped"
|
|
356
|
+
end
|
|
357
|
+
|
|
338
358
|
builder = DeclBuilder.new(declaration_block.mod, declaration_block.raw)
|
|
339
|
-
builder
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
359
|
+
decl = builder.instance_exec(&blk_or_decl).finalize!.decl
|
|
360
|
+
# Record that we've already run `blk` once and constructed a `Declaration`
|
|
361
|
+
declaration_block.blk_or_decl = decl
|
|
362
|
+
decl
|
|
343
363
|
end
|
|
344
364
|
|
|
345
365
|
def self.build_sig(hook_mod, method_name, original_method, current_declaration)
|
|
@@ -400,7 +420,7 @@ module T::Private::Methods
|
|
|
400
420
|
@signatures_by_method[key]
|
|
401
421
|
end
|
|
402
422
|
|
|
403
|
-
def self.unwrap_method(mod, signature, original_method)
|
|
423
|
+
private_class_method def self.unwrap_method(mod, signature, original_method)
|
|
404
424
|
maybe_wrapped_method = CallValidation.wrap_method_if_needed(mod, signature, original_method)
|
|
405
425
|
@signatures_by_method[method_to_key(maybe_wrapped_method)] = signature
|
|
406
426
|
end
|
|
@@ -439,12 +459,6 @@ module T::Private::Methods
|
|
|
439
459
|
method_owner_and_name_to_key(method.owner, method.name)
|
|
440
460
|
end
|
|
441
461
|
|
|
442
|
-
private_class_method def self.key_to_method(key)
|
|
443
|
-
id, name = key.split("#")
|
|
444
|
-
obj = ObjectSpace._id2ref(id.to_i)
|
|
445
|
-
obj.instance_method(name)
|
|
446
|
-
end
|
|
447
|
-
|
|
448
462
|
private_class_method def self.run_sig_block_for_key(key, force_type_init: false)
|
|
449
463
|
blk = @sig_wrappers[key]
|
|
450
464
|
if !blk
|
|
@@ -453,7 +467,7 @@ module T::Private::Methods
|
|
|
453
467
|
# We already ran the sig block, perhaps in another thread.
|
|
454
468
|
return sig
|
|
455
469
|
else
|
|
456
|
-
raise "No `sig` wrapper for #{
|
|
470
|
+
raise "No `sig` wrapper for #{key}. This is likely a bug in sorbet-runtime. If you can reproduce, please report an issue."
|
|
457
471
|
end
|
|
458
472
|
end
|
|
459
473
|
|
|
@@ -464,7 +478,7 @@ module T::Private::Methods
|
|
|
464
478
|
raise
|
|
465
479
|
end
|
|
466
480
|
if @sigs_that_raised[key]
|
|
467
|
-
raise "A previous invocation of #{
|
|
481
|
+
raise "A previous invocation of #{sig.method_desc} raised, and the current one succeeded. Please don't do that."
|
|
468
482
|
end
|
|
469
483
|
|
|
470
484
|
@sig_wrappers.delete(key)
|
|
@@ -527,15 +541,21 @@ module T::Private::Methods
|
|
|
527
541
|
end
|
|
528
542
|
@old_hooks = nil
|
|
529
543
|
else
|
|
530
|
-
|
|
544
|
+
# Grab the original methods before replacing them, so that each block
|
|
545
|
+
# closure can reference a variable that is already assigned.
|
|
546
|
+
# (Do this directly, to avoid pinning errors)
|
|
547
|
+
old_included = Module.instance_method(:included)
|
|
548
|
+
T::Private::ClassUtils.replace_method(old_included, Module, :included) do |arg|
|
|
531
549
|
old_included.bind_call(self, arg)
|
|
532
550
|
::T::Private::Methods._hook_impl(arg, false, self)
|
|
533
551
|
end
|
|
534
|
-
old_extended =
|
|
552
|
+
old_extended = Module.instance_method(:extended)
|
|
553
|
+
T::Private::ClassUtils.replace_method(old_extended, Module, :extended) do |arg|
|
|
535
554
|
old_extended.bind_call(self, arg)
|
|
536
555
|
::T::Private::Methods._hook_impl(arg, true, self)
|
|
537
556
|
end
|
|
538
|
-
old_inherited =
|
|
557
|
+
old_inherited = Class.instance_method(:inherited)
|
|
558
|
+
T::Private::ClassUtils.replace_method(old_inherited, Class, :inherited) do |arg|
|
|
539
559
|
old_inherited.bind_call(self, arg)
|
|
540
560
|
::T::Private::Methods._hook_impl(arg, false, self)
|
|
541
561
|
end
|
|
@@ -588,22 +608,6 @@ module T::Private::Methods
|
|
|
588
608
|
end
|
|
589
609
|
mod.extend(SingletonMethodHooks)
|
|
590
610
|
end
|
|
591
|
-
|
|
592
|
-
# `name` must be an instance method (for class methods, pass in mod.singleton_class)
|
|
593
|
-
def self.visibility_method_name(mod, name)
|
|
594
|
-
if mod.public_method_defined?(name)
|
|
595
|
-
:public
|
|
596
|
-
elsif mod.protected_method_defined?(name)
|
|
597
|
-
:protected
|
|
598
|
-
elsif mod.private_method_defined?(name)
|
|
599
|
-
:private
|
|
600
|
-
else
|
|
601
|
-
# Raises a NameError formatted like the Ruby VM would (the exact text formatting
|
|
602
|
-
# of these errors changed across Ruby VM versions, in ways that would sometimes
|
|
603
|
-
# cause tests to fail if they were dependent on hard coding errors).
|
|
604
|
-
mod.method(name)
|
|
605
|
-
end
|
|
606
|
-
end
|
|
607
611
|
end
|
|
608
612
|
|
|
609
613
|
# This has to be here, and can't be nested inside `T::Private::Methods`,
|
|
@@ -5,6 +5,10 @@ module T::Private::Methods::CallValidation
|
|
|
5
5
|
CallValidation = T::Private::Methods::CallValidation
|
|
6
6
|
Modes = T::Private::Methods::Modes
|
|
7
7
|
|
|
8
|
+
KERNEL_TO_S = Kernel.instance_method(:to_s)
|
|
9
|
+
MODULE_TO_S = Module.instance_method(:to_s)
|
|
10
|
+
private_constant(:KERNEL_TO_S, :MODULE_TO_S)
|
|
11
|
+
|
|
8
12
|
# Wraps a method with a layer of validation for the given type signature.
|
|
9
13
|
# This wrapper is meant to be fast, and is applied by a previous wrapper,
|
|
10
14
|
# which was placed by `_on_method_added`.
|
|
@@ -12,7 +16,7 @@ module T::Private::Methods::CallValidation
|
|
|
12
16
|
# @param method_sig [T::Private::Methods::Signature]
|
|
13
17
|
# @return [UnboundMethod] the new wrapper method (or the original one if we didn't wrap it)
|
|
14
18
|
def self.wrap_method_if_needed(mod, method_sig, original_method)
|
|
15
|
-
original_visibility = T::Private::
|
|
19
|
+
original_visibility = T::Private::ClassUtils.visibility_method_name(mod, method_sig.method_name)
|
|
16
20
|
if method_sig.mode == T::Private::Methods::Modes.abstract
|
|
17
21
|
create_abstract_wrapper(mod, method_sig, original_method, original_visibility)
|
|
18
22
|
# Do nothing in this case; this method was not wrapped in _on_method_added.
|
|
@@ -68,24 +72,32 @@ module T::Private::Methods::CallValidation
|
|
|
68
72
|
end
|
|
69
73
|
|
|
70
74
|
def self.create_validator_method(mod, original_method, method_sig, original_visibility)
|
|
71
|
-
has_fixed_arity = method_sig.kwarg_types.empty? &&
|
|
75
|
+
has_fixed_arity = method_sig.kwarg_types.empty? && method_sig.rest_type.nil? && method_sig.keyrest_type.nil? &&
|
|
72
76
|
original_method.parameters.all? { |(kind, _name)| kind == :req || kind == :block }
|
|
73
|
-
|
|
77
|
+
|
|
78
|
+
# nil implies block_type.nil?
|
|
79
|
+
# true implies !block_type.nil? and block_type.valid?(nil)
|
|
80
|
+
# false implies !block_type.nil? and !block_type.valid?(nil)
|
|
81
|
+
# This formulation avoids a type error without introducing extra method calls or local vars
|
|
82
|
+
can_skip_block_type = method_sig.block_type&.valid?(nil) != false
|
|
83
|
+
|
|
74
84
|
ok_for_fast_path = has_fixed_arity && can_skip_block_type && !method_sig.bind && method_sig.arg_types.length < 5 && is_allowed_to_have_fast_path
|
|
75
85
|
|
|
76
86
|
all_args_are_simple = ok_for_fast_path && method_sig.arg_types.all? { |_name, type| type.is_a?(T::Types::Simple) }
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
|
|
88
|
+
effective_return_type = method_sig.effective_return_type
|
|
89
|
+
simple_method = all_args_are_simple && effective_return_type.is_a?(T::Types::Simple)
|
|
90
|
+
simple_procedure = all_args_are_simple && effective_return_type.is_a?(T::Private::Types::Void)
|
|
79
91
|
|
|
80
92
|
# All the types for which valid? unconditionally returns `true`
|
|
81
93
|
return_is_ignorable =
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
(
|
|
94
|
+
effective_return_type.equal?(T::Types::Untyped::Private::INSTANCE) ||
|
|
95
|
+
effective_return_type.equal?(T::Types::Anything::Private::INSTANCE) ||
|
|
96
|
+
effective_return_type.equal?(T::Types::AttachedClassType::Private::INSTANCE) ||
|
|
97
|
+
effective_return_type.equal?(T::Types::SelfType::Private::INSTANCE) ||
|
|
98
|
+
effective_return_type.is_a?(T::Types::TypeParameter) ||
|
|
99
|
+
effective_return_type.is_a?(T::Types::TypeVariable) ||
|
|
100
|
+
(effective_return_type.is_a?(T::Types::Simple) && effective_return_type.raw_type.equal?(BasicObject))
|
|
89
101
|
|
|
90
102
|
returns_anything_method = all_args_are_simple && return_is_ignorable
|
|
91
103
|
|
|
@@ -97,7 +109,7 @@ module T::Private::Methods::CallValidation
|
|
|
97
109
|
create_validator_method_skip_return_fast(mod, original_method, method_sig, original_visibility)
|
|
98
110
|
elsif simple_procedure
|
|
99
111
|
create_validator_procedure_fast(mod, original_method, method_sig, original_visibility)
|
|
100
|
-
elsif ok_for_fast_path &&
|
|
112
|
+
elsif ok_for_fast_path && effective_return_type.is_a?(T::Private::Types::Void)
|
|
101
113
|
create_validator_procedure_medium(mod, original_method, method_sig, original_visibility)
|
|
102
114
|
elsif ok_for_fast_path && return_is_ignorable
|
|
103
115
|
create_validator_method_skip_return_medium(mod, original_method, method_sig, original_visibility)
|
|
@@ -180,17 +192,17 @@ module T::Private::Methods::CallValidation
|
|
|
180
192
|
|
|
181
193
|
# The only type that is allowed to change the return value is `.void`.
|
|
182
194
|
# It ignores what you returned and changes it to be a private singleton.
|
|
183
|
-
if method_sig.
|
|
195
|
+
if method_sig.effective_return_type.is_a?(T::Private::Types::Void)
|
|
184
196
|
T::Private::Types::Void::VOID
|
|
185
197
|
else
|
|
186
|
-
message = method_sig.
|
|
198
|
+
message = method_sig.effective_return_type.error_message_for_obj(return_value)
|
|
187
199
|
if message
|
|
188
200
|
CallValidation.report_error(
|
|
189
201
|
method_sig,
|
|
190
202
|
message,
|
|
191
203
|
'Return value',
|
|
192
204
|
nil,
|
|
193
|
-
method_sig.
|
|
205
|
+
method_sig.effective_return_type,
|
|
194
206
|
return_value,
|
|
195
207
|
)
|
|
196
208
|
end
|
|
@@ -283,17 +295,17 @@ module T::Private::Methods::CallValidation
|
|
|
283
295
|
|
|
284
296
|
# The only type that is allowed to change the return value is `.void`.
|
|
285
297
|
# It ignores what you returned and changes it to be a private singleton.
|
|
286
|
-
if method_sig.
|
|
298
|
+
if method_sig.effective_return_type.is_a?(T::Private::Types::Void)
|
|
287
299
|
T::Private::Types::Void::VOID
|
|
288
300
|
else
|
|
289
|
-
message = method_sig.
|
|
301
|
+
message = method_sig.effective_return_type.error_message_for_obj(return_value)
|
|
290
302
|
if message
|
|
291
303
|
CallValidation.report_error(
|
|
292
304
|
method_sig,
|
|
293
305
|
message,
|
|
294
306
|
'Return value',
|
|
295
307
|
nil,
|
|
296
|
-
method_sig.
|
|
308
|
+
method_sig.effective_return_type,
|
|
297
309
|
return_value,
|
|
298
310
|
)
|
|
299
311
|
end
|
|
@@ -301,6 +313,16 @@ module T::Private::Methods::CallValidation
|
|
|
301
313
|
end
|
|
302
314
|
end
|
|
303
315
|
|
|
316
|
+
# Get the name of a method owner via its `.to_s`, but fallback if its implementation raises or returns `nil`.
|
|
317
|
+
private_class_method def self.safe_method_owner_to_s(method_owner)
|
|
318
|
+
case method_owner
|
|
319
|
+
when Module # methods are usually owned by a Class or Module...
|
|
320
|
+
MODULE_TO_S.bind_call(method_owner)
|
|
321
|
+
else # ... but could be a singleton method on any kind of Object.
|
|
322
|
+
KERNEL_TO_S.bind_call(method_owner)
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
304
326
|
def self.report_error(method_sig, error_message, kind, name, type, value, caller_offset: 0)
|
|
305
327
|
caller_loc = T.must(caller_locations(3 + caller_offset, 1))[0]
|
|
306
328
|
method = method_sig.method
|
|
@@ -310,9 +332,9 @@ module T::Private::Methods::CallValidation
|
|
|
310
332
|
pretty_method_name =
|
|
311
333
|
if owner.singleton_class? && owner.respond_to?(:attached_object)
|
|
312
334
|
# attached_object is new in Ruby 3.2
|
|
313
|
-
"#{owner.attached_object}.#{method.name}"
|
|
335
|
+
"#{safe_method_owner_to_s(owner.attached_object)}.#{method.name}"
|
|
314
336
|
else
|
|
315
|
-
"#{owner}##{method.name}"
|
|
337
|
+
"#{safe_method_owner_to_s(owner)}##{method.name}"
|
|
316
338
|
end
|
|
317
339
|
|
|
318
340
|
pretty_message = "#{kind}#{name ? " '#{name}'" : ''}: #{error_message}\n" \
|
|
@@ -7,28 +7,28 @@
|
|
|
7
7
|
|
|
8
8
|
module T::Private::Methods::CallValidation
|
|
9
9
|
def self.create_validator_method_fast(mod, original_method, method_sig, original_visibility)
|
|
10
|
-
if method_sig.
|
|
10
|
+
if method_sig.effective_return_type.is_a?(T::Private::Types::Void)
|
|
11
11
|
raise 'Should have used create_validator_procedure_fast'
|
|
12
12
|
end
|
|
13
13
|
# trampoline to reduce stack frame size
|
|
14
14
|
arg_types = method_sig.arg_types
|
|
15
15
|
case arg_types.length
|
|
16
16
|
when 0
|
|
17
|
-
create_validator_method_fast0(mod, original_method, method_sig, original_visibility, method_sig.
|
|
17
|
+
create_validator_method_fast0(mod, original_method, method_sig, original_visibility, method_sig.effective_return_type.raw_type)
|
|
18
18
|
when 1
|
|
19
|
-
create_validator_method_fast1(mod, original_method, method_sig, original_visibility, method_sig.
|
|
19
|
+
create_validator_method_fast1(mod, original_method, method_sig, original_visibility, method_sig.effective_return_type.raw_type,
|
|
20
20
|
arg_types[0][1].raw_type)
|
|
21
21
|
when 2
|
|
22
|
-
create_validator_method_fast2(mod, original_method, method_sig, original_visibility, method_sig.
|
|
22
|
+
create_validator_method_fast2(mod, original_method, method_sig, original_visibility, method_sig.effective_return_type.raw_type,
|
|
23
23
|
arg_types[0][1].raw_type,
|
|
24
24
|
arg_types[1][1].raw_type)
|
|
25
25
|
when 3
|
|
26
|
-
create_validator_method_fast3(mod, original_method, method_sig, original_visibility, method_sig.
|
|
26
|
+
create_validator_method_fast3(mod, original_method, method_sig, original_visibility, method_sig.effective_return_type.raw_type,
|
|
27
27
|
arg_types[0][1].raw_type,
|
|
28
28
|
arg_types[1][1].raw_type,
|
|
29
29
|
arg_types[2][1].raw_type)
|
|
30
30
|
when 4
|
|
31
|
-
create_validator_method_fast4(mod, original_method, method_sig, original_visibility, method_sig.
|
|
31
|
+
create_validator_method_fast4(mod, original_method, method_sig, original_visibility, method_sig.effective_return_type.raw_type,
|
|
32
32
|
arg_types[0][1].raw_type,
|
|
33
33
|
arg_types[1][1].raw_type,
|
|
34
34
|
arg_types[2][1].raw_type,
|
|
@@ -58,14 +58,14 @@ module T::Private::Methods::CallValidation
|
|
|
58
58
|
|
|
59
59
|
return_value = original_method.bind_call(self, &blk)
|
|
60
60
|
unless return_value.is_a?(return_type)
|
|
61
|
-
message = method_sig.
|
|
61
|
+
message = method_sig.effective_return_type.error_message_for_obj(return_value)
|
|
62
62
|
if message
|
|
63
63
|
CallValidation.report_error(
|
|
64
64
|
method_sig,
|
|
65
65
|
message,
|
|
66
66
|
'Return value',
|
|
67
67
|
nil,
|
|
68
|
-
method_sig.
|
|
68
|
+
method_sig.effective_return_type,
|
|
69
69
|
return_value,
|
|
70
70
|
caller_offset: -1
|
|
71
71
|
)
|
|
@@ -107,14 +107,14 @@ module T::Private::Methods::CallValidation
|
|
|
107
107
|
|
|
108
108
|
return_value = original_method.bind_call(self, arg0, &blk)
|
|
109
109
|
unless return_value.is_a?(return_type)
|
|
110
|
-
message = method_sig.
|
|
110
|
+
message = method_sig.effective_return_type.error_message_for_obj(return_value)
|
|
111
111
|
if message
|
|
112
112
|
CallValidation.report_error(
|
|
113
113
|
method_sig,
|
|
114
114
|
message,
|
|
115
115
|
'Return value',
|
|
116
116
|
nil,
|
|
117
|
-
method_sig.
|
|
117
|
+
method_sig.effective_return_type,
|
|
118
118
|
return_value,
|
|
119
119
|
caller_offset: -1
|
|
120
120
|
)
|
|
@@ -168,14 +168,14 @@ module T::Private::Methods::CallValidation
|
|
|
168
168
|
|
|
169
169
|
return_value = original_method.bind_call(self, arg0, arg1, &blk)
|
|
170
170
|
unless return_value.is_a?(return_type)
|
|
171
|
-
message = method_sig.
|
|
171
|
+
message = method_sig.effective_return_type.error_message_for_obj(return_value)
|
|
172
172
|
if message
|
|
173
173
|
CallValidation.report_error(
|
|
174
174
|
method_sig,
|
|
175
175
|
message,
|
|
176
176
|
'Return value',
|
|
177
177
|
nil,
|
|
178
|
-
method_sig.
|
|
178
|
+
method_sig.effective_return_type,
|
|
179
179
|
return_value,
|
|
180
180
|
caller_offset: -1
|
|
181
181
|
)
|
|
@@ -241,14 +241,14 @@ module T::Private::Methods::CallValidation
|
|
|
241
241
|
|
|
242
242
|
return_value = original_method.bind_call(self, arg0, arg1, arg2, &blk)
|
|
243
243
|
unless return_value.is_a?(return_type)
|
|
244
|
-
message = method_sig.
|
|
244
|
+
message = method_sig.effective_return_type.error_message_for_obj(return_value)
|
|
245
245
|
if message
|
|
246
246
|
CallValidation.report_error(
|
|
247
247
|
method_sig,
|
|
248
248
|
message,
|
|
249
249
|
'Return value',
|
|
250
250
|
nil,
|
|
251
|
-
method_sig.
|
|
251
|
+
method_sig.effective_return_type,
|
|
252
252
|
return_value,
|
|
253
253
|
caller_offset: -1
|
|
254
254
|
)
|
|
@@ -326,14 +326,14 @@ module T::Private::Methods::CallValidation
|
|
|
326
326
|
|
|
327
327
|
return_value = original_method.bind_call(self, arg0, arg1, arg2, arg3, &blk)
|
|
328
328
|
unless return_value.is_a?(return_type)
|
|
329
|
-
message = method_sig.
|
|
329
|
+
message = method_sig.effective_return_type.error_message_for_obj(return_value)
|
|
330
330
|
if message
|
|
331
331
|
CallValidation.report_error(
|
|
332
332
|
method_sig,
|
|
333
333
|
message,
|
|
334
334
|
'Return value',
|
|
335
335
|
nil,
|
|
336
|
-
method_sig.
|
|
336
|
+
method_sig.effective_return_type,
|
|
337
337
|
return_value,
|
|
338
338
|
caller_offset: -1
|
|
339
339
|
)
|
|
@@ -867,28 +867,28 @@ module T::Private::Methods::CallValidation
|
|
|
867
867
|
end
|
|
868
868
|
|
|
869
869
|
def self.create_validator_method_medium(mod, original_method, method_sig, original_visibility)
|
|
870
|
-
if method_sig.
|
|
870
|
+
if method_sig.effective_return_type.is_a?(T::Private::Types::Void)
|
|
871
871
|
raise 'Should have used create_validator_procedure_medium'
|
|
872
872
|
end
|
|
873
873
|
# trampoline to reduce stack frame size
|
|
874
874
|
arg_types = method_sig.arg_types
|
|
875
875
|
case arg_types.length
|
|
876
876
|
when 0
|
|
877
|
-
create_validator_method_medium0(mod, original_method, method_sig, original_visibility, method_sig.
|
|
877
|
+
create_validator_method_medium0(mod, original_method, method_sig, original_visibility, method_sig.effective_return_type)
|
|
878
878
|
when 1
|
|
879
|
-
create_validator_method_medium1(mod, original_method, method_sig, original_visibility, method_sig.
|
|
879
|
+
create_validator_method_medium1(mod, original_method, method_sig, original_visibility, method_sig.effective_return_type,
|
|
880
880
|
arg_types[0][1])
|
|
881
881
|
when 2
|
|
882
|
-
create_validator_method_medium2(mod, original_method, method_sig, original_visibility, method_sig.
|
|
882
|
+
create_validator_method_medium2(mod, original_method, method_sig, original_visibility, method_sig.effective_return_type,
|
|
883
883
|
arg_types[0][1],
|
|
884
884
|
arg_types[1][1])
|
|
885
885
|
when 3
|
|
886
|
-
create_validator_method_medium3(mod, original_method, method_sig, original_visibility, method_sig.
|
|
886
|
+
create_validator_method_medium3(mod, original_method, method_sig, original_visibility, method_sig.effective_return_type,
|
|
887
887
|
arg_types[0][1],
|
|
888
888
|
arg_types[1][1],
|
|
889
889
|
arg_types[2][1])
|
|
890
890
|
when 4
|
|
891
|
-
create_validator_method_medium4(mod, original_method, method_sig, original_visibility, method_sig.
|
|
891
|
+
create_validator_method_medium4(mod, original_method, method_sig, original_visibility, method_sig.effective_return_type,
|
|
892
892
|
arg_types[0][1],
|
|
893
893
|
arg_types[1][1],
|
|
894
894
|
arg_types[2][1],
|
|
@@ -918,14 +918,14 @@ module T::Private::Methods::CallValidation
|
|
|
918
918
|
|
|
919
919
|
return_value = original_method.bind_call(self, &blk)
|
|
920
920
|
unless return_type.valid?(return_value)
|
|
921
|
-
message = method_sig.
|
|
921
|
+
message = method_sig.effective_return_type.error_message_for_obj(return_value)
|
|
922
922
|
if message
|
|
923
923
|
CallValidation.report_error(
|
|
924
924
|
method_sig,
|
|
925
925
|
message,
|
|
926
926
|
'Return value',
|
|
927
927
|
nil,
|
|
928
|
-
method_sig.
|
|
928
|
+
method_sig.effective_return_type,
|
|
929
929
|
return_value,
|
|
930
930
|
caller_offset: -1
|
|
931
931
|
)
|
|
@@ -967,14 +967,14 @@ module T::Private::Methods::CallValidation
|
|
|
967
967
|
|
|
968
968
|
return_value = original_method.bind_call(self, arg0, &blk)
|
|
969
969
|
unless return_type.valid?(return_value)
|
|
970
|
-
message = method_sig.
|
|
970
|
+
message = method_sig.effective_return_type.error_message_for_obj(return_value)
|
|
971
971
|
if message
|
|
972
972
|
CallValidation.report_error(
|
|
973
973
|
method_sig,
|
|
974
974
|
message,
|
|
975
975
|
'Return value',
|
|
976
976
|
nil,
|
|
977
|
-
method_sig.
|
|
977
|
+
method_sig.effective_return_type,
|
|
978
978
|
return_value,
|
|
979
979
|
caller_offset: -1
|
|
980
980
|
)
|
|
@@ -1028,14 +1028,14 @@ module T::Private::Methods::CallValidation
|
|
|
1028
1028
|
|
|
1029
1029
|
return_value = original_method.bind_call(self, arg0, arg1, &blk)
|
|
1030
1030
|
unless return_type.valid?(return_value)
|
|
1031
|
-
message = method_sig.
|
|
1031
|
+
message = method_sig.effective_return_type.error_message_for_obj(return_value)
|
|
1032
1032
|
if message
|
|
1033
1033
|
CallValidation.report_error(
|
|
1034
1034
|
method_sig,
|
|
1035
1035
|
message,
|
|
1036
1036
|
'Return value',
|
|
1037
1037
|
nil,
|
|
1038
|
-
method_sig.
|
|
1038
|
+
method_sig.effective_return_type,
|
|
1039
1039
|
return_value,
|
|
1040
1040
|
caller_offset: -1
|
|
1041
1041
|
)
|
|
@@ -1101,14 +1101,14 @@ module T::Private::Methods::CallValidation
|
|
|
1101
1101
|
|
|
1102
1102
|
return_value = original_method.bind_call(self, arg0, arg1, arg2, &blk)
|
|
1103
1103
|
unless return_type.valid?(return_value)
|
|
1104
|
-
message = method_sig.
|
|
1104
|
+
message = method_sig.effective_return_type.error_message_for_obj(return_value)
|
|
1105
1105
|
if message
|
|
1106
1106
|
CallValidation.report_error(
|
|
1107
1107
|
method_sig,
|
|
1108
1108
|
message,
|
|
1109
1109
|
'Return value',
|
|
1110
1110
|
nil,
|
|
1111
|
-
method_sig.
|
|
1111
|
+
method_sig.effective_return_type,
|
|
1112
1112
|
return_value,
|
|
1113
1113
|
caller_offset: -1
|
|
1114
1114
|
)
|
|
@@ -1186,14 +1186,14 @@ module T::Private::Methods::CallValidation
|
|
|
1186
1186
|
|
|
1187
1187
|
return_value = original_method.bind_call(self, arg0, arg1, arg2, arg3, &blk)
|
|
1188
1188
|
unless return_type.valid?(return_value)
|
|
1189
|
-
message = method_sig.
|
|
1189
|
+
message = method_sig.effective_return_type.error_message_for_obj(return_value)
|
|
1190
1190
|
if message
|
|
1191
1191
|
CallValidation.report_error(
|
|
1192
1192
|
method_sig,
|
|
1193
1193
|
message,
|
|
1194
1194
|
'Return value',
|
|
1195
1195
|
nil,
|
|
1196
|
-
method_sig.
|
|
1196
|
+
method_sig.effective_return_type,
|
|
1197
1197
|
return_value,
|
|
1198
1198
|
caller_offset: -1
|
|
1199
1199
|
)
|
|
@@ -22,10 +22,10 @@ module T::Private::Methods
|
|
|
22
22
|
ARG_NOT_PROVIDED, # returns
|
|
23
23
|
ARG_NOT_PROVIDED, # bind
|
|
24
24
|
Modes.standard, # mode
|
|
25
|
-
|
|
25
|
+
nil, # checked
|
|
26
26
|
false, # finalized
|
|
27
27
|
ARG_NOT_PROVIDED, # on_failure
|
|
28
|
-
|
|
28
|
+
false, # override_allow_incompatible
|
|
29
29
|
ARG_NOT_PROVIDED, # type_parameters
|
|
30
30
|
raw
|
|
31
31
|
)
|
|
@@ -98,10 +98,10 @@ module T::Private::Methods
|
|
|
98
98
|
def checked(level)
|
|
99
99
|
check_live!
|
|
100
100
|
|
|
101
|
-
if !decl.checked.
|
|
101
|
+
if !decl.checked.nil?
|
|
102
102
|
raise BuilderError.new("You can't call .checked multiple times in a signature.")
|
|
103
103
|
end
|
|
104
|
-
if
|
|
104
|
+
if :never == level && !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,8 +119,13 @@ 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
|
-
|
|
123
|
-
|
|
122
|
+
effective_checked = decl.checked.nil? ? T::Private::RuntimeLevels.default_checked_level : decl.checked
|
|
123
|
+
if effective_checked == :never
|
|
124
|
+
if decl.checked.nil?
|
|
125
|
+
raise BuilderError.new("To use .on_failure you must additionally call .checked(:tests) or .checked(:always), otherwise, the .on_failure has no effect.")
|
|
126
|
+
else
|
|
127
|
+
raise BuilderError.new("You can't use .on_failure with .checked(:#{effective_checked}) because .on_failure will have no effect.")
|
|
128
|
+
end
|
|
124
129
|
end
|
|
125
130
|
|
|
126
131
|
decl.on_failure = args
|
|
@@ -225,13 +230,6 @@ module T::Private::Methods
|
|
|
225
230
|
if decl.bind.equal?(ARG_NOT_PROVIDED)
|
|
226
231
|
decl.bind = nil
|
|
227
232
|
end
|
|
228
|
-
if decl.checked.equal?(ARG_NOT_PROVIDED)
|
|
229
|
-
default_checked_level = T::Private::RuntimeLevels.default_checked_level
|
|
230
|
-
if default_checked_level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
231
|
-
raise BuilderError.new("To use .on_failure you must additionally call .checked(:tests) or .checked(:always), otherwise, the .on_failure has no effect.")
|
|
232
|
-
end
|
|
233
|
-
decl.checked = default_checked_level
|
|
234
|
-
end
|
|
235
233
|
if decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
236
234
|
decl.on_failure = nil
|
|
237
235
|
end
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
class T::Private::Methods::Signature
|
|
5
5
|
attr_reader :method, :method_name, :arg_types, :kwarg_types, :block_type, :block_name,
|
|
6
|
-
:rest_type, :rest_name, :keyrest_type, :keyrest_name, :bind,
|
|
7
|
-
:return_type, :mode, :req_arg_count, :req_kwarg_names,
|
|
6
|
+
:rest_type, :rest_name, :keyrest_type, :keyrest_name, :bind, :effective_return_type,
|
|
7
|
+
:return_type, :mode, :req_arg_count, :req_kwarg_names,
|
|
8
8
|
:check_level, :parameters, :on_failure, :override_allow_incompatible,
|
|
9
9
|
:defined_raw
|
|
10
10
|
|
|
@@ -37,6 +37,7 @@ class T::Private::Methods::Signature
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def initialize(method:, method_name:, raw_arg_types:, raw_return_type:, bind:, mode:, check_level:, on_failure:, parameters: method.parameters, override_allow_incompatible: false, defined_raw: false)
|
|
40
|
+
check_level = check_level.nil? ? T::Private::RuntimeLevels.default_checked_level : check_level
|
|
40
41
|
@method = method
|
|
41
42
|
@method_name = method_name
|
|
42
43
|
@block_type = nil
|
|
@@ -46,11 +47,14 @@ class T::Private::Methods::Signature
|
|
|
46
47
|
@keyrest_type = nil
|
|
47
48
|
@keyrest_name = nil
|
|
48
49
|
@return_type = T::Utils.coerce(raw_return_type)
|
|
50
|
+
@effective_return_type = if check_level == :tests && @return_type.is_a?(T::Private::Types::Void)
|
|
51
|
+
T::Types::Anything::Private::INSTANCE
|
|
52
|
+
else
|
|
53
|
+
@return_type
|
|
54
|
+
end
|
|
49
55
|
@bind = bind ? T::Utils.coerce(bind) : bind
|
|
50
56
|
@mode = mode
|
|
51
57
|
@check_level = check_level
|
|
52
|
-
@has_rest = false
|
|
53
|
-
@has_keyrest = false
|
|
54
58
|
@parameters = parameters
|
|
55
59
|
@on_failure = on_failure
|
|
56
60
|
@override_allow_incompatible = override_allow_incompatible
|
|
@@ -134,11 +138,9 @@ class T::Private::Methods::Signature
|
|
|
134
138
|
@block_name = param_name
|
|
135
139
|
@block_type = type
|
|
136
140
|
when :rest
|
|
137
|
-
@has_rest = true
|
|
138
141
|
@rest_name = param_name
|
|
139
142
|
@rest_type = type
|
|
140
143
|
when :keyrest
|
|
141
|
-
@has_keyrest = true
|
|
142
144
|
@keyrest_name = param_name
|
|
143
145
|
@keyrest_type = type
|
|
144
146
|
else
|
|
@@ -175,10 +177,6 @@ class T::Private::Methods::Signature
|
|
|
175
177
|
@method.owner
|
|
176
178
|
end
|
|
177
179
|
|
|
178
|
-
def dsl_method
|
|
179
|
-
"#{@mode}_method"
|
|
180
|
-
end
|
|
181
|
-
|
|
182
180
|
# @return [Hash] a mapping like `{arg_name: [val, type], ...}`, for only those args actually present.
|
|
183
181
|
def each_args_value_type(args)
|
|
184
182
|
# Manually split out args and kwargs based on ruby's behavior. Do not try to implement this by
|
|
@@ -189,14 +187,14 @@ class T::Private::Methods::Signature
|
|
|
189
187
|
# causes forwarding **kwargs to do the wrong thing: see https://bugs.ruby-lang.org/issues/10708
|
|
190
188
|
# and https://bugs.ruby-lang.org/issues/11860.
|
|
191
189
|
args_length = args.length
|
|
192
|
-
if (args_length > @req_arg_count) && (!@kwarg_types.empty? ||
|
|
193
|
-
kwargs =
|
|
190
|
+
if (args_length > @req_arg_count) && (!@kwarg_types.empty? || !@keyrest_type.nil?) && (last_arg = args[-1]).is_a?(Hash)
|
|
191
|
+
kwargs = last_arg
|
|
194
192
|
args_length -= 1
|
|
195
193
|
else
|
|
196
194
|
kwargs = EMPTY_HASH
|
|
197
195
|
end
|
|
198
196
|
|
|
199
|
-
if
|
|
197
|
+
if @rest_type.nil? && ((args_length < @req_arg_count) || (args_length > @arg_types.length))
|
|
200
198
|
expected_str = @req_arg_count.to_s
|
|
201
199
|
if @arg_types.length != @req_arg_count
|
|
202
200
|
expected_str += "..#{@arg_types.length}"
|
|
@@ -210,11 +208,12 @@ class T::Private::Methods::Signature
|
|
|
210
208
|
# Process given pre-rest args. When there are no rest args,
|
|
211
209
|
# this is just the given number of args.
|
|
212
210
|
while it < args_length && it < @arg_types.length
|
|
213
|
-
|
|
211
|
+
arg_type = @arg_types.fetch(it)
|
|
212
|
+
yield arg_type[0], args[it], arg_type[1]
|
|
214
213
|
it += 1
|
|
215
214
|
end
|
|
216
215
|
|
|
217
|
-
if
|
|
216
|
+
if !@rest_type.nil?
|
|
218
217
|
rest_count = args_length - @arg_types.length
|
|
219
218
|
rest_count = 0 if rest_count.negative?
|
|
220
219
|
|
|
@@ -227,7 +226,7 @@ class T::Private::Methods::Signature
|
|
|
227
226
|
|
|
228
227
|
kwargs.each do |name, val|
|
|
229
228
|
type = @kwarg_types[name]
|
|
230
|
-
if !type &&
|
|
229
|
+
if !type && !@keyrest_type.nil?
|
|
231
230
|
type = @keyrest_type
|
|
232
231
|
end
|
|
233
232
|
|
|
@@ -236,12 +235,12 @@ class T::Private::Methods::Signature
|
|
|
236
235
|
end
|
|
237
236
|
|
|
238
237
|
def method_desc
|
|
239
|
-
loc = if @method.source_location
|
|
240
|
-
|
|
238
|
+
loc = if (source_loc = @method.source_location)
|
|
239
|
+
source_loc.join(':')
|
|
241
240
|
else
|
|
242
241
|
"<unknown location>"
|
|
243
242
|
end
|
|
244
|
-
"#{@method} at #{loc}"
|
|
243
|
+
"#{@method.owner}##{@method_name} at #{loc}"
|
|
245
244
|
end
|
|
246
245
|
|
|
247
246
|
def force_type_init
|
|
@@ -126,12 +126,12 @@ module T::Private::Methods::SignatureValidation
|
|
|
126
126
|
# Peaceful
|
|
127
127
|
elsif super_signature.mode == Modes.abstract
|
|
128
128
|
raise "You must use `.override` when overriding the abstract method `#{signature.method_name}`.\n" \
|
|
129
|
-
" Abstract definition: #{
|
|
130
|
-
" Implementation definition: #{
|
|
129
|
+
" Abstract definition: #{super_signature.method_desc}\n" \
|
|
130
|
+
" Implementation definition: #{signature.method_desc}\n"
|
|
131
131
|
elsif super_signature.mode != Modes.untyped
|
|
132
132
|
raise "You must use `.override` when overriding the existing method `#{signature.method_name}`.\n" \
|
|
133
|
-
" Parent definition: #{
|
|
134
|
-
" Child definition: #{
|
|
133
|
+
" Parent definition: #{super_signature.method_desc}\n" \
|
|
134
|
+
" Child definition: #{signature.method_desc}\n"
|
|
135
135
|
end
|
|
136
136
|
else
|
|
137
137
|
raise "Unexpected mode: #{signature.mode}. Please report this bug at https://github.com/sorbet/sorbet/issues"
|
|
@@ -153,7 +153,7 @@ module T::Private::Methods::SignatureValidation
|
|
|
153
153
|
else
|
|
154
154
|
raise "You marked `#{signature.method_name}` as #{pretty_mode(signature)}, but that method doesn't already exist in this class/module to be overridden.\n" \
|
|
155
155
|
" Either check for typos and for missing includes or super classes to make the parent method shows up\n" \
|
|
156
|
-
" ... or remove #{pretty_mode(signature)} here: #{
|
|
156
|
+
" ... or remove #{pretty_mode(signature)} here: #{signature.method_desc}\n"
|
|
157
157
|
end
|
|
158
158
|
when Modes.standard, *Modes::NON_OVERRIDE_MODES
|
|
159
159
|
# Peaceful
|
|
@@ -182,13 +182,13 @@ module T::Private::Methods::SignatureValidation
|
|
|
182
182
|
method_name = signature.method_name
|
|
183
183
|
mode_verb = super_signature.mode == Modes.abstract ? 'implements' : 'overrides'
|
|
184
184
|
|
|
185
|
-
if
|
|
185
|
+
if signature.rest_type.nil? && signature.arg_count < super_signature.arg_count
|
|
186
186
|
raise "Your definition of `#{method_name}` must accept at least #{super_signature.arg_count} " \
|
|
187
187
|
"positional arguments to be compatible with the method it #{mode_verb}: " \
|
|
188
188
|
"#{base_override_loc_str(signature, super_signature)}"
|
|
189
189
|
end
|
|
190
190
|
|
|
191
|
-
if
|
|
191
|
+
if signature.rest_type.nil? && !super_signature.rest_type.nil?
|
|
192
192
|
raise "Your definition of `#{method_name}` must have `*#{super_signature.rest_name}` " \
|
|
193
193
|
"to be compatible with the method it #{mode_verb}: " \
|
|
194
194
|
"#{base_override_loc_str(signature, super_signature)}"
|
|
@@ -200,7 +200,7 @@ module T::Private::Methods::SignatureValidation
|
|
|
200
200
|
"#{base_override_loc_str(signature, super_signature)}"
|
|
201
201
|
end
|
|
202
202
|
|
|
203
|
-
if
|
|
203
|
+
if signature.keyrest_type.nil?
|
|
204
204
|
# O(nm), but n and m are tiny here
|
|
205
205
|
missing_kwargs = super_signature.kwarg_names - signature.kwarg_names
|
|
206
206
|
if !missing_kwargs.empty?
|
|
@@ -210,7 +210,7 @@ module T::Private::Methods::SignatureValidation
|
|
|
210
210
|
end
|
|
211
211
|
end
|
|
212
212
|
|
|
213
|
-
if
|
|
213
|
+
if signature.keyrest_type.nil? && !super_signature.keyrest_type.nil?
|
|
214
214
|
raise "Your definition of `#{method_name}` must have `**#{super_signature.keyrest_name}` " \
|
|
215
215
|
"to be compatible with the method it #{mode_verb}: " \
|
|
216
216
|
"#{base_override_loc_str(signature, super_signature)}"
|
|
@@ -244,8 +244,8 @@ module T::Private::Methods::SignatureValidation
|
|
|
244
244
|
if !super_type.subtype_of?(type)
|
|
245
245
|
raise "Incompatible type for arg ##{index + 1} (`#{name}`) in signature for #{mode_noun} of method " \
|
|
246
246
|
"`#{signature.method_name}`:\n" \
|
|
247
|
-
"* Base: `#{super_type}` (in #{
|
|
248
|
-
"* #{mode_noun.capitalize}: `#{type}` (in #{
|
|
247
|
+
"* Base: `#{super_type}` (in #{super_signature.method_desc})\n" \
|
|
248
|
+
"* #{mode_noun.capitalize}: `#{type}` (in #{signature.method_desc})\n" \
|
|
249
249
|
"(The types must be contravariant.)"
|
|
250
250
|
end
|
|
251
251
|
end
|
|
@@ -255,24 +255,24 @@ module T::Private::Methods::SignatureValidation
|
|
|
255
255
|
type = signature.kwarg_types[name]
|
|
256
256
|
if !super_type.subtype_of?(type)
|
|
257
257
|
raise "Incompatible type for arg `#{name}` in signature for #{mode_noun} of method `#{signature.method_name}`:\n" \
|
|
258
|
-
"* Base: `#{super_type}` (in #{
|
|
259
|
-
"* #{mode_noun.capitalize}: `#{type}` (in #{
|
|
258
|
+
"* Base: `#{super_type}` (in #{super_signature.method_desc})\n" \
|
|
259
|
+
"* #{mode_noun.capitalize}: `#{type}` (in #{signature.method_desc})\n" \
|
|
260
260
|
"(The types must be contravariant.)"
|
|
261
261
|
end
|
|
262
262
|
end
|
|
263
263
|
|
|
264
264
|
# return types must be covariant
|
|
265
|
-
super_signature_return_type = super_signature.
|
|
265
|
+
super_signature_return_type = super_signature.effective_return_type
|
|
266
266
|
|
|
267
267
|
if super_signature_return_type == T::Private::Types::Void::Private::INSTANCE
|
|
268
268
|
# Treat `.void` as `T.anything` (see corresponding comment in definition_valitor for more)
|
|
269
269
|
super_signature_return_type = T::Types::Anything::Private::INSTANCE
|
|
270
270
|
end
|
|
271
271
|
|
|
272
|
-
if !signature.
|
|
272
|
+
if !signature.effective_return_type.subtype_of?(super_signature_return_type)
|
|
273
273
|
raise "Incompatible return type in signature for #{mode_noun} of method `#{signature.method_name}`:\n" \
|
|
274
|
-
"* Base: `#{super_signature.
|
|
275
|
-
"* #{mode_noun.capitalize}: `#{signature.
|
|
274
|
+
"* Base: `#{super_signature.effective_return_type}` (in #{super_signature.method_desc})\n" \
|
|
275
|
+
"* #{mode_noun.capitalize}: `#{signature.effective_return_type}` (in #{signature.method_desc})\n" \
|
|
276
276
|
"(The types must be covariant.)"
|
|
277
277
|
end
|
|
278
278
|
end
|
|
@@ -297,14 +297,14 @@ module T::Private::Methods::SignatureValidation
|
|
|
297
297
|
|
|
298
298
|
if visibility_strength(vis) > visibility_strength(super_vis)
|
|
299
299
|
raise "Incompatible visibility for #{mode_noun} of method #{method.name}\n" \
|
|
300
|
-
"* Base: #{super_vis} (in #{
|
|
301
|
-
"* #{mode_noun.capitalize}: #{vis} (in #{
|
|
300
|
+
"* Base: #{super_vis} (in #{super_signature.method_desc})\n" \
|
|
301
|
+
"* #{mode_noun.capitalize}: #{vis} (in #{signature.method_desc})\n" \
|
|
302
302
|
"(The override must be at least as permissive as the supermethod)" \
|
|
303
303
|
end
|
|
304
304
|
end
|
|
305
305
|
|
|
306
306
|
private_class_method def self.method_visibility(method)
|
|
307
|
-
T::Private::
|
|
307
|
+
T::Private::ClassUtils.visibility_method_name(method.owner, method.name)
|
|
308
308
|
end
|
|
309
309
|
|
|
310
310
|
# Higher = more restrictive.
|
|
@@ -317,16 +317,7 @@ module T::Private::Methods::SignatureValidation
|
|
|
317
317
|
|
|
318
318
|
private_class_method def self.base_override_loc_str(signature, super_signature)
|
|
319
319
|
mode_noun = super_signature.mode == Modes.abstract ? 'Implementation' : 'Override'
|
|
320
|
-
"\n * Base definition: in #{
|
|
321
|
-
"\n * #{mode_noun}: in #{
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
private_class_method def self.method_loc_str(method)
|
|
325
|
-
loc = if method.source_location
|
|
326
|
-
method.source_location.join(':')
|
|
327
|
-
else
|
|
328
|
-
"<unknown location>"
|
|
329
|
-
end
|
|
330
|
-
"#{method.owner} at #{loc}"
|
|
320
|
+
"\n * Base definition: in #{super_signature.method_desc}" \
|
|
321
|
+
"\n * #{mode_noun}: in #{signature.method_desc}"
|
|
331
322
|
end
|
|
332
323
|
end
|
data/lib/types/struct.rb
CHANGED
|
@@ -10,7 +10,8 @@ end
|
|
|
10
10
|
class T::Struct < T::InexactStruct
|
|
11
11
|
def self.inherited(subclass)
|
|
12
12
|
super(subclass)
|
|
13
|
-
|
|
13
|
+
original_method = subclass.singleton_class.instance_method(:inherited)
|
|
14
|
+
T::Private::ClassUtils.replace_method(original_method, subclass.singleton_class, :inherited) do |s|
|
|
14
15
|
super(s)
|
|
15
16
|
raise "#{self.name} is a subclass of T::Struct and cannot be subclassed"
|
|
16
17
|
end
|
|
@@ -23,7 +24,8 @@ class T::ImmutableStruct < T::InexactStruct
|
|
|
23
24
|
def self.inherited(subclass)
|
|
24
25
|
super(subclass)
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
original_method = subclass.singleton_class.instance_method(:inherited)
|
|
28
|
+
T::Private::ClassUtils.replace_method(original_method, subclass.singleton_class, :inherited) do |s|
|
|
27
29
|
super(s)
|
|
28
30
|
raise "#{self.name} is a subclass of T::ImmutableStruct and cannot be subclassed"
|
|
29
31
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sorbet-runtime
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.13192
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stripe
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-05-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: benchmark
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
13
27
|
- !ruby/object:Gem::Dependency
|
|
14
28
|
name: minitest
|
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -136,20 +150,6 @@ dependencies:
|
|
|
136
150
|
- - ">="
|
|
137
151
|
- !ruby/object:Gem::Version
|
|
138
152
|
version: '0'
|
|
139
|
-
- !ruby/object:Gem::Dependency
|
|
140
|
-
name: subprocess
|
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
|
142
|
-
requirements:
|
|
143
|
-
- - "~>"
|
|
144
|
-
- !ruby/object:Gem::Version
|
|
145
|
-
version: 1.5.3
|
|
146
|
-
type: :development
|
|
147
|
-
prerelease: false
|
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
-
requirements:
|
|
150
|
-
- - "~>"
|
|
151
|
-
- !ruby/object:Gem::Version
|
|
152
|
-
version: 1.5.3
|
|
153
153
|
description: Sorbet's runtime type checking component
|
|
154
154
|
email:
|
|
155
155
|
executables: []
|