sorbet-runtime 0.5.5841
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 +7 -0
- data/lib/sorbet-runtime.rb +116 -0
- data/lib/types/_types.rb +285 -0
- data/lib/types/abstract_utils.rb +50 -0
- data/lib/types/boolean.rb +8 -0
- data/lib/types/compatibility_patches.rb +95 -0
- data/lib/types/configuration.rb +428 -0
- data/lib/types/enum.rb +349 -0
- data/lib/types/generic.rb +23 -0
- data/lib/types/helpers.rb +39 -0
- data/lib/types/interface_wrapper.rb +158 -0
- data/lib/types/non_forcing_constants.rb +51 -0
- data/lib/types/private/abstract/data.rb +36 -0
- data/lib/types/private/abstract/declare.rb +48 -0
- data/lib/types/private/abstract/hooks.rb +43 -0
- data/lib/types/private/abstract/validate.rb +128 -0
- data/lib/types/private/casts.rb +22 -0
- data/lib/types/private/class_utils.rb +111 -0
- data/lib/types/private/decl_state.rb +30 -0
- data/lib/types/private/final.rb +51 -0
- data/lib/types/private/methods/_methods.rb +460 -0
- data/lib/types/private/methods/call_validation.rb +1149 -0
- data/lib/types/private/methods/decl_builder.rb +228 -0
- data/lib/types/private/methods/modes.rb +16 -0
- data/lib/types/private/methods/signature.rb +196 -0
- data/lib/types/private/methods/signature_validation.rb +229 -0
- data/lib/types/private/mixins/mixins.rb +27 -0
- data/lib/types/private/retry.rb +10 -0
- data/lib/types/private/runtime_levels.rb +56 -0
- data/lib/types/private/sealed.rb +65 -0
- data/lib/types/private/types/not_typed.rb +23 -0
- data/lib/types/private/types/string_holder.rb +26 -0
- data/lib/types/private/types/type_alias.rb +26 -0
- data/lib/types/private/types/void.rb +34 -0
- data/lib/types/profile.rb +31 -0
- data/lib/types/props/_props.rb +161 -0
- data/lib/types/props/constructor.rb +40 -0
- data/lib/types/props/custom_type.rb +108 -0
- data/lib/types/props/decorator.rb +672 -0
- data/lib/types/props/errors.rb +8 -0
- data/lib/types/props/generated_code_validation.rb +268 -0
- data/lib/types/props/has_lazily_specialized_methods.rb +92 -0
- data/lib/types/props/optional.rb +81 -0
- data/lib/types/props/plugin.rb +37 -0
- data/lib/types/props/pretty_printable.rb +107 -0
- data/lib/types/props/private/apply_default.rb +170 -0
- data/lib/types/props/private/deserializer_generator.rb +165 -0
- data/lib/types/props/private/parser.rb +32 -0
- data/lib/types/props/private/serde_transform.rb +192 -0
- data/lib/types/props/private/serializer_generator.rb +77 -0
- data/lib/types/props/private/setter_factory.rb +134 -0
- data/lib/types/props/serializable.rb +330 -0
- data/lib/types/props/type_validation.rb +111 -0
- data/lib/types/props/utils.rb +59 -0
- data/lib/types/props/weak_constructor.rb +67 -0
- data/lib/types/runtime_profiled.rb +24 -0
- data/lib/types/sig.rb +30 -0
- data/lib/types/struct.rb +18 -0
- data/lib/types/types/attached_class.rb +37 -0
- data/lib/types/types/base.rb +151 -0
- data/lib/types/types/class_of.rb +38 -0
- data/lib/types/types/enum.rb +42 -0
- data/lib/types/types/fixed_array.rb +60 -0
- data/lib/types/types/fixed_hash.rb +59 -0
- data/lib/types/types/intersection.rb +37 -0
- data/lib/types/types/noreturn.rb +29 -0
- data/lib/types/types/proc.rb +51 -0
- data/lib/types/types/self_type.rb +35 -0
- data/lib/types/types/simple.rb +33 -0
- data/lib/types/types/t_enum.rb +38 -0
- data/lib/types/types/type_member.rb +7 -0
- data/lib/types/types/type_parameter.rb +23 -0
- data/lib/types/types/type_template.rb +7 -0
- data/lib/types/types/type_variable.rb +31 -0
- data/lib/types/types/typed_array.rb +34 -0
- data/lib/types/types/typed_enumerable.rb +161 -0
- data/lib/types/types/typed_enumerator.rb +36 -0
- data/lib/types/types/typed_hash.rb +43 -0
- data/lib/types/types/typed_range.rb +26 -0
- data/lib/types/types/typed_set.rb +36 -0
- data/lib/types/types/union.rb +56 -0
- data/lib/types/types/untyped.rb +29 -0
- data/lib/types/utils.rb +217 -0
- metadata +223 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
module T::Types
|
5
|
+
# Since we do type erasure at runtime, this just validates the variance and
|
6
|
+
# provides some syntax for the static type checker
|
7
|
+
class TypeVariable < Base
|
8
|
+
attr_reader :variance
|
9
|
+
|
10
|
+
VALID_VARIANCES = [:in, :out, :invariant]
|
11
|
+
|
12
|
+
def initialize(variance)
|
13
|
+
if !VALID_VARIANCES.include?(variance)
|
14
|
+
raise TypeError.new("invalid variance #{variance}")
|
15
|
+
end
|
16
|
+
@variance = variance
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?(obj)
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def subtype_of_single?(type)
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def name
|
28
|
+
Untyped.new.name
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
module T::Types
|
5
|
+
class TypedArray < TypedEnumerable
|
6
|
+
# @override Base
|
7
|
+
def name
|
8
|
+
"T::Array[#{@type.name}]"
|
9
|
+
end
|
10
|
+
|
11
|
+
def underlying_class
|
12
|
+
Array
|
13
|
+
end
|
14
|
+
|
15
|
+
# @override Base
|
16
|
+
def valid?(obj)
|
17
|
+
obj.is_a?(Array) && super
|
18
|
+
end
|
19
|
+
|
20
|
+
def new(*args) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
21
|
+
Array.new(*T.unsafe(args))
|
22
|
+
end
|
23
|
+
|
24
|
+
class Untyped < TypedArray
|
25
|
+
def initialize
|
26
|
+
super(T.untyped)
|
27
|
+
end
|
28
|
+
|
29
|
+
def valid?(obj)
|
30
|
+
obj.is_a?(Array)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
module T::Types
|
5
|
+
# Note: All subclasses of Enumerable should add themselves to the
|
6
|
+
# `case` statement below in `describe_obj` in order to get better
|
7
|
+
# error messages.
|
8
|
+
class TypedEnumerable < Base
|
9
|
+
attr_reader :type
|
10
|
+
|
11
|
+
def initialize(type)
|
12
|
+
@type = T::Utils.coerce(type)
|
13
|
+
end
|
14
|
+
|
15
|
+
def underlying_class
|
16
|
+
Enumerable
|
17
|
+
end
|
18
|
+
|
19
|
+
# @override Base
|
20
|
+
def name
|
21
|
+
"T::Enumerable[#{@type.name}]"
|
22
|
+
end
|
23
|
+
|
24
|
+
# @override Base
|
25
|
+
def valid?(obj)
|
26
|
+
return false unless obj.is_a?(Enumerable)
|
27
|
+
case obj
|
28
|
+
when Array
|
29
|
+
begin
|
30
|
+
it = 0
|
31
|
+
while it < obj.count
|
32
|
+
return false unless @type.valid?(obj[it])
|
33
|
+
it += 1
|
34
|
+
end
|
35
|
+
return true
|
36
|
+
end
|
37
|
+
when Hash
|
38
|
+
return false unless @type.is_a?(FixedArray)
|
39
|
+
types = @type.types
|
40
|
+
return false if types.count != 2
|
41
|
+
key_type = types[0]
|
42
|
+
value_type = types[1]
|
43
|
+
obj.each_pair do |key, val|
|
44
|
+
# Some objects (I'm looking at you Rack::Utils::HeaderHash) don't
|
45
|
+
# iterate over a [key, value] array, so we can't juse use the @type.valid?(v)
|
46
|
+
return false if !key_type.valid?(key) || !value_type.valid?(val)
|
47
|
+
end
|
48
|
+
return true
|
49
|
+
when Enumerator
|
50
|
+
# Enumerators can be unbounded: see `[:foo, :bar].cycle`
|
51
|
+
return true
|
52
|
+
when Range
|
53
|
+
# A nil beginning or a nil end does not provide any type information. That is, nil in a range represents
|
54
|
+
# boundlessness, it does not express a type. For example `(nil...nil)` is not a T::Range[NilClass], its a range
|
55
|
+
# of unknown types (T::Range[T.untyped]).
|
56
|
+
# Similarly, `(nil...1)` is not a `T::Range[T.nilable(Integer)]`, it's a boundless range of Integer.
|
57
|
+
(obj.begin.nil? || @type.valid?(obj.begin)) && (obj.end.nil? || @type.valid?(obj.end))
|
58
|
+
when Set
|
59
|
+
obj.each do |item|
|
60
|
+
return false unless @type.valid?(item)
|
61
|
+
end
|
62
|
+
|
63
|
+
return true
|
64
|
+
else
|
65
|
+
# We don't check the enumerable since it isn't guaranteed to be
|
66
|
+
# rewindable (e.g. STDIN) and it may be expensive to enumerate
|
67
|
+
# (e.g. an enumerator that makes an HTTP request)"
|
68
|
+
true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# @override Base
|
73
|
+
private def subtype_of_single?(other)
|
74
|
+
if other.class <= TypedEnumerable &&
|
75
|
+
underlying_class <= other.underlying_class
|
76
|
+
# Enumerables are covariant because they are read only
|
77
|
+
#
|
78
|
+
# Properly speaking, many Enumerable subtypes (e.g. Set)
|
79
|
+
# should be invariant because they are mutable and support
|
80
|
+
# both reading and writing. However, Sorbet treats *all*
|
81
|
+
# Enumerable subclasses as covariant for ease of adoption.
|
82
|
+
@type.subtype_of?(other.type)
|
83
|
+
else
|
84
|
+
false
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# @override Base
|
89
|
+
def describe_obj(obj)
|
90
|
+
return super unless obj.is_a?(Enumerable)
|
91
|
+
type_from_instance(obj).name
|
92
|
+
end
|
93
|
+
|
94
|
+
private def type_from_instances(objs)
|
95
|
+
return objs.class unless objs.is_a?(Enumerable)
|
96
|
+
obtained_types = []
|
97
|
+
begin
|
98
|
+
objs.each do |x|
|
99
|
+
obtained_types << type_from_instance(x)
|
100
|
+
end
|
101
|
+
rescue
|
102
|
+
return T.untyped # all we can do is go with the types we have so far
|
103
|
+
end
|
104
|
+
if obtained_types.count > 1
|
105
|
+
# Multiple kinds of bad types showed up, we'll suggest a union
|
106
|
+
# type you might want.
|
107
|
+
Union.new(obtained_types)
|
108
|
+
elsif obtained_types.empty?
|
109
|
+
T.noreturn
|
110
|
+
else
|
111
|
+
# Everything was the same bad type, lets just show that
|
112
|
+
obtained_types.first
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private def type_from_instance(obj)
|
117
|
+
if [true, false].include?(obj)
|
118
|
+
return T::Boolean
|
119
|
+
elsif !obj.is_a?(Enumerable)
|
120
|
+
return obj.class
|
121
|
+
end
|
122
|
+
|
123
|
+
case obj
|
124
|
+
when Array
|
125
|
+
T::Array[type_from_instances(obj)]
|
126
|
+
when Hash
|
127
|
+
inferred_key = type_from_instances(obj.keys)
|
128
|
+
inferred_val = type_from_instances(obj.values)
|
129
|
+
T::Hash[inferred_key, inferred_val]
|
130
|
+
when Range
|
131
|
+
# We can't get any information from `NilClass` in ranges (since nil is used to represent boundlessness).
|
132
|
+
typeable_objects = [obj.begin, obj.end].compact
|
133
|
+
if typeable_objects.empty?
|
134
|
+
T::Range[T.untyped]
|
135
|
+
else
|
136
|
+
T::Range[type_from_instances(typeable_objects)]
|
137
|
+
end
|
138
|
+
when Enumerator
|
139
|
+
T::Enumerator[type_from_instances(obj)]
|
140
|
+
when Set
|
141
|
+
T::Set[type_from_instances(obj)]
|
142
|
+
when IO
|
143
|
+
# Short circuit for anything IO-like (File, etc.). In these cases,
|
144
|
+
# enumerating the object is a destructive operation and might hang.
|
145
|
+
obj.class
|
146
|
+
else
|
147
|
+
self.class.new(type_from_instances(obj))
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class Untyped < TypedEnumerable
|
152
|
+
def initialize
|
153
|
+
super(T.untyped)
|
154
|
+
end
|
155
|
+
|
156
|
+
def valid?(obj)
|
157
|
+
obj.is_a?(Enumerable)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
module T::Types
|
5
|
+
class TypedEnumerator < TypedEnumerable
|
6
|
+
attr_reader :type
|
7
|
+
|
8
|
+
def underlying_class
|
9
|
+
Enumerator
|
10
|
+
end
|
11
|
+
|
12
|
+
# @override Base
|
13
|
+
def name
|
14
|
+
"T::Enumerator[#{@type.name}]"
|
15
|
+
end
|
16
|
+
|
17
|
+
# @override Base
|
18
|
+
def valid?(obj)
|
19
|
+
obj.is_a?(Enumerator) && super
|
20
|
+
end
|
21
|
+
|
22
|
+
def new(*args, &blk) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
23
|
+
T.unsafe(Enumerator).new(*args, &blk)
|
24
|
+
end
|
25
|
+
|
26
|
+
class Untyped < TypedEnumerator
|
27
|
+
def initialize
|
28
|
+
super(T.untyped)
|
29
|
+
end
|
30
|
+
|
31
|
+
def valid?(obj)
|
32
|
+
obj.is_a?(Enumerator)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
module T::Types
|
5
|
+
class TypedHash < TypedEnumerable
|
6
|
+
# Technically we don't need these, but they are a nice api
|
7
|
+
attr_reader :keys, :values
|
8
|
+
|
9
|
+
def underlying_class
|
10
|
+
Hash
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(keys:, values:)
|
14
|
+
@keys = T::Utils.coerce(keys)
|
15
|
+
@values = T::Utils.coerce(values)
|
16
|
+
@type = T::Utils.coerce([keys, values])
|
17
|
+
end
|
18
|
+
|
19
|
+
# @override Base
|
20
|
+
def name
|
21
|
+
"T::Hash[#{@keys.name}, #{@values.name}]"
|
22
|
+
end
|
23
|
+
|
24
|
+
# @override Base
|
25
|
+
def valid?(obj)
|
26
|
+
obj.is_a?(Hash) && super
|
27
|
+
end
|
28
|
+
|
29
|
+
def new(*args, &blk) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
30
|
+
Hash.new(*T.unsafe(args), &blk) # rubocop:disable PrisonGuard/RestrictHashDefaults
|
31
|
+
end
|
32
|
+
|
33
|
+
class Untyped < TypedHash
|
34
|
+
def initialize
|
35
|
+
super(keys: T.untyped, values: T.untyped)
|
36
|
+
end
|
37
|
+
|
38
|
+
def valid?(obj)
|
39
|
+
obj.is_a?(Hash)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
module T::Types
|
5
|
+
class TypedRange < TypedEnumerable
|
6
|
+
attr_reader :type
|
7
|
+
|
8
|
+
def underlying_class
|
9
|
+
Hash
|
10
|
+
end
|
11
|
+
|
12
|
+
# @override Base
|
13
|
+
def name
|
14
|
+
"T::Range[#{@type.name}]"
|
15
|
+
end
|
16
|
+
|
17
|
+
# @override Base
|
18
|
+
def valid?(obj)
|
19
|
+
obj.is_a?(Range) && super
|
20
|
+
end
|
21
|
+
|
22
|
+
def new(*args) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
23
|
+
T.unsafe(Range).new(*args)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
module T::Types
|
5
|
+
class TypedSet < TypedEnumerable
|
6
|
+
attr_reader :type
|
7
|
+
|
8
|
+
def underlying_class
|
9
|
+
Hash
|
10
|
+
end
|
11
|
+
|
12
|
+
# @override Base
|
13
|
+
def name
|
14
|
+
"T::Set[#{@type.name}]"
|
15
|
+
end
|
16
|
+
|
17
|
+
# @override Base
|
18
|
+
def valid?(obj)
|
19
|
+
obj.is_a?(Set) && super
|
20
|
+
end
|
21
|
+
|
22
|
+
def new(*args) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
|
23
|
+
Set.new(*T.unsafe(args))
|
24
|
+
end
|
25
|
+
|
26
|
+
class Untyped < TypedSet
|
27
|
+
def initialize
|
28
|
+
super(T.untyped)
|
29
|
+
end
|
30
|
+
|
31
|
+
def valid?(obj)
|
32
|
+
obj.is_a?(Set)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
module T::Types
|
5
|
+
# Takes a list of types. Validates that an object matches at least one of the types.
|
6
|
+
class Union < Base
|
7
|
+
attr_reader :types
|
8
|
+
|
9
|
+
def initialize(types)
|
10
|
+
@types = types.flat_map do |type|
|
11
|
+
type = T::Utils.resolve_alias(type)
|
12
|
+
if type.is_a?(Union)
|
13
|
+
# Simplify nested unions (mostly so `name` returns a nicer value)
|
14
|
+
type.types
|
15
|
+
else
|
16
|
+
T::Utils.coerce(type)
|
17
|
+
end
|
18
|
+
end.uniq
|
19
|
+
end
|
20
|
+
|
21
|
+
# @override Base
|
22
|
+
def name
|
23
|
+
type_shortcuts(@types)
|
24
|
+
end
|
25
|
+
|
26
|
+
private def type_shortcuts(types)
|
27
|
+
if types.size == 1
|
28
|
+
return types[0].name
|
29
|
+
end
|
30
|
+
nilable = T::Utils.coerce(NilClass)
|
31
|
+
trueclass = T::Utils.coerce(TrueClass)
|
32
|
+
falseclass = T::Utils.coerce(FalseClass)
|
33
|
+
if types.any? {|t| t == nilable}
|
34
|
+
remaining_types = types.reject {|t| t == nilable}
|
35
|
+
"T.nilable(#{type_shortcuts(remaining_types)})"
|
36
|
+
elsif types.any? {|t| t == trueclass} && types.any? {|t| t == falseclass}
|
37
|
+
remaining_types = types.reject {|t| t == trueclass || t == falseclass}
|
38
|
+
type_shortcuts([T::Private::Types::StringHolder.new("T::Boolean")] + remaining_types)
|
39
|
+
else
|
40
|
+
names = types.map(&:name).compact.sort
|
41
|
+
"T.any(#{names.join(', ')})"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# @override Base
|
46
|
+
def valid?(obj)
|
47
|
+
@types.any? {|type| type.valid?(obj)}
|
48
|
+
end
|
49
|
+
|
50
|
+
# @override Base
|
51
|
+
private def subtype_of_single?(other)
|
52
|
+
raise "This should never be reached if you're going through `subtype_of?` (and you should be)"
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
module T::Types
|
5
|
+
# A dynamic type, which permits whatever
|
6
|
+
class Untyped < Base
|
7
|
+
|
8
|
+
def initialize; end
|
9
|
+
|
10
|
+
# @override Base
|
11
|
+
def name
|
12
|
+
"T.untyped"
|
13
|
+
end
|
14
|
+
|
15
|
+
# @override Base
|
16
|
+
def valid?(obj)
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
# @override Base
|
21
|
+
private def subtype_of_single?(other)
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
25
|
+
module Private
|
26
|
+
INSTANCE = Untyped.new.freeze
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|