sorbet-runtime 0.5.11144 → 0.5.11266

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sorbet-runtime.rb +1 -1
  3. data/lib/types/compatibility_patches.rb +1 -1
  4. data/lib/types/configuration.rb +1 -1
  5. data/lib/types/private/abstract/declare.rb +4 -5
  6. data/lib/types/private/caller_utils.rb +21 -0
  7. data/lib/types/private/methods/_methods.rb +35 -30
  8. data/lib/types/private/methods/call_validation.rb +16 -2
  9. data/lib/types/private/methods/call_validation_2_6.rb +518 -0
  10. data/lib/types/private/methods/call_validation_2_7.rb +518 -0
  11. data/lib/types/private/methods/decl_builder.rb +1 -1
  12. data/lib/types/private/methods/signature.rb +10 -2
  13. data/lib/types/private/methods/signature_validation.rb +12 -6
  14. data/lib/types/private/sealed.rb +6 -6
  15. data/lib/types/private/types/not_typed.rb +4 -0
  16. data/lib/types/private/types/string_holder.rb +4 -0
  17. data/lib/types/private/types/type_alias.rb +4 -0
  18. data/lib/types/private/types/void.rb +4 -0
  19. data/lib/types/props/_props.rb +2 -2
  20. data/lib/types/props/decorator.rb +8 -7
  21. data/lib/types/props/has_lazily_specialized_methods.rb +2 -0
  22. data/lib/types/props/pretty_printable.rb +1 -1
  23. data/lib/types/props/private/deserializer_generator.rb +4 -1
  24. data/lib/types/props/private/setter_factory.rb +129 -69
  25. data/lib/types/props/serializable.rb +7 -1
  26. data/lib/types/types/anything.rb +4 -0
  27. data/lib/types/types/attached_class.rb +4 -0
  28. data/lib/types/types/base.rb +6 -0
  29. data/lib/types/types/class_of.rb +4 -0
  30. data/lib/types/types/enum.rb +4 -0
  31. data/lib/types/types/fixed_array.rb +19 -12
  32. data/lib/types/types/fixed_hash.rb +16 -9
  33. data/lib/types/types/intersection.rb +13 -6
  34. data/lib/types/types/noreturn.rb +4 -0
  35. data/lib/types/types/proc.rb +18 -8
  36. data/lib/types/types/self_type.rb +4 -0
  37. data/lib/types/types/simple.rb +9 -0
  38. data/lib/types/types/t_enum.rb +4 -0
  39. data/lib/types/types/type_parameter.rb +4 -0
  40. data/lib/types/types/type_variable.rb +4 -0
  41. data/lib/types/types/typed_array.rb +6 -1
  42. data/lib/types/types/typed_class.rb +21 -4
  43. data/lib/types/types/typed_enumerable.rb +19 -12
  44. data/lib/types/types/typed_enumerator.rb +1 -3
  45. data/lib/types/types/typed_enumerator_chain.rb +1 -3
  46. data/lib/types/types/typed_enumerator_lazy.rb +1 -3
  47. data/lib/types/types/typed_hash.rb +17 -7
  48. data/lib/types/types/typed_range.rb +1 -3
  49. data/lib/types/types/typed_set.rb +1 -3
  50. data/lib/types/types/union.rb +12 -5
  51. data/lib/types/types/untyped.rb +4 -0
  52. data/lib/types/utils.rb +6 -4
  53. metadata +16 -30
  54. data/lib/types/interface_wrapper.rb +0 -162
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5b21bcb5dabd49853b11434c9845cf1530e7c5b1fa475b93fda398e5b8121bb
4
- data.tar.gz: 34af59fbefda1547828f8aa5fc668cf588754d9b8b1ac1221a804ba2840ad99b
3
+ metadata.gz: 62a1d832c6ab11c77c2604ee4f41e90ce19504ceb77e26a2ac1a1946316c5850
4
+ data.tar.gz: ef76ff59edbc69784d52817720f36fc38d3705849b4eea653f40b52bf7c4b1dd
5
5
  SHA512:
6
- metadata.gz: a093baa9c20a21486f6af5bd315bae13c37e59e2581dfff5a8dd6f3e95be0a50222a988358fbc2b7e14f2642d6cc14d6b3f33227d7bf73e03ecaebde1b1cb08d
7
- data.tar.gz: d814fc35c1b03fdd2d73639515eb52cd438caa7c6719d647917add140bf9a8432757ee037836eab5011b8e8c677378092225d956452e9f6e3ab063609856d805
6
+ metadata.gz: e666a6f08ec47051bcd8a7b92320089d1841544c526be65c3cdb17d0a0cea3fd4e2e921e7b389ea52b836c2a076e18346215d2c484b7efbda372cd6dd232dc58
7
+ data.tar.gz: e44d0e46981e86bd7c5f124ea1a1592d64a44955f9f405e0dcb6a61f02fb03ac4021d13bb9e01f1ac6599d94c9f7521d3164cd98f0b7efe3cc687fcb799fa6cf
@@ -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'
@@ -73,7 +74,6 @@ require_relative 'types/private/abstract/validate'
73
74
 
74
75
  # Catch all. Sort of built by `cd extn; find types -type f | grep -v test | sort`
75
76
  require_relative 'types/generic'
76
- require_relative 'types/interface_wrapper'
77
77
  require_relative 'types/private/abstract/declare'
78
78
  require_relative 'types/private/abstract/hooks'
79
79
  require_relative 'types/private/casts'
@@ -38,7 +38,7 @@ if defined? ::RSpec::Mocks
38
38
 
39
39
  module MethodDoubleExtensions
40
40
  def initialize(object, method_name, proxy)
41
- if ::Kernel.instance_method(:respond_to?).bind(object).call(method_name, true)
41
+ if ::Kernel.instance_method(:respond_to?).bind(object).call(method_name, true) # rubocop:disable Performance/BindCall
42
42
  method = ::RSpec::Support.method_handle_for(object, method_name)
43
43
  T::Private::Methods.maybe_run_sig_block_for_method(method)
44
44
  end
@@ -451,7 +451,7 @@ module T::Configuration
451
451
  @default_module_name_mangler = if T::Configuration::AT_LEAST_RUBY_2_7
452
452
  ->(type) {MODULE_NAME.bind_call(type)}
453
453
  else
454
- ->(type) {MODULE_NAME.bind(type).call}
454
+ ->(type) {MODULE_NAME.bind(type).call} # rubocop:disable Performance/BindCall
455
455
  end
456
456
 
457
457
  @module_name_mangler = nil
@@ -18,7 +18,6 @@ module T::Private::Abstract::Declare
18
18
  Abstract::Data.set(mod, :abstract_type, type)
19
19
 
20
20
  mod.extend(Abstract::Hooks)
21
- mod.extend(T::InterfaceWrapper::Helpers)
22
21
 
23
22
  if mod.is_a?(Class)
24
23
  if type == :interface
@@ -35,11 +34,11 @@ module T::Private::Abstract::Declare
35
34
  # define_method because of the guard above
36
35
 
37
36
  mod.send(:define_singleton_method, :new) do |*args, &blk|
38
- super(*args, &blk).tap do |result|
39
- if result.instance_of?(mod)
40
- raise "#{mod} is declared as abstract; it cannot be instantiated"
41
- end
37
+ result = super(*args, &blk)
38
+ if result.instance_of?(mod)
39
+ raise "#{mod} is declared as abstract; it cannot be instantiated"
42
40
  end
41
+ result
43
42
  end
44
43
 
45
44
  # Ruby doesn not emit "method redefined" warnings for aliased methods
@@ -0,0 +1,21 @@
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
+ Thread.each_caller_location do |loc|
8
+ next if loc.path&.start_with?("<internal:")
9
+
10
+ return loc if yield(loc)
11
+ end
12
+ nil
13
+ end
14
+ else
15
+ def self.find_caller
16
+ caller_locations(2).find do |loc|
17
+ !loc.path&.start_with?("<internal:") && yield(loc)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -3,12 +3,17 @@
3
3
 
4
4
  module T::Private::Methods
5
5
  @installed_hooks = {}
6
- @signatures_by_method = {}
7
- @sig_wrappers = {}
6
+ if defined?(Concurrent::Hash)
7
+ @signatures_by_method = Concurrent::Hash.new
8
+ @sig_wrappers = Concurrent::Hash.new
9
+ else
10
+ @signatures_by_method = {}
11
+ @sig_wrappers = {}
12
+ end
8
13
  @sigs_that_raised = {}
9
14
  # stores method names that were declared final without regard for where.
10
15
  # enables early rejection of names that we know can't induce final method violations.
11
- @was_ever_final_names = {}
16
+ @was_ever_final_names = {}.compare_by_identity
12
17
  # maps from a module's object_id to the set of final methods declared in that module.
13
18
  # we also overload entries slightly: if the value is nil, that means that the
14
19
  # module has final methods somewhere along its ancestor chain, but does not itself
@@ -20,7 +25,7 @@ module T::Private::Methods
20
25
  # twice is permitted). we could do this with two tables, but it seems slightly
21
26
  # cleaner with a single table.
22
27
  # Effectively T::Hash[Module, T.nilable(Set))]
23
- @modules_with_final = Hash.new {|hash, key| hash[key] = nil}
28
+ @modules_with_final = Hash.new {|hash, key| hash[key] = nil}.compare_by_identity
24
29
  # this stores the old [included, extended] hooks for Module and inherited hook for Class that we override when
25
30
  # enabling final checks for when those hooks are called. the 'hooks' here don't have anything to do with the 'hooks'
26
31
  # in installed_hooks.
@@ -132,7 +137,7 @@ module T::Private::Methods
132
137
  source_ancestors = nil
133
138
  # use reverse_each to check farther-up ancestors first, for better error messages.
134
139
  target_ancestors.reverse_each do |ancestor|
135
- final_methods = @modules_with_final.fetch(ancestor.object_id, nil)
140
+ final_methods = @modules_with_final.fetch(ancestor, nil)
136
141
  # In this case, either ancestor didn't have any final methods anywhere in its
137
142
  # ancestor chain, or ancestor did have final methods somewhere in its ancestor
138
143
  # chain, but no final methods defined in ancestor itself. Either way, there
@@ -150,20 +155,20 @@ module T::Private::Methods
150
155
  # filter out things without actual final methods just to make sure that
151
156
  # the below checks (which should be uncommon) go as quickly as possible.
152
157
  source_ancestors.select! do |a|
153
- @modules_with_final.fetch(a.object_id, nil)
158
+ @modules_with_final.fetch(a, nil)
154
159
  end
155
160
  end
156
161
  # final-ness means that there should be no more than one index for which
157
162
  # the below block returns true.
158
163
  defining_ancestor_idx = source_ancestors.index do |a|
159
- @modules_with_final.fetch(a.object_id).include?(method_name)
164
+ @modules_with_final.fetch(a).include?(method_name)
160
165
  end
161
166
  next if defining_ancestor_idx && source_ancestors[defining_ancestor_idx] == ancestor
162
167
  end
163
168
 
164
169
  definition_file, definition_line = T::Private::Methods.signature_for_method(ancestor.instance_method(method_name)).method.source_location
165
170
  is_redefined = target == ancestor
166
- 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)}
167
172
  extra_info = "\n"
168
173
  if caller_loc
169
174
  extra_info = (is_redefined ? "Redefined" : "Overridden") + " here: #{caller_loc.path}:#{caller_loc.lineno}\n"
@@ -191,13 +196,11 @@ module T::Private::Methods
191
196
  end
192
197
  end
193
198
 
194
- def self.add_module_with_final_method(mod, method_name, is_singleton_method)
195
- m = is_singleton_method ? mod.singleton_class : mod
196
- mid = m.object_id
197
- methods = @modules_with_final[mid]
199
+ def self.add_module_with_final_method(mod, method_name)
200
+ methods = @modules_with_final[mod]
198
201
  if methods.nil?
199
202
  methods = {}
200
- @modules_with_final[mid] = methods
203
+ @modules_with_final[mod] = methods
201
204
  end
202
205
  methods[method_name] = true
203
206
  nil
@@ -205,24 +208,23 @@ module T::Private::Methods
205
208
 
206
209
  def self.note_module_deals_with_final(mod)
207
210
  # Side-effectfully initialize the value if it's not already there
208
- @modules_with_final[mod.object_id]
209
- @modules_with_final[mod.singleton_class.object_id]
211
+ @modules_with_final[mod]
212
+ @modules_with_final[mod.singleton_class]
210
213
  end
211
214
 
212
215
  # Only public because it needs to get called below inside the replace_method blocks below.
213
- def self._on_method_added(hook_mod, method_name, is_singleton_method: false)
216
+ def self._on_method_added(hook_mod, mod, method_name)
214
217
  if T::Private::DeclState.current.skip_on_method_added
215
218
  return
216
219
  end
217
220
 
218
221
  current_declaration = T::Private::DeclState.current.active_declaration
219
- mod = is_singleton_method ? hook_mod.singleton_class : hook_mod
220
222
 
221
223
  if T::Private::Final.final_module?(mod) && (current_declaration.nil? || !current_declaration.final)
222
224
  raise "#{mod} was declared as final but its method `#{method_name}` was not declared as final"
223
225
  end
224
226
  # Don't compute mod.ancestors if we don't need to bother checking final-ness.
225
- if @was_ever_final_names.include?(method_name) && @modules_with_final.include?(mod.object_id)
227
+ if @was_ever_final_names.include?(method_name) && @modules_with_final.include?(mod)
226
228
  _check_final_ancestors(mod, mod.ancestors, [method_name], nil)
227
229
  # We need to fetch the active declaration again, as _check_final_ancestors
228
230
  # may have reset it (see the comment in that method for details).
@@ -276,7 +278,7 @@ module T::Private::Methods
276
278
  elsif T::Configuration::AT_LEAST_RUBY_2_7
277
279
  original_method.bind_call(self, *args, &blk)
278
280
  else
279
- original_method.bind(self).call(*args, &blk)
281
+ original_method.bind(self).call(*args, &blk) # rubocop:disable Performance/BindCall
280
282
  end
281
283
  end
282
284
  end
@@ -287,7 +289,7 @@ module T::Private::Methods
287
289
  # use hook_mod, not mod, because for example, we want class C to be marked as having final if we def C.foo as
288
290
  # final. change this to mod to see some final_method tests fail.
289
291
  note_module_deals_with_final(hook_mod)
290
- add_module_with_final_method(hook_mod, method_name, is_singleton_method)
292
+ add_module_with_final_method(mod, method_name)
291
293
  end
292
294
  end
293
295
 
@@ -431,7 +433,7 @@ module T::Private::Methods
431
433
  run_sig_block_for_key(method_to_key(method))
432
434
  end
433
435
 
434
- private_class_method def self.run_sig_block_for_key(key)
436
+ private_class_method def self.run_sig_block_for_key(key, force_type_init: false)
435
437
  blk = @sig_wrappers[key]
436
438
  if !blk
437
439
  sig = @signatures_by_method[key]
@@ -454,14 +456,17 @@ module T::Private::Methods
454
456
  end
455
457
 
456
458
  @sig_wrappers.delete(key)
459
+
460
+ sig.force_type_init if force_type_init
461
+
457
462
  sig
458
463
  end
459
464
 
460
- def self.run_all_sig_blocks
465
+ def self.run_all_sig_blocks(force_type_init: true)
461
466
  loop do
462
467
  break if @sig_wrappers.empty?
463
468
  key, = @sig_wrappers.first
464
- run_sig_block_for_key(key)
469
+ run_sig_block_for_key(key, force_type_init: force_type_init)
465
470
  end
466
471
  end
467
472
 
@@ -474,8 +479,8 @@ module T::Private::Methods
474
479
  def self._hook_impl(target, singleton_class, source)
475
480
  # we do not need to call add_was_ever_final here, because we have already marked
476
481
  # any such methods when source was originally defined.
477
- if !@modules_with_final.include?(target.object_id)
478
- if !@modules_with_final.include?(source.object_id)
482
+ if !@modules_with_final.include?(target)
483
+ if !@modules_with_final.include?(source)
479
484
  return
480
485
  end
481
486
  note_module_deals_with_final(target)
@@ -514,7 +519,7 @@ module T::Private::Methods
514
519
  if T::Configuration::AT_LEAST_RUBY_2_7
515
520
  old_included.bind_call(self, arg)
516
521
  else
517
- old_included.bind(self).call(arg)
522
+ old_included.bind(self).call(arg) # rubocop:disable Performance/BindCall
518
523
  end
519
524
  ::T::Private::Methods._hook_impl(arg, false, self)
520
525
  end
@@ -522,7 +527,7 @@ module T::Private::Methods
522
527
  if T::Configuration::AT_LEAST_RUBY_2_7
523
528
  old_extended.bind_call(self, arg)
524
529
  else
525
- old_extended.bind(self).call(arg)
530
+ old_extended.bind(self).call(arg) # rubocop:disable Performance/BindCall
526
531
  end
527
532
  ::T::Private::Methods._hook_impl(arg, true, self)
528
533
  end
@@ -530,7 +535,7 @@ module T::Private::Methods
530
535
  if T::Configuration::AT_LEAST_RUBY_2_7
531
536
  old_inherited.bind_call(self, arg)
532
537
  else
533
- old_inherited.bind(self).call(arg)
538
+ old_inherited.bind(self).call(arg) # rubocop:disable Performance/BindCall
534
539
  end
535
540
  ::T::Private::Methods._hook_impl(arg, false, self)
536
541
  end
@@ -541,14 +546,14 @@ module T::Private::Methods
541
546
  module MethodHooks
542
547
  def method_added(name)
543
548
  super(name)
544
- ::T::Private::Methods._on_method_added(self, name, is_singleton_method: false)
549
+ ::T::Private::Methods._on_method_added(self, self, name)
545
550
  end
546
551
  end
547
552
 
548
553
  module SingletonMethodHooks
549
554
  def singleton_method_added(name)
550
555
  super(name)
551
- ::T::Private::Methods._on_method_added(self, name, is_singleton_method: true)
556
+ ::T::Private::Methods._on_method_added(self, singleton_class, name)
552
557
  end
553
558
  end
554
559
 
@@ -15,8 +15,6 @@ module T::Private::Methods::CallValidation
15
15
  original_visibility = visibility_method_name(mod, method_sig.method_name)
16
16
  if method_sig.mode == T::Private::Methods::Modes.abstract
17
17
  T::Private::ClassUtils.replace_method(mod, method_sig.method_name, true) do |*args, &blk|
18
- # TODO: write a cop to ensure that abstract methods have an empty body
19
- #
20
18
  # We allow abstract methods to be implemented by things further down the ancestor chain.
21
19
  # So, if a super method exists, call it.
22
20
  if defined?(super)
@@ -67,14 +65,30 @@ module T::Private::Methods::CallValidation
67
65
  simple_method = all_args_are_simple && method_sig.return_type.is_a?(T::Types::Simple)
68
66
  simple_procedure = all_args_are_simple && method_sig.return_type.is_a?(T::Private::Types::Void)
69
67
 
68
+ # All the types for which valid? unconditionally returns `true`
69
+ return_is_ignorable =
70
+ (method_sig.return_type.equal?(T::Types::Untyped::Private::INSTANCE) ||
71
+ method_sig.return_type.equal?(T::Types::Anything::Private::INSTANCE) ||
72
+ method_sig.return_type.equal?(T::Types::AttachedClassType::Private::INSTANCE) ||
73
+ method_sig.return_type.equal?(T::Types::SelfType::Private::INSTANCE) ||
74
+ method_sig.return_type.is_a?(T::Types::TypeParameter) ||
75
+ method_sig.return_type.is_a?(T::Types::TypeVariable) ||
76
+ (method_sig.return_type.is_a?(T::Types::Simple) && method_sig.return_type.raw_type.equal?(BasicObject)))
77
+
78
+ returns_anything_method = all_args_are_simple && return_is_ignorable
79
+
70
80
  T::Configuration.without_ruby_warnings do
71
81
  T::Private::DeclState.current.without_on_method_added do
72
82
  if simple_method
73
83
  create_validator_method_fast(mod, original_method, method_sig, original_visibility)
84
+ elsif returns_anything_method
85
+ create_validator_method_skip_return_fast(mod, original_method, method_sig, original_visibility)
74
86
  elsif simple_procedure
75
87
  create_validator_procedure_fast(mod, original_method, method_sig, original_visibility)
76
88
  elsif ok_for_fast_path && method_sig.return_type.is_a?(T::Private::Types::Void)
77
89
  create_validator_procedure_medium(mod, original_method, method_sig, original_visibility)
90
+ elsif ok_for_fast_path && return_is_ignorable
91
+ create_validator_method_skip_return_medium(mod, original_method, method_sig, original_visibility)
78
92
  elsif ok_for_fast_path
79
93
  create_validator_method_medium(mod, original_method, method_sig, original_visibility)
80
94
  elsif can_skip_block_type