sorbet-runtime 0.5.6324 → 0.5.6341

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: d32edb62f9d95ef7cda78766959c2855150ad4b4b921ff7161c02a9b8ac104a2
4
- data.tar.gz: fa7529bc57b5c025452a888f53722945c74e3e38e566e8ce22a665046a3ef199
3
+ metadata.gz: ac27b172d55e3a40caded5e635c88edeeb1620bd1ef925b9e9fa741c33e630a9
4
+ data.tar.gz: e36feac21c69b5cb622128fe1b33ca75a55a2f08af5daa26beb3376b632a31d7
5
5
  SHA512:
6
- metadata.gz: f0f93246a969b6a474113d5f2133d39a5c1c8bfa5239cf83a931b9ce5f312b1c48f44613f0a79f144f34bdf8b5803587c6f7f86fdcd7942265f696b57a2797e2
7
- data.tar.gz: bc2a8464f8fdbc79672cbe473c75da40e311a3c150181632999dbb49850e0fe4b49719ea90efc2b06f4d32536ae3db0bc6eaf984232542fc80db3ef1a64771e3
6
+ metadata.gz: 7c3dbac967ee74b48c6daf8287b493c6e19785f876b09a865de66e3d3f94a35361dd6b42206f4524e3c9a8b9448563fc341e2b3968ede856fc5436f97dd3c076
7
+ data.tar.gz: e079e875e6cd268f83721fc4283463a0330ef96e36c359280203623309861c3abfd6f3f242d130828287790e566bdfb0ff97e456c5d403bcc6ffc2b6da4507ea
@@ -11,6 +11,9 @@ module T::Private::Methods
11
11
  # - they are done possibly before any sig block has run.
12
12
  # - they are done even if the method being defined doesn't have a sig.
13
13
  @final_methods = Set.new
14
+ # stores method names that were declared final without regard for where.
15
+ # enables early rejection of names that we know can't induce final method violations.
16
+ @was_ever_final_names = Set.new
14
17
  # a non-singleton is a module for which at least one of the following is true:
15
18
  # - is declared final
16
19
  # - defines a method that is declared final
@@ -96,13 +99,14 @@ module T::Private::Methods
96
99
  # when target includes a module with instance methods source_method_names, ensure there is zero intersection between
97
100
  # the final instance methods of target and source_method_names. so, for every m in source_method_names, check if there
98
101
  # is already a method defined on one of target_ancestors with the same name that is final.
102
+ #
103
+ # we assume that source_method_names has already been filtered to only include method
104
+ # names that were declared final at one point.
99
105
  def self._check_final_ancestors(target, target_ancestors, source_method_names)
100
- if !module_with_final?(target)
101
- return
102
- end
103
106
  # use reverse_each to check farther-up ancestors first, for better error messages. we could avoid this if we were on
104
107
  # the version of ruby that adds the optional argument to method_defined? that allows you to exclude ancestors.
105
108
  target_ancestors.reverse_each do |ancestor|
109
+ next if !module_with_final?(ancestor)
106
110
  source_method_names.each do |method_name|
107
111
  # the usage of method_owner_and_name_to_key(ancestor, method_name) instead of
108
112
  # method_to_key(ancestor.instance_method(method_name)) is not (just) an optimization, but also required for
@@ -148,6 +152,14 @@ module T::Private::Methods
148
152
  @final_methods.include?(method_key)
149
153
  end
150
154
 
155
+ private_class_method def self.add_was_ever_final(method_name)
156
+ @was_ever_final_names.add(method_name)
157
+ end
158
+
159
+ private_class_method def self.was_ever_final?(method_name)
160
+ @was_ever_final_names.include?(method_name)
161
+ end
162
+
151
163
  def self.add_module_with_final(mod)
152
164
  @modules_with_final.add(mod)
153
165
  @modules_with_final.add(mod.singleton_class)
@@ -169,7 +181,10 @@ module T::Private::Methods
169
181
  if T::Private::Final.final_module?(mod) && (current_declaration.nil? || !current_declaration.final)
170
182
  raise "#{mod} was declared as final but its method `#{method_name}` was not declared as final"
171
183
  end
172
- _check_final_ancestors(mod, mod.ancestors, [method_name])
184
+ # Don't compute mod.ancestors if we don't need to bother checking final-ness.
185
+ if was_ever_final?(method_name) && module_with_final?(mod)
186
+ _check_final_ancestors(mod, mod.ancestors, [method_name])
187
+ end
173
188
 
174
189
  # We need to fetch the active declaration again, as _check_final_ancestors
175
190
  # may have reset it (see the comment in that method for details).
@@ -229,6 +244,7 @@ module T::Private::Methods
229
244
  @sig_wrappers[key] = sig_block
230
245
  if current_declaration.final
231
246
  add_final_method(key)
247
+ add_was_ever_final(method_name)
232
248
  # use hook_mod, not mod, because for example, we want class C to be marked as having final if we def C.foo as
233
249
  # final. change this to mod to see some final_method tests fail.
234
250
  add_module_with_final(hook_mod)
@@ -407,13 +423,30 @@ module T::Private::Methods
407
423
 
408
424
  # the module target is adding the methods from the module source to itself. we need to check that for all instance
409
425
  # methods M on source, M is not defined on any of target's ancestors.
410
- def self._hook_impl(target, target_ancestors, source)
411
- if !module_with_final?(target) && !module_with_final?(source)
426
+ def self._hook_impl(target, singleton_class, source)
427
+ target_was_final = module_with_final?(target)
428
+ if !target_was_final && !module_with_final?(source)
412
429
  return
413
430
  end
431
+ # we do not need to call add_was_ever_final here, because we have already marked
432
+ # any such methods when source was originally defined.
414
433
  add_module_with_final(target)
415
434
  install_hooks(target)
416
- _check_final_ancestors(target, target_ancestors - source.ancestors, source.instance_methods)
435
+
436
+ if !target_was_final
437
+ return
438
+ end
439
+
440
+ methods = source.instance_methods
441
+ methods.select! do |method_name|
442
+ was_ever_final?(method_name)
443
+ end
444
+ if methods.empty?
445
+ return
446
+ end
447
+
448
+ target_ancestors = singleton_class ? target.singleton_class.ancestors : target.ancestors
449
+ _check_final_ancestors(target, target_ancestors - source.ancestors, methods)
417
450
  end
418
451
 
419
452
  def self.set_final_checks_on_hooks(enable)
@@ -427,15 +460,15 @@ module T::Private::Methods
427
460
  else
428
461
  old_included = T::Private::ClassUtils.replace_method(Module, :included) do |arg|
429
462
  old_included.bind(self).call(arg)
430
- ::T::Private::Methods._hook_impl(arg, arg.ancestors, self)
463
+ ::T::Private::Methods._hook_impl(arg, false, self)
431
464
  end
432
465
  old_extended = T::Private::ClassUtils.replace_method(Module, :extended) do |arg|
433
466
  old_extended.bind(self).call(arg)
434
- ::T::Private::Methods._hook_impl(arg, arg.singleton_class.ancestors, self)
467
+ ::T::Private::Methods._hook_impl(arg, true, self)
435
468
  end
436
469
  old_inherited = T::Private::ClassUtils.replace_method(Class, :inherited) do |arg|
437
470
  old_inherited.bind(self).call(arg)
438
- ::T::Private::Methods._hook_impl(arg, arg.ancestors, self)
471
+ ::T::Private::Methods._hook_impl(arg, false, self)
439
472
  end
440
473
  @old_hooks = [old_included, old_extended, old_inherited]
441
474
  end
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.6324
4
+ version: 0.5.6341
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-06 00:00:00.000000000 Z
11
+ date: 2021-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest