sorbet-runtime 0.5.11258 → 0.5.11422

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2bce12129d6264f3e6cbfbe582a5e7a3e2ee6d852a9002dc78ca173dd1712f5b
4
- data.tar.gz: 6baca29859ae322cc2c8ae26260781790c3fe092c4a3f8b5e593b3085d23ce3d
3
+ metadata.gz: a675bfbf51b32916be960aadcc1411329f21729d5ceb2218509da82d20387ddd
4
+ data.tar.gz: a39ec7df0cf067c2c31d22f557caea810c37c4985c1437a28e03b5db72036c0b
5
5
  SHA512:
6
- metadata.gz: 264379318720331ccb920ff4b7c21d4396473a96e8ad81b7daf52121d40dcd09819853e1d6c35a49c8d2e16a3a50c87b8b443be71f1d709a7709def8dc6780c2
7
- data.tar.gz: e82f3616393a7c7fe4533b67e00b3f8757dd850b53e3b37963aa7f290b13febda9b6c07e9f478c35da05f2a22567ef7e3c873c226953aedaca39f96b380cf60a
6
+ metadata.gz: dab2fb9c543e4eb0c652446435ad9c7a41d3850a3a2eefda6fc25a64181cbbe8a027e7313f37eea42c1bc14771be5bd6ff2799b4589668d43c4d1a3f91840953
7
+ data.tar.gz: '09c74373b54c24f90a63106bc726ab4fb66d61dca523bb4323effc9072bf08162135b52deb3ad648b31be156ccd609f907efc30015a5bac3b14f83f5d53bf384'
@@ -19,6 +19,7 @@ module T::Private::Types; end
19
19
  require_relative 'types/configuration'
20
20
  require_relative 'types/_types'
21
21
  require_relative 'types/private/decl_state'
22
+ require_relative 'types/private/caller_utils'
22
23
  require_relative 'types/private/class_utils'
23
24
  require_relative 'types/private/runtime_levels'
24
25
  require_relative 'types/private/methods/_methods'
@@ -116,6 +117,3 @@ require_relative 'types/struct'
116
117
  require_relative 'types/non_forcing_constants'
117
118
 
118
119
  require_relative 'types/compatibility_patches'
119
-
120
- # Sorbet Compiler support module
121
- 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,62 +192,83 @@ 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 ###
@@ -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)
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ # typed: false
3
+
4
+ module T::Private::CallerUtils
5
+ if Thread.respond_to?(:each_caller_location) # RUBY_VERSION >= "3.2"
6
+ def self.find_caller
7
+ skipped_first = false
8
+ Thread.each_caller_location do |loc|
9
+ unless skipped_first
10
+ skipped_first = true
11
+ next
12
+ end
13
+
14
+ next if loc.path&.start_with?("<internal:")
15
+
16
+ return loc if yield(loc)
17
+ end
18
+ nil
19
+ end
20
+ else
21
+ def self.find_caller
22
+ caller_locations(2).find do |loc|
23
+ !loc.path&.start_with?("<internal:") && yield(loc)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -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
 
@@ -168,7 +168,7 @@ module T::Private::Methods
168
168
 
169
169
  definition_file, definition_line = T::Private::Methods.signature_for_method(ancestor.instance_method(method_name)).method.source_location
170
170
  is_redefined = target == ancestor
171
- caller_loc = caller_locations.find {|l| !l.to_s.start_with?(SORBET_RUNTIME_LIB_PATH)}
171
+ caller_loc = T::Private::CallerUtils.find_caller {|loc| !loc.path.to_s.start_with?(SORBET_RUNTIME_LIB_PATH)}
172
172
  extra_info = "\n"
173
173
  if caller_loc
174
174
  extra_info = (is_redefined ? "Redefined" : "Overridden") + " here: #{caller_loc.path}:#{caller_loc.lineno}\n"
@@ -291,11 +291,21 @@ module T::Private::Methods::CallValidation
291
291
 
292
292
  def self.report_error(method_sig, error_message, kind, name, type, value, caller_offset: 0)
293
293
  caller_loc = T.must(caller_locations(3 + caller_offset, 1))[0]
294
- definition_file, definition_line = method_sig.method.source_location
294
+ method = method_sig.method
295
+ definition_file, definition_line = method.source_location
296
+
297
+ owner = method.owner
298
+ pretty_method_name =
299
+ if owner.singleton_class? && owner.respond_to?(:attached_object)
300
+ # attached_object is new in Ruby 3.2
301
+ "#{owner.attached_object}.#{method.name}"
302
+ else
303
+ "#{owner}##{method.name}"
304
+ end
295
305
 
296
306
  pretty_message = "#{kind}#{name ? " '#{name}'" : ''}: #{error_message}\n" \
297
307
  "Caller: #{caller_loc.path}:#{caller_loc.lineno}\n" \
298
- "Definition: #{definition_file}:#{definition_line}"
308
+ "Definition: #{definition_file}:#{definition_line} (#{pretty_method_name})"
299
309
 
300
310
  T::Configuration.call_validation_error_handler(
301
311
  method_sig,
@@ -318,7 +328,7 @@ module T::Private::Methods::CallValidation
318
328
  elsif mod.private_method_defined?(name)
319
329
  :private
320
330
  else
321
- raise NameError.new("undefined method `#{name}` for `#{mod}`")
331
+ mod.method(name) # Raises
322
332
  end
323
333
  end
324
334
  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
- this_line = Kernel.caller.find {|line| !line.match(/in `inherited'$/)}
9
- T::Private::Sealed.validate_inheritance(this_line, 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
 
@@ -22,15 +22,15 @@ module T::Private::Sealed
22
22
  module NoIncludeExtend
23
23
  def included(child)
24
24
  super
25
- this_line = Kernel.caller.find {|line| !line.match(/in `included'$/)}
26
- T::Private::Sealed.validate_inheritance(this_line, self, child, 'included')
25
+ caller_loc = T::Private::CallerUtils.find_caller {|loc| !loc.to_s.match(/in `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
- this_line = Kernel.caller.find {|line| !line.match(/in `extended'$/)}
33
- T::Private::Sealed.validate_inheritance(this_line, self, child, 'extended')
32
+ caller_loc = T::Private::CallerUtils.find_caller {|loc| !loc.to_s.match(/in `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
@@ -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
 
@@ -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
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.11258
4
+ version: 0.5.11422
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-15 00:00:00.000000000 Z
11
+ date: 2024-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -156,9 +156,9 @@ files:
156
156
  - lib/types/private/abstract/declare.rb
157
157
  - lib/types/private/abstract/hooks.rb
158
158
  - lib/types/private/abstract/validate.rb
159
+ - lib/types/private/caller_utils.rb
159
160
  - lib/types/private/casts.rb
160
161
  - lib/types/private/class_utils.rb
161
- - lib/types/private/compiler.rb
162
162
  - lib/types/private/decl_state.rb
163
163
  - lib/types/private/final.rb
164
164
  - 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