sorbet-runtime 0.4.4788 → 0.4.5059

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: 31271303dfeb98e19ae3042f9c577f080415b592e005a407be7dab657cae0f77
4
- data.tar.gz: 10ebdce3b1e460c9a95b6144e0b0662f98eb77574eb586a1d248c38c91e01b73
3
+ metadata.gz: '08896772fcca300510e9b2e62c6a16bc70ee4f6eb3bb5409d6e0324f7ae98382'
4
+ data.tar.gz: 98abf40add7ee4518be064fd14b8eded16d8a326910409d9db13ec6a88e23ea1
5
5
  SHA512:
6
- metadata.gz: '0027993a7fa1be8694fd2eb2b0b3c64978430bb6d44b91a54ebd8922cbab1a9b40b4ecab04f8d3331acfded84873e49926b6930be53acbd565f418c34e817484'
7
- data.tar.gz: 89c69d15484d2f69df868ab465dc8085c1123adae026b1678c28b268211c0b2eb80ef991af6b930572a2c0113fc8bc165e3aba1138d7af187c1487aa79aa2632
6
+ metadata.gz: 55a0df02cbade8623577ce15eb939435b7cb2fca7d2fc043a7fff25dc83d69659eb777021be2efc134c637a625566f84a6523577266f7f0b33bb23c0bcf2cc79
7
+ data.tar.gz: d0f9ae6831387b11d283e0badc92d5629e39dde5d5f8fa4d786a6f784b3bdc9648992485b0787e298a8c5bd8832642df83dcee17e346c337dd951c8daa80d959
@@ -24,7 +24,6 @@ require_relative 'types/_types'
24
24
  require_relative 'types/private/decl_state'
25
25
  require_relative 'types/runtime_profiled'
26
26
  require_relative 'types/private/class_utils'
27
- require_relative 'types/private/error_handler'
28
27
  require_relative 'types/private/runtime_levels'
29
28
  require_relative 'types/private/methods/_methods'
30
29
  require_relative 'types/sig'
@@ -43,9 +42,10 @@ require_relative 'types/types/fixed_hash'
43
42
  require_relative 'types/types/intersection'
44
43
  require_relative 'types/types/noreturn'
45
44
  require_relative 'types/types/proc'
45
+ require_relative 'types/types/attached_class'
46
46
  require_relative 'types/types/self_type'
47
47
  require_relative 'types/types/simple'
48
- require_relative 'types/types/opus_enum'
48
+ require_relative 'types/types/t_enum'
49
49
  require_relative 'types/types/type_parameter'
50
50
  require_relative 'types/types/typed_array'
51
51
  require_relative 'types/types/typed_enumerator'
@@ -57,6 +57,7 @@ require_relative 'types/types/untyped'
57
57
  require_relative 'types/private/types/not_typed'
58
58
  require_relative 'types/private/types/void'
59
59
  require_relative 'types/private/types/string_holder'
60
+ require_relative 'types/private/types/type_alias'
60
61
 
61
62
  require_relative 'types/types/type_variable'
62
63
  require_relative 'types/types/type_member'
@@ -98,6 +99,8 @@ require_relative 'types/props/constructor'
98
99
  require_relative 'types/props/pretty_printable'
99
100
  require_relative 'types/props/serializable'
100
101
  require_relative 'types/props/type_validation'
102
+
101
103
  require_relative 'types/struct'
104
+ require_relative 'types/enum'
102
105
 
103
106
  require_relative 'types/compatibility_patches'
data/lib/types/_types.rb CHANGED
@@ -65,6 +65,11 @@ module T
65
65
  T::Types::SelfType.new
66
66
  end
67
67
 
68
+ # Matches the instance type in a singleton-class context
69
+ def self.experimental_attached_class
70
+ T::Types::AttachedClassType.new
71
+ end
72
+
68
73
  # Matches any class that subclasses or includes the provided class
69
74
  # or module
70
75
  def self.class_of(klass)
@@ -75,11 +80,11 @@ module T
75
80
  ## END OF THE METHODS TO PASS TO `sig`.
76
81
 
77
82
 
78
- # Constructs a type alias. Used to create a short name for a larger
79
- # type. In Ruby this is just equivalent to assignment, but this is
80
- # needed for support by the static checker. Example usage:
83
+ # Constructs a type alias. Used to create a short name for a larger type. In Ruby this returns a
84
+ # wrapper that contains a proc that is evaluated to get the underlying type. This syntax however
85
+ # is needed for support by the static checker. Example usage:
81
86
  #
82
- # NilableString = T.type_alias(T.nilable(String))
87
+ # NilableString = T.type_alias {T.nilable(String)}
83
88
  #
84
89
  # sig {params(arg: NilableString, default: String).returns(String)}
85
90
  # def or_else(arg, default)
@@ -88,8 +93,14 @@ module T
88
93
  #
89
94
  # The name of the type alias is not preserved; Error messages will
90
95
  # be printed with reference to the underlying type.
91
- def self.type_alias(type)
92
- T::Utils.coerce(type)
96
+ #
97
+ # TODO Remove `type` parameter. This was left in to make life easier while migrating.
98
+ def self.type_alias(type=nil, &blk)
99
+ if blk
100
+ T::Private::Types::TypeAlias.new(blk)
101
+ else
102
+ T::Utils.coerce(type)
103
+ end
93
104
  end
94
105
 
95
106
  # References a type paramater which was previously defined with
data/lib/types/boolean.rb CHANGED
@@ -4,5 +4,5 @@
4
4
  module T
5
5
  # T::Boolean is a type alias helper for the common `T.any(TrueClass, FalseClass)`.
6
6
  # Defined separately from _types.rb because it has a dependency on T::Types::Union.
7
- Boolean = T.type_alias(T.any(TrueClass, FalseClass))
7
+ Boolean = T.type_alias {T.any(TrueClass, FalseClass)}
8
8
  end
@@ -356,6 +356,7 @@ module T::Configuration
356
356
  String
357
357
  Symbol
358
358
  Time
359
+ T::Enum
359
360
  }).freeze
360
361
 
361
362
  def self.scalar_types
@@ -382,6 +383,15 @@ module T::Configuration
382
383
  end
383
384
  end
384
385
 
386
+ def self.enable_legacy_t_enum_migration_mode
387
+ @legacy_t_enum_migration_mode = true
388
+ end
389
+ def self.disable_legacy_t_enum_migration_mode
390
+ @legacy_t_enum_migration_mode = false
391
+ end
392
+ def self.legacy_t_enum_migration_mode?
393
+ @legacy_t_enum_migration_mode || false
394
+ end
385
395
 
386
396
  private_class_method def self.validate_lambda_given!(value)
387
397
  if !value.nil? && !value.respond_to?(:call)
data/lib/types/enum.rb ADDED
@@ -0,0 +1,343 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ # Enumerations allow for type-safe declarations of a fixed set of values.
5
+ #
6
+ # Every value is a singleton instance of the class (i.e. `Suit::SPADE.is_a?(Suit) == true`).
7
+ #
8
+ # Each value has a corresponding serialized value. By default this is the constant's name converted
9
+ # to lowercase (e.g. `Suit::Club.serialize == 'club'`); however a custom value may be passed to the
10
+ # constructor. Enum will `freeze` the serialized value.
11
+ #
12
+ # @example Declaring an Enum:
13
+ # class Suit < T::Enum
14
+ # enums do
15
+ # CLUB = new
16
+ # SPADE = new
17
+ # DIAMOND = new
18
+ # HEART = new
19
+ # end
20
+ # end
21
+ #
22
+ # @example Custom serialization value:
23
+ # class Status < T::Enum
24
+ # enums do
25
+ # READY = new('rdy')
26
+ # ...
27
+ # end
28
+ # end
29
+ #
30
+ # @example Accessing values:
31
+ # Suit::SPADE
32
+ #
33
+ # @example Converting from serialized value to enum instance:
34
+ # Suit.deserialize('club') == Suit::CLUB
35
+ #
36
+ # @example Using enums in type signatures:
37
+ # sig {params(suit: Suit).returns(Boolean)}
38
+ # def is_red?(suit); ...; end
39
+ #
40
+ # WARNING: Enum instances are singletons that are shared among all their users. Their internals
41
+ # should be kept immutable to avoid unpredictable action at a distance.
42
+ class T::Enum
43
+ extend T::Sig
44
+ extend T::Props::CustomType
45
+
46
+ # TODO(jez) Might want to restrict this, or make subclasses provide this type
47
+ SerializedVal = T.type_alias {T.untyped}
48
+ private_constant :SerializedVal
49
+
50
+ ## Enum class methods ##
51
+ sig {returns(T::Array[T.experimental_attached_class])}
52
+ def self.values
53
+ if @values.nil?
54
+ raise "Attempting to access values of #{self.class} before it has been initialized." \
55
+ " Enums are not initialized until the 'enums do' block they are defined in has finished running."
56
+ end
57
+ @values
58
+ end
59
+
60
+ # Convert from serialized value to enum instance
61
+ #
62
+ # Note: It would have been nice to make this method final before people started overriding it.
63
+ # Note: Failed CriticalMethodsNoRuntimeTypingTest
64
+ sig {params(serialized_val: SerializedVal).returns(T.nilable(T.experimental_attached_class)).checked(:never)}
65
+ def self.try_deserialize(serialized_val)
66
+ if @mapping.nil?
67
+ raise "Attempting to access serialization map of #{self.class} before it has been initialized." \
68
+ " Enums are not initialized until the 'enums do' block they are defined in has finished running."
69
+ end
70
+ @mapping[serialized_val]
71
+ end
72
+
73
+ # Convert from serialized value to enum instance.
74
+ #
75
+ # Note: It would have been nice to make this method final before people started overriding it.
76
+ # Note: Failed CriticalMethodsNoRuntimeTypingTest
77
+ #
78
+ # @return [self]
79
+ # @raise [KeyError] if serialized value does not match any instance.
80
+ sig {overridable.params(serialized_val: SerializedVal).returns(T.experimental_attached_class).checked(:never)}
81
+ def self.from_serialized(serialized_val)
82
+ res = try_deserialize(serialized_val)
83
+ if res.nil?
84
+ raise KeyError.new("Enum #{self} key not found: #{serialized_val.inspect}")
85
+ end
86
+ res
87
+ end
88
+
89
+ # Note: It would have been nice to make this method final before people started overriding it.
90
+ # @return [Boolean] Does the given serialized value correspond with any of this enum's values.
91
+ sig {overridable.params(serialized_val: SerializedVal).returns(T::Boolean)}
92
+ def self.has_serialized?(serialized_val)
93
+ if @mapping.nil?
94
+ raise "Attempting to access serialization map of #{self.class} before it has been initialized." \
95
+ " Enums are not initialized until the 'enums do' block they are defined in has finished running."
96
+ end
97
+ @mapping.include?(serialized_val)
98
+ end
99
+
100
+
101
+ ## T::Props::CustomType
102
+
103
+ # Note: Failed CriticalMethodsNoRuntimeTypingTest
104
+ sig {params(value: T.untyped).returns(T::Boolean).checked(:never)}
105
+ def self.instance?(value)
106
+ value.is_a?(self)
107
+ end
108
+
109
+ # Note: Failed CriticalMethodsNoRuntimeTypingTest
110
+ sig {params(instance: T.nilable(T::Enum)).returns(SerializedVal).checked(:never)}
111
+ def self.serialize(instance)
112
+ # This is needed otherwise if a Chalk::ODM::Document with a property of the shape
113
+ # T::Hash[T.nilable(MyEnum), Integer] and a value that looks like {nil => 0} is
114
+ # serialized, we throw the error on L102.
115
+ return nil if instance.nil?
116
+
117
+ if self == T::Enum
118
+ raise "Cannot call T::Enum.serialize directly. You must call on a specific child class."
119
+ end
120
+ if instance.class != self
121
+ raise "Cannot call #serialize on a value that is not an instance of #{self}."
122
+ end
123
+ instance.serialize
124
+ end
125
+
126
+ # Note: Failed CriticalMethodsNoRuntimeTypingTest
127
+ sig {params(mongo_value: SerializedVal).returns(T.experimental_attached_class).checked(:never)}
128
+ def self.deserialize(mongo_value)
129
+ if self == T::Enum
130
+ raise "Cannot call T::Enum.deserialize directly. You must call on a specific child class."
131
+ end
132
+ self.from_serialized(mongo_value)
133
+ end
134
+
135
+
136
+ ## Enum instance methods ##
137
+
138
+
139
+ sig {returns(T.self_type)}
140
+ def dup
141
+ self
142
+ end
143
+
144
+ sig {returns(T.self_type).checked(:tests)}
145
+ def clone
146
+ self
147
+ end
148
+
149
+ # Note: Failed CriticalMethodsNoRuntimeTypingTest
150
+ sig {returns(SerializedVal).checked(:never)}
151
+ def serialize
152
+ assert_bound!
153
+ @serialized_val
154
+ end
155
+
156
+ sig {params(args: T.untyped).returns(T.untyped)}
157
+ def to_json(*args)
158
+ serialize.to_json(*args)
159
+ end
160
+
161
+ sig {returns(String)}
162
+ def to_s
163
+ inspect
164
+ end
165
+
166
+ sig {returns(String)}
167
+ def inspect
168
+ "#<#{self.class.name}::#{@const_name || '__UNINITIALIZED__'}>"
169
+ end
170
+
171
+ sig {params(other: BasicObject).returns(T.nilable(Integer))}
172
+ def <=>(other)
173
+ case other
174
+ when self.class
175
+ self.serialize <=> other.serialize
176
+ else
177
+ nil
178
+ end
179
+ end
180
+
181
+
182
+ # NB: Do not call this method. This exists to allow for a safe migration path in places where enum
183
+ # values are compared directly against string values.
184
+ #
185
+ # Ruby's string has a weird quirk where `'my_string' == obj` calls obj.==('my_string') if obj
186
+ # responds to the `to_str` method. It does not actually call `to_str` however.
187
+ #
188
+ # See https://ruby-doc.org/core-2.4.0/String.html#method-i-3D-3D
189
+ sig {returns(String)}
190
+ def to_str
191
+ msg = 'Implicit conversion of Enum instances to strings is not allowed. Call #serialize instead.'
192
+ if T::Configuration.legacy_t_enum_migration_mode?
193
+ T::Configuration.soft_assert_handler(
194
+ msg,
195
+ storytime: {class: self.class.name},
196
+ )
197
+ serialize.to_s
198
+ else
199
+ raise NoMethodError.new(msg)
200
+ end
201
+ end
202
+
203
+ sig {params(other: BasicObject).returns(T::Boolean).checked(:never)}
204
+ def ==(other)
205
+ case other
206
+ when String
207
+ if T::Configuration.legacy_t_enum_migration_mode?
208
+ comparison_assertion_failed(:==, other)
209
+ self.serialize == other
210
+ else
211
+ false
212
+ end
213
+ else
214
+ super(other)
215
+ end
216
+ end
217
+
218
+ sig {params(other: BasicObject).returns(T::Boolean).checked(:never)}
219
+ def ===(other)
220
+ case other
221
+ when String
222
+ if T::Configuration.legacy_t_enum_migration_mode?
223
+ comparison_assertion_failed(:===, other)
224
+ self.serialize == other
225
+ else
226
+ false
227
+ end
228
+ else
229
+ super(other)
230
+ end
231
+ end
232
+
233
+ sig {params(method: Symbol, other: T.untyped).void}
234
+ private def comparison_assertion_failed(method, other)
235
+ T::Configuration.soft_assert_handler(
236
+ 'Enum to string comparison not allowed. Compare to the Enum instance directly instead. See go/enum-migration',
237
+ storytime: {
238
+ class: self.class.name,
239
+ self: self.inspect,
240
+ other: other,
241
+ other_class: other.class.name,
242
+ method: method,
243
+ }
244
+ )
245
+ end
246
+
247
+
248
+ ## Private implementation ##
249
+
250
+
251
+ sig {params(serialized_val: SerializedVal).void}
252
+ private def initialize(serialized_val=nil)
253
+ raise 'T::Enum is abstract' if self.class == T::Enum
254
+ if !self.class.started_initializing?
255
+ raise "Must instantiate all enum values of #{self.class} inside 'enums do'."
256
+ end
257
+ if self.class.fully_initialized?
258
+ raise "Cannot instantiate a new enum value of #{self.class} after it has been initialized."
259
+ end
260
+
261
+ serialized_val = serialized_val.frozen? ? serialized_val : serialized_val.dup.freeze
262
+ @serialized_val = T.let(serialized_val, T.nilable(SerializedVal))
263
+ @const_name = T.let(nil, T.nilable(Symbol))
264
+ end
265
+
266
+ sig {returns(NilClass).checked(:never)}
267
+ private def assert_bound!
268
+ if @const_name.nil?
269
+ raise "Attempting to access Enum value on #{self.class} before it has been initialized." \
270
+ " Enums are not initialized until the 'enums do' block they are defined in has finished running."
271
+ end
272
+ end
273
+
274
+ sig {params(const_name: Symbol).void}
275
+ def _bind_name(const_name)
276
+ @const_name = const_name
277
+ @serialized_val = const_to_serialized_val(const_name) if @serialized_val.nil?
278
+ freeze
279
+ end
280
+
281
+ sig {params(const_name: Symbol).returns(String)}
282
+ private def const_to_serialized_val(const_name)
283
+ # Historical note: We convert to lowercase names because the majority of existing calls to
284
+ # `make_accessible` were arrays of lowercase strings. Doing this conversion allowed for the
285
+ # least amount of repetition in migrated declarations.
286
+ const_name.to_s.downcase.freeze
287
+ end
288
+
289
+ sig {returns(T::Boolean)}
290
+ def self.started_initializing?
291
+ @started_initializing = T.let(@started_initializing, T.nilable(T::Boolean))
292
+ @started_initializing ||= false
293
+ end
294
+
295
+ sig {returns(T::Boolean)}
296
+ def self.fully_initialized?
297
+ @fully_initialized = T.let(@fully_initialized, T.nilable(T::Boolean))
298
+ @fully_initialized ||= false
299
+ end
300
+
301
+ # Entrypoint for allowing people to register new enum values.
302
+ # All enum values must be defined within this block.
303
+ sig {params(blk: T.proc.void).void}
304
+ def self.enums(&blk)
305
+ raise "enums cannot be defined for T::Enum" if self == T::Enum
306
+ raise "Enum #{self} was already initialized" if @fully_initialized
307
+ raise "Enum #{self} is still initializing" if @started_initializing
308
+
309
+ @started_initializing = true
310
+
311
+ yield
312
+
313
+ @values = T.let(nil, T.nilable(T::Array[T.experimental_attached_class]))
314
+ @mapping = T.let(nil, T.nilable(T::Hash[SerializedVal, T.experimental_attached_class]))
315
+
316
+ # Freeze the Enum class and bind the constant names into each of the instances.
317
+ @mapping = {}
318
+ self.constants(false).each do |const_name|
319
+ instance = self.const_get(const_name, false)
320
+ if !instance.is_a?(self)
321
+ raise "Invalid constant #{self}::#{const_name} on enum. " \
322
+ "All constants defined for an enum must be instances itself (e.g. `Foo = new`)."
323
+ end
324
+
325
+ instance._bind_name(const_name)
326
+ serialized = instance.serialize
327
+ if @mapping.include?(serialized)
328
+ raise "Enum values must have unique serializations. Value '#{serialized}' is repeated on #{self}."
329
+ end
330
+ @mapping[serialized] = instance
331
+ end
332
+ @values = @mapping.values.sort.freeze
333
+ @mapping.freeze
334
+ @fully_initialized = true
335
+ end
336
+
337
+ sig {params(child_class: Module).void}
338
+ def self.inherited(child_class)
339
+ super
340
+
341
+ raise "Inheriting from children of T::Enum is prohibited" if self != T::Enum
342
+ end
343
+ end
@@ -58,11 +58,7 @@ module T::Private::Methods::SignatureValidation
58
58
  def self.validate_override_mode(signature, super_signature)
59
59
  case signature.mode
60
60
  when *Modes::OVERRIDE_MODES
61
- if !Modes::OVERRIDABLE_MODES.include?(super_signature.mode)
62
- raise "You declared `#{signature.method_name}` as #{pretty_mode(signature)}, but the method it overrides is not declared as `overridable` or `abstract`.\n" \
63
- " Parent definition: #{method_loc_str(super_signature.method)}\n" \
64
- " Child definition: #{method_loc_str(signature.method)}\n"
65
- end
61
+ # Peaceful
66
62
  when *Modes::NON_OVERRIDE_MODES
67
63
  if super_signature.mode == Modes.standard
68
64
  # Peaceful
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ module T::Private::Types
5
+ # Wraps a proc for a type alias to defer its evaluation.
6
+ class TypeAlias < T::Types::Base
7
+
8
+ def initialize(callable)
9
+ @callable = callable
10
+ end
11
+
12
+ def aliased_type
13
+ @aliased_type ||= T::Utils.coerce(@callable.call)
14
+ end
15
+
16
+ # @override Base
17
+ def name
18
+ aliased_type.name
19
+ end
20
+
21
+ # @override Base
22
+ def valid?(obj)
23
+ aliased_type.valid?(obj)
24
+ end
25
+ end
26
+ end
@@ -10,11 +10,11 @@
10
10
  class T::Props::Decorator
11
11
  extend T::Sig
12
12
 
13
- Rules = T.type_alias(T::Hash[Symbol, T.untyped])
14
- DecoratedClass = T.type_alias(T.untyped) # T.class_of(T::Props), but that produces circular reference errors in some circumstances
15
- DecoratedInstance = T.type_alias(T.untyped) # Would be T::Props, but that produces circular reference errors in some circumstances
16
- PropType = T.type_alias(T.any(T::Types::Base, T::Props::CustomType))
17
- PropTypeOrClass = T.type_alias(T.any(PropType, Module))
13
+ Rules = T.type_alias {T::Hash[Symbol, T.untyped]}
14
+ DecoratedClass = T.type_alias {T.untyped} # T.class_of(T::Props), but that produces circular reference errors in some circumstances
15
+ DecoratedInstance = T.type_alias {T.untyped} # Would be T::Props, but that produces circular reference errors in some circumstances
16
+ PropType = T.type_alias {T.any(T::Types::Base, T::Props::CustomType)}
17
+ PropTypeOrClass = T.type_alias {T.any(PropType, Module)}
18
18
 
19
19
  class NoRulesError < StandardError; end
20
20
 
@@ -156,10 +156,27 @@ class T::Props::Decorator
156
156
  else
157
157
  type_object.valid?(val)
158
158
  end
159
+
159
160
  if !valid
160
161
  raise T::Props::InvalidValueError.new("Can't set #{@class.name}.#{prop} to #{val.inspect} " \
161
162
  "(instance of #{val.class}) - need a #{type_object}")
162
163
  end
164
+ rescue T::Props::InvalidValueError => err
165
+ caller_loc = T.must(caller_locations(8, 1))[0]
166
+
167
+ pretty_message = "Parameter '#{prop}': #{err.message}\n" \
168
+ "Caller: #{caller_loc.path}:#{caller_loc.lineno}\n"
169
+
170
+ T::Configuration.call_validation_error_handler(
171
+ nil,
172
+ message: err.message,
173
+ pretty_message: pretty_message,
174
+ kind: 'Parameter',
175
+ name: prop,
176
+ type: type,
177
+ value: val,
178
+ location: caller_loc,
179
+ )
163
180
  end
164
181
 
165
182
  # For performance, don't use named params here.
@@ -330,6 +347,7 @@ class T::Props::Decorator
330
347
  .void
331
348
  end
332
349
  def prop_defined(name, cls, rules={})
350
+ cls = T::Utils.resolve_alias(cls)
333
351
  if rules[:optional] == true
334
352
  T::Configuration.hard_assert_handler(
335
353
  'Use of `optional: true` is deprecated, please use `T.nilable(...)` instead.',
@@ -534,7 +552,7 @@ class T::Props::Decorator
534
552
  nil
535
553
  end
536
554
 
537
- # returns the type of the hash key, or nil. Any CustomType could be a key, but we only expect Opus::Enum right now.
555
+ # returns the type of the hash key, or nil. Any CustomType could be a key, but we only expect T::Enum right now.
538
556
  sig do
539
557
  params(type: PropType)
540
558
  .returns(T.nilable(Module))
@@ -553,9 +571,6 @@ class T::Props::Decorator
553
571
 
554
572
  # From T::Props::Utils.deep_clone_object, plus String
555
573
  TYPES_NOT_NEEDING_CLONE = [TrueClass, FalseClass, NilClass, Symbol, String, Numeric]
556
- if defined?(Opus) && defined?(Opus::Enum)
557
- TYPES_NOT_NEEDING_CLONE << Opus::Enum
558
- end
559
574
 
560
575
  sig {params(type: PropType).returns(T::Boolean)}
561
576
  private def shallow_clone_ok(type)
@@ -64,6 +64,8 @@ module T::Props::TypeValidation
64
64
  type.types.map {|subtype| find_invalid_subtype(subtype)}.compact.first
65
65
  when T::Types::Enum, T::Types::ClassOf
66
66
  nil
67
+ when T::Private::Types::TypeAlias
68
+ find_invalid_subtype(type.aliased_type)
67
69
  when T::Types::Simple
68
70
  # TODO Could we manage to define a whitelist, consisting of something
69
71
  # like primitives, subdocs, DataInterfaces, and collections/enums/unions
@@ -23,14 +23,10 @@ module T::Props::Utils
23
23
  h
24
24
  when Regexp
25
25
  what.dup
26
+ when T::Enum
27
+ what
26
28
  else
27
- # Some unfortunate nastiness to get around Opus::Enum potentially not
28
- # being defined.
29
- if defined?(Opus) && defined?(Opus::Enum) && what.class == Opus::Enum
30
- what
31
- else
32
- what.clone
33
- end
29
+ what.clone
34
30
  end
35
31
  freeze ? result.freeze : result
36
32
  end
data/lib/types/sig.rb CHANGED
@@ -7,15 +7,15 @@ module T::Sig
7
7
  module WithoutRuntime
8
8
  # At runtime, does nothing, but statically it is treated exactly the same
9
9
  # as T::Sig#sig. Only use it in cases where you can't use T::Sig#sig.
10
- def self.sig(arg=nil, &blk); end # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
10
+ def self.sig(arg0=nil, &blk); end # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
11
11
 
12
12
  original_verbose = $VERBOSE
13
13
  $VERBOSE = false
14
14
 
15
15
  # At runtime, does nothing, but statically it is treated exactly the same
16
16
  # as T::Sig#sig. Only use it in cases where you can't use T::Sig#sig.
17
- T::Sig::WithoutRuntime.sig {params(arg: T.nilable(Symbol), blk: T.proc.bind(T::Private::Methods::DeclBuilder).void).void}
18
- def self.sig(arg=nil, &blk); end # rubocop:disable PrisonGuard/BanBuiltinMethodOverride, Lint/DuplicateMethods
17
+ T::Sig::WithoutRuntime.sig {params(arg0: T.nilable(Symbol), blk: T.proc.bind(T::Private::Methods::DeclBuilder).void).void}
18
+ def self.sig(arg0=nil, &blk); end # rubocop:disable PrisonGuard/BanBuiltinMethodOverride, Lint/DuplicateMethods
19
19
 
20
20
  $VERBOSE = original_verbose
21
21
  end
@@ -23,8 +23,8 @@ module T::Sig
23
23
  # Declares a method with type signatures and/or
24
24
  # abstract/override/... helpers. See the documentation URL on
25
25
  # {T::Helpers}
26
- T::Sig::WithoutRuntime.sig {params(arg: T.nilable(Symbol), blk: T.proc.bind(T::Private::Methods::DeclBuilder).void).void}
27
- def sig(arg=nil, &blk) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
28
- T::Private::Methods.declare_sig(self, arg, &blk)
26
+ T::Sig::WithoutRuntime.sig {params(arg0: T.nilable(Symbol), blk: T.proc.bind(T::Private::Methods::DeclBuilder).void).void}
27
+ def sig(arg0=nil, &blk) # rubocop:disable PrisonGuard/BanBuiltinMethodOverride
28
+ T::Private::Methods.declare_sig(self, arg0, &blk)
29
29
  end
30
30
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ module T::Types
5
+ # Modeling AttachedClass properly at runtime would require additional
6
+ # tracking, so at runtime we permit all values and rely on the static checker.
7
+ # As AttachedClass is modeled statically as a type member on every singleton
8
+ # class, this is consistent with the runtime behavior for all type members.
9
+ class AttachedClassType < Base
10
+
11
+ def initialize(); end
12
+
13
+ # @override Base
14
+ def name
15
+ "AttachedClass"
16
+ end
17
+
18
+ # @override Base
19
+ def valid?(obj)
20
+ true
21
+ end
22
+
23
+ # @override Base
24
+ private def subtype_of_single?(other)
25
+ case other
26
+ when AttachedClassType
27
+ true
28
+ else
29
+ false
30
+ end
31
+ end
32
+ end
33
+ end
@@ -41,6 +41,14 @@ module T::Types
41
41
  def subtype_of?(t2)
42
42
  t1 = self
43
43
 
44
+ if t2.is_a?(T::Private::Types::TypeAlias)
45
+ t2 = t2.aliased_type
46
+ end
47
+
48
+ if t1.is_a?(T::Private::Types::TypeAlias)
49
+ return t1.aliased_type.subtype_of?(t2)
50
+ end
51
+
44
52
  # pairs to cover: 1 (_, _)
45
53
  # 2 (_, And)
46
54
  # 3 (_, Or)
@@ -134,7 +142,8 @@ module T::Types
134
142
  end
135
143
 
136
144
  def ==(other)
137
- other.class == self.class && other.name == self.name
145
+ (T::Utils.resolve_alias(other).class == T::Utils.resolve_alias(self).class) &&
146
+ other.name == self.name
138
147
  end
139
148
 
140
149
  alias_method :eql?, :==
@@ -8,6 +8,7 @@ module T::Types
8
8
 
9
9
  def initialize(types)
10
10
  @types = types.flat_map do |type|
11
+ type = T::Utils.resolve_alias(type)
11
12
  if type.is_a?(Intersection)
12
13
  # Simplify nested intersections (mostly so `name` returns a nicer value)
13
14
  type.types
@@ -2,8 +2,8 @@
2
2
  # typed: true
3
3
 
4
4
  module T::Types
5
- # Validates that an object is equal to another Opus::Enum singleton value.
6
- class OpusEnum < Base
5
+ # Validates that an object is equal to another T::Enum singleton value.
6
+ class TEnum < Base
7
7
  attr_reader :val
8
8
 
9
9
  def initialize(val)
@@ -23,7 +23,7 @@ module T::Types
23
23
  # @override Base
24
24
  private def subtype_of_single?(other)
25
25
  case other
26
- when OpusEnum
26
+ when TEnum
27
27
  @val == other.val
28
28
  else
29
29
  false
@@ -46,13 +46,8 @@ module T::Types
46
46
  return false if !key_type.valid?(key) || !value_type.valid?(val)
47
47
  end
48
48
  return true
49
- when Enumerator::Lazy
50
- # Users don't want these walked
51
- return true
52
49
  when Enumerator
53
- obj.each do |elem|
54
- return false unless @type.valid?(elem)
55
- end
50
+ # Enumerators can be unbounded: see `[:foo, :bar].cycle`
56
51
  return true
57
52
  when Range
58
53
  @type.valid?(obj.first) && @type.valid?(obj.last)
@@ -8,6 +8,7 @@ module T::Types
8
8
 
9
9
  def initialize(types)
10
10
  @types = types.flat_map do |type|
11
+ type = T::Utils.resolve_alias(type)
11
12
  if type.is_a?(Union)
12
13
  # Simplify nested unions (mostly so `name` returns a nicer value)
13
14
  type.types
data/lib/types/utils.rb CHANGED
@@ -4,7 +4,9 @@
4
4
  module T::Utils
5
5
  # Used to convert from a type specification to a `T::Types::Base`.
6
6
  def self.coerce(val)
7
- if val.is_a?(T::Types::Base)
7
+ if val.is_a?(T::Private::Types::TypeAlias)
8
+ val.aliased_type
9
+ elsif val.is_a?(T::Types::Base)
8
10
  val
9
11
  elsif val == ::Array
10
12
  T::Array[T.untyped]
@@ -26,8 +28,11 @@ module T::Utils
26
28
  T::Types::FixedHash.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
27
29
  elsif val.is_a?(T::Private::Methods::DeclBuilder)
28
30
  T::Private::Methods.finalize_proc(val.decl)
29
- elsif defined?(::Opus) && defined?(::Opus::Enum) && val.is_a?(::Opus::Enum)
30
- T::Types::OpusEnum.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
31
+ elsif val.is_a?(::T::Enum)
32
+ T::Types::TEnum.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
33
+ elsif val.is_a?(::String)
34
+ raise "Invalid String literal for type constraint. Must be an #{T::Types::Base}, a " \
35
+ "class/module, or an array. Got a String with value `#{val}`."
31
36
  else
32
37
  raise "Invalid value for type constraint. Must be an #{T::Types::Base}, a " \
33
38
  "class/module, or an array. Got a `#{val.class}`."
@@ -76,6 +81,16 @@ module T::Utils
76
81
  T::Private::Methods.run_all_sig_blocks
77
82
  end
78
83
 
84
+ # Return the underlying type for a type alias. Otherwise returns type.
85
+ def self.resolve_alias(type)
86
+ case type
87
+ when T::Private::Types::TypeAlias
88
+ type.aliased_type
89
+ else
90
+ type
91
+ end
92
+ end
93
+
79
94
  # Give a type which is a subclass of T::Types::Base, determines if the type is a simple nilable type (union of NilClass and something else).
80
95
  # If so, returns the T::Types::Base of the something else. Otherwise, returns nil.
81
96
  def self.unwrap_nilable(type)
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.4.4788
4
+ version: 0.4.5059
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-24 00:00:00.000000000 Z
11
+ date: 2019-11-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -78,6 +78,7 @@ files:
78
78
  - lib/types/boolean.rb
79
79
  - lib/types/compatibility_patches.rb
80
80
  - lib/types/configuration.rb
81
+ - lib/types/enum.rb
81
82
  - lib/types/generic.rb
82
83
  - lib/types/helpers.rb
83
84
  - lib/types/interface_wrapper.rb
@@ -88,7 +89,6 @@ files:
88
89
  - lib/types/private/casts.rb
89
90
  - lib/types/private/class_utils.rb
90
91
  - lib/types/private/decl_state.rb
91
- - lib/types/private/error_handler.rb
92
92
  - lib/types/private/final.rb
93
93
  - lib/types/private/methods/_methods.rb
94
94
  - lib/types/private/methods/call_validation.rb
@@ -101,6 +101,7 @@ files:
101
101
  - lib/types/private/sealed.rb
102
102
  - lib/types/private/types/not_typed.rb
103
103
  - lib/types/private/types/string_holder.rb
104
+ - lib/types/private/types/type_alias.rb
104
105
  - lib/types/private/types/void.rb
105
106
  - lib/types/profile.rb
106
107
  - lib/types/props/_props.rb
@@ -118,6 +119,7 @@ files:
118
119
  - lib/types/runtime_profiled.rb
119
120
  - lib/types/sig.rb
120
121
  - lib/types/struct.rb
122
+ - lib/types/types/attached_class.rb
121
123
  - lib/types/types/base.rb
122
124
  - lib/types/types/class_of.rb
123
125
  - lib/types/types/enum.rb
@@ -125,10 +127,10 @@ files:
125
127
  - lib/types/types/fixed_hash.rb
126
128
  - lib/types/types/intersection.rb
127
129
  - lib/types/types/noreturn.rb
128
- - lib/types/types/opus_enum.rb
129
130
  - lib/types/types/proc.rb
130
131
  - lib/types/types/self_type.rb
131
132
  - lib/types/types/simple.rb
133
+ - lib/types/types/t_enum.rb
132
134
  - lib/types/types/type_member.rb
133
135
  - lib/types/types/type_parameter.rb
134
136
  - lib/types/types/type_template.rb
@@ -145,7 +147,8 @@ files:
145
147
  homepage: https://sorbet.run
146
148
  licenses:
147
149
  - Apache-2.0
148
- metadata: {}
150
+ metadata:
151
+ source_code_uri: https://github.com/sorbet/sorbet
149
152
  post_install_message:
150
153
  rdoc_options: []
151
154
  require_paths:
@@ -155,9 +158,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
155
158
  - - ">="
156
159
  - !ruby/object:Gem::Version
157
160
  version: 2.3.0
158
- - - "<"
159
- - !ruby/object:Gem::Version
160
- version: 2.7.0.preview1
161
161
  required_rubygems_version: !ruby/object:Gem::Requirement
162
162
  requirements:
163
163
  - - ">="
File without changes