sorbet-runtime 0.5.11266 → 0.5.11647

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: 62a1d832c6ab11c77c2604ee4f41e90ce19504ceb77e26a2ac1a1946316c5850
4
- data.tar.gz: ef76ff59edbc69784d52817720f36fc38d3705849b4eea653f40b52bf7c4b1dd
3
+ metadata.gz: cbc4c99744f25d0ec157e3a068f29bd639264546679e435c57324e6678d5b508
4
+ data.tar.gz: 48163adbeccaff12cac4aeabfef8613c327b93937a43d510d3d9db8b01c36eb4
5
5
  SHA512:
6
- metadata.gz: e666a6f08ec47051bcd8a7b92320089d1841544c526be65c3cdb17d0a0cea3fd4e2e921e7b389ea52b836c2a076e18346215d2c484b7efbda372cd6dd232dc58
7
- data.tar.gz: e44d0e46981e86bd7c5f124ea1a1592d64a44955f9f405e0dcb6a61f02fb03ac4021d13bb9e01f1ac6599d94c9f7521d3164cd98f0b7efe3cc687fcb799fa6cf
6
+ metadata.gz: 317425a0c17154e3f3cb3f850cc32317b63cb68898fe9f3c9c97f83a41432c0b3331936211241b25a4866a6f47ce037b20fdc54fd072d97d985ebfaded497b30
7
+ data.tar.gz: ab4e236b016f4e3c9f0123d1ee5b03b556f318755a483127facfad6d2247fac47ac4a83d90a168f68af94797a4b07d01efc12dc29c6e7841967528964512ddd5
@@ -117,6 +117,3 @@ require_relative 'types/struct'
117
117
  require_relative 'types/non_forcing_constants'
118
118
 
119
119
  require_relative 'types/compatibility_patches'
120
-
121
- # Sorbet Compiler support module
122
- require_relative 'types/private/compiler'
@@ -113,7 +113,7 @@ module T::Configuration
113
113
  # statically, so that methods don't have to guard themselves from being
114
114
  # called incorrectly by untyped code.
115
115
  #
116
- # @param [:never, :compiled, :tests, :always] default_checked_level
116
+ # @param [:never, :tests, :always] default_checked_level
117
117
  def self.default_checked_level=(default_checked_level)
118
118
  T::Private::RuntimeLevels.default_checked_level = default_checked_level
119
119
  end
@@ -536,6 +536,7 @@ module T::Configuration
536
536
 
537
537
  @legacy_t_enum_migration_mode = false
538
538
  def self.enable_legacy_t_enum_migration_mode
539
+ T::Enum.include(T::Enum::LegacyMigrationMode)
539
540
  @legacy_t_enum_migration_mode = true
540
541
  end
541
542
  def self.disable_legacy_t_enum_migration_mode
data/lib/types/enum.rb CHANGED
@@ -192,68 +192,92 @@ class T::Enum
192
192
  # responds to the `to_str` method. It does not actually call `to_str` however.
193
193
  #
194
194
  # See https://ruby-doc.org/core-2.4.0/String.html#method-i-3D-3D
195
- sig {returns(String)}
195
+ T::Sig::WithoutRuntime.sig {returns(String)}
196
196
  def to_str
197
197
  msg = 'Implicit conversion of Enum instances to strings is not allowed. Call #serialize instead.'
198
198
  if T::Configuration.legacy_t_enum_migration_mode?
199
199
  T::Configuration.soft_assert_handler(
200
200
  msg,
201
- storytime: {class: self.class.name},
201
+ storytime: {
202
+ class: self.class.name,
203
+ caller_location: Kernel.caller_locations(1..1)&.[](0)&.then {"#{_1.path}:#{_1.lineno}"},
204
+ },
202
205
  )
203
206
  serialize.to_s
204
207
  else
205
- raise NoMethodError.new(msg)
208
+ Kernel.raise NoMethodError.new(msg)
206
209
  end
207
210
  end
208
211
 
209
- sig {params(other: BasicObject).returns(T::Boolean).checked(:never)}
210
- def ==(other)
211
- case other
212
- when String
213
- if T::Configuration.legacy_t_enum_migration_mode?
214
- comparison_assertion_failed(:==, other)
215
- self.serialize == other
212
+ module LegacyMigrationMode
213
+ include Kernel
214
+ extend T::Helpers
215
+ abstract!
216
+
217
+ if T.unsafe(false)
218
+ # Declare to the type system that the `serialize` method for sure exists
219
+ # on whatever we mix this into.
220
+ T::Sig::WithoutRuntime.sig {abstract.returns(T.untyped)}
221
+ def serialize; end
222
+ end
223
+
224
+ # WithoutRuntime so that comparison_assertion_failed can assume a constant stack depth
225
+ T::Sig::WithoutRuntime.sig {params(other: BasicObject).returns(T::Boolean)}
226
+ def ==(other)
227
+ case other
228
+ when String
229
+ if T::Configuration.legacy_t_enum_migration_mode?
230
+ comparison_assertion_failed(:==, other)
231
+ self.serialize == other
232
+ else
233
+ false
234
+ end
216
235
  else
217
- false
236
+ super(other)
218
237
  end
219
- else
220
- super(other)
221
238
  end
222
- end
223
239
 
224
- sig {params(other: BasicObject).returns(T::Boolean).checked(:never)}
225
- def ===(other)
226
- case other
227
- when String
228
- if T::Configuration.legacy_t_enum_migration_mode?
229
- comparison_assertion_failed(:===, other)
230
- self.serialize == other
240
+ # WithoutRuntime so that comparison_assertion_failed can assume a constant stack depth
241
+ T::Sig::WithoutRuntime.sig {params(other: BasicObject).returns(T::Boolean)}
242
+ def ===(other)
243
+ case other
244
+ when String
245
+ if T::Configuration.legacy_t_enum_migration_mode?
246
+ comparison_assertion_failed(:===, other)
247
+ self.serialize == other
248
+ else
249
+ false
250
+ end
231
251
  else
232
- false
252
+ super(other)
233
253
  end
234
- else
235
- super(other)
236
254
  end
237
- end
238
255
 
239
- sig {params(method: Symbol, other: T.untyped).void}
240
- private def comparison_assertion_failed(method, other)
241
- T::Configuration.soft_assert_handler(
242
- 'Enum to string comparison not allowed. Compare to the Enum instance directly instead. See go/enum-migration',
243
- storytime: {
244
- class: self.class.name,
245
- self: self.inspect,
246
- other: other,
247
- other_class: other.class.name,
248
- method: method,
249
- }
250
- )
256
+ # WithoutRuntime so that caller_locations can assume a constant stack depth
257
+ # (Otherwise, the first call would be the method with the wrapping, which would have a different stack depth.)
258
+ T::Sig::WithoutRuntime.sig {params(method: Symbol, other: T.untyped).void}
259
+ private def comparison_assertion_failed(method, other)
260
+ T::Configuration.soft_assert_handler(
261
+ 'Enum to string comparison not allowed. Compare to the Enum instance directly instead. See go/enum-migration',
262
+ storytime: {
263
+ class: self.class.name,
264
+ self: self.inspect,
265
+ other: other,
266
+ other_class: other.class.name,
267
+ method: method,
268
+ caller_location: Kernel.caller_locations(2..2)&.[](0)&.then {"#{_1.path}:#{_1.lineno}"},
269
+ }
270
+ )
271
+ end
251
272
  end
252
273
 
253
274
  ### Private implementation ###
254
275
 
276
+ UNSET = T.let(Module.new.freeze, Module)
277
+ private_constant :UNSET
278
+
255
279
  sig {params(serialized_val: SerializedVal).void}
256
- def initialize(serialized_val=nil)
280
+ def initialize(serialized_val=UNSET)
257
281
  raise 'T::Enum is abstract' if self.class == T::Enum
258
282
  if !self.class.started_initializing?
259
283
  raise "Must instantiate all enum values of #{self.class} inside 'enums do'."
@@ -279,7 +303,7 @@ class T::Enum
279
303
  sig {params(const_name: Symbol).void}
280
304
  def _bind_name(const_name)
281
305
  @const_name = const_name
282
- @serialized_val = const_to_serialized_val(const_name) if @serialized_val.nil?
306
+ @serialized_val = const_to_serialized_val(const_name) if @serialized_val.equal?(UNSET)
283
307
  freeze
284
308
  end
285
309
 
@@ -4,20 +4,13 @@
4
4
  module T::NonForcingConstants
5
5
  # NOTE: This method is documented on the RBI in Sorbet's payload, so that it
6
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)
7
+ T::Sig::WithoutRuntime.sig {params(val: BasicObject, klass: String).returns(T::Boolean)}
8
+ def self.non_forcing_is_a?(val, klass)
9
9
  method_name = "T::NonForcingConstants.non_forcing_is_a?"
10
10
  if klass.empty?
11
11
  raise ArgumentError.new("The string given to `#{method_name}` must not be empty")
12
12
  end
13
13
 
14
- # We don't treat packages differently at runtime, but the static
15
- # type-checker still needs to have the package and constant
16
- # separated out. This just re-assembles the string as needed
17
- if !package.nil?
18
- klass = "::#{package}::#{klass}"
19
- end
20
-
21
14
  current_klass = T.let(nil, T.nilable(Module))
22
15
  current_prefix = T.let(nil, T.nilable(String))
23
16
 
@@ -25,10 +18,7 @@ module T::NonForcingConstants
25
18
  parts.each do |part|
26
19
  if current_klass.nil?
27
20
  # First iteration
28
- if part != "" && package.nil?
29
- # if we've supplied a package, we're probably running in
30
- # package mode, which means absolute references are
31
- # meaningless
21
+ if part != ""
32
22
  raise ArgumentError.new("The string given to `#{method_name}` must be an absolute constant reference that starts with `::`")
33
23
  end
34
24
 
@@ -37,7 +27,7 @@ module T::NonForcingConstants
37
27
 
38
28
  # if this had a :: prefix, then there's no more loading to
39
29
  # do---skip to the next one
40
- next if part == ""
30
+ next
41
31
  end
42
32
 
43
33
  if current_klass.autoload?(part)
@@ -4,7 +4,13 @@
4
4
  module T::Private::CallerUtils
5
5
  if Thread.respond_to?(:each_caller_location) # RUBY_VERSION >= "3.2"
6
6
  def self.find_caller
7
+ skipped_first = false
7
8
  Thread.each_caller_location do |loc|
9
+ unless skipped_first
10
+ skipped_first = true
11
+ next
12
+ end
13
+
8
14
  next if loc.path&.start_with?("<internal:")
9
15
 
10
16
  return loc if yield(loc)
@@ -65,7 +65,7 @@ module T::Private::ClassUtils
65
65
  elsif mod.private_method_defined?(name)
66
66
  :private
67
67
  else
68
- raise NameError.new("undefined method `#{name}` for `#{mod}`")
68
+ mod.method(name) # Raises
69
69
  end
70
70
  end
71
71
 
@@ -14,17 +14,7 @@ module T::Private::Methods::CallValidation
14
14
  def self.wrap_method_if_needed(mod, method_sig, original_method)
15
15
  original_visibility = visibility_method_name(mod, method_sig.method_name)
16
16
  if method_sig.mode == T::Private::Methods::Modes.abstract
17
- T::Private::ClassUtils.replace_method(mod, method_sig.method_name, true) do |*args, &blk|
18
- # We allow abstract methods to be implemented by things further down the ancestor chain.
19
- # So, if a super method exists, call it.
20
- if defined?(super)
21
- super(*args, &blk)
22
- else
23
- raise NotImplementedError.new(
24
- "The method `#{method_sig.method_name}` on #{mod} is declared as `abstract`. It does not have an implementation."
25
- )
26
- end
27
- end
17
+ create_abstract_wrapper(mod, method_sig, original_method, original_visibility)
28
18
  # Do nothing in this case; this method was not wrapped in _on_method_added.
29
19
  elsif method_sig.defined_raw
30
20
  # Note, this logic is duplicated (intentionally, for micro-perf) at `Methods._on_method_added`,
@@ -55,6 +45,24 @@ module T::Private::Methods::CallValidation
55
45
  @is_allowed_to_have_fast_path = false
56
46
  end
57
47
 
48
+ def self.create_abstract_wrapper(mod, method_sig, original_method, original_visibility)
49
+ mod.module_eval(<<~METHOD, __FILE__, __LINE__ + 1)
50
+ #{original_visibility}
51
+
52
+ def #{method_sig.method_name}(...)
53
+ # We allow abstract methods to be implemented by things further down the ancestor chain.
54
+ # So, if a super method exists, call it.
55
+ if defined?(super)
56
+ super
57
+ else
58
+ raise NotImplementedError.new(
59
+ "The method `#{method_sig.method_name}` on #{mod} is declared as `abstract`. It does not have an implementation."
60
+ )
61
+ end
62
+ end
63
+ METHOD
64
+ end
65
+
58
66
  def self.create_validator_method(mod, original_method, method_sig, original_visibility)
59
67
  has_fixed_arity = method_sig.kwarg_types.empty? && !method_sig.has_rest && !method_sig.has_keyrest &&
60
68
  original_method.parameters.all? {|(kind, _name)| kind == :req || kind == :block}
@@ -291,11 +299,21 @@ module T::Private::Methods::CallValidation
291
299
 
292
300
  def self.report_error(method_sig, error_message, kind, name, type, value, caller_offset: 0)
293
301
  caller_loc = T.must(caller_locations(3 + caller_offset, 1))[0]
294
- definition_file, definition_line = method_sig.method.source_location
302
+ method = method_sig.method
303
+ definition_file, definition_line = method.source_location
304
+
305
+ owner = method.owner
306
+ pretty_method_name =
307
+ if owner.singleton_class? && owner.respond_to?(:attached_object)
308
+ # attached_object is new in Ruby 3.2
309
+ "#{owner.attached_object}.#{method.name}"
310
+ else
311
+ "#{owner}##{method.name}"
312
+ end
295
313
 
296
314
  pretty_message = "#{kind}#{name ? " '#{name}'" : ''}: #{error_message}\n" \
297
315
  "Caller: #{caller_loc.path}:#{caller_loc.lineno}\n" \
298
- "Definition: #{definition_file}:#{definition_line}"
316
+ "Definition: #{definition_file}:#{definition_line} (#{pretty_method_name})"
299
317
 
300
318
  T::Configuration.call_validation_error_handler(
301
319
  method_sig,
@@ -318,7 +336,7 @@ module T::Private::Methods::CallValidation
318
336
  elsif mod.private_method_defined?(name)
319
337
  :private
320
338
  else
321
- raise NameError.new("undefined method `#{name}` for `#{mod}`")
339
+ mod.method(name) # Raises
322
340
  end
323
341
  end
324
342
  end
@@ -101,7 +101,7 @@ module T::Private::Methods
101
101
  if !decl.checked.equal?(ARG_NOT_PROVIDED)
102
102
  raise BuilderError.new("You can't call .checked multiple times in a signature.")
103
103
  end
104
- if (level == :never || level == :compiled) && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
104
+ if level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
105
105
  raise BuilderError.new("You can't use .checked(:#{level}) with .on_failure because .on_failure will have no effect.")
106
106
  end
107
107
  if !T::Private::RuntimeLevels::LEVELS.include?(level)
@@ -119,7 +119,7 @@ module T::Private::Methods
119
119
  if !decl.on_failure.equal?(ARG_NOT_PROVIDED)
120
120
  raise BuilderError.new("You can't call .on_failure multiple times in a signature.")
121
121
  end
122
- if decl.checked == :never || decl.checked == :compiled
122
+ if decl.checked == :never
123
123
  raise BuilderError.new("You can't use .on_failure with .checked(:#{decl.checked}) because .on_failure will have no effect.")
124
124
  end
125
125
 
@@ -222,7 +222,7 @@ module T::Private::Methods
222
222
  end
223
223
  if decl.checked.equal?(ARG_NOT_PROVIDED)
224
224
  default_checked_level = T::Private::RuntimeLevels.default_checked_level
225
- if (default_checked_level == :never || default_checked_level == :compiled) && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
225
+ if default_checked_level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
226
226
  raise BuilderError.new("To use .on_failure you must additionally call .checked(:tests) or .checked(:always), otherwise, the .on_failure has no effect.")
227
227
  end
228
228
  decl.checked = default_checked_level
@@ -234,7 +234,7 @@ module T::Private::Methods::SignatureValidation
234
234
  return if signature.override_allow_incompatible
235
235
  return if super_signature.mode == Modes.untyped
236
236
  return unless [signature, super_signature].all? do |sig|
237
- sig.check_level == :always || sig.check_level == :compiled || (sig.check_level == :tests && T::Private::RuntimeLevels.check_tests?)
237
+ sig.check_level == :always || (sig.check_level == :tests && T::Private::RuntimeLevels.check_tests?)
238
238
  end
239
239
  mode_noun = super_signature.mode == Modes.abstract ? 'implementation' : 'override'
240
240
 
@@ -12,9 +12,6 @@ module T::Private::RuntimeLevels
12
12
  # Don't even validate in tests, b/c too expensive,
13
13
  # or b/c we fully trust the static typing
14
14
  :never,
15
- # Validate the sig when the file is using the Sorbet Compiler.
16
- # Behaves like :never when interpreted.
17
- :compiled,
18
15
  ].freeze
19
16
 
20
17
  @check_tests = false
@@ -5,8 +5,8 @@ module T::Private::Sealed
5
5
  module NoInherit
6
6
  def inherited(child)
7
7
  super
8
- caller_loc = T::Private::CallerUtils.find_caller {|loc| !loc.to_s.match(/in `inherited'$/)}
9
- T::Private::Sealed.validate_inheritance(caller_loc&.to_s, self, child, 'inherited')
8
+ caller_loc = T::Private::CallerUtils.find_caller {|loc| loc.base_label != 'inherited'}
9
+ T::Private::Sealed.validate_inheritance(caller_loc, self, child, 'inherited')
10
10
  @sorbet_sealed_module_all_subclasses << child
11
11
  end
12
12
 
@@ -23,14 +23,14 @@ module T::Private::Sealed
23
23
  def included(child)
24
24
  super
25
25
  caller_loc = T::Private::CallerUtils.find_caller {|loc| !loc.to_s.match(/in `included'$/)}
26
- T::Private::Sealed.validate_inheritance(caller_loc&.to_s, self, child, 'included')
26
+ T::Private::Sealed.validate_inheritance(caller_loc, self, child, 'included')
27
27
  @sorbet_sealed_module_all_subclasses << child
28
28
  end
29
29
 
30
30
  def extended(child)
31
31
  super
32
32
  caller_loc = T::Private::CallerUtils.find_caller {|loc| !loc.to_s.match(/in `extended'$/)}
33
- T::Private::Sealed.validate_inheritance(caller_loc&.to_s, self, child, 'extended')
33
+ T::Private::Sealed.validate_inheritance(caller_loc, self, child, 'extended')
34
34
  @sorbet_sealed_module_all_subclasses << child
35
35
  end
36
36
 
@@ -68,8 +68,8 @@ module T::Private::Sealed
68
68
  mod.instance_variable_defined?(:@sorbet_sealed_module_decl_file)
69
69
  end
70
70
 
71
- def self.validate_inheritance(this_line, parent, child, verb)
72
- this_file = this_line&.split(':')&.first
71
+ def self.validate_inheritance(caller_loc, parent, child, verb)
72
+ this_file = caller_loc&.path
73
73
  decl_file = parent.instance_variable_get(:@sorbet_sealed_module_decl_file) if sealed_module?(parent)
74
74
 
75
75
  if !this_file
@@ -110,7 +110,7 @@ module T::Props
110
110
  #
111
111
  # @return [void]
112
112
  sig {params(name: Symbol, cls: T.untyped, rules: T.untyped).void}
113
- def prop(name, cls, rules={})
113
+ def prop(name, cls, **rules)
114
114
  cls = T::Utils.coerce(cls) if !cls.is_a?(Module)
115
115
  decorator.prop_defined(name, cls, rules)
116
116
  end
@@ -132,16 +132,16 @@ module T::Props
132
132
  end
133
133
 
134
134
  # Shorthand helper to define a `prop` with `immutable => true`
135
- sig {params(name: Symbol, cls_or_args: T.untyped, args: T::Hash[Symbol, T.untyped]).void}
136
- def const(name, cls_or_args, args={})
135
+ sig {params(name: Symbol, cls_or_args: T.untyped, args: T.untyped).void}
136
+ def const(name, cls_or_args, **args)
137
137
  if (cls_or_args.is_a?(Hash) && cls_or_args.key?(:immutable)) || args.key?(:immutable)
138
138
  Kernel.raise ArgumentError.new("Cannot pass 'immutable' argument when using 'const' keyword to define a prop")
139
139
  end
140
140
 
141
141
  if cls_or_args.is_a?(Hash)
142
- self.prop(name, cls_or_args.merge(immutable: true))
142
+ self.prop(name, **cls_or_args.merge(immutable: true))
143
143
  else
144
- self.prop(name, cls_or_args, args.merge(immutable: true))
144
+ self.prop(name, cls_or_args, **args.merge(immutable: true))
145
145
  end
146
146
  end
147
147
 
@@ -430,7 +430,7 @@ class T::Props::Decorator
430
430
  else
431
431
  nonnil_type = T::Utils.unwrap_nilable(type)
432
432
  if nonnil_type
433
- T.unsafe(T.nilable(T.all(nonnil_type, T.deprecated_enum(enum))))
433
+ T.unsafe(T.nilable(T.all(T.unsafe(nonnil_type), T.deprecated_enum(enum))))
434
434
  else
435
435
  T.unsafe(T.all(T.unsafe(type), T.deprecated_enum(enum)))
436
436
  end
@@ -62,7 +62,9 @@ module T::Props
62
62
  source = lazily_defined_methods.fetch(name).call
63
63
 
64
64
  cls = decorated_class
65
- cls.class_eval(source.to_s)
65
+ T::Configuration.without_ruby_warnings do
66
+ cls.class_eval(source.to_s)
67
+ end
66
68
  cls.send(:private, name)
67
69
  end
68
70
 
@@ -7,13 +7,13 @@ module T::Props::PrettyPrintable
7
7
 
8
8
  # Override the PP gem with something that's similar, but gives us a hook to do redaction and customization
9
9
  def pretty_print(pp)
10
- clazz = T.unsafe(T.cast(self, Object).class).decorator
10
+ klass = T.unsafe(T.cast(self, Object).class).decorator
11
11
  multiline = pp.is_a?(PP)
12
- pp.group(1, "<#{clazz.inspect_class_with_decoration(self)}", ">") do
13
- clazz.all_props.sort.each do |prop|
12
+ pp.group(1, "<#{klass.inspect_class_with_decoration(self)}", ">") do
13
+ klass.all_props.sort.each do |prop|
14
14
  pp.breakable
15
- val = clazz.get(self, prop)
16
- rules = clazz.prop_rules(prop)
15
+ val = klass.get(self, prop)
16
+ rules = klass.prop_rules(prop)
17
17
  pp.text("#{prop}=")
18
18
  if (custom_inspect = rules[:inspect])
19
19
  inspected = if T::Utils.arity(custom_inspect) == 1
@@ -28,7 +28,7 @@ module T::Props::PrettyPrintable
28
28
  val.pretty_print(pp)
29
29
  end
30
30
  end
31
- clazz.pretty_print_extra(self, pp)
31
+ klass.pretty_print_extra(self, pp)
32
32
  end
33
33
  end
34
34
 
@@ -261,15 +261,30 @@ module T::Props::Serializable::DecoratorMethods
261
261
  end
262
262
 
263
263
  def message_with_generated_source_context(error, generated_method, generate_source_method)
264
- line_label = error.backtrace.find {|l| l.end_with?("in `#{generated_method}'")}
265
- return unless line_label
264
+ generated_method = generated_method.to_s
265
+ if error.backtrace_locations
266
+ line_loc = error.backtrace_locations.find {|l| l.base_label == generated_method}
267
+ return unless line_loc
266
268
 
267
- line_num = if line_label.start_with?("(eval)")
268
- # (eval):13:in `__t_props_generated_serialize'
269
- line_label.split(':')[1]&.to_i
269
+ line_num = line_loc.lineno
270
270
  else
271
- # (eval at /Users/jez/stripe/sorbet/gems/sorbet-runtime/lib/types/props/has_lazily_specialized_methods.rb:65):13:in `__t_props_generated_serialize'
272
- line_label.split(':')[2]&.to_i
271
+ label = if RUBY_VERSION >= "3.4"
272
+ # in 'ClassName#__t_props_generated_serialize'"
273
+ "##{generated_method}'"
274
+ else
275
+ # in `__t_props_generated_serialize'"
276
+ "in `#{generated_method}'"
277
+ end
278
+ line_label = error.backtrace.find {|l| l.end_with?(label)}
279
+ return unless line_label
280
+
281
+ line_num = if line_label.start_with?("(eval)")
282
+ # (eval):13:in ...
283
+ line_label.split(':')[1]&.to_i
284
+ else
285
+ # (eval at /Users/jez/stripe/sorbet/gems/sorbet-runtime/lib/types/props/has_lazily_specialized_methods.rb:65):13:in ...
286
+ line_label.split(':')[2]&.to_i
287
+ end
273
288
  end
274
289
  return unless line_num
275
290
 
data/lib/types/struct.rb CHANGED
@@ -39,7 +39,7 @@ class T::ImmutableStruct < T::InexactStruct
39
39
 
40
40
  # Matches the signature in Props, but raises since this is an immutable struct and only const is allowed
41
41
  sig {params(name: Symbol, cls: T.untyped, rules: T.untyped).void}
42
- def self.prop(name, cls, rules={})
42
+ def self.prop(name, cls, **rules)
43
43
  return super if (cls.is_a?(Hash) && cls[:immutable]) || rules[:immutable]
44
44
 
45
45
  raise "Cannot use `prop` in #{self.name} because it is an immutable struct. Use `const` instead"
@@ -21,7 +21,7 @@ module T::Types
21
21
  valid?(obj)
22
22
  end
23
23
 
24
- def valid?(obj)
24
+ define_method(:valid?) do |_obj|
25
25
  raise NotImplementedError
26
26
  end
27
27
 
@@ -35,12 +35,12 @@ module T::Types
35
35
 
36
36
  # Force any lazy initialization that this type might need to do
37
37
  # It's unusual to call this directly; you probably want to call it indirectly via `T::Utils.run_all_sig_blocks`.
38
- def build_type
38
+ define_method(:build_type) do
39
39
  raise NotImplementedError
40
40
  end
41
41
 
42
42
  # Equality is based on name, so be sure the name reflects all relevant state when implementing.
43
- def name
43
+ define_method(:name) do
44
44
  raise NotImplementedError
45
45
  end
46
46
 
@@ -21,7 +21,7 @@ module T::Types
21
21
 
22
22
  # overrides Base
23
23
  def valid?(obj)
24
- obj.is_a?(Module) && obj <= @type
24
+ obj.is_a?(Module) && (obj <= @type || false)
25
25
  end
26
26
 
27
27
  # overrides Base
@@ -32,7 +32,7 @@ module T::Types
32
32
  when Simple
33
33
  @type.is_a?(other.raw_type)
34
34
  when TypedClass
35
- true
35
+ @type.is_a?(other.underlying_class)
36
36
  else
37
37
  false
38
38
  end
@@ -33,7 +33,7 @@ module T::Types
33
33
 
34
34
  # overrides Base
35
35
  def name
36
- @name ||= "T.deprecated_enum([#{@values.map(&:inspect).join(', ')}])"
36
+ @name ||= "T.deprecated_enum([#{@values.map(&:inspect).sort.join(', ')}])"
37
37
  end
38
38
 
39
39
  # overrides Base
@@ -51,7 +51,7 @@ module T::Types
51
51
  return false
52
52
  end
53
53
  arg_types.values.zip(other.arg_types.values).all? do |a, b|
54
- b.subtype_of?(a)
54
+ !b.nil? && b.subtype_of?(a)
55
55
  end && returns.subtype_of?(other.returns)
56
56
  else
57
57
  false
@@ -53,7 +53,7 @@ module T::Types
53
53
 
54
54
  class Untyped < TypedArray
55
55
  def initialize
56
- super(T.untyped)
56
+ super(T::Types::Untyped::Private::INSTANCE)
57
57
  end
58
58
 
59
59
  def valid?(obj)
@@ -71,7 +71,7 @@ module T::Types
71
71
 
72
72
  class Untyped < TypedClass
73
73
  def initialize
74
- super(T.untyped)
74
+ super(T::Types::Untyped::Private::INSTANCE)
75
75
  end
76
76
 
77
77
  def freeze
@@ -47,11 +47,10 @@ module T::Types
47
47
  true
48
48
  end
49
49
  when Hash
50
- return false unless type.is_a?(FixedArray)
51
- types = type.types
52
- return false if types.count != 2
53
- key_type = types[0]
54
- value_type = types[1]
50
+ type_ = self.type
51
+ return false unless type_.is_a?(FixedArray)
52
+ key_type, value_type = type_.types
53
+ return false if key_type.nil? || value_type.nil? || type_.types.size > 2
55
54
  obj.each_pair do |key, val|
56
55
  # Some objects (I'm looking at you Rack::Utils::HeaderHash) don't
57
56
  # iterate over a [key, value] array, so we can't just use the type.recursively_valid?(v)
@@ -179,7 +178,7 @@ module T::Types
179
178
 
180
179
  class Untyped < TypedEnumerable
181
180
  def initialize
182
- super(T.untyped)
181
+ super(T::Types::Untyped::Private::INSTANCE)
183
182
  end
184
183
 
185
184
  def valid?(obj)
@@ -28,7 +28,7 @@ module T::Types
28
28
 
29
29
  class Untyped < TypedEnumerator
30
30
  def initialize
31
- super(T.untyped)
31
+ super(T::Types::Untyped::Private::INSTANCE)
32
32
  end
33
33
 
34
34
  def valid?(obj)
@@ -28,7 +28,7 @@ module T::Types
28
28
 
29
29
  class Untyped < TypedEnumeratorChain
30
30
  def initialize
31
- super(T.untyped)
31
+ super(T::Types::Untyped::Private::INSTANCE)
32
32
  end
33
33
 
34
34
  def valid?(obj)
@@ -28,7 +28,7 @@ module T::Types
28
28
 
29
29
  class Untyped < TypedEnumeratorLazy
30
30
  def initialize
31
- super(T.untyped)
31
+ super(T::Types::Untyped::Private::INSTANCE)
32
32
  end
33
33
 
34
34
  def valid?(obj)
@@ -4,7 +4,7 @@
4
4
  module T::Types
5
5
  class TypedRange < TypedEnumerable
6
6
  def underlying_class
7
- Hash
7
+ Range
8
8
  end
9
9
 
10
10
  # overrides Base
@@ -4,7 +4,7 @@
4
4
  module T::Types
5
5
  class TypedSet < TypedEnumerable
6
6
  def underlying_class
7
- Hash
7
+ Set
8
8
  end
9
9
 
10
10
  # overrides Base
@@ -37,7 +37,7 @@ module T::Types
37
37
 
38
38
  class Untyped < TypedSet
39
39
  def initialize
40
- super(T.untyped)
40
+ super(T::Types::Untyped::Private::INSTANCE)
41
41
  end
42
42
 
43
43
  def valid?(obj)
data/lib/types/utils.rb CHANGED
@@ -155,7 +155,7 @@ module T::Utils
155
155
  raise ArgumentError.new("#{enum.inspect} is not a T.deprecated_enum")
156
156
  end
157
157
 
158
- classes = enum.values.map(&:class).uniq
158
+ classes = T.unsafe(enum.values).map(&:class).uniq
159
159
  if classes.empty?
160
160
  T.untyped
161
161
  elsif classes.length > 1
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.11266
4
+ version: 0.5.11647
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-23 00:00:00.000000000 Z
11
+ date: 2024-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 1.1.5
97
+ - !ruby/object:Gem::Dependency
98
+ name: debug
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: pry
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -159,7 +173,6 @@ files:
159
173
  - lib/types/private/caller_utils.rb
160
174
  - lib/types/private/casts.rb
161
175
  - lib/types/private/class_utils.rb
162
- - lib/types/private/compiler.rb
163
176
  - lib/types/private/decl_state.rb
164
177
  - lib/types/private/final.rb
165
178
  - lib/types/private/methods/_methods.rb
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: true
3
-
4
- module T::Private
5
- module Compiler
6
- # If this code ever runs, the caller is running interpreted (or the
7
- # compiler didn't see the call to `running_compiled?` statically.)
8
- #
9
- # The Sorbet Compiler replaces calls to this method unconditionally (no
10
- # runtime guards) to return `true` when compiling a file.
11
- def self.running_compiled?
12
- false
13
- end
14
-
15
- # Returns `nil` because the compiler isn't running.
16
- #
17
- # The Sorbet Compiler replaces calls to this method unconditionally (no
18
- # runtime guards) to return a String showing the Sorbet Compiler's version
19
- # string.
20
- def self.compiler_version
21
- nil
22
- end
23
- end
24
- end