sorbet-runtime 0.5.10804 → 0.5.10810

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: fa7a0490c3f7444ff040bb55e99d4fb52ee3943c97bd873427c52d58a67dee92
4
- data.tar.gz: c2475595abbccc6900c35cb0747dc872ffc5fd0b8043d955a53bc8b5ecb6e13d
3
+ metadata.gz: 9ce397971b7d821fb18a9d6e46c976b36f6aff58d41ce9c450b55b556a847038
4
+ data.tar.gz: 27e289b6c887fd4e55b3a4614cd8fd24e4eaf0a5597074f638bdc15832294feb
5
5
  SHA512:
6
- metadata.gz: b9367983c2a15754f5a2b39de9238d8d9ae387a6b1964edbd60e9d4f084877cd01a24a17095bc17dbb675b42f9b172f88f8a84560d585cc5af02f14e6bf83f9c
7
- data.tar.gz: 65b7e38725846375455d4bef55314cc6e795a48c72761e9a24d2cd86764855e99351c93fa1beb59e62dc42f6f4c941853a8ddc15549532e7e2c78b065a7c706d
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
@@ -50,9 +50,9 @@ class T::Props::Decorator
50
50
  override = rules.delete(:override)
51
51
 
52
52
  if props.include?(prop) && !override
53
- raise ArgumentError.new("Attempted to redefine prop #{prop.inspect} that's already defined without specifying :override => true: #{prop_rules(prop)}")
53
+ raise ArgumentError.new("Attempted to redefine prop #{prop.inspect} on class #{@class} that's already defined without specifying :override => true: #{prop_rules(prop)}")
54
54
  elsif !props.include?(prop) && override
55
- raise ArgumentError.new("Attempted to override a prop #{prop.inspect} that doesn't already exist")
55
+ raise ArgumentError.new("Attempted to override a prop #{prop.inspect} on class #{@class} that doesn't already exist")
56
56
  end
57
57
 
58
58
  @props = @props.merge(prop => rules.freeze).freeze
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.10804
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-06 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