sorbet-runtime 0.5.5200 → 0.5.5226

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: 80710bef2aa0399340fc377530a27026e271cd80f4a290b76ba56d4fc7a90094
4
- data.tar.gz: 6e35bef9804041e6a23a05b503b213e1a4052af7260f785162af3c20d04c0bff
3
+ metadata.gz: ce5d31efe70f4a4a9fedee60cddc4545cce308285d1a92e9b75f7c6c5cfd0ead
4
+ data.tar.gz: 8ff1cb8a2b9a7c0f1987925899bfcf674c27b594156c9dd8e60ee27ec51d1dd1
5
5
  SHA512:
6
- metadata.gz: 1ecde44bd9fed96fabc8d2f9b8249375daa79d9f97b9c662daac690c54fee1d96f8eb41571ba83e8508f7c28ab0cb8fbe2dbbf75148195dba93aa1b619b11327
7
- data.tar.gz: f0e44dc08ec3d2eca82db242634b2eea7f128f582369f11b1554c61407a08840dacf8c93121cbe758ccfc1965b3f26cfa2dddaa6801a8f62a91485d9c2aaa3a6
6
+ metadata.gz: bc94cf76fd49747ab049a66bfbd30dc4a0b037ac0f8988a4c6f6a5e6421abf92f209c14a8fe42c0268ca34d8fa5e77cc4fcddc24f08bd8cc6e7175068cc0285e
7
+ data.tar.gz: 38dc583fc54332f763cb1982bce24e5c23e2d2125a0dfd451354eb16f5adc8bab07ee2c4cfda1642b83795bc1539d153b7063df2ffd367faa4d1798ca856cd13
data/lib/types/_types.rb CHANGED
@@ -65,12 +65,8 @@ module T
65
65
  T::Types::SelfType.new
66
66
  end
67
67
 
68
- # TODO(jez) Matches the instance type in a singleton-class context
69
- def self.attached_class
70
- T::Types::AttachedClassType.new
71
- end
72
68
  # Matches the instance type in a singleton-class context
73
- def self.experimental_attached_class
69
+ def self.attached_class
74
70
  T::Types::AttachedClassType.new
75
71
  end
76
72
 
data/lib/types/enum.rb CHANGED
@@ -48,7 +48,7 @@ class T::Enum
48
48
  private_constant :SerializedVal
49
49
 
50
50
  ## Enum class methods ##
51
- sig {returns(T::Array[T.experimental_attached_class])}
51
+ sig {returns(T::Array[T.attached_class])}
52
52
  def self.values
53
53
  if @values.nil?
54
54
  raise "Attempting to access values of #{self.class} before it has been initialized." \
@@ -61,7 +61,7 @@ class T::Enum
61
61
  #
62
62
  # Note: It would have been nice to make this method final before people started overriding it.
63
63
  # Note: Failed CriticalMethodsNoRuntimeTypingTest
64
- sig {params(serialized_val: SerializedVal).returns(T.nilable(T.experimental_attached_class)).checked(:never)}
64
+ sig {params(serialized_val: SerializedVal).returns(T.nilable(T.attached_class)).checked(:never)}
65
65
  def self.try_deserialize(serialized_val)
66
66
  if @mapping.nil?
67
67
  raise "Attempting to access serialization map of #{self.class} before it has been initialized." \
@@ -77,7 +77,7 @@ class T::Enum
77
77
  #
78
78
  # @return [self]
79
79
  # @raise [KeyError] if serialized value does not match any instance.
80
- sig {overridable.params(serialized_val: SerializedVal).returns(T.experimental_attached_class).checked(:never)}
80
+ sig {overridable.params(serialized_val: SerializedVal).returns(T.attached_class).checked(:never)}
81
81
  def self.from_serialized(serialized_val)
82
82
  res = try_deserialize(serialized_val)
83
83
  if res.nil?
@@ -124,7 +124,7 @@ class T::Enum
124
124
  end
125
125
 
126
126
  # Note: Failed CriticalMethodsNoRuntimeTypingTest
127
- sig {params(mongo_value: SerializedVal).returns(T.experimental_attached_class).checked(:never)}
127
+ sig {params(mongo_value: SerializedVal).returns(T.attached_class).checked(:never)}
128
128
  def self.deserialize(mongo_value)
129
129
  if self == T::Enum
130
130
  raise "Cannot call T::Enum.deserialize directly. You must call on a specific child class."
@@ -310,8 +310,8 @@ class T::Enum
310
310
 
311
311
  yield
312
312
 
313
- @values = T.let(nil, T.nilable(T::Array[T.experimental_attached_class]))
314
- @mapping = T.let(nil, T.nilable(T::Hash[SerializedVal, T.experimental_attached_class]))
313
+ @values = T.let(nil, T.nilable(T::Array[T.attached_class]))
314
+ @mapping = T.let(nil, T.nilable(T::Hash[SerializedVal, T.attached_class]))
315
315
 
316
316
  # Freeze the Enum class and bind the constant names into each of the instances.
317
317
  @mapping = {}
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- # typed: false
2
+ # typed: true
3
3
 
4
4
  # A mixin for defining typed properties (attributes).
5
5
  # To get serialization methods (to/from JSON-style hashes), add T::Props::Serializable.
@@ -131,7 +131,7 @@ module T::Props
131
131
  sig {params(name: T.any(Symbol, String), cls_or_args: T.untyped, args: T::Hash[Symbol, T.untyped]).void}
132
132
  def const(name, cls_or_args, args={})
133
133
  if (cls_or_args.is_a?(Hash) && cls_or_args.key?(:immutable)) || args.key?(:immutable)
134
- raise ArgumentError.new("Cannot pass 'immutable' argument when using 'const' keyword to define a prop")
134
+ Kernel.raise ArgumentError.new("Cannot pass 'immutable' argument when using 'const' keyword to define a prop")
135
135
  end
136
136
 
137
137
  if cls_or_args.is_a?(Hash)
@@ -18,7 +18,7 @@ class T::Props::Decorator
18
18
 
19
19
  class NoRulesError < StandardError; end
20
20
 
21
- T::Sig::WithoutRuntime.sig {params(klass: DecoratedClass).void}
21
+ sig {params(klass: DecoratedClass).void.checked(:never)}
22
22
  def initialize(klass)
23
23
  @class = klass
24
24
  klass.plugins.each do |mod|
@@ -26,7 +26,7 @@ class T::Props::Decorator
26
26
  end
27
27
  end
28
28
 
29
- # prop stuff
29
+ # checked(:never) - O(prop accesses)
30
30
  sig {returns(T::Hash[Symbol, Rules]).checked(:never)}
31
31
  def props
32
32
  @props ||= {}.freeze
@@ -44,12 +44,13 @@ class T::Props::Decorator
44
44
  sig {returns(T::Array[Symbol])}
45
45
  def all_props; props.keys; end
46
46
 
47
+ # checked(:never) - O(prop accesses)
47
48
  sig {params(prop: T.any(Symbol, String)).returns(Rules).checked(:never)}
48
49
  def prop_rules(prop); props[prop.to_sym] || raise("No such prop: #{prop.inspect}"); end
49
50
 
50
- sig {params(prop: Symbol, rules: Rules).void}
51
+ # checked(:never) - Rules hash is expensive to check
52
+ sig {params(prop: Symbol, rules: Rules).void.checked(:never)}
51
53
  def add_prop_definition(prop, rules)
52
- prop = prop.to_sym
53
54
  override = rules.delete(:override)
54
55
 
55
56
  if props.include?(prop) && !override
@@ -61,25 +62,36 @@ class T::Props::Decorator
61
62
  @props = @props.merge(prop => rules.freeze).freeze
62
63
  end
63
64
 
64
- sig {returns(T::Array[Symbol])}
65
+ VALID_RULE_KEYS = %i{
66
+ enum
67
+ foreign
68
+ foreign_hint_only
69
+ ifunset
70
+ immutable
71
+ override
72
+ redaction
73
+ sensitivity
74
+ without_accessors
75
+ clobber_existing_method!
76
+ extra
77
+ optional
78
+ _tnilable
79
+ }.to_set.freeze
80
+ private_constant :VALID_RULE_KEYS
81
+
82
+ sig {params(key: Symbol).returns(T::Boolean).checked(:never)}
83
+ def valid_rule_key?(key)
84
+ valid_props.include?(key)
85
+ end
86
+
87
+ # Deprecated, kept temporarily to support overrides in pay-server
88
+ # during the transition to `valid_rule_key?`
89
+ sig {returns(T::Set[Symbol]).checked(:never)}
65
90
  def valid_props
66
- %i{
67
- enum
68
- foreign
69
- foreign_hint_only
70
- ifunset
71
- immutable
72
- override
73
- redaction
74
- sensitivity
75
- without_accessors
76
- clobber_existing_method!
77
- extra
78
- optional
79
- _tnilable
80
- }
91
+ VALID_RULE_KEYS
81
92
  end
82
93
 
94
+ # checked(:never) - O(prop accesses)
83
95
  sig {returns(DecoratedClass).checked(:never)}
84
96
  def decorated_class; @class; end
85
97
 
@@ -87,6 +99,8 @@ class T::Props::Decorator
87
99
 
88
100
  # For performance, don't use named params here.
89
101
  # Passing in rules here is purely a performance optimization.
102
+ #
103
+ # checked(:never) - O(prop accesses)
90
104
  sig do
91
105
  params(
92
106
  instance: DecoratedInstance,
@@ -104,6 +118,8 @@ class T::Props::Decorator
104
118
 
105
119
  # For performance, don't use named params here.
106
120
  # Passing in rules here is purely a performance optimization.
121
+ #
122
+ # checked(:never) - O(prop accesses)
107
123
  sig do
108
124
  params(
109
125
  instance: DecoratedInstance,
@@ -121,6 +137,8 @@ class T::Props::Decorator
121
137
  end
122
138
 
123
139
  # Use this to validate that a value will validate for a given prop. Useful for knowing whether a value can be set on a model without setting it.
140
+ #
141
+ # checked(:never) - potentially O(prop accesses) depending on usage pattern
124
142
  sig {params(prop: Symbol, val: T.untyped).void.checked(:never)}
125
143
  def validate_prop_value(prop, val)
126
144
  # This implements a 'public api' on document so that we don't allow callers to pass in rules
@@ -129,6 +147,8 @@ class T::Props::Decorator
129
147
  end
130
148
 
131
149
  # Passing in rules here is purely a performance optimization.
150
+ #
151
+ # checked(:never) - O(prop accesses)
132
152
  sig {params(prop: Symbol, val: T.untyped, rules: Rules).void.checked(:never)}
133
153
  private def check_prop_type(prop, val, rules=prop_rules(prop))
134
154
  type_object = rules.fetch(:type_object)
@@ -184,6 +204,8 @@ class T::Props::Decorator
184
204
  # Unlike the other methods that take rules, this one calls prop_rules for
185
205
  # the default, which raises if the prop doesn't exist (this maintains
186
206
  # preexisting behavior).
207
+ #
208
+ # checked(:never) - O(prop accesses)
187
209
  sig do
188
210
  params(
189
211
  instance: DecoratedInstance,
@@ -201,6 +223,11 @@ class T::Props::Decorator
201
223
 
202
224
  # For performance, don't use named params here.
203
225
  # Passing in rules here is purely a performance optimization.
226
+ #
227
+ # Note this path is NOT used by generated getters on instances,
228
+ # unless `ifunset` is used on the prop, or `prop_get` is overridden.
229
+ #
230
+ # checked(:never) - O(prop accesses)
204
231
  sig do
205
232
  params(
206
233
  instance: DecoratedInstance,
@@ -213,15 +240,7 @@ class T::Props::Decorator
213
240
  def prop_get(instance, prop, rules=props[prop.to_sym])
214
241
  val = get(instance, prop, rules)
215
242
 
216
- # NB: Do NOT change this to check `val.nil?` instead. BSON::ByteBuffer overrides `==` such
217
- # that `== nil` can return true while `.nil?` returns false. Tests will break in mysterious
218
- # ways. A special thanks to Ruby for enabling this type of bug.
219
- #
220
- # One side effect here is that _if_ a class (like BSON::ByteBuffer) defines ==
221
- # in such a way that instances which are not `nil`, ie are not NilClass, nevertheless
222
- # are `== nil`, then we will transparently convert such instances to `nil` on read.
223
- # Yes, our code relies on this behavior (as of writing). :thisisfine:
224
- if val != nil # rubocop:disable Style/NonNilCheck
243
+ if !val.nil?
225
244
  val
226
245
  else
227
246
  raise NoRulesError.new if !rules
@@ -234,6 +253,7 @@ class T::Props::Decorator
234
253
  end
235
254
  end
236
255
 
256
+ # checked(:never) - O(prop accesses)
237
257
  sig do
238
258
  params(
239
259
  instance: DecoratedInstance,
@@ -250,6 +270,10 @@ class T::Props::Decorator
250
270
  foreign_class.load(value, {}, opts)
251
271
  end
252
272
 
273
+ # TODO: we should really be checking all the methods on `cls`, not just Object
274
+ BANNED_METHOD_NAMES = Object.instance_methods.to_set.freeze
275
+
276
+ # checked(:never) - Rules hash is expensive to check
253
277
  sig do
254
278
  params(
255
279
  name: Symbol,
@@ -258,6 +282,7 @@ class T::Props::Decorator
258
282
  type: PropTypeOrClass
259
283
  )
260
284
  .void
285
+ .checked(:never)
261
286
  end
262
287
  def prop_validate_definition!(name, cls, rules, type)
263
288
  validate_prop_name(name)
@@ -267,7 +292,7 @@ class T::Props::Decorator
267
292
  "to 'sensitivity:' (in prop #{@class.name}.#{name})")
268
293
  end
269
294
 
270
- if !(rules.keys - valid_props).empty?
295
+ if rules.keys.any? {|k| !valid_rule_key?(k)}
271
296
  raise ArgumentError.new("At least one invalid prop arg supplied in #{self}: #{rules.keys.inspect}")
272
297
  end
273
298
 
@@ -278,8 +303,7 @@ class T::Props::Decorator
278
303
  end
279
304
 
280
305
  if !(rules[:clobber_existing_method!]) && !(rules[:without_accessors])
281
- # TODO: we should really be checking all the methods on `cls`, not just Object
282
- if Object.instance_methods.include?(name.to_sym)
306
+ if BANNED_METHOD_NAMES.include?(name.to_sym)
283
307
  raise ArgumentError.new(
284
308
  "#{name} can't be used as a prop in #{@class} because a method with " \
285
309
  "that name already exists (defined by #{@class.instance_method(name).owner} " \
@@ -303,13 +327,6 @@ class T::Props::Decorator
303
327
  end
304
328
  end
305
329
 
306
- # Check if this cls represents a T.nilable(type)
307
- sig {params(type: PropTypeOrClass).returns(T::Boolean)}
308
- private def is_nilable?(type)
309
- return false if !type.is_a?(T::Types::Union)
310
- type.types.any? {|t| t == T::Utils.coerce(NilClass)}
311
- end
312
-
313
330
  # This converts the type from a T::Type to a regular old ruby class.
314
331
  sig {params(type: T::Types::Base).returns(Module)}
315
332
  private def convert_type_to_class(type)
@@ -338,6 +355,7 @@ class T::Props::Decorator
338
355
  end
339
356
  end
340
357
 
358
+ # checked(:never) - Rules hash is expensive to check
341
359
  sig do
342
360
  params(
343
361
  name: T.any(Symbol, String),
@@ -345,6 +363,7 @@ class T::Props::Decorator
345
363
  rules: Rules,
346
364
  )
347
365
  .void
366
+ .checked(:never)
348
367
  end
349
368
  def prop_defined(name, cls, rules={})
350
369
  cls = T::Utils.resolve_alias(cls)
@@ -501,7 +520,8 @@ class T::Props::Decorator
501
520
  handle_redaction_option(name, rules[:redaction]) if rules[:redaction]
502
521
  end
503
522
 
504
- sig {params(name: Symbol, rules: Rules).void}
523
+ # checked(:never) - Rules hash is expensive to check
524
+ sig {params(name: Symbol, rules: Rules).void.checked(:never)}
505
525
  private def define_getter_and_setter(name, rules)
506
526
  T::Configuration.without_ruby_warnings do
507
527
  if !rules[:immutable]
@@ -510,16 +530,24 @@ class T::Props::Decorator
510
530
  end
511
531
  end
512
532
 
513
- @class.send(:define_method, name) do
514
- self.class.decorator.prop_get(self, name, rules)
533
+ if method(:prop_get).owner != T::Props::Decorator || rules.key?(:ifunset)
534
+ @class.send(:define_method, name) do
535
+ self.class.decorator.prop_get(self, name, rules)
536
+ end
537
+ else
538
+ # Fast path (~30x faster as of Ruby 2.6)
539
+ @class.attr_reader(name)
515
540
  end
516
541
  end
517
542
  end
518
543
 
519
544
  # returns the subdoc of the array type, or nil if it's not a Document type
545
+ #
546
+ # checked(:never) - Typechecks internally
520
547
  sig do
521
548
  params(type: PropType)
522
549
  .returns(T.nilable(Module))
550
+ .checked(:never)
523
551
  end
524
552
  private def array_subdoc_type(type)
525
553
  if type.is_a?(T::Types::TypedArray)
@@ -535,9 +563,12 @@ class T::Props::Decorator
535
563
  end
536
564
 
537
565
  # returns the subdoc of the hash value type, or nil if it's not a Document type
566
+ #
567
+ # checked(:never) - Typechecks internally
538
568
  sig do
539
569
  params(type: PropType)
540
570
  .returns(T.nilable(Module))
571
+ .checked(:never)
541
572
  end
542
573
  private def hash_value_subdoc_type(type)
543
574
  if type.is_a?(T::Types::TypedHash)
@@ -553,9 +584,12 @@ class T::Props::Decorator
553
584
  end
554
585
 
555
586
  # returns the type of the hash key, or nil. Any CustomType could be a key, but we only expect T::Enum right now.
587
+ #
588
+ # checked(:never) - Typechecks internally
556
589
  sig do
557
590
  params(type: PropType)
558
591
  .returns(T.nilable(Module))
592
+ .checked(:never)
559
593
  end
560
594
  private def hash_key_custom_type(type)
561
595
  if type.is_a?(T::Types::TypedHash)
@@ -572,7 +606,8 @@ class T::Props::Decorator
572
606
  # From T::Props::Utils.deep_clone_object, plus String
573
607
  TYPES_NOT_NEEDING_CLONE = [TrueClass, FalseClass, NilClass, Symbol, String, Numeric]
574
608
 
575
- sig {params(type: PropType).returns(T::Boolean)}
609
+ # checked(:never) - Typechecks internally
610
+ sig {params(type: PropType).returns(T::Boolean).checked(:never)}
576
611
  private def shallow_clone_ok(type)
577
612
  inner_type =
578
613
  if type.is_a?(T::Types::TypedArray)
@@ -613,7 +648,8 @@ class T::Props::Decorator
613
648
  end
614
649
  end
615
650
 
616
- sig {params(prop_name: Symbol, rules: Hash).void}
651
+ # checked(:never) - Rules hash is expensive to check
652
+ sig {params(prop_name: Symbol, rules: Hash).void.checked(:never)}
617
653
  private def validate_not_missing_sensitivity(prop_name, rules)
618
654
  if rules[:sensitivity].nil?
619
655
  if rules[:redaction]
@@ -700,6 +736,7 @@ class T::Props::Decorator
700
736
  )
701
737
  end
702
738
 
739
+ # checked(:never) - Rules hash is expensive to check
703
740
  sig do
704
741
  params(
705
742
  prop_name: T.any(String, Symbol),
@@ -707,6 +744,7 @@ class T::Props::Decorator
707
744
  foreign: T.untyped,
708
745
  )
709
746
  .void
747
+ .checked(:never)
710
748
  end
711
749
  private def define_foreign_method(prop_name, rules, foreign)
712
750
  fk_method = "#{prop_name}_"
@@ -758,6 +796,7 @@ class T::Props::Decorator
758
796
  end
759
797
  end
760
798
 
799
+ # checked(:never) - Rules hash is expensive to check
761
800
  sig do
762
801
  params(
763
802
  prop_name: Symbol,
@@ -766,6 +805,7 @@ class T::Props::Decorator
766
805
  foreign: T.untyped,
767
806
  )
768
807
  .void
808
+ .checked(:never)
769
809
  end
770
810
  private def handle_foreign_option(prop_name, prop_cls, rules, foreign)
771
811
  validate_foreign_option(
@@ -793,7 +833,7 @@ class T::Props::Decorator
793
833
  #
794
834
  # This gets called when a module or class that extends T::Props gets included, extended,
795
835
  # prepended, or inherited.
796
- T::Sig::WithoutRuntime.sig {params(child: DecoratedClass).void}
836
+ sig {params(child: DecoratedClass).void.checked(:never)}
797
837
  def model_inherited(child)
798
838
  child.extend(T::Props::ClassMethods)
799
839
  child.plugins.concat(decorated_class.plugins)
@@ -811,10 +851,27 @@ class T::Props::Decorator
811
851
  # time. Any class that defines props and also overrides the `decorator_class` method is going
812
852
  # to reach this line before its override take effect, turning it into a no-op.
813
853
  child.decorator.add_prop_definition(name, copied_rules)
854
+
855
+ # It's a bit tricky to support `prop_get` hooks added by plugins without
856
+ # sacrificing the `attr_reader` fast path or clobbering customized getters
857
+ # defined manually on a child.
858
+ #
859
+ # To make this work, we _do_ clobber getters defined on the child, but only if:
860
+ # (a) it's needed in order to support a `prop_get` hook, and
861
+ # (b) it's safe because the getter was defined by this file.
862
+ #
863
+ unless rules[:without_accessors]
864
+ if child.decorator.method(:prop_get).owner != method(:prop_get).owner &&
865
+ child.instance_method(name).source_location.first == __FILE__
866
+ child.send(:define_method, name) do
867
+ self.class.decorator.prop_get(self, name, rules)
868
+ end
869
+ end
870
+ end
814
871
  end
815
872
  end
816
873
 
817
- T::Sig::WithoutRuntime.sig {params(mod: Module).void}
874
+ sig {params(mod: Module).void.checked(:never)}
818
875
  def plugin(mod)
819
876
  decorated_class.plugins << mod
820
877
  Private.apply_class_methods(mod, decorated_class)
@@ -21,12 +21,15 @@ module T::Props::Optional::DecoratorMethods
21
21
  true,
22
22
  ].freeze
23
23
 
24
- def valid_props
25
- super + [
26
- :default,
27
- :factory,
28
- :optional,
29
- ]
24
+ VALID_RULE_KEYS = Set[
25
+ :default,
26
+ :factory,
27
+ :optional,
28
+ ].freeze
29
+ private_constant :VALID_RULE_KEYS
30
+
31
+ def valid_rule_key?(key)
32
+ super || VALID_RULE_KEYS.include?(key)
30
33
  end
31
34
 
32
35
  def prop_optional?(prop); prop_rules(prop)[:fully_optional]; end
@@ -18,9 +18,9 @@ module T::Props::PrettyPrintable
18
18
  module DecoratorMethods
19
19
  extend T::Sig
20
20
 
21
- sig {returns(T::Array[Symbol])}
22
- def valid_props
23
- super + [:inspect]
21
+ sig {params(key: Symbol).returns(T::Boolean).checked(:never)}
22
+ def valid_rule_key?(key)
23
+ super || key == :inspect
24
24
  end
25
25
 
26
26
  sig do
@@ -274,12 +274,12 @@ end
274
274
  # NB: This must stay in the same file where T::Props::Serializable is defined due to
275
275
  # T::Props::Decorator#apply_plugin; see https://git.corp.stripe.com/stripe-internal/pay-server/blob/fc7f15593b49875f2d0499ffecfd19798bac05b3/chalk/odm/lib/chalk-odm/document_decorator.rb#L716-L717
276
276
  module T::Props::Serializable::DecoratorMethods
277
- def valid_props
278
- super + [
279
- :dont_store,
280
- :name,
281
- :raise_on_nil_write,
282
- ]
277
+
278
+ VALID_RULE_KEYS = Set[:dont_store, :name, :raise_on_nil_write].freeze
279
+ private_constant :VALID_RULE_KEYS
280
+
281
+ def valid_rule_key?(key)
282
+ super || VALID_RULE_KEYS.include?(key)
283
283
  end
284
284
 
285
285
  def required_props
@@ -11,9 +11,9 @@ module T::Props::TypeValidation
11
11
  module DecoratorMethods
12
12
  extend T::Sig
13
13
 
14
- sig {returns(T::Array[Symbol])}
15
- def valid_props
16
- super + [:DEPRECATED_underspecified_type]
14
+ sig {params(key: Symbol).returns(T::Boolean).checked(:never)}
15
+ def valid_rule_key?(key)
16
+ super || :DEPRECATED_underspecified_type == key
17
17
  end
18
18
 
19
19
  sig do
@@ -53,7 +53,9 @@ module T::Props::TypeValidation
53
53
  # a subtype like the type of the values of a typed hash.
54
54
  #
55
55
  # If the type is fully valid, returns nil.
56
- sig {params(type: T::Types::Base).returns(T.nilable(T::Types::Base))}
56
+ #
57
+ # checked(:never) - called potentially many times recursively
58
+ sig {params(type: T::Types::Base).returns(T.nilable(T::Types::Base)).checked(:never)}
57
59
  private def find_invalid_subtype(type)
58
60
  case type
59
61
  when T::Types::TypedEnumerable
data/lib/types/utils.rb CHANGED
@@ -96,7 +96,7 @@ module T::Utils
96
96
  def self.unwrap_nilable(type)
97
97
  case type
98
98
  when T::Types::Union
99
- non_nil_types = type.types.reject {|t| t == T::Utils.coerce(NilClass)}
99
+ non_nil_types = type.types.reject {|t| t == Nilable::NIL_TYPE}
100
100
  if non_nil_types.length == 1
101
101
  non_nil_types.first
102
102
  else
@@ -156,6 +156,8 @@ module T::Utils
156
156
  # :non_nilable_type, Class: if it is an T.nilable type, the corresponding underlying type; otherwise, nil.
157
157
  TypeInfo = Struct.new(:is_union_type, :non_nilable_type)
158
158
 
159
+ NIL_TYPE = T::Utils.coerce(NilClass)
160
+
159
161
  def self.get_type_info(prop_type)
160
162
  if prop_type.is_a?(T::Types::Union)
161
163
  non_nilable_type = T::Utils.unwrap_nilable(prop_type)
@@ -191,7 +193,7 @@ module T::Utils
191
193
  def self.is_union_with_nilclass(prop_type)
192
194
  case prop_type
193
195
  when T::Types::Union
194
- prop_type.types.any? {|t| t == T::Utils.coerce(NilClass)}
196
+ prop_type.types.include?(NIL_TYPE)
195
197
  else
196
198
  false
197
199
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorbet-runtime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5200
4
+ version: 0.5.5226
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-04 00:00:00.000000000 Z
11
+ date: 2020-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest