sorbet-runtime 0.5.10805 → 0.5.10813
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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d139387630eac4ebd032d807b545028012c477eddbacdce1bc24cca8cbadedf3
|
4
|
+
data.tar.gz: 5764af0e42e85f0bb094a83c1c258479ba9f20a4a61da50269a4cae040313bd0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02dde0ee309fdeb78efaeec183db979fa09892e3c9dd75c661f785d0ea026e9ba5424d59a5d5ad3f2fe9117f639b6d16480c56c00790b49887574b12b6cfe127
|
7
|
+
data.tar.gz: 75bf26f1cb4ce0689bfd4a3d4b85f649eff942b48553259ae971000d620f81364875b6150b62c28ff53f07211a6d9b43690b942ab9ef59aa946aabf914b86324
|
@@ -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.
|
31
|
-
raise "You must call `abstract!` *before* defining
|
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(:
|
38
|
-
if self
|
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, :
|
46
|
+
mod.singleton_class.send(:alias_method, :new, :new)
|
47
47
|
|
48
|
-
if mod.respond_to?(:ruby2_keywords, true)
|
49
|
-
mod.send(:ruby2_keywords, :
|
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
|
@@ -231,15 +231,17 @@ module T::Private::Methods
|
|
231
231
|
decl.on_failure = nil
|
232
232
|
end
|
233
233
|
if decl.params.equal?(ARG_NOT_PROVIDED)
|
234
|
-
decl.params =
|
234
|
+
decl.params = FROZEN_HASH
|
235
235
|
end
|
236
236
|
if decl.type_parameters.equal?(ARG_NOT_PROVIDED)
|
237
|
-
decl.type_parameters =
|
237
|
+
decl.type_parameters = FROZEN_HASH
|
238
238
|
end
|
239
239
|
|
240
240
|
decl.finalized = true
|
241
241
|
|
242
242
|
self
|
243
243
|
end
|
244
|
+
|
245
|
+
FROZEN_HASH = {}.freeze
|
244
246
|
end
|
245
247
|
end
|
@@ -8,6 +8,9 @@ class T::Private::Methods::Signature
|
|
8
8
|
:check_level, :parameters, :on_failure, :override_allow_incompatible,
|
9
9
|
:defined_raw
|
10
10
|
|
11
|
+
SIG_EMPTY_DECLARED_PARAMETERS = [nil].freeze
|
12
|
+
UNNAMED_REQUIRED_PARAMETERS = [[:req]].freeze
|
13
|
+
|
11
14
|
def self.new_untyped(method:, mode: T::Private::Methods::Modes.untyped, parameters: method.parameters)
|
12
15
|
# Using `Untyped` ensures we'll get an error if we ever try validation on these.
|
13
16
|
not_typed = T::Private::Types::NotTyped.new
|
@@ -16,9 +19,9 @@ class T::Private::Methods::Signature
|
|
16
19
|
parameters = parameters.each_with_index.map do |(param_kind, param_name), index|
|
17
20
|
[param_kind, param_name || "arg#{index}"]
|
18
21
|
end
|
19
|
-
raw_arg_types = parameters.
|
22
|
+
raw_arg_types = parameters.to_h do |_param_kind, param_name|
|
20
23
|
[param_name, not_typed]
|
21
|
-
end
|
24
|
+
end
|
22
25
|
|
23
26
|
self.new(
|
24
27
|
method: method,
|
@@ -61,17 +64,19 @@ class T::Private::Methods::Signature
|
|
61
64
|
# If sig params are declared but there is a single parameter with a missing name
|
62
65
|
# **and** the method ends with a "=", assume it is a writer method generated
|
63
66
|
# by attr_writer or attr_accessor
|
64
|
-
writer_method = declared_param_names !=
|
67
|
+
writer_method = declared_param_names != SIG_EMPTY_DECLARED_PARAMETERS && parameters == UNNAMED_REQUIRED_PARAMETERS && method_name[-1] == "="
|
65
68
|
# For writer methods, map the single parameter to the method name without the "=" at the end
|
66
69
|
parameters = [[:req, method_name[0...-1].to_sym]] if writer_method
|
67
70
|
param_names = parameters.map {|_, name| name}
|
68
71
|
missing_names = param_names - declared_param_names
|
69
|
-
extra_names = declared_param_names - param_names
|
70
72
|
if !missing_names.empty?
|
71
73
|
raise "The declaration for `#{method.name}` is missing parameter(s): #{missing_names.join(', ')}"
|
72
|
-
|
73
|
-
|
74
|
-
|
74
|
+
elsif param_names.length == declared_param_names.length
|
75
|
+
else
|
76
|
+
extra_names = declared_param_names - param_names
|
77
|
+
if !extra_names.empty?
|
78
|
+
raise "The declaration for `#{method.name}` has extra parameter(s): #{extra_names.join(', ')}"
|
79
|
+
end
|
75
80
|
end
|
76
81
|
|
77
82
|
if parameters.size != raw_arg_types.size
|
@@ -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
|
-
|
11
|
-
|
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.
|
4
|
+
version: 0.5.10813
|
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-
|
11
|
+
date: 2023-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|