sorbet-runtime 0.5.5316 → 0.5.5956

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sorbet-runtime.rb +10 -1
  3. data/lib/types/_types.rb +10 -9
  4. data/lib/types/compatibility_patches.rb +65 -8
  5. data/lib/types/configuration.rb +3 -3
  6. data/lib/types/enum.rb +33 -16
  7. data/lib/types/generic.rb +2 -2
  8. data/lib/types/interface_wrapper.rb +4 -4
  9. data/lib/types/non_forcing_constants.rb +57 -0
  10. data/lib/types/private/abstract/data.rb +2 -2
  11. data/lib/types/private/abstract/declare.rb +3 -0
  12. data/lib/types/private/casts.rb +27 -0
  13. data/lib/types/private/class_utils.rb +8 -5
  14. data/lib/types/private/methods/_methods.rb +73 -23
  15. data/lib/types/private/methods/call_validation.rb +3 -0
  16. data/lib/types/private/methods/signature.rb +16 -6
  17. data/lib/types/private/retry.rb +10 -0
  18. data/lib/types/private/sealed.rb +1 -1
  19. data/lib/types/private/types/type_alias.rb +5 -0
  20. data/lib/types/private/types/void.rb +4 -3
  21. data/lib/types/profile.rb +5 -1
  22. data/lib/types/props/_props.rb +1 -5
  23. data/lib/types/props/constructor.rb +29 -9
  24. data/lib/types/props/custom_type.rb +51 -27
  25. data/lib/types/props/decorator.rb +70 -207
  26. data/lib/types/props/generated_code_validation.rb +268 -0
  27. data/lib/types/props/has_lazily_specialized_methods.rb +92 -0
  28. data/lib/types/props/optional.rb +28 -28
  29. data/lib/types/props/plugin.rb +2 -2
  30. data/lib/types/props/private/apply_default.rb +170 -0
  31. data/lib/types/props/private/deserializer_generator.rb +165 -0
  32. data/lib/types/props/private/parser.rb +32 -0
  33. data/lib/types/props/private/serde_transform.rb +192 -0
  34. data/lib/types/props/private/serializer_generator.rb +77 -0
  35. data/lib/types/props/private/setter_factory.rb +78 -26
  36. data/lib/types/props/serializable.rb +126 -181
  37. data/lib/types/props/type_validation.rb +10 -1
  38. data/lib/types/props/weak_constructor.rb +51 -14
  39. data/lib/types/sig.rb +3 -3
  40. data/lib/types/types/attached_class.rb +5 -1
  41. data/lib/types/types/base.rb +13 -0
  42. data/lib/types/types/fixed_array.rb +28 -2
  43. data/lib/types/types/fixed_hash.rb +10 -9
  44. data/lib/types/types/intersection.rb +5 -0
  45. data/lib/types/types/noreturn.rb +4 -0
  46. data/lib/types/types/self_type.rb +4 -0
  47. data/lib/types/types/simple.rb +22 -1
  48. data/lib/types/types/t_enum.rb +6 -1
  49. data/lib/types/types/type_parameter.rb +1 -1
  50. data/lib/types/types/typed_array.rb +7 -2
  51. data/lib/types/types/typed_enumerable.rb +23 -7
  52. data/lib/types/types/typed_enumerator.rb +7 -2
  53. data/lib/types/types/typed_hash.rb +8 -3
  54. data/lib/types/types/typed_range.rb +7 -2
  55. data/lib/types/types/typed_set.rb +7 -2
  56. data/lib/types/types/union.rb +36 -5
  57. data/lib/types/types/untyped.rb +4 -0
  58. data/lib/types/utils.rb +21 -6
  59. metadata +95 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96ac3f40e289c8880e546f48cc793e4e12461e713ac5a6d5daf9777d91af2774
4
- data.tar.gz: 425ccca3f410868f357385eba3bbf0e8cc9cdd4b2cdc252137b0da96b36d5002
3
+ metadata.gz: 569e1e784f7d9e4c911cc92571704e406dfe981df3285218ae06b245b2e113db
4
+ data.tar.gz: 2d7b5f9878d6fe05add390255cdfe0dd70c69a77bbd06d5a32a1d02deec7f1b1
5
5
  SHA512:
6
- metadata.gz: 28df096a88491a837b89157f6b3fb2a779d0e61729e0c9363740a9fa8ddef7d23156f0c910fcc0b9569daba0826dfef9e22441bb82718872923a444c09b9536c
7
- data.tar.gz: cae44a94689f106188a491200eccf8b0da90e61ce2b089f79dbf8bcbb0ac4c486c9a10934f3647762aa3c179df677bfeee571665e1154b5929ebb8275ed3d7cf
6
+ metadata.gz: e93ae059f1d875a26242803edbae96a335a179a3ef2862ad1c2ad9c1729cb8041ec44c8fcd4520a25e33de9ff421a7edd67032579a1d60b6e8d6c649f6b6d0a1
7
+ data.tar.gz: 8b9b92b336911870b563666c7495b2f5ac52ddb3b2ec805dfcb1fbd48393dbfc63c89dd35c13f18ffeed04b7cdb9ff619591e011cf115975fc5392b6ab01be2b
@@ -80,6 +80,7 @@ require_relative 'types/private/abstract/hooks'
80
80
  require_relative 'types/private/casts'
81
81
  require_relative 'types/private/methods/decl_builder'
82
82
  require_relative 'types/private/methods/signature'
83
+ require_relative 'types/private/retry'
83
84
  require_relative 'types/utils'
84
85
  require_relative 'types/boolean'
85
86
 
@@ -92,16 +93,24 @@ require_relative 'types/props/decorator'
92
93
  require_relative 'types/props/errors'
93
94
  require_relative 'types/props/plugin'
94
95
  require_relative 'types/props/utils'
96
+ require_relative 'types/enum'
95
97
  # Props that run sigs statically so have to be after all the others :(
96
98
  require_relative 'types/props/private/setter_factory'
99
+ require_relative 'types/props/private/apply_default'
100
+ require_relative 'types/props/has_lazily_specialized_methods'
97
101
  require_relative 'types/props/optional'
98
102
  require_relative 'types/props/weak_constructor'
99
103
  require_relative 'types/props/constructor'
100
104
  require_relative 'types/props/pretty_printable'
105
+ require_relative 'types/props/private/serde_transform'
106
+ require_relative 'types/props/private/deserializer_generator'
107
+ require_relative 'types/props/private/serializer_generator'
101
108
  require_relative 'types/props/serializable'
102
109
  require_relative 'types/props/type_validation'
110
+ require_relative 'types/props/private/parser'
111
+ require_relative 'types/props/generated_code_validation'
103
112
 
104
113
  require_relative 'types/struct'
105
- require_relative 'types/enum'
114
+ require_relative 'types/non_forcing_constants'
106
115
 
107
116
  require_relative 'types/compatibility_patches'
data/lib/types/_types.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  # typed: true
3
3
  # This is where we define the shortcuts, so we can't use them here
4
- # rubocop:disable PrisonGuard/UseOpusTypesShortcut
5
4
 
6
5
  # _____
7
6
  # |_ _| _ _ __ ___ ___
@@ -26,23 +25,26 @@
26
25
  module T
27
26
  # T.any(<Type>, <Type>, ...) -- matches any of the types listed
28
27
  def self.any(type_a, type_b, *types)
29
- T::Types::Union.new([type_a, type_b] + types)
28
+ type_a = T::Utils.coerce(type_a)
29
+ type_b = T::Utils.coerce(type_b)
30
+ types = types.map {|t| T::Utils.coerce(t)} if !types.empty?
31
+ T::Types::Union::Private::Pool.union_of_types(type_a, type_b, types)
30
32
  end
31
33
 
32
34
  # Shorthand for T.any(type, NilClass)
33
35
  def self.nilable(type)
34
- T::Types::Union.new([type, NilClass])
36
+ T::Types::Union::Private::Pool.union_of_types(T::Utils.coerce(type), T::Utils::Nilable::NIL_TYPE)
35
37
  end
36
38
 
37
39
  # Matches any object. In the static checker, T.untyped allows any
38
40
  # method calls or operations.
39
41
  def self.untyped
40
- T::Types::Untyped.new
42
+ T::Types::Untyped::Private::INSTANCE
41
43
  end
42
44
 
43
45
  # Indicates a function never returns (e.g. "Kernel#raise")
44
46
  def self.noreturn
45
- T::Types::NoReturn.new
47
+ T::Types::NoReturn::Private::INSTANCE
46
48
  end
47
49
 
48
50
  # T.all(<Type>, <Type>, ...) -- matches an object that has all of the types listed
@@ -62,12 +64,12 @@ module T
62
64
 
63
65
  # Matches `self`:
64
66
  def self.self_type
65
- T::Types::SelfType.new
67
+ T::Types::SelfType::Private::INSTANCE
66
68
  end
67
69
 
68
70
  # Matches the instance type in a singleton-class context
69
71
  def self.attached_class
70
- T::Types::AttachedClassType.new
72
+ T::Types::AttachedClassType::Private::INSTANCE
71
73
  end
72
74
 
73
75
  # Matches any class that subclasses or includes the provided class
@@ -103,7 +105,7 @@ module T
103
105
  end
104
106
  end
105
107
 
106
- # References a type paramater which was previously defined with
108
+ # References a type parameter which was previously defined with
107
109
  # `type_parameters`.
108
110
  #
109
111
  # This is used for generic methods. Example usage:
@@ -282,4 +284,3 @@ module T
282
284
  end
283
285
  end
284
286
  end
285
- # rubocop:enable PrisonGuard/UseOpusTypesShortcut
@@ -4,7 +4,8 @@
4
4
  require_relative 'private/methods/_methods'
5
5
 
6
6
  # Work around an interaction bug with sorbet-runtime and rspec-mocks,
7
- # which occurs when using *_any_instance_of and and_call_original.
7
+ # which occurs when using message expectations (*_any_instance_of,
8
+ # expect, allow) and and_call_original.
8
9
  #
9
10
  # When a sig is defined, sorbet-runtime will replace the sigged method
10
11
  # with a wrapper that, upon first invocation, re-wraps the method with a faster
@@ -22,17 +23,73 @@ require_relative 'private/methods/_methods'
22
23
  #
23
24
  # We work around this by forcing re-wrapping before rspec stores a reference
24
25
  # to the method.
25
- if defined? ::RSpec::Mocks::AnyInstance
26
+ if defined? ::RSpec::Mocks
26
27
  module T
27
28
  module CompatibilityPatches
28
- module RecorderExtensions
29
- def observe!(method_name)
30
- method = @klass.instance_method(method_name.to_sym)
31
- T::Private::Methods.maybe_run_sig_block_for_method(method)
32
- super(method_name)
29
+ module RSpecCompatibility
30
+ module RecorderExtensions
31
+ def observe!(method_name)
32
+ method = @klass.instance_method(method_name.to_sym)
33
+ T::Private::Methods.maybe_run_sig_block_for_method(method)
34
+ super(method_name)
35
+ end
33
36
  end
37
+ ::RSpec::Mocks::AnyInstance::Recorder.prepend(RecorderExtensions) if defined?(::RSpec::Mocks::AnyInstance::Recorder)
38
+
39
+ module MethodDoubleExtensions
40
+ def initialize(object, method_name, proxy)
41
+ if ::Kernel.instance_method(:respond_to?).bind(object).call(method_name, true)
42
+ method = ::RSpec::Support.method_handle_for(object, method_name)
43
+ T::Private::Methods.maybe_run_sig_block_for_method(method)
44
+ end
45
+ super(object, method_name, proxy)
46
+ end
47
+ end
48
+ ::RSpec::Mocks::MethodDouble.prepend(MethodDoubleExtensions) if defined?(::RSpec::Mocks::MethodDouble)
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ # Work around for sorbet-runtime wrapped methods.
55
+ #
56
+ # When a sig is defined, sorbet-runtime will replace the sigged method
57
+ # with a wrapper. Those wrapper methods look like `foo(*args, &blk)`
58
+ # so that wrappers can handle and pass on all the arguments supplied.
59
+ #
60
+ # However, that creates a problem with runtime reflection on the methods,
61
+ # since when a sigged method is introspected, it will always return its
62
+ # `arity` as `-1`, its `parameters` as `[[:rest, :args], [:block, :blk]]`,
63
+ # and its `source_location` as `[<some_file_in_sorbet>, <some_line_number>]`.
64
+ #
65
+ # This might be a problem for some applications that rely on getting the
66
+ # correct information from these methods.
67
+ #
68
+ # This compatibility module, when prepended to the `Method` class, would fix
69
+ # the return values of `arity`, `parameters` and `source_location`.
70
+ #
71
+ # @example
72
+ # require 'sorbet-runtime'
73
+ # ::Method.prepend(T::CompatibilityPatches::MethodExtensions)
74
+ module T
75
+ module CompatibilityPatches
76
+ module MethodExtensions
77
+ def arity
78
+ arity = super
79
+ return arity if arity != -1 || self.is_a?(Proc)
80
+ sig = T::Private::Methods.signature_for_method(self)
81
+ sig ? sig.method.arity : arity
82
+ end
83
+
84
+ def source_location
85
+ sig = T::Private::Methods.signature_for_method(self)
86
+ sig ? sig.method.source_location : super
87
+ end
88
+
89
+ def parameters
90
+ sig = T::Private::Methods.signature_for_method(self)
91
+ sig ? sig.method.parameters : super
34
92
  end
35
- ::RSpec::Mocks::AnyInstance::Recorder.prepend(RecorderExtensions)
36
93
  end
37
94
  end
38
95
  end
@@ -248,7 +248,7 @@ module T::Configuration
248
248
  end
249
249
 
250
250
  private_class_method def self.log_info_handler_default(str, extra)
251
- puts "#{str}, extra: #{extra}" # rubocop:disable PrisonGuard/NoBarePuts
251
+ puts "#{str}, extra: #{extra}"
252
252
  end
253
253
 
254
254
  def self.log_info_handler(str, extra)
@@ -282,7 +282,7 @@ module T::Configuration
282
282
  end
283
283
 
284
284
  private_class_method def self.soft_assert_handler_default(str, extra)
285
- puts "#{str}, extra: #{extra}" # rubocop:disable PrisonGuard/NoBarePuts
285
+ puts "#{str}, extra: #{extra}"
286
286
  end
287
287
 
288
288
  def self.soft_assert_handler(str, extra)
@@ -336,7 +336,7 @@ module T::Configuration
336
336
  # T::Configuration.scalar_types = ["NilClass", "TrueClass", "FalseClass", ...]
337
337
  def self.scalar_types=(values)
338
338
  if values.nil?
339
- @scalar_tyeps = values
339
+ @scalar_types = values
340
340
  else
341
341
  bad_values = values.select {|v| v.class != String}
342
342
  unless bad_values.empty?
data/lib/types/enum.rb CHANGED
@@ -57,6 +57,17 @@ class T::Enum
57
57
  @values
58
58
  end
59
59
 
60
+ # This exists for compatibility with the interface of `Hash` & mostly to support
61
+ # the HashEachMethods Rubocop.
62
+ sig {params(blk: T.nilable(T.proc.params(arg0: T.attached_class).void)).returns(T.any(T::Enumerator[T.attached_class], T::Array[T.attached_class]))}
63
+ def self.each_value(&blk)
64
+ if blk
65
+ values.each(&blk)
66
+ else
67
+ values.each
68
+ end
69
+ end
70
+
60
71
  # Convert from serialized value to enum instance
61
72
  #
62
73
  # Note: It would have been nice to make this method final before people started overriding it.
@@ -88,7 +99,7 @@ class T::Enum
88
99
 
89
100
  # Note: It would have been nice to make this method final before people started overriding it.
90
101
  # @return [Boolean] Does the given serialized value correspond with any of this enum's values.
91
- sig {overridable.params(serialized_val: SerializedVal).returns(T::Boolean)}
102
+ sig {overridable.params(serialized_val: SerializedVal).returns(T::Boolean).checked(:never)}
92
103
  def self.has_serialized?(serialized_val)
93
104
  if @mapping.nil?
94
105
  raise "Attempting to access serialization map of #{self.class} before it has been initialized." \
@@ -97,17 +108,8 @@ class T::Enum
97
108
  @mapping.include?(serialized_val)
98
109
  end
99
110
 
100
-
101
- ## T::Props::CustomType
102
-
103
- # Note: Failed CriticalMethodsNoRuntimeTypingTest
104
- sig {params(value: T.untyped).returns(T::Boolean).checked(:never)}
105
- def self.instance?(value)
106
- value.is_a?(self)
107
- end
108
-
109
111
  # Note: Failed CriticalMethodsNoRuntimeTypingTest
110
- sig {params(instance: T.nilable(T::Enum)).returns(SerializedVal).checked(:never)}
112
+ sig {override.params(instance: T.nilable(T::Enum)).returns(SerializedVal).checked(:never)}
111
113
  def self.serialize(instance)
112
114
  # This is needed otherwise if a Chalk::ODM::Document with a property of the shape
113
115
  # T::Hash[T.nilable(MyEnum), Integer] and a value that looks like {nil => 0} is
@@ -124,7 +126,7 @@ class T::Enum
124
126
  end
125
127
 
126
128
  # Note: Failed CriticalMethodsNoRuntimeTypingTest
127
- sig {params(mongo_value: SerializedVal).returns(T.attached_class).checked(:never)}
129
+ sig {override.params(mongo_value: SerializedVal).returns(T.attached_class).checked(:never)}
128
130
  def self.deserialize(mongo_value)
129
131
  if self == T::Enum
130
132
  raise "Cannot call T::Enum.deserialize directly. You must call on a specific child class."
@@ -249,7 +251,7 @@ class T::Enum
249
251
 
250
252
 
251
253
  sig {params(serialized_val: SerializedVal).void}
252
- private def initialize(serialized_val=nil)
254
+ def initialize(serialized_val=nil)
253
255
  raise 'T::Enum is abstract' if self.class == T::Enum
254
256
  if !self.class.started_initializing?
255
257
  raise "Must instantiate all enum values of #{self.class} inside 'enums do'."
@@ -261,6 +263,7 @@ class T::Enum
261
263
  serialized_val = serialized_val.frozen? ? serialized_val : serialized_val.dup.freeze
262
264
  @serialized_val = T.let(serialized_val, T.nilable(SerializedVal))
263
265
  @const_name = T.let(nil, T.nilable(Symbol))
266
+ self.class._register_instance(self)
264
267
  end
265
268
 
266
269
  sig {returns(NilClass).checked(:never)}
@@ -298,6 +301,13 @@ class T::Enum
298
301
  @fully_initialized ||= false
299
302
  end
300
303
 
304
+ # Maintains the order in which values are defined
305
+ sig {params(instance: T.untyped).void}
306
+ def self._register_instance(instance)
307
+ @values ||= []
308
+ @values << T.cast(instance, T.attached_class)
309
+ end
310
+
301
311
  # Entrypoint for allowing people to register new enum values.
302
312
  # All enum values must be defined within this block.
303
313
  sig {params(blk: T.proc.void).void}
@@ -308,13 +318,14 @@ class T::Enum
308
318
 
309
319
  @started_initializing = true
310
320
 
321
+ @values = T.let(nil, T.nilable(T::Array[T.attached_class]))
322
+
311
323
  yield
312
324
 
313
- @values = T.let(nil, T.nilable(T::Array[T.attached_class]))
314
325
  @mapping = T.let(nil, T.nilable(T::Hash[SerializedVal, T.attached_class]))
326
+ @mapping = {}
315
327
 
316
328
  # Freeze the Enum class and bind the constant names into each of the instances.
317
- @mapping = {}
318
329
  self.constants(false).each do |const_name|
319
330
  instance = self.const_get(const_name, false)
320
331
  if !instance.is_a?(self)
@@ -329,8 +340,14 @@ class T::Enum
329
340
  end
330
341
  @mapping[serialized] = instance
331
342
  end
332
- @values = @mapping.values.sort.freeze
343
+ @values.freeze
333
344
  @mapping.freeze
345
+
346
+ orphaned_instances = T.must(@values) - @mapping.values
347
+ if !orphaned_instances.empty?
348
+ raise "Enum values must be assigned to constants: #{orphaned_instances.map {|v| v.instance_variable_get('@serialized_val')}}"
349
+ end
350
+
334
351
  @fully_initialized = true
335
352
  end
336
353
 
data/lib/types/generic.rb CHANGED
@@ -14,10 +14,10 @@ module T::Generic
14
14
  end
15
15
 
16
16
  def type_member(variance=:invariant, fixed: nil, lower: T.untyped, upper: BasicObject)
17
- T::Types::TypeMember.new(variance) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
17
+ T::Types::TypeMember.new(variance)
18
18
  end
19
19
 
20
20
  def type_template(variance=:invariant, fixed: nil, lower: T.untyped, upper: BasicObject)
21
- T::Types::TypeTemplate.new(variance) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
21
+ T::Types::TypeTemplate.new(variance)
22
22
  end
23
23
  end
@@ -83,11 +83,11 @@ class T::InterfaceWrapper
83
83
  end
84
84
  end
85
85
 
86
- def kind_of?(other) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
86
+ def kind_of?(other)
87
87
  is_a?(other)
88
88
  end
89
89
 
90
- def is_a?(other) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
90
+ def is_a?(other)
91
91
  if !other.is_a?(Module)
92
92
  raise TypeError.new("class or module required")
93
93
  end
@@ -99,13 +99,13 @@ class T::InterfaceWrapper
99
99
 
100
100
  # Prefixed because we're polluting the namespace of the interface we're wrapping, and we don't
101
101
  # want anyone else (besides dynamic_cast) calling it.
102
- def __target_obj_DO_NOT_USE
102
+ def __target_obj_DO_NOT_USE # rubocop:disable Naming/MethodName
103
103
  @target_obj
104
104
  end
105
105
 
106
106
  # Prefixed because we're polluting the namespace of the interface we're wrapping, and we don't
107
107
  # want anyone else (besides wrapped_dynamic_cast) calling it.
108
- def __interface_mod_DO_NOT_USE
108
+ def __interface_mod_DO_NOT_USE # rubocop:disable Naming/MethodName
109
109
  @interface_mod
110
110
  end
111
111
 
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module T::NonForcingConstants
5
+ # NOTE: This method is documented on the RBI in Sorbet's payload, so that it
6
+ # shows up in the hover/completion documentation via LSP.
7
+ T::Sig::WithoutRuntime.sig {params(val: BasicObject, klass: String, package: T.nilable(String)).returns(T::Boolean)}
8
+ def self.non_forcing_is_a?(val, klass, package: nil)
9
+ # TODO(gdritter): once we have a runtime implementation of
10
+ # packages, we'll need to actually handle the `package` argument
11
+ # here.
12
+ method_name = "T::NonForcingConstants.non_forcing_is_a?"
13
+ if klass.empty?
14
+ raise ArgumentError.new("The string given to `#{method_name}` must not be empty")
15
+ end
16
+
17
+ current_klass = T.let(nil, T.nilable(Module))
18
+ current_prefix = T.let(nil, T.nilable(String))
19
+
20
+ parts = klass.split('::')
21
+ parts.each do |part|
22
+ if current_klass.nil?
23
+ # First iteration
24
+ if part != "" && package.nil?
25
+ # if we've supplied a package, we're probably running in
26
+ # package mode, which means absolute references are
27
+ # meaningless
28
+ raise ArgumentError.new("The string given to `#{method_name}` must be an absolute constant reference that starts with `::`")
29
+ end
30
+
31
+ current_klass = Object
32
+ current_prefix = ''
33
+ else
34
+ if current_klass.autoload?(part)
35
+ # There's an autoload registered for that constant, which means it's not
36
+ # yet loaded. `value` can't be an instance of something not yet loaded.
37
+ return false
38
+ end
39
+
40
+ # Sorbet guarantees that the string is an absolutely resolved name.
41
+ search_inheritance_chain = false
42
+ if !current_klass.const_defined?(part, search_inheritance_chain)
43
+ return false
44
+ end
45
+
46
+ current_klass = current_klass.const_get(part)
47
+ current_prefix = "#{current_prefix}::#{part}"
48
+
49
+ if !Module.===(current_klass)
50
+ raise ArgumentError.new("#{current_prefix} is not a class or module")
51
+ end
52
+ end
53
+ end
54
+
55
+ return current_klass.===(val)
56
+ end
57
+ end
@@ -12,11 +12,11 @@
12
12
  # modules that override the `hash` method with something completely broken.
13
13
  module T::Private::Abstract::Data
14
14
  def self.get(mod, key)
15
- mod.instance_variable_get("@opus_abstract__#{key}") # rubocop:disable PrisonGuard/NoLurkyInstanceVariableAccess
15
+ mod.instance_variable_get("@opus_abstract__#{key}")
16
16
  end
17
17
 
18
18
  def self.set(mod, key, value)
19
- mod.instance_variable_set("@opus_abstract__#{key}", value) # rubocop:disable PrisonGuard/NoLurkyInstanceVariableAccess
19
+ mod.instance_variable_set("@opus_abstract__#{key}", value)
20
20
  end
21
21
 
22
22
  def self.key?(mod, key)
@@ -40,6 +40,9 @@ module T::Private::Abstract::Declare
40
40
  end
41
41
  super(*args, &blk)
42
42
  end
43
+ if mod.respond_to?(:ruby2_keywords, true)
44
+ mod.send(:ruby2_keywords, :initialize)
45
+ end
43
46
  end
44
47
  end
45
48
  end
@@ -2,6 +2,14 @@
2
2
  # typed: false
3
3
 
4
4
  module T::Private
5
+ # Dynamically confirm that `value` is recursively a valid value of
6
+ # type `type`, including recursively through collections. Note that
7
+ # in some cases this runtime check can be very expensive, especially
8
+ # with large collections of objects.
9
+ def self.check_type_recursive!(value, type)
10
+ T::Private::Casts.cast_recursive(value, type, cast_method: "T.check_type_recursive!")
11
+ end
12
+
5
13
  module Casts
6
14
  def self.cast(value, type, cast_method:)
7
15
  begin
@@ -18,5 +26,24 @@ module T::Private
18
26
  value
19
27
  end
20
28
  end
29
+
30
+ # there's a lot of shared logic with the above one, but factoring
31
+ # it out like this makes it easier to hopefully one day delete
32
+ # this one
33
+ def self.cast_recursive(value, type, cast_method:)
34
+ begin
35
+ error = T::Utils.coerce(type).error_message_for_obj_recursive(value)
36
+ return value unless error
37
+
38
+ caller_loc = T.must(caller_locations(2..2)).first
39
+
40
+ suffix = "Caller: #{T.must(caller_loc).path}:#{T.must(caller_loc).lineno}"
41
+
42
+ raise TypeError.new("#{cast_method}: #{error}\n#{suffix}")
43
+ rescue TypeError => e # raise into rescue to ensure e.backtrace is populated
44
+ T::Configuration.inline_type_error_handler(e)
45
+ value
46
+ end
47
+ end
21
48
  end
22
49
  end
@@ -33,16 +33,16 @@ module T::Private::ClassUtils
33
33
  if @overwritten
34
34
  # The original method was overwritten. Overwrite again to restore it.
35
35
  T::Configuration.without_ruby_warnings do
36
- @mod.send(:define_method, @old_method.name, @old_method) # rubocop:disable PrisonGuard/UsePublicSend
36
+ @mod.send(:define_method, @old_method.name, @old_method)
37
37
  end
38
38
  else
39
39
  # The original method was in an ancestor. Restore it by removing the overriding method.
40
- @mod.send(:remove_method, @old_method.name) # rubocop:disable PrisonGuard/UsePublicSend
40
+ @mod.send(:remove_method, @old_method.name)
41
41
  end
42
42
 
43
43
  # Restore the visibility. Note that we need to do this even when we call remove_method
44
44
  # above, because the module may have set custom visibility for a method it inherited.
45
- @mod.send(@visibility, @old_method.name) # rubocop:disable PrisonGuard/UsePublicSend
45
+ @mod.send(@visibility, @old_method.name)
46
46
 
47
47
  nil
48
48
  end
@@ -97,10 +97,13 @@ module T::Private::ClassUtils
97
97
  overwritten = original_owner == mod
98
98
  T::Configuration.without_ruby_warnings do
99
99
  T::Private::DeclState.current.without_on_method_added do
100
- mod.send(:define_method, name, &blk) # rubocop:disable PrisonGuard/UsePublicSend
100
+ mod.send(:define_method, name, &blk)
101
+ if blk.arity < 0 && mod.respond_to?(:ruby2_keywords, true)
102
+ mod.send(:ruby2_keywords, name)
103
+ end
101
104
  end
102
105
  end
103
- mod.send(original_visibility, name) # rubocop:disable PrisonGuard/UsePublicSend
106
+ mod.send(original_visibility, name)
104
107
  new_method = mod.instance_method(name)
105
108
 
106
109
  ReplacedMethod.new(mod, original_method, new_method, overwritten, original_visibility)