sorbet-runtime 0.4.4331 → 0.4.4398

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
  SHA1:
3
- metadata.gz: 23fe6d1adf71c97852b2e1bd12133d79212b7855
4
- data.tar.gz: f4ba79a25eb179f3aeba3a0c758876c363a3dc3c
3
+ metadata.gz: af4d1867e5caafedef289561e2ad9413bffa3fad
4
+ data.tar.gz: 5652f7e1c9d2d54b253fcc6d2e5e5330c9c34691
5
5
  SHA512:
6
- metadata.gz: cec9cff7dcb4ef500914a038bf009180436bdecb607d6eedbf2c6692a6267360f8b0c48e90b5cd70c0b667761d6ad2db4e8e583bdd40bdb16043bc1122d45e23
7
- data.tar.gz: b9dda89def4e0ea5e5dd33e4393b93999a8226f788a9080a5ffbd689df880990ec290e01c843fcf7eee336c6ec466984811cb0d32abc21cad03fe2a635bd6880
6
+ metadata.gz: 430f858624d11168a7a5a7109115fc02d26bb919e4d14aa1bb94018abf88276d143a7550e23f320ce135be24d283dc70198d250a568339da9cb2a02ad94dfbbb
7
+ data.tar.gz: 1f1e4cdaba1209536d9cc5da0ef766f841c80a50963146f11dcda2374beaa62835dd79ce5d8c2d6093f354d176bbac42f34d03067b9adf23d391f50e553e329e
data/lib/types/_types.rb CHANGED
@@ -176,21 +176,15 @@ module T
176
176
  # Intended to be used to promise sorbet that a given nilable value happens
177
177
  # to contain a non-nil value at this point.
178
178
  #
179
- # sig {params(arg: T.nilable(A), msg: T.nilable(String)).returns(A)}
180
- def self.must(arg, msg=nil)
179
+ # sig {params(arg: T.nilable(A)).returns(A)}
180
+ def self.must(arg)
181
+ return arg if arg
182
+ return arg if arg == false
183
+
181
184
  begin
182
- if msg
183
- if !T.unsafe(msg).is_a?(String)
184
- raise TypeError.new("T.must expects a string as second argument")
185
- end
186
- else
187
- msg = "Passed `nil` into T.must"
188
- end
189
- raise TypeError.new(msg) if arg.nil?
190
- arg
185
+ raise TypeError.new("Passed `nil` into T.must")
191
186
  rescue TypeError => e # raise into rescue to ensure e.backtrace is populated
192
187
  T::Private::ErrorHandler.handle_inline_type_error(e)
193
- arg
194
188
  end
195
189
  end
196
190
 
@@ -17,6 +17,19 @@ module T::Configuration
17
17
  T::Private::RuntimeLevels.enable_checking_in_tests
18
18
  end
19
19
 
20
+ # Configure the default checked level for a sig with no explicit `.checked`
21
+ # builder. When unset, the default checked level is `:always`.
22
+ #
23
+ # Note: setting this option is potentially dangerous! Sorbet can't check all
24
+ # code statically. The runtime checks complement the checks that Sorbet does
25
+ # statically, so that methods don't have to guard themselves from being
26
+ # called incorrectly by untyped code.
27
+ #
28
+ # @param [:never, :tests, :always] default_checked_level
29
+ def self.default_checked_level=(default_checked_level)
30
+ T::Private::RuntimeLevels.default_checked_level = default_checked_level
31
+ end
32
+
20
33
  # Set a handler to handle `TypeError`s raised by any in-line type assertions,
21
34
  # including `T.must`, `T.let`, `T.cast`, and `T.assert_type!`.
22
35
  #
@@ -175,14 +188,7 @@ module T::Configuration
175
188
  end
176
189
 
177
190
  private_class_method def self.call_validation_error_handler_default(signature, opts)
178
- method_file, method_line = signature.method.source_location
179
- location = opts[:location]
180
-
181
- error_message = "#{opts[:kind]}#{opts[:name] ? " '#{opts[:name]}'" : ''}: #{opts[:message]}\n" \
182
- "Caller: #{location.path}:#{location.lineno}\n" \
183
- "Definition: #{method_file}:#{method_line}"
184
-
185
- raise TypeError.new(error_message)
191
+ raise TypeError.new(opts[:pretty_message])
186
192
  end
187
193
 
188
194
  def self.call_validation_error_handler(signature, opts)
@@ -43,8 +43,8 @@ module T::Private::Methods
43
43
  if decl.returns == ARG_NOT_PROVIDED
44
44
  raise "Procs must specify a return type"
45
45
  end
46
- if decl.soft_notify != ARG_NOT_PROVIDED
47
- raise "Procs cannot use .soft"
46
+ if decl.on_failure != ARG_NOT_PROVIDED
47
+ raise "Procs cannot use .on_failure"
48
48
  end
49
49
 
50
50
  if decl.params == ARG_NOT_PROVIDED
@@ -224,7 +224,7 @@ module T::Private::Methods
224
224
  bind: current_declaration.bind,
225
225
  mode: current_declaration.mode,
226
226
  check_level: current_declaration.checked,
227
- soft_notify: current_declaration.soft_notify,
227
+ on_failure: current_declaration.on_failure,
228
228
  override_allow_incompatible: current_declaration.override_allow_incompatible,
229
229
  generated: current_declaration.generated,
230
230
  )
@@ -1150,10 +1150,16 @@ module T::Private::Methods::CallValidation
1150
1150
  def self.report_error(method_sig, error_message, kind, name, type, value, caller_offset: 0)
1151
1151
  method_sig.mark_failed
1152
1152
  caller_loc = T.must(caller_locations(3 + caller_offset, 1))[0]
1153
+ definition_file, definition_line = method_sig.method.source_location
1154
+
1155
+ pretty_message = "#{kind}#{name ? " '#{name}'" : ''}: #{error_message}\n" \
1156
+ "Caller: #{caller_loc.path}:#{caller_loc.lineno}\n" \
1157
+ "Definition: #{definition_file}:#{definition_line}"
1153
1158
 
1154
1159
  T::Private::ErrorHandler.handle_call_validation_error(
1155
1160
  method_sig,
1156
1161
  message: error_message,
1162
+ pretty_message: pretty_message,
1157
1163
  kind: kind,
1158
1164
  name: name,
1159
1165
  type: type,
@@ -2,7 +2,7 @@
2
2
  # typed: true
3
3
 
4
4
  module T::Private::Methods
5
- Declaration = Struct.new(:mod, :params, :returns, :bind, :mode, :checked, :finalized, :soft_notify, :override_allow_incompatible, :type_parameters, :generated)
5
+ Declaration = Struct.new(:mod, :params, :returns, :bind, :mode, :checked, :finalized, :on_failure, :override_allow_incompatible, :type_parameters, :generated)
6
6
 
7
7
  class DeclBuilder
8
8
  attr_reader :decl
@@ -25,7 +25,7 @@ module T::Private::Methods
25
25
  Modes.standard, # mode
26
26
  ARG_NOT_PROVIDED, # checked
27
27
  false, # finalized
28
- ARG_NOT_PROVIDED, # soft_notify
28
+ ARG_NOT_PROVIDED, # on_failure
29
29
  nil, # override_allow_incompatible
30
30
  ARG_NOT_PROVIDED, # type_parameters
31
31
  ARG_NOT_PROVIDED, # generated
@@ -80,16 +80,13 @@ module T::Private::Methods
80
80
  end
81
81
 
82
82
  def checked(level)
83
- if T.unsafe(true)
84
- raise "The .checked API is unstable, so we don't want it used until we redesign it. To change Sorbet's runtime behavior, see https://sorbet.org/docs/tconfiguration"
85
- end
86
83
  check_live!
87
84
 
88
85
  if !decl.checked.equal?(ARG_NOT_PROVIDED)
89
86
  raise BuilderError.new("You can't call .checked multiple times in a signature.")
90
87
  end
91
- if !decl.soft_notify.equal?(ARG_NOT_PROVIDED)
92
- raise BuilderError.new("You can't use .checked with .soft.")
88
+ if level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
89
+ raise BuilderError.new("You can't use .checked(:never) with .on_failure because .on_failure will have no effect.")
93
90
  end
94
91
  if !decl.generated.equal?(ARG_NOT_PROVIDED)
95
92
  raise BuilderError.new("You can't use .checked with .generated.")
@@ -103,37 +100,25 @@ module T::Private::Methods
103
100
  self
104
101
  end
105
102
 
106
- def soft(notify:)
107
- if T.unsafe(true)
108
- raise "The .soft API is unstable, so we don't want it used until we redesign it. To change Sorbet's runtime behavior, see https://sorbet.org/docs/tconfiguration"
109
- end
103
+ def on_failure(*args)
110
104
  check_live!
111
105
 
112
- if !decl.soft_notify.equal?(ARG_NOT_PROVIDED)
113
- raise BuilderError.new("You can't call .soft multiple times in a signature.")
106
+ if !decl.on_failure.equal?(ARG_NOT_PROVIDED)
107
+ raise BuilderError.new("You can't call .on_failure multiple times in a signature.")
114
108
  end
115
- if !decl.checked.equal?(ARG_NOT_PROVIDED)
116
- raise BuilderError.new("You can't use .soft with .checked.")
109
+ if decl.checked == :never
110
+ raise BuilderError.new("You can't use .on_failure with .checked(:never) because .on_failure will have no effect.")
117
111
  end
118
112
  if !decl.generated.equal?(ARG_NOT_PROVIDED)
119
- raise BuilderError.new("You can't use .soft with .generated.")
113
+ raise BuilderError.new("You can't use .on_failure with .generated.")
120
114
  end
121
115
 
122
- # TODO consider validating that :notify is a project that sentry knows about,
123
- # as per https://git.corp.stripe.com/stripe-internal/pay-server/blob/master/lib/event/job/sentry_job.rb#L125
124
- if !notify || notify == ''
125
- raise BuilderError.new("You can't provide an empty notify to .soft().")
126
- end
127
-
128
- decl.soft_notify = notify
116
+ decl.on_failure = args
129
117
 
130
118
  self
131
119
  end
132
120
 
133
121
  def generated
134
- if T.unsafe(true)
135
- raise "The .generated API is unstable, so we don't want it used until we redesign it. To change Sorbet's runtime behavior, see https://sorbet.org/docs/tconfiguration"
136
- end
137
122
  check_live!
138
123
 
139
124
  if !decl.generated.equal?(ARG_NOT_PROVIDED)
@@ -142,8 +127,8 @@ module T::Private::Methods
142
127
  if !decl.checked.equal?(ARG_NOT_PROVIDED)
143
128
  raise BuilderError.new("You can't use .generated with .checked.")
144
129
  end
145
- if !decl.soft_notify.equal?(ARG_NOT_PROVIDED)
146
- raise BuilderError.new("You can't use .generated with .soft.")
130
+ if !decl.on_failure.equal?(ARG_NOT_PROVIDED)
131
+ raise BuilderError.new("You can't use .generated with .on_failure.")
147
132
  end
148
133
 
149
134
  decl.generated = true
@@ -252,10 +237,14 @@ module T::Private::Methods
252
237
  decl.bind = nil
253
238
  end
254
239
  if decl.checked.equal?(ARG_NOT_PROVIDED)
255
- decl.checked = :always
256
- end
257
- if decl.soft_notify.equal?(ARG_NOT_PROVIDED)
258
- decl.soft_notify = nil
240
+ default_checked_level = T::Private::RuntimeLevels.default_checked_level
241
+ if default_checked_level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
242
+ raise BuilderError.new("To use .on_failure you must additionally call .checked(:tests) or .checked(:always), otherwise, the .on_failure has no effect.")
243
+ end
244
+ decl.checked = default_checked_level
245
+ end
246
+ if decl.on_failure.equal?(ARG_NOT_PROVIDED)
247
+ decl.on_failure = nil
259
248
  end
260
249
  if decl.generated.equal?(ARG_NOT_PROVIDED)
261
250
  decl.generated = false
@@ -5,7 +5,7 @@ class T::Private::Methods::Signature
5
5
  attr_reader :method, :method_name, :arg_types, :kwarg_types, :block_type, :block_name,
6
6
  :rest_type, :rest_name, :keyrest_type, :keyrest_name, :bind,
7
7
  :return_type, :mode, :req_arg_count, :req_kwarg_names, :has_rest, :has_keyrest,
8
- :check_level, :generated, :parameters, :soft_notify, :override_allow_incompatible, :ever_failed
8
+ :check_level, :generated, :parameters, :on_failure, :override_allow_incompatible, :ever_failed
9
9
 
10
10
  def self.new_untyped(method:, mode: T::Private::Methods::Modes.untyped, parameters: method.parameters)
11
11
  # Using `Untyped` ensures we'll get an error if we ever try validation on these.
@@ -24,7 +24,7 @@ class T::Private::Methods::Signature
24
24
  mode: mode,
25
25
  check_level: :never,
26
26
  parameters: parameters,
27
- soft_notify: nil,
27
+ on_failure: nil,
28
28
  )
29
29
  end
30
30
 
@@ -32,7 +32,7 @@ class T::Private::Methods::Signature
32
32
  @ever_failed = true
33
33
  end
34
34
 
35
- def initialize(method:, method_name:, raw_arg_types:, raw_return_type:, bind:, mode:, check_level:, parameters: method.parameters, soft_notify:, generated: false, override_allow_incompatible: false)
35
+ def initialize(method:, method_name:, raw_arg_types:, raw_return_type:, bind:, mode:, check_level:, parameters: method.parameters, on_failure:, generated: false, override_allow_incompatible: false)
36
36
  @method = method
37
37
  @method_name = method_name
38
38
  @arg_types = []
@@ -52,7 +52,7 @@ class T::Private::Methods::Signature
52
52
  @has_rest = false
53
53
  @has_keyrest = false
54
54
  @parameters = parameters
55
- @soft_notify = soft_notify
55
+ @on_failure = on_failure
56
56
  @override_allow_incompatible = override_allow_incompatible
57
57
  @generated = generated
58
58
  @ever_failed = false
@@ -17,6 +17,9 @@ module T::Private::RuntimeLevels
17
17
  @check_tests = false
18
18
  @wrapped_tests_with_validation = false
19
19
 
20
+ @has_read_default_checked_level = false
21
+ @default_checked_level = :always
22
+
20
23
  def self.check_tests?
21
24
  # Assume that this code path means that some `sig.checked(:tests)`
22
25
  # has been wrapped (or not wrapped) already, which is a trapdoor
@@ -35,6 +38,18 @@ module T::Private::RuntimeLevels
35
38
  _toggle_checking_tests(true)
36
39
  end
37
40
 
41
+ def self.default_checked_level
42
+ @has_read_default_checked_level = true
43
+ @default_checked_level
44
+ end
45
+
46
+ def self.default_checked_level=(default_checked_level)
47
+ if @has_read_default_checked_level
48
+ raise "Set the default checked level earlier. There are already some methods whose sig blocks have evaluated which would not be affected by the new default."
49
+ end
50
+ @default_checked_level = default_checked_level
51
+ end
52
+
38
53
  def self._toggle_checking_tests(checked)
39
54
  @check_tests = checked
40
55
  end
@@ -18,7 +18,7 @@ class T::Props::Decorator
18
18
 
19
19
  class NoRulesError < StandardError; end
20
20
 
21
- sig {params(klass: DecoratedClass).void}
21
+ T::Sig::WithoutRuntime.sig {params(klass: DecoratedClass).void}
22
22
  def initialize(klass)
23
23
  @class = klass
24
24
  klass.plugins.each do |mod|
@@ -27,7 +27,7 @@ class T::Props::Decorator
27
27
  end
28
28
 
29
29
  # prop stuff
30
- sig {returns(T::Hash[Symbol, Rules])}
30
+ sig {returns(T::Hash[Symbol, Rules]).checked(:never)}
31
31
  def props
32
32
  @props ||= {}.freeze
33
33
  end
@@ -44,7 +44,7 @@ class T::Props::Decorator
44
44
  sig {returns(T::Array[Symbol])}
45
45
  def all_props; props.keys; end
46
46
 
47
- sig {params(prop: T.any(Symbol, String)).returns(Rules)}
47
+ sig {params(prop: T.any(Symbol, String)).returns(Rules).checked(:never)}
48
48
  def prop_rules(prop); props[prop.to_sym] || raise("No such prop: #{prop.inspect}"); end
49
49
 
50
50
  sig {params(prop: Symbol, rules: Rules).void}
@@ -80,7 +80,7 @@ class T::Props::Decorator
80
80
  }
81
81
  end
82
82
 
83
- sig {returns(DecoratedClass)}
83
+ sig {returns(DecoratedClass).checked(:never)}
84
84
  def decorated_class; @class; end
85
85
 
86
86
  # Accessors
@@ -94,6 +94,7 @@ class T::Props::Decorator
94
94
  rules: T.nilable(Rules)
95
95
  )
96
96
  .returns(T.untyped)
97
+ .checked(:never)
97
98
  end
98
99
  def get(instance, prop, rules=props[prop.to_sym])
99
100
  # For backwards compatibility, fall back to reconstructing the accessor key
@@ -111,6 +112,7 @@ class T::Props::Decorator
111
112
  rules: T.nilable(Rules)
112
113
  )
113
114
  .void
115
+ .checked(:never)
114
116
  end
115
117
  def set(instance, prop, value, rules=props[prop.to_sym])
116
118
  # For backwards compatibility, fall back to reconstructing the accessor key
@@ -119,7 +121,7 @@ class T::Props::Decorator
119
121
  end
120
122
 
121
123
  # 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.
122
- sig {params(prop: Symbol, val: T.untyped).void}
124
+ sig {params(prop: Symbol, val: T.untyped).void.checked(:never)}
123
125
  def validate_prop_value(prop, val)
124
126
  # This implements a 'public api' on document so that we don't allow callers to pass in rules
125
127
  # Rules seem like an implementation detail so it seems good to now allow people to specify them manually.
@@ -127,7 +129,7 @@ class T::Props::Decorator
127
129
  end
128
130
 
129
131
  # Passing in rules here is purely a performance optimization.
130
- sig {params(prop: Symbol, val: T.untyped, rules: Rules).void}
132
+ sig {params(prop: Symbol, val: T.untyped, rules: Rules).void.checked(:never)}
131
133
  private def check_prop_type(prop, val, rules=prop_rules(prop))
132
134
  type_object = rules.fetch(:type_object)
133
135
  type = rules.fetch(:type)
@@ -173,6 +175,7 @@ class T::Props::Decorator
173
175
  rules: T.nilable(Rules)
174
176
  )
175
177
  .void
178
+ .checked(:never)
176
179
  end
177
180
  def prop_set(instance, prop, val, rules=prop_rules(prop))
178
181
  check_prop_type(prop, val, T.must(rules))
@@ -188,6 +191,7 @@ class T::Props::Decorator
188
191
  rules: T.nilable(Rules)
189
192
  )
190
193
  .returns(T.untyped)
194
+ .checked(:never)
191
195
  end
192
196
  def prop_get(instance, prop, rules=props[prop.to_sym])
193
197
  val = get(instance, prop, rules)
@@ -222,6 +226,7 @@ class T::Props::Decorator
222
226
  opts: Hash
223
227
  )
224
228
  .returns(T.untyped)
229
+ .checked(:never)
225
230
  end
226
231
  def foreign_prop_get(instance, prop, foreign_class, rules=props[prop.to_sym], opts={})
227
232
  return if !(value = prop_get(instance, prop, rules))
@@ -325,7 +330,6 @@ class T::Props::Decorator
325
330
  .void
326
331
  end
327
332
  def prop_defined(name, cls, rules={})
328
- # TODO(jerry): Create similar soft assertions against false
329
333
  if rules[:optional] == true
330
334
  T::Configuration.hard_assert_handler(
331
335
  'Use of `optional: true` is deprecated, please use `T.nilable(...)` instead.',
@@ -776,7 +780,7 @@ class T::Props::Decorator
776
780
  #
777
781
  # This gets called when a module or class that extends T::Props gets included, extended,
778
782
  # prepended, or inherited.
779
- sig {params(child: DecoratedClass).void}
783
+ T::Sig::WithoutRuntime.sig {params(child: DecoratedClass).void}
780
784
  def model_inherited(child)
781
785
  child.extend(T::Props::ClassMethods)
782
786
  child.plugins.concat(decorated_class.plugins)
@@ -797,7 +801,7 @@ class T::Props::Decorator
797
801
  end
798
802
  end
799
803
 
800
- sig {params(mod: Module).void}
804
+ T::Sig::WithoutRuntime.sig {params(mod: Module).void}
801
805
  def plugin(mod)
802
806
  decorated_class.plugins << mod
803
807
  Private.apply_class_methods(mod, decorated_class)
@@ -70,6 +70,7 @@ module T::Props::PrettyPrintable
70
70
  sig do
71
71
  params(instance: T::Props::PrettyPrintable, prop: Symbol, multiline: T::Boolean, indent: String)
72
72
  .returns(String)
73
+ .checked(:never)
73
74
  end
74
75
  private def inspect_prop_value(instance, prop, multiline:, indent:)
75
76
  val = T.unsafe(self).get(instance, prop)
@@ -2,35 +2,23 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  #
5
- # Hey there!
5
+ # From the static system, T::Utils::RuntimeProfiled is T.untyped.
6
6
  #
7
- # T::Utils::Runtime is just a random class. Chances are[^1] it's not a class
8
- # that your variables are instances of, which means that using it in a type
9
- # signature will always create a type error.
7
+ # But from the runtime system, it's a random class (specifically, a class that
8
+ # normal programs currently don't have any instances of).
10
9
  #
11
- # At first, it doesn't seem like a good thing to have a type that's sole
12
- # purpose is to cause type errors. The trick is that within the ruby-types
13
- # team, we only use T::Utils::RuntimeProfiled within 'generated' sigs.
10
+ # Thus, T::Utils::RuntimeProfiled can be used to introduce runtime-only type
11
+ # errors. This seems like a bad idea, but it's not. It can be used to gather
12
+ # runtime type information from running code via a custom T::Configuration
13
+ # handler.
14
14
  #
15
- # Unlike normal sigs, generated sigs never raise at runtime. They also log the
16
- # actual, observed type on type error to a central location. We're using these
17
- # observed types to refine and expand our type coverage in pay-server.
15
+ # This process has only ever been used at Stripe, and is likely to have rough
16
+ # edges. If you've managed to find your way here and you're curious to try it,
17
+ # please chat with us on Slack. There are no docs.
18
18
  #
19
- # What does this all mean for you?
20
- #
21
- # - If you were just curious, that's it! Leave the sig as is, and carry on.
22
- # - If you wanted to replace this sig with a better, hand-authored one:
23
- #
24
- # 1. Remove 'generated' from the sig.
25
- # 2. Update the sig to your liking
26
- #
27
- # Questions? :portal-to: => #ruby-types
28
- #
29
- # [^1]: Unless you happen to be calling T::Utils::RuntimeProfiled.new directly...
19
+ # See also: the --suggest-runtime-profiled flag to sorbet.
30
20
  #
31
21
 
32
22
  module T; end
33
23
  module T::Utils; end
34
- # Sorbet guesses this type instead of T.untyped when passed --suggest-runtime-profiled
35
-
36
24
  class T::Utils::RuntimeProfiled; end
data/lib/types/utils.rb CHANGED
@@ -74,26 +74,6 @@ module T::Utils
74
74
  T::Private::Methods.run_all_sig_blocks
75
75
  end
76
76
 
77
- # This can be called in a wholesome test to make sure all the `sig`s are well
78
- # formed.
79
- def self.validate_sigs
80
- exceptions = []
81
- run_all_sig_blocks
82
- ObjectSpace.each_object(Module) do |mod| # rubocop:disable PrisonGuard/NoDynamicConstAccess
83
- begin
84
- T::Private::Abstract::Validate.validate_subclass(mod)
85
- if T::AbstractUtils.abstract_module?(mod)
86
- T::Private::Abstract::Validate.validate_abstract_module(mod)
87
- end
88
- rescue => e
89
- exceptions << e
90
- end
91
- end
92
- if !exceptions.empty?
93
- raise "#{exceptions.count} exception thrown during validation:\n\n#{exceptions.map(&:message).sort.join("\n\n")}"
94
- end
95
- end
96
-
97
77
  # Give a type which is a subclass of T::Types::Base, determines if the type is a simple nilable type (union of NilClass and something else).
98
78
  # If so, returns the T::Types::Base of the something else. Otherwise, returns nil.
99
79
  def self.unwrap_nilable(type)
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.4.4331
4
+ version: 0.4.4398
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-27 00:00:00.000000000 Z
11
+ date: 2019-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest