sorbet-runtime 0.5.10805 → 0.5.10810

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: 8aaf11e42b38458ad4f9df3fcccea9d2e9c3abcb16cfc6b68e63464537ecf9eb
4
- data.tar.gz: c5736c17b5d9152b421062d3fd5db31b7ce6d64a512e23ed11d417cb46fb3c04
3
+ metadata.gz: 9ce397971b7d821fb18a9d6e46c976b36f6aff58d41ce9c450b55b556a847038
4
+ data.tar.gz: 27e289b6c887fd4e55b3a4614cd8fd24e4eaf0a5597074f638bdc15832294feb
5
5
  SHA512:
6
- metadata.gz: 7184b5d378814c673d1f65ca83c0c4c206892775fbbe543bcefbd0aa873df3abd0564a27a6cb32410b1e5a13c77de82d4729eecb82132cf5f0404905272cebb9
7
- data.tar.gz: e3caf0d197620e66f66b1ae81d381755aa9a06055829e6a8c7ad46bf4e0a3b4a289ebb8ed477237cffd5eaa7ffd29699e6c544f0f524ff92de37a3501315576a
6
+ metadata.gz: 761d5c3f85446fb6c2f743868ecdf74f625b3d2c31d2e3045ca91ee626093f09f85f6fdcfdba1d1413896f5e451df450659bb619637fd66fa8d1ed95735d8223
7
+ data.tar.gz: e6e883faf46cfec00205731384229290d7ef8bbaa1044694d87d2e236d8f37172acf7a477e5a11e2077c6b47f53376ab6f5b7495b14eecd651a23635a7112e50
@@ -27,15 +27,15 @@ module T::Private::Abstract::Declare
27
27
  raise "Classes can't be interfaces. Use `abstract!` instead of `interface!`."
28
28
  end
29
29
 
30
- if mod.instance_method(:initialize).owner == mod
31
- raise "You must call `abstract!` *before* defining an initialize method"
30
+ if mod.method(:new).owner == mod
31
+ raise "You must call `abstract!` *before* defining a `new` method"
32
32
  end
33
33
 
34
34
  # Don't need to silence warnings via without_ruby_warnings when calling
35
35
  # define_method because of the guard above
36
36
 
37
- mod.send(:define_method, :initialize) do |*args, &blk|
38
- if self.class == mod
37
+ mod.send(:define_singleton_method, :new) do |*args, &blk|
38
+ if T.unsafe(self) == mod
39
39
  raise "#{mod} is declared as abstract; it cannot be instantiated"
40
40
  end
41
41
  super(*args, &blk)
@@ -43,10 +43,10 @@ module T::Private::Abstract::Declare
43
43
 
44
44
  # Ruby doesn not emit "method redefined" warnings for aliased methods
45
45
  # (more robust than undef_method that would create a small window in which the method doesn't exist)
46
- mod.send(:alias_method, :initialize, :initialize)
46
+ mod.singleton_class.send(:alias_method, :new, :new)
47
47
 
48
- if mod.respond_to?(:ruby2_keywords, true)
49
- mod.send(:ruby2_keywords, :initialize)
48
+ if mod.singleton_class.respond_to?(:ruby2_keywords, true)
49
+ mod.singleton_class.send(:ruby2_keywords, :new)
50
50
  end
51
51
  end
52
52
  end
@@ -6,14 +6,63 @@ module T::Private::Methods::SignatureValidation
6
6
  Modes = Methods::Modes
7
7
 
8
8
  def self.validate(signature)
9
+ # Constructors in any language are always a bit weird: they're called in a
10
+ # static context, but their bodies are implemented by instance methods. So
11
+ # a mix of the rules that apply to instance methods and class methods
12
+ # apply.
13
+ #
14
+ # In languages like Java and Scala, static methods/companion object methods
15
+ # are never inherited. (In Java it almost looks like you can inherit them,
16
+ # because `Child.static_parent_method` works, but this method is simply
17
+ # resolved statically to `Parent.static_parent_method`). Even though most
18
+ # instance methods overrides have variance checking done, constructors are
19
+ # not treated like this, because static methods are never
20
+ # inherited/overridden, and the constructor can only ever be called
21
+ # indirectly by way of the static method. (Note: this is only a mental
22
+ # model--there's not actually a static method for the constructor in Java,
23
+ # there's an `invokespecial` JVM instruction that handles this).
24
+ #
25
+ # But Ruby is not like Java: singleton class methods in Ruby *are*
26
+ # inherited, unlike static methods in Java. In fact, this is similar to how
27
+ # JavaScript works. TypeScript simply then sidesteps the issue with
28
+ # structural typing: `typeof Parent` is not compatible with `typeof Child`
29
+ # if their constructors are different. (In a nominal type system, simply
30
+ # having Child descend from Parent should be the only factor in determining
31
+ # whether those types are compatible).
32
+ #
33
+ # Flow has nominal subtyping for classes. When overriding (static and
34
+ # instance) methods in a child class, the overrides must satisfy variance
35
+ # constraints. But it still carves out an exception for constructors,
36
+ # because then literally every class would have to have the same
37
+ # constructor. This is simply unsound. Hack does a similar thing--static
38
+ # method overrides are checked, but not constructors. Though what Hack
39
+ # *does* have is a way to opt into override checking for constructors with
40
+ # a special annotation.
41
+ #
42
+ # It turns out, Sorbet already has this special annotation: either
43
+ # `abstract` or `overridable`. At time of writing, *no* static override
44
+ # checking happens unless marked with these keywords (though at runtime, it
45
+ # always happens). Getting the static system to parity with the runtime by
46
+ # always checking overrides would be a great place to get to one day, but
47
+ # for now we can take advantage of it by only doing override checks for
48
+ # constructors if they've opted in.
49
+ #
50
+ # (When we get around to more widely checking overrides statically, we will
51
+ # need to build a matching special case for constructors statically.)
52
+ #
53
+ # Note that this breaks with tradition: normally, constructors are not
54
+ # allowed to be abstract. But that's kind of a side-effect of everything
55
+ # above: in Java/Scala, singleton class methods are never abstract because
56
+ # they're not inherited, and this extends to constructors. TypeScript
57
+ # simply rejects `new klass()` entirely if `klass` is
58
+ # `typeof AbstractClass`, requiring instead that you write
59
+ # `{ new(): AbstractClass }`. We may want to consider building some
60
+ # analogue to `T.class_of` in the future that works like this `{new():
61
+ # ...}` type.
9
62
  if signature.method_name == :initialize && signature.method.owner.is_a?(Class)
10
- # Constructors are special. They look like overrides in terms of a super_method existing,
11
- # but in practice, you never call them polymorphically. Conceptually, they're standard
12
- # methods (this is consistent with how they're treated in other languages, e.g. Java)
13
- if signature.mode != Modes.standard
14
- raise "`initialize` should not use `.abstract` or `.implementation` or any other inheritance modifiers."
63
+ if signature.mode == Modes.standard
64
+ return
15
65
  end
16
- return
17
66
  end
18
67
 
19
68
  super_method = signature.method.super_method
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.10805
4
+ version: 0.5.10810
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-08 00:00:00.000000000 Z
11
+ date: 2023-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest