sorbet-runtime 0.5.12203 → 0.5.12366
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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 621006dee0ec596b46c4eba003534e49eb71ccff6b0af7fa32efd16dc9ba436e
|
4
|
+
data.tar.gz: 6cc3bc9bbec95f0c9b34643c995be28939c355cf824c15e4da3888a48e7d9563
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9f02e2b3b76d2adc6b872fc7aed55c2c0009233f66cd650062d57e2af4a50b56c9747c759de737eca620494da190884576d90c7fd652e6b3d1661acf759060a
|
7
|
+
data.tar.gz: d8aa60c7ee08f3cedda81996841fe5822a33ab2a9a37b3b4cb26957e36e246e7b5ea4f0c76b91f9b62b1e605ebb13312adc263fa0cebd3dee22580dca39f0a2c
|
@@ -545,15 +545,15 @@ module T::Private::Methods
|
|
545
545
|
|
546
546
|
module MethodHooks
|
547
547
|
def method_added(name)
|
548
|
-
super(name)
|
549
548
|
::T::Private::Methods._on_method_added(self, self, name)
|
549
|
+
super(name)
|
550
550
|
end
|
551
551
|
end
|
552
552
|
|
553
553
|
module SingletonMethodHooks
|
554
554
|
def singleton_method_added(name)
|
555
|
-
super(name)
|
556
555
|
::T::Private::Methods._on_method_added(self, singleton_class, name)
|
556
|
+
super(name)
|
557
557
|
end
|
558
558
|
end
|
559
559
|
|
@@ -589,6 +589,22 @@ module T::Private::Methods
|
|
589
589
|
mod.extend(SingletonMethodHooks)
|
590
590
|
end
|
591
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
|
+
|
592
608
|
# use this directly if you don't want/need to box up the method into an object to pass to method_to_key.
|
593
609
|
private_class_method def self.method_owner_and_name_to_key(owner, name)
|
594
610
|
"#{owner.object_id}##{name}"
|
@@ -12,7 +12,7 @@ module T::Private::Methods::CallValidation
|
|
12
12
|
# @param method_sig [T::Private::Methods::Signature]
|
13
13
|
# @return [UnboundMethod] the new wrapper method (or the original one if we didn't wrap it)
|
14
14
|
def self.wrap_method_if_needed(mod, method_sig, original_method)
|
15
|
-
original_visibility = visibility_method_name(mod, method_sig.method_name)
|
15
|
+
original_visibility = T::Private::Methods.visibility_method_name(mod, method_sig.method_name)
|
16
16
|
if method_sig.mode == T::Private::Methods::Modes.abstract
|
17
17
|
create_abstract_wrapper(mod, method_sig, original_method, original_visibility)
|
18
18
|
# Do nothing in this case; this method was not wrapped in _on_method_added.
|
@@ -330,19 +330,6 @@ module T::Private::Methods::CallValidation
|
|
330
330
|
location: caller_loc
|
331
331
|
)
|
332
332
|
end
|
333
|
-
|
334
|
-
# `name` must be an instance method (for class methods, pass in mod.singleton_class)
|
335
|
-
private_class_method def self.visibility_method_name(mod, name)
|
336
|
-
if mod.public_method_defined?(name)
|
337
|
-
:public
|
338
|
-
elsif mod.protected_method_defined?(name)
|
339
|
-
:protected
|
340
|
-
elsif mod.private_method_defined?(name)
|
341
|
-
:private
|
342
|
-
else
|
343
|
-
mod.method(name) # Raises
|
344
|
-
end
|
345
|
-
end
|
346
333
|
end
|
347
334
|
|
348
335
|
if T::Configuration::AT_LEAST_RUBY_2_7
|
@@ -89,6 +89,7 @@ module T::Private::Methods::SignatureValidation
|
|
89
89
|
validate_override_mode(signature, super_signature)
|
90
90
|
validate_override_shape(signature, super_signature)
|
91
91
|
validate_override_types(signature, super_signature)
|
92
|
+
validate_override_visibility(signature, super_signature)
|
92
93
|
end
|
93
94
|
else
|
94
95
|
validate_non_override_mode(signature)
|
@@ -276,6 +277,38 @@ module T::Private::Methods::SignatureValidation
|
|
276
277
|
end
|
277
278
|
end
|
278
279
|
|
280
|
+
def self.validate_override_visibility(signature, super_signature)
|
281
|
+
return if super_signature.mode == Modes.untyped
|
282
|
+
# This departs from the behavior of other `validate_override_whatever` functions in that it
|
283
|
+
# only comes into effect when the child signature explicitly says the word `override`. This was
|
284
|
+
# done because the primary method for silencing these errors (`allow_incompatible: :visibility`)
|
285
|
+
# requires an `override` node to attach to. Once we have static override checking for implicitly
|
286
|
+
# overridden methods, we can remove this.
|
287
|
+
return unless [Modes.override, Modes.overridable_override].include?(signature.mode)
|
288
|
+
return if [:visibility, true].include?(signature.override_allow_incompatible)
|
289
|
+
method = signature.method
|
290
|
+
super_method = super_signature.method
|
291
|
+
mode_noun = super_signature.mode == Modes.abstract ? 'implementation' : 'override'
|
292
|
+
vis = method_visibility(method)
|
293
|
+
super_vis = method_visibility(super_method)
|
294
|
+
|
295
|
+
if visibility_strength(vis) > visibility_strength(super_vis)
|
296
|
+
raise "Incompatible visibility for #{mode_noun} of method #{method.name}\n" \
|
297
|
+
"* Base: #{super_vis} (in #{method_loc_str(super_method)})\n" \
|
298
|
+
"* #{mode_noun.capitalize}: #{vis} (in #{method_loc_str(method)})\n" \
|
299
|
+
"(The override must be at least as permissive as the supermethod)" \
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
private_class_method def self.method_visibility(method)
|
304
|
+
T::Private::Methods.visibility_method_name(method.owner, method.name)
|
305
|
+
end
|
306
|
+
|
307
|
+
# Higher = more restrictive.
|
308
|
+
private_class_method def self.visibility_strength(vis)
|
309
|
+
%i[public protected private].find_index(vis)
|
310
|
+
end
|
311
|
+
|
279
312
|
private_class_method def self.base_override_loc_str(signature, super_signature)
|
280
313
|
mode_noun = super_signature.mode == Modes.abstract ? 'Implementation' : 'Override'
|
281
314
|
"\n * Base definition: in #{method_loc_str(super_signature.method)}" \
|
@@ -14,12 +14,28 @@ class T::Props::Decorator
|
|
14
14
|
DecoratedInstance = T.type_alias { Object } # Would be T::Props, but that produces circular reference errors in some circumstances
|
15
15
|
PropType = T.type_alias { T::Types::Base }
|
16
16
|
PropTypeOrClass = T.type_alias { T.any(PropType, Module) }
|
17
|
+
OverrideRules = T.type_alias { T::Hash[Symbol, {allow_incompatible: T::Boolean}] }
|
17
18
|
|
18
19
|
class NoRulesError < StandardError; end
|
19
20
|
|
20
21
|
EMPTY_PROPS = T.let({}.freeze, T::Hash[Symbol, Rules], checked: false)
|
21
22
|
private_constant :EMPTY_PROPS
|
22
23
|
|
24
|
+
OVERRIDE_TRUE = T.let({
|
25
|
+
reader: {allow_incompatible: false}.freeze,
|
26
|
+
writer: {allow_incompatible: false}.freeze,
|
27
|
+
}.freeze, OverrideRules)
|
28
|
+
|
29
|
+
OVERRIDE_READER = T.let({
|
30
|
+
reader: {allow_incompatible: false}.freeze,
|
31
|
+
}.freeze, OverrideRules)
|
32
|
+
|
33
|
+
OVERRIDE_WRITER = T.let({
|
34
|
+
writer: {allow_incompatible: false}.freeze,
|
35
|
+
}.freeze, OverrideRules)
|
36
|
+
|
37
|
+
OVERRIDE_EMPTY = T.let({}.freeze, OverrideRules)
|
38
|
+
|
23
39
|
sig { params(klass: T.untyped).void.checked(:never) }
|
24
40
|
def initialize(klass)
|
25
41
|
@class = T.let(klass, T.all(Module, T::Props::ClassMethods))
|
@@ -45,17 +61,15 @@ class T::Props::Decorator
|
|
45
61
|
end
|
46
62
|
|
47
63
|
# checked(:never) - Rules hash is expensive to check
|
48
|
-
sig { params(
|
49
|
-
def add_prop_definition(
|
64
|
+
sig { params(name: Symbol, rules: Rules).void.checked(:never) }
|
65
|
+
def add_prop_definition(name, rules)
|
50
66
|
override = rules.delete(:override)
|
51
67
|
|
52
|
-
if props.include?(
|
53
|
-
raise ArgumentError.new("Attempted to redefine prop #{
|
54
|
-
elsif !props.include?(prop) && override
|
55
|
-
raise ArgumentError.new("Attempted to override a prop #{prop.inspect} on class #{@class} that doesn't already exist")
|
68
|
+
if props.include?(name) && !override
|
69
|
+
raise ArgumentError.new("Attempted to redefine prop #{name.inspect} on class #{@class} that's already defined without specifying :override => true: #{prop_rules(name)}")
|
56
70
|
end
|
57
71
|
|
58
|
-
@props = @props.merge(
|
72
|
+
@props = @props.merge(name => rules.freeze).freeze
|
59
73
|
end
|
60
74
|
|
61
75
|
# Heads up!
|
@@ -302,6 +316,27 @@ class T::Props::Decorator
|
|
302
316
|
T::Utils::Nilable.is_union_with_nilclass(cls) || ((cls == T.untyped || cls == NilClass) && rules.key?(:default) && rules[:default].nil?)
|
303
317
|
end
|
304
318
|
|
319
|
+
sig(:final) { params(name: Symbol).returns(T::Boolean).checked(:never) }
|
320
|
+
private def method_defined_on_ancestor?(name)
|
321
|
+
@class.method_defined?(name) && !@class.method_defined?(name, false)
|
322
|
+
end
|
323
|
+
|
324
|
+
sig(:final) { params(name: Symbol, rules: Rules).void.checked(:never) }
|
325
|
+
private def validate_overrides(name, rules)
|
326
|
+
override = elaborate_override(name, rules[:override])
|
327
|
+
|
328
|
+
return if rules[:without_accessors]
|
329
|
+
|
330
|
+
if override[:reader] && !method_defined_on_ancestor?(name) && !props.include?(name)
|
331
|
+
raise ArgumentError.new("You marked the getter for prop #{name.inspect} as `override`, but the method `#{name}` doesn't exist to be overridden.")
|
332
|
+
end
|
333
|
+
|
334
|
+
# Properly, we should also check whether `props[name]` is immutable, but the old code didn't either.
|
335
|
+
if !rules[:immutable] && override[:writer] && !method_defined_on_ancestor?("#{name}=".to_sym) && !props.include?(name)
|
336
|
+
raise ArgumentError.new("You marked the setter for prop #{name.inspect} as `override`, but the method `#{name}=` doesn't exist to be overridden.")
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
305
340
|
# checked(:never) - Rules hash is expensive to check
|
306
341
|
sig do
|
307
342
|
params(
|
@@ -381,6 +416,7 @@ class T::Props::Decorator
|
|
381
416
|
rules[:setter_proc] = setter_proc
|
382
417
|
rules[:value_validate_proc] = value_validate_proc
|
383
418
|
|
419
|
+
validate_overrides(name, rules)
|
384
420
|
add_prop_definition(name, rules)
|
385
421
|
|
386
422
|
# NB: using `without_accessors` doesn't make much sense unless you also define some other way to
|
@@ -405,6 +441,7 @@ class T::Props::Decorator
|
|
405
441
|
# Fast path (~4x faster as of Ruby 2.6)
|
406
442
|
@class.send(:define_method, "#{name}=", &rules.fetch(:setter_proc))
|
407
443
|
end
|
444
|
+
|
408
445
|
end
|
409
446
|
|
410
447
|
if method(:prop_get).owner != T::Props::Decorator || rules.key?(:ifunset)
|
@@ -627,7 +664,7 @@ class T::Props::Decorator
|
|
627
664
|
|
628
665
|
props.each do |name, rules|
|
629
666
|
copied_rules = rules.dup
|
630
|
-
# NB: Calling `child.decorator` here is a
|
667
|
+
# NB: Calling `child.decorator` here is a time bomb that's going to give someone a really bad
|
631
668
|
# time. Any class that defines props and also overrides the `decorator_class` method is going
|
632
669
|
# to reach this line before its override take effect, turning it into a no-op.
|
633
670
|
child.decorator.add_prop_definition(name, copied_rules)
|
@@ -656,6 +693,52 @@ class T::Props::Decorator
|
|
656
693
|
end
|
657
694
|
end
|
658
695
|
|
696
|
+
sig(:final) do
|
697
|
+
params(key: Symbol, d: T.untyped, out: T::Hash[Symbol, {allow_incompatible: T::Boolean}])
|
698
|
+
.void
|
699
|
+
.checked(:never)
|
700
|
+
end
|
701
|
+
private def elaborate_override_entry(key, d, out)
|
702
|
+
# It's written this way so that `{reader: false}` will omit the entry for `reader` in the
|
703
|
+
# result entirely
|
704
|
+
case d[key]
|
705
|
+
when TrueClass
|
706
|
+
out[key] = {allow_incompatible: false}
|
707
|
+
when Hash
|
708
|
+
out[key] = {allow_incompatible: !!d[key][:allow_incompatible]}
|
709
|
+
end
|
710
|
+
end
|
711
|
+
|
712
|
+
sig(:final) do
|
713
|
+
params(name: Symbol, d: T.untyped)
|
714
|
+
.returns(T::Hash[Symbol, {allow_incompatible: T::Boolean}])
|
715
|
+
.checked(:never)
|
716
|
+
end
|
717
|
+
private def elaborate_override(name, d)
|
718
|
+
return OVERRIDE_TRUE if d == true
|
719
|
+
return OVERRIDE_READER if d == :reader
|
720
|
+
return OVERRIDE_WRITER if d == :writer
|
721
|
+
return OVERRIDE_EMPTY if d == false || d.nil?
|
722
|
+
unless d.is_a?(Hash)
|
723
|
+
raise ArgumentError.new("`override` only accepts `true`, `:reader`, `:writer`, or a Hash in prop #{@class.name}.#{name} (got #{d.class})")
|
724
|
+
end
|
725
|
+
|
726
|
+
# cwong: should we check for bad keys? `sig { override(not_real: true) }` on a normal function
|
727
|
+
# errors statically but not at runtime.
|
728
|
+
|
729
|
+
# XX cwong: this means {reader: false, allow_incompatible: true} will become {allow_incompatible: true},
|
730
|
+
# is that fine?
|
731
|
+
unless (allow_incompatible = d[:allow_incompatible]).nil?
|
732
|
+
return {reader: {allow_incompatible: !!allow_incompatible},
|
733
|
+
writer: {allow_incompatible: !!allow_incompatible}}.to_h
|
734
|
+
end
|
735
|
+
|
736
|
+
result = {}
|
737
|
+
elaborate_override_entry(:reader, d, result)
|
738
|
+
elaborate_override_entry(:writer, d, result)
|
739
|
+
result
|
740
|
+
end
|
741
|
+
|
659
742
|
sig { params(child: T.all(Module, T::Props::ClassMethods), prop: Symbol).returns(T::Boolean).checked(:never) }
|
660
743
|
private def clobber_getter?(child, prop)
|
661
744
|
!!(child.decorator.method(:prop_get).owner != method(:prop_get).owner &&
|
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.12366
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stripe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|