sorbet-runtime 0.5.5794 → 0.5.6539

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sorbet-runtime.rb +0 -2
  3. data/lib/types/_types.rb +28 -8
  4. data/lib/types/compatibility_patches.rb +0 -2
  5. data/lib/types/configuration.rb +136 -6
  6. data/lib/types/enum.rb +24 -2
  7. data/lib/types/generic.rb +2 -3
  8. data/lib/types/helpers.rb +19 -2
  9. data/lib/types/interface_wrapper.rb +4 -4
  10. data/lib/types/non_forcing_constants.rb +38 -20
  11. data/lib/types/private/abstract/data.rb +2 -2
  12. data/lib/types/private/abstract/validate.rb +6 -6
  13. data/lib/types/private/casts.rb +27 -0
  14. data/lib/types/private/class_utils.rb +5 -5
  15. data/lib/types/private/final.rb +0 -1
  16. data/lib/types/private/methods/_methods.rb +255 -140
  17. data/lib/types/private/methods/call_validation.rb +54 -982
  18. data/lib/types/private/methods/call_validation_2_6.rb +1203 -0
  19. data/lib/types/private/methods/call_validation_2_7.rb +1203 -0
  20. data/lib/types/private/methods/decl_builder.rb +7 -3
  21. data/lib/types/private/methods/modes.rb +3 -3
  22. data/lib/types/private/methods/signature.rb +31 -11
  23. data/lib/types/private/methods/signature_validation.rb +14 -17
  24. data/lib/types/private/mixins/mixins.rb +5 -5
  25. data/lib/types/private/sealed.rb +17 -2
  26. data/lib/types/private/types/type_alias.rb +5 -0
  27. data/lib/types/props/_props.rb +2 -1
  28. data/lib/types/props/constructor.rb +9 -3
  29. data/lib/types/props/decorator.rb +48 -41
  30. data/lib/types/props/generated_code_validation.rb +18 -9
  31. data/lib/types/props/has_lazily_specialized_methods.rb +44 -1
  32. data/lib/types/props/plugin.rb +2 -2
  33. data/lib/types/props/private/deserializer_generator.rb +7 -12
  34. data/lib/types/props/private/serde_transform.rb +12 -18
  35. data/lib/types/props/private/setter_factory.rb +74 -11
  36. data/lib/types/props/serializable.rb +41 -11
  37. data/lib/types/props/type_validation.rb +2 -2
  38. data/lib/types/props/weak_constructor.rb +14 -9
  39. data/lib/types/sig.rb +4 -4
  40. data/lib/types/types/attached_class.rb +5 -1
  41. data/lib/types/types/base.rb +16 -1
  42. data/lib/types/types/fixed_array.rb +28 -2
  43. data/lib/types/types/fixed_hash.rb +21 -12
  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 +37 -1
  48. data/lib/types/types/type_variable.rb +1 -1
  49. data/lib/types/types/typed_array.rb +7 -2
  50. data/lib/types/types/typed_enumerable.rb +20 -10
  51. data/lib/types/types/typed_enumerator.rb +7 -2
  52. data/lib/types/types/typed_hash.rb +8 -3
  53. data/lib/types/types/typed_range.rb +7 -2
  54. data/lib/types/types/typed_set.rb +7 -2
  55. data/lib/types/types/union.rb +38 -7
  56. data/lib/types/types/untyped.rb +4 -0
  57. data/lib/types/utils.rb +17 -33
  58. metadata +49 -7
  59. data/lib/types/profile.rb +0 -27
  60. data/lib/types/runtime_profiled.rb +0 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac9a48252c9529d0ca91f96108b141c85388c88180281e5c8a682b16c11a9d5a
4
- data.tar.gz: 31dc95eabc00327b1672a8fc142da7dc47f0ee0699fd4112358042248628675b
3
+ metadata.gz: 3594dc0c726d2a7189c7544226a6ced4240f4a6df2c18bdae635cc30bb223e7b
4
+ data.tar.gz: dae60008d7f685ecdf231edefdf0b01b595c597c6ae646e7ba7070eada079fa2
5
5
  SHA512:
6
- metadata.gz: 21b1ef4ffdd76365effafe0c6a3eea4b15c1f9c36f2f402a1c8ba382d2f03d89f2202c1b8ac2aa82c315c7471f0989f7501d1888a49f67d401d33d26ac8e4d3a
7
- data.tar.gz: 0f4c110725910ae452ea72fe6852538aa1c31cbb576dc242fe3631bd318e3b2bfda7b0fe3b05362584bd53885c9788a4f3eb2d5920d285c1c39ce727fb0ebd14
6
+ metadata.gz: 519bf1b1c4f04792d88c817a9bb3a213b01e783a96597e1e328a8a5c9736e78ff7a0a93ef31d56787fd9468d09980e4670edffcd71f59ff299cc7a09a80a714b
7
+ data.tar.gz: 0150d316fb26d07fd0693d3b948dfaa6fe1979053dc12f9811c5c9c6d29b711affaa3e6be16a34a08fd6abf5a1db816b4872b7b655895353cdf65094f7e0ad5c
@@ -19,10 +19,8 @@ require 'set'
19
19
 
20
20
  # These are pre-reqs for almost everything in here.
21
21
  require_relative 'types/configuration'
22
- require_relative 'types/profile'
23
22
  require_relative 'types/_types'
24
23
  require_relative 'types/private/decl_state'
25
- require_relative 'types/runtime_profiled'
26
24
  require_relative 'types/private/class_utils'
27
25
  require_relative 'types/private/runtime_levels'
28
26
  require_relative 'types/private/methods/_methods'
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
@@ -145,6 +147,25 @@ module T
145
147
  Private::Casts.cast(value, type, cast_method: "T.let")
146
148
  end
147
149
 
150
+ # Tells the type checker to treat `self` in the current block as `type`.
151
+ # Useful for blocks that are captured and executed later with instance_exec.
152
+ # Use like:
153
+ #
154
+ # seconds = lambda do
155
+ # T.bind(self, NewBinding)
156
+ # ...
157
+ # end
158
+ #
159
+ # `T.bind` behaves like `T.cast` in that it is assumed to be true statically.
160
+ #
161
+ # If `checked` is true, raises an exception at runtime if the value
162
+ # doesn't match the type (this is the default).
163
+ def self.bind(value, type, checked: true)
164
+ return value unless checked
165
+
166
+ Private::Casts.cast(value, type, cast_method: "T.bind")
167
+ end
168
+
148
169
  # Tells the typechecker to ensure that `value` is of type `type` (if not, the typechecker will
149
170
  # fail). Use this for debugging typechecking errors, or to ensure that type information is
150
171
  # statically known and being checked appropriately. If `checked` is true, raises an exception at
@@ -282,4 +303,3 @@ module T
282
303
  end
283
304
  end
284
305
  end
285
- # rubocop:enable PrisonGuard/UseOpusTypesShortcut
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  # typed: ignore
3
3
 
4
- require_relative 'private/methods/_methods'
5
-
6
4
  # Work around an interaction bug with sorbet-runtime and rspec-mocks,
7
5
  # which occurs when using message expectations (*_any_instance_of,
8
6
  # expect, allow) and and_call_original.
@@ -2,6 +2,9 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module T::Configuration
5
+ # Cache this comparisonn to avoid two allocations all over the place.
6
+ AT_LEAST_RUBY_2_7 = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7')
7
+
5
8
  # Announces to Sorbet that we are currently in a test environment, so it
6
9
  # should treat any sigs which are marked `.checked(:tests)` as if they were
7
10
  # just a normal sig.
@@ -42,6 +45,65 @@ module T::Configuration
42
45
  T::Private::Methods.set_final_checks_on_hooks(false)
43
46
  end
44
47
 
48
+ @include_value_in_type_errors = true
49
+ # Whether to include values in TypeError messages.
50
+ #
51
+ # Including values is useful for debugging, but can potentially leak
52
+ # sensitive information to logs.
53
+ #
54
+ # @return [T::Boolean]
55
+ def self.include_value_in_type_errors?
56
+ @include_value_in_type_errors
57
+ end
58
+
59
+ # Configure if type errors excludes the value of the problematic type.
60
+ #
61
+ # The default is to include values in type errors:
62
+ # TypeError: Expected type Integer, got String with value "foo"
63
+ #
64
+ # When values are excluded from type errors:
65
+ # TypeError: Expected type Integer, got String
66
+ def self.exclude_value_in_type_errors
67
+ @include_value_in_type_errors = false
68
+ end
69
+
70
+ # Opposite of exclude_value_in_type_errors.
71
+ # (Including values in type errors is the default)
72
+ def self.include_value_in_type_errors
73
+ @include_value_in_type_errors = true
74
+ end
75
+
76
+ # Whether VM-defined prop serialization/deserialization routines can be enabled.
77
+ #
78
+ # @return [T::Boolean]
79
+ def self.can_enable_vm_prop_serde?
80
+ T::Props::Private::DeserializerGenerator.respond_to?(:generate2)
81
+ end
82
+
83
+ # Whether to use VM-defined prop serialization/deserialization routines.
84
+ #
85
+ # The default is to use runtime codegen inside sorbet-runtime itself.
86
+ #
87
+ # @return [T::Boolean]
88
+ def self.use_vm_prop_serde?
89
+ @use_vm_prop_serde || false
90
+ end
91
+
92
+ # Enable using VM-defined prop serialization/deserialization routines.
93
+ #
94
+ # This method is likely to break things outside of Stripe's systems.
95
+ def self.enable_vm_prop_serde
96
+ if !can_enable_vm_prop_serde?
97
+ hard_assert_handler('Ruby VM is not setup to use VM-defined prop serde')
98
+ end
99
+ @use_vm_prop_serde = true
100
+ end
101
+
102
+ # Disable using VM-defined prop serialization/deserialization routines.
103
+ def self.disable_vm_prop_serde
104
+ @use_vm_prop_serde = false
105
+ end
106
+
45
107
  # Configure the default checked level for a sig with no explicit `.checked`
46
108
  # builder. When unset, the default checked level is `:always`.
47
109
  #
@@ -248,7 +310,7 @@ module T::Configuration
248
310
  end
249
311
 
250
312
  private_class_method def self.log_info_handler_default(str, extra)
251
- puts "#{str}, extra: #{extra}" # rubocop:disable PrisonGuard/NoBarePuts
313
+ puts "#{str}, extra: #{extra}"
252
314
  end
253
315
 
254
316
  def self.log_info_handler(str, extra)
@@ -282,7 +344,7 @@ module T::Configuration
282
344
  end
283
345
 
284
346
  private_class_method def self.soft_assert_handler_default(str, extra)
285
- puts "#{str}, extra: #{extra}" # rubocop:disable PrisonGuard/NoBarePuts
347
+ puts "#{str}, extra: #{extra}"
286
348
  end
287
349
 
288
350
  def self.soft_assert_handler(str, extra)
@@ -338,7 +400,7 @@ module T::Configuration
338
400
  if values.nil?
339
401
  @scalar_types = values
340
402
  else
341
- bad_values = values.select {|v| v.class != String}
403
+ bad_values = values.reject {|v| v.class == String}
342
404
  unless bad_values.empty?
343
405
  raise ArgumentError.new("Provided values must all be class name strings.")
344
406
  end
@@ -347,7 +409,7 @@ module T::Configuration
347
409
  end
348
410
  end
349
411
 
350
- @default_scalar_types = Set.new(%w{
412
+ @default_scalar_types = Set.new(%w[
351
413
  NilClass
352
414
  TrueClass
353
415
  FalseClass
@@ -357,12 +419,80 @@ module T::Configuration
357
419
  Symbol
358
420
  Time
359
421
  T::Enum
360
- }).freeze
422
+ ]).freeze
361
423
 
362
424
  def self.scalar_types
363
425
  @scalar_types || @default_scalar_types
364
426
  end
365
427
 
428
+ # Guard against overrides of `name` or `to_s`
429
+ MODULE_NAME = Module.instance_method(:name)
430
+ private_constant :MODULE_NAME
431
+
432
+ if T::Configuration::AT_LEAST_RUBY_2_7
433
+ @default_module_name_mangler = ->(type) {MODULE_NAME.bind_call(type)}
434
+ else
435
+ @default_module_name_mangler = ->(type) {MODULE_NAME.bind(type).call}
436
+ end
437
+
438
+ @module_name_mangler = nil
439
+
440
+ def self.module_name_mangler
441
+ @module_name_mangler || @default_module_name_mangler
442
+ end
443
+
444
+ # Set to override the default behavior for converting types
445
+ # to names in generated code. Used by the runtime implementation
446
+ # associated with `--stripe-packages` mode.
447
+ #
448
+ # @param [Lambda, Proc, nil] value Proc that converts a type (Class/Module)
449
+ # to a String (pass nil to reset to default behavior)
450
+ def self.module_name_mangler=(handler)
451
+ @module_name_mangler = handler
452
+ end
453
+
454
+ # Set to a PII handler function. This will be called with the `sensitivity:`
455
+ # annotations on things that use `T::Props` and can modify them ahead-of-time.
456
+ #
457
+ # @param [Lambda, Proc, nil] value Proc that takes a hash mapping symbols to the
458
+ # prop values. Pass nil to avoid changing `sensitivity:` annotations.
459
+ def self.normalize_sensitivity_and_pii_handler=(handler)
460
+ @sensitivity_and_pii_handler = handler
461
+ end
462
+
463
+ def self.normalize_sensitivity_and_pii_handler
464
+ @sensitivity_and_pii_handler
465
+ end
466
+
467
+ @redaction_handler = nil
468
+ # Set to a redaction handling function. This will be called when the
469
+ # `_redacted` version of a prop reader is used. By default this is set to
470
+ # `nil` and will raise an exception when the redacted version of a prop is
471
+ # accessed.
472
+ #
473
+ # @param [Lambda, Proc, nil] value Proc that converts a value into its
474
+ # redacted version according to the spec passed as the second argument.
475
+ def self.redaction_handler=(handler)
476
+ @redaction_handler = handler
477
+ end
478
+
479
+ def self.redaction_handler
480
+ @redaction_handler
481
+ end
482
+
483
+ # Set to a function which can get the 'owner' of a class. This is
484
+ # used in reporting deserialization errors
485
+ #
486
+ # @param [Lambda, Proc, nil] value Proc that takes a class and
487
+ # produces its owner, or `nil` if it does not have one.
488
+ def self.class_owner_finder=(handler)
489
+ @class_owner_finder = handler
490
+ end
491
+
492
+ def self.class_owner_finder
493
+ @class_owner_finder
494
+ end
495
+
366
496
  # Temporarily disable ruby warnings while executing the given block. This is
367
497
  # useful when doing something that would normally cause a warning to be
368
498
  # emitted in Ruby verbose mode ($VERBOSE = true).
@@ -398,7 +528,7 @@ module T::Configuration
398
528
  # should be allowed. Useful to whitelist benign violations, like shim files
399
529
  # generated for an autoloader.
400
530
  def self.sealed_violation_whitelist=(sealed_violation_whitelist)
401
- if @sealed_violation_whitelist != nil
531
+ if !@sealed_violation_whitelist.nil?
402
532
  raise ArgumentError.new("Cannot overwrite sealed_violation_whitelist after setting it")
403
533
  end
404
534
 
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." \
@@ -240,7 +251,7 @@ class T::Enum
240
251
 
241
252
 
242
253
  sig {params(serialized_val: SerializedVal).void}
243
- private def initialize(serialized_val=nil)
254
+ def initialize(serialized_val=nil)
244
255
  raise 'T::Enum is abstract' if self.class == T::Enum
245
256
  if !self.class.started_initializing?
246
257
  raise "Must instantiate all enum values of #{self.class} inside 'enums do'."
@@ -346,4 +357,15 @@ class T::Enum
346
357
 
347
358
  raise "Inheriting from children of T::Enum is prohibited" if self != T::Enum
348
359
  end
360
+
361
+ # Marshal support
362
+ sig {params(_level: Integer).returns(String)}
363
+ def _dump(_level)
364
+ Marshal.dump(serialize)
365
+ end
366
+
367
+ sig {params(args: String).returns(T.attached_class)}
368
+ def self._load(args)
369
+ deserialize(Marshal.load(args))
370
+ end
349
371
  end
data/lib/types/generic.rb CHANGED
@@ -2,7 +2,6 @@
2
2
  # typed: true
3
3
 
4
4
  # Use as a mixin with extend (`extend T::Generic`).
5
- # Docs at https://hackpad.corp.stripe.com/Type-Validation-in-pay-server-1JaoTHir5Mo.
6
5
  module T::Generic
7
6
  include T::Helpers
8
7
  include Kernel
@@ -14,10 +13,10 @@ module T::Generic
14
13
  end
15
14
 
16
15
  def type_member(variance=:invariant, fixed: nil, lower: T.untyped, upper: BasicObject)
17
- T::Types::TypeMember.new(variance) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
16
+ T::Types::TypeMember.new(variance)
18
17
  end
19
18
 
20
19
  def type_template(variance=:invariant, fixed: nil, lower: T.untyped, upper: BasicObject)
21
- T::Types::TypeTemplate.new(variance) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
20
+ T::Types::TypeTemplate.new(variance)
22
21
  end
23
22
  end
data/lib/types/helpers.rb CHANGED
@@ -33,7 +33,24 @@ module T::Helpers
33
33
  # end
34
34
  #
35
35
  # Except that it is statically analyzed by sorbet.
36
- def mixes_in_class_methods(mod)
37
- Private::Mixins.declare_mixes_in_class_methods(self, mod)
36
+ def mixes_in_class_methods(mod, *mods)
37
+ Private::Mixins.declare_mixes_in_class_methods(self, [mod].concat(mods))
38
38
  end
39
+
40
+ # Specify an inclusion or inheritance requirement for `self`.
41
+ #
42
+ # Example:
43
+ #
44
+ # module MyHelper
45
+ # extend T::Helpers
46
+ #
47
+ # requires_ancestor Kernel
48
+ # end
49
+ #
50
+ # class MyClass < BasicObject # error: `MyClass` must include `Kernel` (required by `MyHelper`)
51
+ # include MyHelper
52
+ # end
53
+ #
54
+ # TODO: implement the checks in sorbet-runtime.
55
+ def requires_ancestor(mod, *mods); end
39
56
  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
 
@@ -2,15 +2,26 @@
2
2
  # typed: strict
3
3
 
4
4
  module T::NonForcingConstants
5
+ T::Sig::WithoutRuntime.sig {returns(T::Boolean)}
6
+ private_class_method def self.stripe_packages_enabled?
7
+ const_defined?('StripePackages') && const_get('StripePackages').enabled?
8
+ end
9
+
5
10
  # NOTE: This method is documented on the RBI in Sorbet's payload, so that it
6
11
  # shows up in the hover/completion documentation via LSP.
7
- T::Sig::WithoutRuntime.sig {params(val: BasicObject, klass: String).returns(T::Boolean)}
8
- def self.non_forcing_is_a?(val, klass)
12
+ T::Sig::WithoutRuntime.sig {params(val: BasicObject, klass: String, package: T.nilable(String)).returns(T::Boolean)}
13
+ def self.non_forcing_is_a?(val, klass, package: nil)
9
14
  method_name = "T::NonForcingConstants.non_forcing_is_a?"
10
15
  if klass.empty?
11
16
  raise ArgumentError.new("The string given to `#{method_name}` must not be empty")
12
17
  end
13
18
 
19
+ # TODO(gdritter): this might not be want we want in a multipackage
20
+ # world; revisit this implementation we move on from the monopackage
21
+ if stripe_packages_enabled?
22
+ klass = "PkgRegistry::#{package}::#{klass}"
23
+ end
24
+
14
25
  current_klass = T.let(nil, T.nilable(Module))
15
26
  current_prefix = T.let(nil, T.nilable(String))
16
27
 
@@ -18,34 +29,41 @@ module T::NonForcingConstants
18
29
  parts.each do |part|
19
30
  if current_klass.nil?
20
31
  # First iteration
21
- if part != ""
32
+ if part != "" && package.nil?
33
+ # if we've supplied a package, we're probably running in
34
+ # package mode, which means absolute references are
35
+ # meaningless
22
36
  raise ArgumentError.new("The string given to `#{method_name}` must be an absolute constant reference that starts with `::`")
23
37
  end
24
38
 
25
39
  current_klass = Object
26
40
  current_prefix = ''
27
- else
28
- if current_klass.autoload?(part)
29
- # There's an autoload registered for that constant, which means it's not
30
- # yet loaded. `value` can't be an instance of something not yet loaded.
31
- return false
32
- end
33
41
 
34
- # Sorbet guarantees that the string is an absolutely resolved name.
35
- search_inheritance_chain = false
36
- if !current_klass.const_defined?(part, search_inheritance_chain)
37
- return false
38
- end
42
+ # if this had a :: prefix, then there's no more loading to
43
+ # do---skip to the next one
44
+ next if part == ""
45
+ end
39
46
 
40
- current_klass = current_klass.const_get(part)
41
- current_prefix = "#{current_prefix}::#{part}"
47
+ if current_klass.autoload?(part)
48
+ # There's an autoload registered for that constant, which means it's not
49
+ # yet loaded. `value` can't be an instance of something not yet loaded.
50
+ return false
51
+ end
42
52
 
43
- if !Module.===(current_klass)
44
- raise ArgumentError.new("#{current_prefix} is not a class or module")
45
- end
53
+ # Sorbet guarantees that the string is an absolutely resolved name.
54
+ search_inheritance_chain = false
55
+ if !current_klass.const_defined?(part, search_inheritance_chain)
56
+ return false
57
+ end
58
+
59
+ current_klass = current_klass.const_get(part)
60
+ current_prefix = "#{current_prefix}::#{part}"
61
+
62
+ if !Module.===(current_klass)
63
+ raise ArgumentError.new("#{current_prefix} is not a class or module")
46
64
  end
47
65
  end
48
66
 
49
- return current_klass.===(val)
67
+ current_klass.===(val)
50
68
  end
51
69
  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)
@@ -111,16 +111,16 @@ module T::Private::Abstract::Validate
111
111
  end
112
112
 
113
113
  private_class_method def self.describe_method(method, show_owner: true)
114
- if method.source_location
115
- loc = method.source_location.join(':')
114
+ loc = if method.source_location
115
+ method.source_location.join(':')
116
116
  else
117
- loc = "<unknown location>"
117
+ "<unknown location>"
118
118
  end
119
119
 
120
- if show_owner
121
- owner = " declared in #{method.owner}"
120
+ owner = if show_owner
121
+ " declared in #{method.owner}"
122
122
  else
123
- owner = ""
123
+ ""
124
124
  end
125
125
 
126
126
  " * `#{method.name}`#{owner} at #{loc}"
@@ -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,13 +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
101
  if blk.arity < 0 && mod.respond_to?(:ruby2_keywords, true)
102
102
  mod.send(:ruby2_keywords, name)
103
103
  end
104
104
  end
105
105
  end
106
- mod.send(original_visibility, name) # rubocop:disable PrisonGuard/UsePublicSend
106
+ mod.send(original_visibility, name)
107
107
  new_method = mod.instance_method(name)
108
108
 
109
109
  ReplacedMethod.new(mod, original_method, new_method, overwritten, original_visibility)
@@ -37,7 +37,6 @@ module T::Private::Final
37
37
  mod.extend(mod.is_a?(Class) ? NoInherit : NoIncludeExtend)
38
38
  mark_as_final_module(mod)
39
39
  mark_as_final_module(mod.singleton_class)
40
- T::Private::Methods.add_module_with_final(mod)
41
40
  T::Private::Methods.install_hooks(mod)
42
41
  end
43
42