sorbet-runtime 0.6.13244 → 0.6.13245

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: 352f00e93850eaf9666fe8a2959835594e53f30717be77305368e05494ad09f3
4
- data.tar.gz: 9c433b7af903c36e58535d12bc3b088a108bb3900b3cac1d4ecba30d3cdd346e
3
+ metadata.gz: 2c95e19aa29070164c0a98a1d6d2dcf47c9ea2a5f12e98296d60c001472c1f01
4
+ data.tar.gz: cf5b34fe0327d15854d1115dd13ad26d3d687ae7471c36b18e952d3337dae68f
5
5
  SHA512:
6
- metadata.gz: c764f72cbf8dfa35d6641a3830e9022565207e16bdf669aece0e9f8c459380182dfcc373cc53bc8ce83d96d407f9504c10abd5555849ffbe54c66ac9ad7497ca
7
- data.tar.gz: 32fb241d879635f582b49762b7bdb1e08cb2eb3a8006728b62fd84f6b3696ff1d175a17a18a1cfd430e8388342bee02215d89eb3017e3583871dae1a208f65e5
6
+ metadata.gz: 3927fc9602822bfa8f3ee986f90b26f196d123b89d151bbe8141c7c1528a8246528e3bf2f616d78d60f98b26e7dfe7e769f0adeb336c2125f5f9419c6026ec02
7
+ data.tar.gz: '014459f5f1cc56477fe4975e239efbff546d5cdf6bd14058c7d3f3a573d494925d8de5cb8aa7be38ff6344dc47dea247baff2574bb814f0312b8403fbee2580c'
@@ -51,8 +51,6 @@ module T::Private::Methods
51
51
  DeclarationBlock = Struct.new(:mod, :loc, :blk_or_decl, :final)
52
52
 
53
53
  def self.declare_sig(mod, loc, arg, &blk)
54
- install_hooks(mod)
55
-
56
54
  if T::Private::DeclState.current.active_declaration
57
55
  T::Private::DeclState.current.reset!
58
56
  raise "You called sig twice without declaring a method in between"
@@ -561,24 +559,18 @@ module T::Private::Methods
561
559
  end
562
560
  end
563
561
 
562
+ # Normally, this should be taken care of by simply `extend T::Sig`.
563
+ #
564
+ # But there are a few cases where we actually want the hooks to be "viral"
565
+ # for final modules and final methods, such that we actually want to forcibly
566
+ # install the hooks even if they would not have naturally been there via
567
+ # inheritance.
568
+ #
569
+ # As such, we don't have to handle quite as many edge cases as `lib/types/sig.rb` does
564
570
  def self.install_hooks(mod)
565
571
  return if @installed_hooks.include?(mod)
566
572
  @installed_hooks[mod] = true
567
573
 
568
- if mod == TOP_SELF
569
- # self at the top-level of a file is weirdly special in Ruby
570
- # The Ruby VM on startup creates an `Object.new` and stashes it.
571
- # Unlike when we're using sig inside a module, `self` is actually a
572
- # normal object, not an instance of Module.
573
- #
574
- # Thus we can't ask things like mod.singleton_class? (since that's
575
- # defined only on Module, not on Object) and even if we could, the places
576
- # where we need to install the hooks are special.
577
- mod.extend(SingletonMethodHooks) # def self.foo; end (at top level)
578
- Object.extend(MethodHooks) # def foo; end (at top level)
579
- return
580
- end
581
-
582
574
  # See https://github.com/sorbet/sorbet/pull/3964 for an explanation of why this
583
575
  # check (which theoretically should not be needed) is actually needed.
584
576
  if !mod.is_a?(Module)
data/lib/types/sig.rb CHANGED
@@ -4,6 +4,77 @@
4
4
  # Used as a mixin to any class so that you can call `sig`.
5
5
  # Docs at https://sorbet.org/docs/sigs
6
6
  module T::Sig
7
+ include T::Private::Methods::MethodHooks
8
+ include T::Private::Methods::SingletonMethodHooks
9
+
10
+ private_class_method def self.included(other)
11
+ return unless Module == other
12
+
13
+ # Module#method_added is normally a no-op method that does not call
14
+ # `super` and immediately returns `nil`. This means that `method_added`
15
+ # methods defined on an ancestor of `Module` are never called, so for
16
+ # `Module` itself, we need to redefine to call `super` to forward to the
17
+ # `method_added` defined above and which is already in the hierarchy.
18
+ #
19
+ # (`singleton_method_added` is defined on `BasicObject`, so ours does
20
+ # override that one.)
21
+ other.prepend(T::Private::Methods::MethodHooks)
22
+ end
23
+
24
+ private_class_method def self.extended(other)
25
+ if other == T::Private::Methods::TOP_SELF
26
+ # Methods defined via `def foo; end` at the top-level of a file are
27
+ # actually defined as private instance methods on `Object`, so we have to
28
+ # register our `method_added` hook there.
29
+ #
30
+ # Methods defined via `def self.foo; end` at the top-level are defined on
31
+ # a special instance of `Object` called `main` (initialized by the VM on
32
+ # startup), and putting `extend T::Sig` at the top-level of a file has
33
+ # the effect of putting `singleton_method_added` on the singleton class
34
+ # of `main`, which is catches those methods.
35
+ Object.extend(T::Private::Methods::MethodHooks)
36
+ return
37
+ end
38
+
39
+ return unless Module.===(other) && other.singleton_class?
40
+
41
+ # Given this:
42
+ #
43
+ # class A
44
+ # class << self
45
+ # extend T::Sig
46
+ # end
47
+ # end
48
+ #
49
+ # The `singleton_method_added` hook will end up defined as if
50
+ # `A.singleton_class.singleton_class#singleton_method_added`[1], so methods
51
+ # defined via `def self.` inside the `class << self` will be hooked, but
52
+ # not "instance" methods, because for better or worse Ruby chooses to call
53
+ # `A.singleton_method_added` even for `def foo` (an instance method) inside
54
+ # a `class << self` definition.[2]
55
+ #
56
+ # This forces a problem on users: they need `extend T::Sig` to make `sig`
57
+ # callable at the class body, but they need `include T::Sig` to make sure
58
+ # that the `singleton_method_added` hook lands on the right place. To
59
+ # avoid users needing to do that, we define an extra
60
+ # `singleton_method_added` on the `attached_object` of the singleton
61
+ # class, aka `A.singleton_method_added`.[3]
62
+ #
63
+ # [1] Not actually--it will be in the ancestor chain, but callable on
64
+ # values of that type.
65
+ #
66
+ # [2] I imagine this is for backwards compatibility in the common case of
67
+ # one level of `class << self` nesting, so that people can define a
68
+ # single `singleton_method_added` hook and have it fire for `def
69
+ # self.foo` methods outside and `def foo` inside.
70
+ #
71
+ # [3] Before switching to having the hooks defined eagerly `T::Sig`
72
+ # itself, this was done lazily via `include(SingletonMethodHooks)`
73
+ # instead of `extend(MethodHooks)` on the first call to `sig` inside
74
+ # the `class << self`.
75
+ other.include(T::Private::Methods::SingletonMethodHooks)
76
+ end
77
+
7
78
  module WithoutRuntime
8
79
  # At runtime, does nothing, but statically it is treated exactly the same
9
80
  # as T::Sig#sig. Only use it in cases where you can't use T::Sig#sig.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorbet-runtime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.13244
4
+ version: 0.6.13245
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe