sorbet-runtime 0.5.5316 → 0.5.5956

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sorbet-runtime.rb +10 -1
  3. data/lib/types/_types.rb +10 -9
  4. data/lib/types/compatibility_patches.rb +65 -8
  5. data/lib/types/configuration.rb +3 -3
  6. data/lib/types/enum.rb +33 -16
  7. data/lib/types/generic.rb +2 -2
  8. data/lib/types/interface_wrapper.rb +4 -4
  9. data/lib/types/non_forcing_constants.rb +57 -0
  10. data/lib/types/private/abstract/data.rb +2 -2
  11. data/lib/types/private/abstract/declare.rb +3 -0
  12. data/lib/types/private/casts.rb +27 -0
  13. data/lib/types/private/class_utils.rb +8 -5
  14. data/lib/types/private/methods/_methods.rb +73 -23
  15. data/lib/types/private/methods/call_validation.rb +3 -0
  16. data/lib/types/private/methods/signature.rb +16 -6
  17. data/lib/types/private/retry.rb +10 -0
  18. data/lib/types/private/sealed.rb +1 -1
  19. data/lib/types/private/types/type_alias.rb +5 -0
  20. data/lib/types/private/types/void.rb +4 -3
  21. data/lib/types/profile.rb +5 -1
  22. data/lib/types/props/_props.rb +1 -5
  23. data/lib/types/props/constructor.rb +29 -9
  24. data/lib/types/props/custom_type.rb +51 -27
  25. data/lib/types/props/decorator.rb +70 -207
  26. data/lib/types/props/generated_code_validation.rb +268 -0
  27. data/lib/types/props/has_lazily_specialized_methods.rb +92 -0
  28. data/lib/types/props/optional.rb +28 -28
  29. data/lib/types/props/plugin.rb +2 -2
  30. data/lib/types/props/private/apply_default.rb +170 -0
  31. data/lib/types/props/private/deserializer_generator.rb +165 -0
  32. data/lib/types/props/private/parser.rb +32 -0
  33. data/lib/types/props/private/serde_transform.rb +192 -0
  34. data/lib/types/props/private/serializer_generator.rb +77 -0
  35. data/lib/types/props/private/setter_factory.rb +78 -26
  36. data/lib/types/props/serializable.rb +126 -181
  37. data/lib/types/props/type_validation.rb +10 -1
  38. data/lib/types/props/weak_constructor.rb +51 -14
  39. data/lib/types/sig.rb +3 -3
  40. data/lib/types/types/attached_class.rb +5 -1
  41. data/lib/types/types/base.rb +13 -0
  42. data/lib/types/types/fixed_array.rb +28 -2
  43. data/lib/types/types/fixed_hash.rb +10 -9
  44. data/lib/types/types/intersection.rb +5 -0
  45. data/lib/types/types/noreturn.rb +4 -0
  46. data/lib/types/types/self_type.rb +4 -0
  47. data/lib/types/types/simple.rb +22 -1
  48. data/lib/types/types/t_enum.rb +6 -1
  49. data/lib/types/types/type_parameter.rb +1 -1
  50. data/lib/types/types/typed_array.rb +7 -2
  51. data/lib/types/types/typed_enumerable.rb +23 -7
  52. data/lib/types/types/typed_enumerator.rb +7 -2
  53. data/lib/types/types/typed_hash.rb +8 -3
  54. data/lib/types/types/typed_range.rb +7 -2
  55. data/lib/types/types/typed_set.rb +7 -2
  56. data/lib/types/types/union.rb +36 -5
  57. data/lib/types/types/untyped.rb +4 -0
  58. data/lib/types/utils.rb +21 -6
  59. metadata +95 -2
@@ -12,7 +12,11 @@ module T::Types
12
12
 
13
13
  # @override Base
14
14
  def name
15
- @raw_type.name
15
+ # Memoize to mitigate pathological performance with anonymous modules (https://bugs.ruby-lang.org/issues/11119)
16
+ #
17
+ # `name` isn't normally a hot path for types, but it is used in initializing a T::Types::Union,
18
+ # and so in `T.nilable`, and so in runtime constructions like `x = T.let(nil, T.nilable(Integer))`.
19
+ @name ||= @raw_type.name.freeze
16
20
  end
17
21
 
18
22
  # @override Base
@@ -29,5 +33,22 @@ module T::Types
29
33
  false
30
34
  end
31
35
  end
36
+
37
+ def to_nilable
38
+ @nilable ||= T::Types::Union.new([self, T::Utils::Nilable::NIL_TYPE])
39
+ end
40
+
41
+ module Private
42
+ module Pool
43
+ def self.type_for_module(mod)
44
+ cached = mod.instance_variable_get(:@__as_sorbet_simple_type)
45
+ return cached if cached
46
+
47
+ type = Simple.new(mod)
48
+ mod.instance_variable_set(:@__as_sorbet_simple_type, type) unless mod.frozen?
49
+ type
50
+ end
51
+ end
52
+ end
32
53
  end
33
54
  end
@@ -12,7 +12,12 @@ module T::Types
12
12
 
13
13
  # @override Base
14
14
  def name
15
- @val.inspect
15
+ # Strips the #<...> off, just leaving the ...
16
+ # Reasoning: the user will have written something like
17
+ # T.any(MyEnum::A, MyEnum::B)
18
+ # in the type, so we should print what they wrote in errors, not:
19
+ # T.any(#<MyEnum::A>, #<MyEnum::B>)
20
+ @val.inspect[2..-2]
16
21
  end
17
22
 
18
23
  # @override Base
@@ -17,7 +17,7 @@ module T::Types
17
17
  end
18
18
 
19
19
  def name
20
- "T.type_parameter(#{@name})"
20
+ "T.type_parameter(:#{@name})"
21
21
  end
22
22
  end
23
23
  end
@@ -13,11 +13,16 @@ module T::Types
13
13
  end
14
14
 
15
15
  # @override Base
16
- def valid?(obj)
16
+ def recursively_valid?(obj)
17
17
  obj.is_a?(Array) && super
18
18
  end
19
19
 
20
- def new(*args) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
20
+ # @override Base
21
+ def valid?(obj)
22
+ obj.is_a?(Array)
23
+ end
24
+
25
+ def new(*args)
21
26
  Array.new(*T.unsafe(args))
22
27
  end
23
28
 
@@ -23,13 +23,18 @@ module T::Types
23
23
 
24
24
  # @override Base
25
25
  def valid?(obj)
26
+ obj.is_a?(Enumerable)
27
+ end
28
+
29
+ # @override Base
30
+ def recursively_valid?(obj)
26
31
  return false unless obj.is_a?(Enumerable)
27
32
  case obj
28
33
  when Array
29
34
  begin
30
35
  it = 0
31
36
  while it < obj.count
32
- return false unless @type.valid?(obj[it])
37
+ return false unless @type.recursively_valid?(obj[it])
33
38
  it += 1
34
39
  end
35
40
  return true
@@ -42,18 +47,22 @@ module T::Types
42
47
  value_type = types[1]
43
48
  obj.each_pair do |key, val|
44
49
  # 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)
50
+ # iterate over a [key, value] array, so we can't juse use the @type.recursively_valid?(v)
51
+ return false if !key_type.recursively_valid?(key) || !value_type.recursively_valid?(val)
47
52
  end
48
53
  return true
49
54
  when Enumerator
50
55
  # Enumerators can be unbounded: see `[:foo, :bar].cycle`
51
56
  return true
52
57
  when Range
53
- @type.valid?(obj.first) && @type.valid?(obj.last)
58
+ # A nil beginning or a nil end does not provide any type information. That is, nil in a range represents
59
+ # boundlessness, it does not express a type. For example `(nil...nil)` is not a T::Range[NilClass], its a range
60
+ # of unknown types (T::Range[T.untyped]).
61
+ # Similarly, `(nil...1)` is not a `T::Range[T.nilable(Integer)]`, it's a boundless range of Integer.
62
+ (obj.begin.nil? || @type.recursively_valid?(obj.begin)) && (obj.end.nil? || @type.recursively_valid?(obj.end))
54
63
  when Set
55
64
  obj.each do |item|
56
- return false unless @type.valid?(item)
65
+ return false unless @type.recursively_valid?(item)
57
66
  end
58
67
 
59
68
  return true
@@ -124,7 +133,13 @@ module T::Types
124
133
  inferred_val = type_from_instances(obj.values)
125
134
  T::Hash[inferred_key, inferred_val]
126
135
  when Range
127
- T::Range[type_from_instances([obj.first, obj.last])]
136
+ # We can't get any information from `NilClass` in ranges (since nil is used to represent boundlessness).
137
+ typeable_objects = [obj.begin, obj.end].compact
138
+ if typeable_objects.empty?
139
+ T::Range[T.untyped]
140
+ else
141
+ T::Range[type_from_instances(typeable_objects)]
142
+ end
128
143
  when Enumerator
129
144
  T::Enumerator[type_from_instances(obj)]
130
145
  when Set
@@ -134,7 +149,8 @@ module T::Types
134
149
  # enumerating the object is a destructive operation and might hang.
135
150
  obj.class
136
151
  else
137
- self.class.new(type_from_instances(obj))
152
+ # This is a specialized enumerable type, just return the class.
153
+ Object.instance_method(:class).bind(obj).call
138
154
  end
139
155
  end
140
156
 
@@ -15,11 +15,16 @@ module T::Types
15
15
  end
16
16
 
17
17
  # @override Base
18
- def valid?(obj)
18
+ def recursively_valid?(obj)
19
19
  obj.is_a?(Enumerator) && super
20
20
  end
21
21
 
22
- def new(*args, &blk) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
22
+ # @override Base
23
+ def valid?(obj)
24
+ obj.is_a?(Enumerator)
25
+ end
26
+
27
+ def new(*args, &blk)
23
28
  T.unsafe(Enumerator).new(*args, &blk)
24
29
  end
25
30
 
@@ -22,12 +22,17 @@ module T::Types
22
22
  end
23
23
 
24
24
  # @override Base
25
- def valid?(obj)
25
+ def recursively_valid?(obj)
26
26
  obj.is_a?(Hash) && super
27
27
  end
28
28
 
29
- def new(*args, &blk) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
30
- Hash.new(*T.unsafe(args), &blk) # rubocop:disable PrisonGuard/RestrictHashDefaults
29
+ # @override Base
30
+ def valid?(obj)
31
+ obj.is_a?(Hash)
32
+ end
33
+
34
+ def new(*args, &blk)
35
+ Hash.new(*T.unsafe(args), &blk)
31
36
  end
32
37
 
33
38
  class Untyped < TypedHash
@@ -15,11 +15,16 @@ module T::Types
15
15
  end
16
16
 
17
17
  # @override Base
18
- def valid?(obj)
18
+ def recursively_valid?(obj)
19
19
  obj.is_a?(Range) && super
20
20
  end
21
21
 
22
- def new(*args) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
22
+ # @override Base
23
+ def valid?(obj)
24
+ obj.is_a?(Range)
25
+ end
26
+
27
+ def new(*args)
23
28
  T.unsafe(Range).new(*args)
24
29
  end
25
30
  end
@@ -15,11 +15,16 @@ module T::Types
15
15
  end
16
16
 
17
17
  # @override Base
18
- def valid?(obj)
18
+ def recursively_valid?(obj)
19
19
  obj.is_a?(Set) && super
20
20
  end
21
21
 
22
- def new(*args) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
22
+ # @override Base
23
+ def valid?(obj)
24
+ obj.is_a?(Set)
25
+ end
26
+
27
+ def new(*args)
23
28
  Set.new(*T.unsafe(args))
24
29
  end
25
30
 
@@ -43,12 +43,13 @@ module T::Types
43
43
  end
44
44
 
45
45
  # @override Base
46
- def valid?(obj)
47
- @types.each do |type|
48
- return true if type.valid?(obj)
49
- end
46
+ def recursively_valid?(obj)
47
+ @types.any? {|type| type.recursively_valid?(obj)}
48
+ end
50
49
 
51
- false
50
+ # @override Base
51
+ def valid?(obj)
52
+ @types.any? {|type| type.valid?(obj)}
52
53
  end
53
54
 
54
55
  # @override Base
@@ -56,5 +57,35 @@ module T::Types
56
57
  raise "This should never be reached if you're going through `subtype_of?` (and you should be)"
57
58
  end
58
59
 
60
+ module Private
61
+ module Pool
62
+ EMPTY_ARRAY = [].freeze
63
+ private_constant :EMPTY_ARRAY
64
+
65
+ # @param type_a [T::Types::Base]
66
+ # @param type_b [T::Types::Base]
67
+ # @param types [Array] optional array of additional T::Types::Base instances
68
+ def self.union_of_types(type_a, type_b, types=EMPTY_ARRAY)
69
+ if types.empty?
70
+ # We aren't guaranteed to detect a simple `T.nilable(<Module>)` type here
71
+ # in cases where there are duplicate types, nested unions, etc.
72
+ #
73
+ # That's ok, because this is an optimization which isn't necessary for
74
+ # correctness.
75
+ if type_b == T::Utils::Nilable::NIL_TYPE && type_a.is_a?(T::Types::Simple)
76
+ type_a.to_nilable
77
+ elsif type_a == T::Utils::Nilable::NIL_TYPE && type_b.is_a?(T::Types::Simple)
78
+ type_b.to_nilable
79
+ else
80
+ Union.new([type_a, type_b])
81
+ end
82
+ else
83
+ # This can't be a `T.nilable(<Module>)` case unless there are duplicates,
84
+ # which is possible but unexpected.
85
+ Union.new([type_a, type_b] + types)
86
+ end
87
+ end
88
+ end
89
+ end
59
90
  end
60
91
  end
@@ -21,5 +21,9 @@ module T::Types
21
21
  private def subtype_of_single?(other)
22
22
  true
23
23
  end
24
+
25
+ module Private
26
+ INSTANCE = Untyped.new.freeze
27
+ end
24
28
  end
25
29
  end
data/lib/types/utils.rb CHANGED
@@ -21,15 +21,15 @@ module T::Utils
21
21
  elsif val == ::Range
22
22
  T::Range[T.untyped]
23
23
  elsif val.is_a?(Module)
24
- T::Types::Simple.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
24
+ T::Types::Simple::Private::Pool.type_for_module(val)
25
25
  elsif val.is_a?(::Array)
26
- T::Types::FixedArray.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
26
+ T::Types::FixedArray.new(val)
27
27
  elsif val.is_a?(::Hash)
28
- T::Types::FixedHash.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
28
+ T::Types::FixedHash.new(val)
29
29
  elsif val.is_a?(T::Private::Methods::DeclBuilder)
30
30
  T::Private::Methods.finalize_proc(val.decl)
31
31
  elsif val.is_a?(::T::Enum)
32
- T::Types::TEnum.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
32
+ T::Types::TEnum.new(val)
33
33
  elsif val.is_a?(::String)
34
34
  raise "Invalid String literal for type constraint. Must be an #{T::Types::Base}, a " \
35
35
  "class/module, or an array. Got a String with value `#{val}`."
@@ -109,10 +109,10 @@ module T::Utils
109
109
 
110
110
  # Returns the arity of a method, unwrapping the sig if needed
111
111
  def self.arity(method)
112
- arity = method.arity # rubocop:disable PrisonGuard/NoArity
112
+ arity = method.arity
113
113
  return arity if arity != -1 || method.is_a?(Proc)
114
114
  sig = T::Private::Methods.signature_for_method(method)
115
- sig ? sig.method.arity : arity # rubocop:disable PrisonGuard/NoArity
115
+ sig ? sig.method.arity : arity
116
116
  end
117
117
 
118
118
  # Elide the middle of a string as needed and replace it with an ellipsis.
@@ -151,6 +151,21 @@ module T::Utils
151
151
  "#{start_part}#{ellipsis}#{end_part}"
152
152
  end
153
153
 
154
+ def self.lift_enum(enum)
155
+ unless enum.is_a?(T::Types::Enum)
156
+ raise ArgumentError.new("#{enum.inspect} is not a T.enum")
157
+ end
158
+
159
+ classes = enum.values.map(&:class).uniq
160
+ if classes.empty?
161
+ T.untyped
162
+ elsif classes.length > 1
163
+ T::Types::Union.new(classes)
164
+ else
165
+ T::Types::Simple::Private::Pool.type_for_module(classes.first)
166
+ end
167
+ end
168
+
154
169
  module Nilable
155
170
  # :is_union_type, T::Boolean: whether the type is an T::Types::Union type
156
171
  # :non_nilable_type, Class: if it is an T.nilable type, the corresponding underlying type; otherwise, nil.
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.5316
4
+ version: 0.5.5956
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-31 00:00:00.000000000 Z
11
+ date: 2020-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.90.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.90.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-performance
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.8.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.8.0
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: concurrent-ruby
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +94,62 @@ dependencies:
66
94
  - - "~>"
67
95
  - !ruby/object:Gem::Version
68
96
  version: 1.1.5
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry-byebug
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: parser
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 2.7.1
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 2.7.1
139
+ - !ruby/object:Gem::Dependency
140
+ name: subprocess
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 1.5.3
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 1.5.3
69
153
  description: Sorbet's runtime type checking component
70
154
  email:
71
155
  executables: []
@@ -82,6 +166,7 @@ files:
82
166
  - lib/types/generic.rb
83
167
  - lib/types/helpers.rb
84
168
  - lib/types/interface_wrapper.rb
169
+ - lib/types/non_forcing_constants.rb
85
170
  - lib/types/private/abstract/data.rb
86
171
  - lib/types/private/abstract/declare.rb
87
172
  - lib/types/private/abstract/hooks.rb
@@ -97,6 +182,7 @@ files:
97
182
  - lib/types/private/methods/signature.rb
98
183
  - lib/types/private/methods/signature_validation.rb
99
184
  - lib/types/private/mixins/mixins.rb
185
+ - lib/types/private/retry.rb
100
186
  - lib/types/private/runtime_levels.rb
101
187
  - lib/types/private/sealed.rb
102
188
  - lib/types/private/types/not_typed.rb
@@ -109,9 +195,16 @@ files:
109
195
  - lib/types/props/custom_type.rb
110
196
  - lib/types/props/decorator.rb
111
197
  - lib/types/props/errors.rb
198
+ - lib/types/props/generated_code_validation.rb
199
+ - lib/types/props/has_lazily_specialized_methods.rb
112
200
  - lib/types/props/optional.rb
113
201
  - lib/types/props/plugin.rb
114
202
  - lib/types/props/pretty_printable.rb
203
+ - lib/types/props/private/apply_default.rb
204
+ - lib/types/props/private/deserializer_generator.rb
205
+ - lib/types/props/private/parser.rb
206
+ - lib/types/props/private/serde_transform.rb
207
+ - lib/types/props/private/serializer_generator.rb
115
208
  - lib/types/props/private/setter_factory.rb
116
209
  - lib/types/props/serializable.rb
117
210
  - lib/types/props/type_validation.rb