sorbet-runtime 0.5.11144 → 0.5.11218

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sorbet-runtime.rb +0 -1
  3. data/lib/types/private/abstract/declare.rb +4 -5
  4. data/lib/types/private/methods/_methods.rb +23 -23
  5. data/lib/types/private/methods/call_validation.rb +16 -2
  6. data/lib/types/private/methods/call_validation_2_6.rb +518 -0
  7. data/lib/types/private/methods/call_validation_2_7.rb +518 -0
  8. data/lib/types/private/methods/decl_builder.rb +1 -1
  9. data/lib/types/private/methods/signature.rb +9 -0
  10. data/lib/types/private/methods/signature_validation.rb +9 -2
  11. data/lib/types/private/types/not_typed.rb +4 -0
  12. data/lib/types/private/types/string_holder.rb +4 -0
  13. data/lib/types/private/types/type_alias.rb +4 -0
  14. data/lib/types/private/types/void.rb +4 -0
  15. data/lib/types/props/_props.rb +2 -2
  16. data/lib/types/props/decorator.rb +7 -6
  17. data/lib/types/props/pretty_printable.rb +1 -1
  18. data/lib/types/props/private/setter_factory.rb +129 -69
  19. data/lib/types/types/anything.rb +4 -0
  20. data/lib/types/types/attached_class.rb +4 -0
  21. data/lib/types/types/base.rb +6 -0
  22. data/lib/types/types/class_of.rb +4 -0
  23. data/lib/types/types/enum.rb +4 -0
  24. data/lib/types/types/fixed_array.rb +19 -12
  25. data/lib/types/types/fixed_hash.rb +16 -9
  26. data/lib/types/types/intersection.rb +13 -6
  27. data/lib/types/types/noreturn.rb +4 -0
  28. data/lib/types/types/proc.rb +19 -9
  29. data/lib/types/types/self_type.rb +4 -0
  30. data/lib/types/types/simple.rb +4 -0
  31. data/lib/types/types/t_enum.rb +4 -0
  32. data/lib/types/types/type_parameter.rb +4 -0
  33. data/lib/types/types/type_variable.rb +4 -0
  34. data/lib/types/types/typed_array.rb +6 -1
  35. data/lib/types/types/typed_class.rb +21 -4
  36. data/lib/types/types/typed_enumerable.rb +18 -11
  37. data/lib/types/types/typed_enumerator.rb +1 -3
  38. data/lib/types/types/typed_enumerator_chain.rb +1 -3
  39. data/lib/types/types/typed_enumerator_lazy.rb +1 -3
  40. data/lib/types/types/typed_hash.rb +17 -7
  41. data/lib/types/types/typed_range.rb +1 -3
  42. data/lib/types/types/typed_set.rb +1 -3
  43. data/lib/types/types/union.rb +12 -5
  44. data/lib/types/types/untyped.rb +4 -0
  45. data/lib/types/utils.rb +2 -2
  46. metadata +2 -3
  47. data/lib/types/interface_wrapper.rb +0 -162
@@ -6,10 +6,17 @@ module T::Types
6
6
  # `case` statement below in `describe_obj` in order to get better
7
7
  # error messages.
8
8
  class TypedEnumerable < Base
9
- attr_reader :type
10
-
11
9
  def initialize(type)
12
- @type = T::Utils.coerce(type)
10
+ @inner_type = type
11
+ end
12
+
13
+ def type
14
+ @type ||= T::Utils.coerce(@inner_type)
15
+ end
16
+
17
+ def build_type
18
+ type
19
+ nil
13
20
  end
14
21
 
15
22
  def underlying_class
@@ -18,7 +25,7 @@ module T::Types
18
25
 
19
26
  # overrides Base
20
27
  def name
21
- "T::Enumerable[#{@type.name}]"
28
+ "T::Enumerable[#{type.name}]"
22
29
  end
23
30
 
24
31
  # overrides Base
@@ -34,20 +41,20 @@ module T::Types
34
41
  begin
35
42
  it = 0
36
43
  while it < obj.count
37
- return false unless @type.recursively_valid?(obj[it])
44
+ return false unless type.recursively_valid?(obj[it])
38
45
  it += 1
39
46
  end
40
47
  true
41
48
  end
42
49
  when Hash
43
- return false unless @type.is_a?(FixedArray)
44
- types = @type.types
50
+ return false unless type.is_a?(FixedArray)
51
+ types = type.types
45
52
  return false if types.count != 2
46
53
  key_type = types[0]
47
54
  value_type = types[1]
48
55
  obj.each_pair do |key, val|
49
56
  # Some objects (I'm looking at you Rack::Utils::HeaderHash) don't
50
- # iterate over a [key, value] array, so we can't juse use the @type.recursively_valid?(v)
57
+ # iterate over a [key, value] array, so we can't just use the type.recursively_valid?(v)
51
58
  return false if !key_type.recursively_valid?(key) || !value_type.recursively_valid?(val)
52
59
  end
53
60
  true
@@ -65,10 +72,10 @@ module T::Types
65
72
  # boundlessness, it does not express a type. For example `(nil...nil)` is not a T::Range[NilClass], its a range
66
73
  # of unknown types (T::Range[T.untyped]).
67
74
  # Similarly, `(nil...1)` is not a `T::Range[T.nilable(Integer)]`, it's a boundless range of Integer.
68
- (obj.begin.nil? || @type.recursively_valid?(obj.begin)) && (obj.end.nil? || @type.recursively_valid?(obj.end))
75
+ (obj.begin.nil? || type.recursively_valid?(obj.begin)) && (obj.end.nil? || type.recursively_valid?(obj.end))
69
76
  when Set
70
77
  obj.each do |item|
71
- return false unless @type.recursively_valid?(item)
78
+ return false unless type.recursively_valid?(item)
72
79
  end
73
80
 
74
81
  true
@@ -90,7 +97,7 @@ module T::Types
90
97
  # should be invariant because they are mutable and support
91
98
  # both reading and writing. However, Sorbet treats *all*
92
99
  # Enumerable subclasses as covariant for ease of adoption.
93
- @type.subtype_of?(other.type)
100
+ type.subtype_of?(other.type)
94
101
  elsif other.class <= Simple
95
102
  underlying_class <= other.raw_type
96
103
  else
@@ -3,15 +3,13 @@
3
3
 
4
4
  module T::Types
5
5
  class TypedEnumerator < TypedEnumerable
6
- attr_reader :type
7
-
8
6
  def underlying_class
9
7
  Enumerator
10
8
  end
11
9
 
12
10
  # overrides Base
13
11
  def name
14
- "T::Enumerator[#{@type.name}]"
12
+ "T::Enumerator[#{type.name}]"
15
13
  end
16
14
 
17
15
  # overrides Base
@@ -3,15 +3,13 @@
3
3
 
4
4
  module T::Types
5
5
  class TypedEnumeratorChain < TypedEnumerable
6
- attr_reader :type
7
-
8
6
  def underlying_class
9
7
  Enumerator::Chain
10
8
  end
11
9
 
12
10
  # overrides Base
13
11
  def name
14
- "T::Enumerator::Chain[#{@type.name}]"
12
+ "T::Enumerator::Chain[#{type.name}]"
15
13
  end
16
14
 
17
15
  # overrides Base
@@ -3,15 +3,13 @@
3
3
 
4
4
  module T::Types
5
5
  class TypedEnumeratorLazy < TypedEnumerable
6
- attr_reader :type
7
-
8
6
  def underlying_class
9
7
  Enumerator::Lazy
10
8
  end
11
9
 
12
10
  # overrides Base
13
11
  def name
14
- "T::Enumerator::Lazy[#{@type.name}]"
12
+ "T::Enumerator::Lazy[#{type.name}]"
15
13
  end
16
14
 
17
15
  # overrides Base
@@ -3,22 +3,32 @@
3
3
 
4
4
  module T::Types
5
5
  class TypedHash < TypedEnumerable
6
- # Technically we don't need these, but they are a nice api
7
- attr_reader :keys, :values
8
-
9
6
  def underlying_class
10
7
  Hash
11
8
  end
12
9
 
13
10
  def initialize(keys:, values:)
14
- @keys = T::Utils.coerce(keys)
15
- @values = T::Utils.coerce(values)
16
- @type = T::Utils.coerce([keys, values])
11
+ @inner_keys = keys
12
+ @inner_values = values
13
+ end
14
+
15
+ # Technically we don't need this, but it is a nice api
16
+ def keys
17
+ @keys ||= T::Utils.coerce(@inner_keys)
18
+ end
19
+
20
+ # Technically we don't need this, but it is a nice api
21
+ def values
22
+ @values ||= T::Utils.coerce(@inner_values)
23
+ end
24
+
25
+ def type
26
+ @type ||= T::Utils.coerce([keys, values])
17
27
  end
18
28
 
19
29
  # overrides Base
20
30
  def name
21
- "T::Hash[#{@keys.name}, #{@values.name}]"
31
+ "T::Hash[#{keys.name}, #{values.name}]"
22
32
  end
23
33
 
24
34
  # overrides Base
@@ -3,15 +3,13 @@
3
3
 
4
4
  module T::Types
5
5
  class TypedRange < TypedEnumerable
6
- attr_reader :type
7
-
8
6
  def underlying_class
9
7
  Hash
10
8
  end
11
9
 
12
10
  # overrides Base
13
11
  def name
14
- "T::Range[#{@type.name}]"
12
+ "T::Range[#{type.name}]"
15
13
  end
16
14
 
17
15
  # overrides Base
@@ -3,15 +3,13 @@
3
3
 
4
4
  module T::Types
5
5
  class TypedSet < TypedEnumerable
6
- attr_reader :type
7
-
8
6
  def underlying_class
9
7
  Hash
10
8
  end
11
9
 
12
10
  # overrides Base
13
11
  def name
14
- "T::Set[#{@type.name}]"
12
+ "T::Set[#{type.name}]"
15
13
  end
16
14
 
17
15
  # overrides Base
@@ -4,12 +4,14 @@
4
4
  module T::Types
5
5
  # Takes a list of types. Validates that an object matches at least one of the types.
6
6
  class Union < Base
7
- attr_reader :types
8
-
9
7
  # Don't use Union.new directly, use `Private::Pool.union_of_types`
10
8
  # inside sorbet-runtime and `T.any` elsewhere.
11
9
  def initialize(types)
12
- @types = types.flat_map do |type|
10
+ @inner_types = types
11
+ end
12
+
13
+ def types
14
+ @types ||= @inner_types.flat_map do |type|
13
15
  type = T::Utils.coerce(type)
14
16
  if type.is_a?(Union)
15
17
  # Simplify nested unions (mostly so `name` returns a nicer value)
@@ -20,6 +22,11 @@ module T::Types
20
22
  end.uniq
21
23
  end
22
24
 
25
+ def build_type
26
+ types
27
+ nil
28
+ end
29
+
23
30
  # overrides Base
24
31
  def name
25
32
  # Use the attr_reader here so we can override it in SimplePairUnion
@@ -51,12 +58,12 @@ module T::Types
51
58
 
52
59
  # overrides Base
53
60
  def recursively_valid?(obj)
54
- @types.any? {|type| type.recursively_valid?(obj)}
61
+ types.any? {|type| type.recursively_valid?(obj)}
55
62
  end
56
63
 
57
64
  # overrides Base
58
65
  def valid?(obj)
59
- @types.any? {|type| type.valid?(obj)}
66
+ types.any? {|type| type.valid?(obj)}
60
67
  end
61
68
 
62
69
  # overrides Base
@@ -7,6 +7,10 @@ module T::Types
7
7
 
8
8
  def initialize; end
9
9
 
10
+ def build_type
11
+ nil
12
+ end
13
+
10
14
  # overrides Base
11
15
  def name
12
16
  "T.untyped"
data/lib/types/utils.rb CHANGED
@@ -79,8 +79,8 @@ module T::Utils
79
79
  end
80
80
 
81
81
  # Unwraps all the sigs.
82
- def self.run_all_sig_blocks
83
- T::Private::Methods.run_all_sig_blocks
82
+ def self.run_all_sig_blocks(force_type_init: true)
83
+ T::Private::Methods.run_all_sig_blocks(force_type_init: force_type_init)
84
84
  end
85
85
 
86
86
  # Return the underlying type for a type alias. Otherwise returns 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.5.11144
4
+ version: 0.5.11218
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-01 00:00:00.000000000 Z
11
+ date: 2024-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -165,7 +165,6 @@ files:
165
165
  - lib/types/enum.rb
166
166
  - lib/types/generic.rb
167
167
  - lib/types/helpers.rb
168
- - lib/types/interface_wrapper.rb
169
168
  - lib/types/non_forcing_constants.rb
170
169
  - lib/types/private/abstract/data.rb
171
170
  - lib/types/private/abstract/declare.rb
@@ -1,162 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: false
3
-
4
- # Wraps an object, exposing only the methods defined on a given class/module. The idea is that, in
5
- # the absence of a static type checker that would prevent you from calling non-Bar methods on a
6
- # variable of type Bar, we can use these wrappers as a way of enforcing it at runtime.
7
- #
8
- # Once we ship static type checking, we should get rid of this entirely.
9
- class T::InterfaceWrapper
10
- extend T::Sig
11
-
12
- module Helpers
13
- def wrap_instance(obj)
14
- T::InterfaceWrapper.wrap_instance(obj, self)
15
- end
16
-
17
- def wrap_instances(arr)
18
- T::InterfaceWrapper.wrap_instances(arr, self)
19
- end
20
- end
21
-
22
- private_class_method :new # use `wrap_instance`
23
-
24
- def self.wrap_instance(obj, interface_mod)
25
- wrapper = wrapped_dynamic_cast(obj, interface_mod)
26
- if wrapper.nil?
27
- raise "#{obj.class} cannot be cast to #{interface_mod}"
28
- end
29
- wrapper
30
- end
31
-
32
- sig do
33
- params(
34
- arr: Array,
35
- interface_mod: T.untyped
36
- )
37
- .returns(Array)
38
- end
39
- def self.wrap_instances(arr, interface_mod)
40
- arr.map {|instance| self.wrap_instance(instance, interface_mod)}
41
- end
42
-
43
- def initialize(target_obj, interface_mod)
44
- if target_obj.is_a?(T::InterfaceWrapper)
45
- # wrapped_dynamic_cast should guarantee this never happens.
46
- raise "Unexpected: wrapping a wrapper. Please report this bug at https://github.com/sorbet/sorbet/issues"
47
- end
48
-
49
- if !target_obj.is_a?(interface_mod)
50
- # wrapped_dynamic_cast should guarantee this never happens.
51
- raise "Unexpected: `is_a?` failed. Please report this bug at https://github.com/sorbet/sorbet/issues"
52
- end
53
-
54
- if target_obj.class == interface_mod
55
- # wrapped_dynamic_cast should guarantee this never happens.
56
- raise "Unexpected: exact class match. Please report this bug at https://github.com/sorbet/sorbet/issues"
57
- end
58
-
59
- @target_obj = target_obj
60
- @interface_mod = interface_mod
61
- self_methods = self.class.self_methods
62
-
63
- # If perf becomes an issue, we can define these on an anonymous subclass, and keep a cache
64
- # so we only need to do it once per unique `interface_mod`
65
- T::Utils.methods_excluding_object(interface_mod).each do |method_name|
66
- if self_methods.include?(method_name)
67
- raise "interface_mod has a method that conflicts with #{self.class}: #{method_name}"
68
- end
69
-
70
- define_singleton_method(method_name) do |*args, &blk|
71
- target_obj.send(method_name, *args, &blk)
72
- end
73
-
74
- if singleton_class.respond_to?(:ruby2_keywords, true)
75
- singleton_class.send(:ruby2_keywords, method_name)
76
- end
77
-
78
- if target_obj.singleton_class.public_method_defined?(method_name)
79
- # no-op, it's already public
80
- elsif target_obj.singleton_class.protected_method_defined?(method_name)
81
- singleton_class.send(:protected, method_name)
82
- elsif target_obj.singleton_class.private_method_defined?(method_name)
83
- singleton_class.send(:private, method_name)
84
- else
85
- raise "This should never happen. Report this bug at https://github.com/sorbet/sorbet/issues"
86
- end
87
- end
88
- end
89
-
90
- def kind_of?(other)
91
- is_a?(other)
92
- end
93
-
94
- def is_a?(other)
95
- if !other.is_a?(Module)
96
- raise TypeError.new("class or module required")
97
- end
98
-
99
- # This makes is_a? return true for T::InterfaceWrapper (and its ancestors),
100
- # as well as for @interface_mod and its ancestors.
101
- self.class <= other || @interface_mod <= other
102
- end
103
-
104
- # Prefixed because we're polluting the namespace of the interface we're wrapping, and we don't
105
- # want anyone else (besides dynamic_cast) calling it.
106
- def __target_obj_DO_NOT_USE # rubocop:disable Naming/MethodName
107
- @target_obj
108
- end
109
-
110
- # Prefixed because we're polluting the namespace of the interface we're wrapping, and we don't
111
- # want anyone else (besides wrapped_dynamic_cast) calling it.
112
- def __interface_mod_DO_NOT_USE # rubocop:disable Naming/MethodName
113
- @interface_mod
114
- end
115
-
116
- # "Cast" an object to another type. If `obj` is an InterfaceWrapper, returns the the wrapped
117
- # object if that matches `type`. Otherwise, returns `obj` if it matches `type`. Otherwise,
118
- # returns nil.
119
- #
120
- # @param obj [Object] object to cast
121
- # @param mod [Module] type to cast `obj` to
122
- #
123
- # @example
124
- # if (impl = T::InterfaceWrapper.dynamic_cast(iface, MyImplementation))
125
- # impl.do_things
126
- # end
127
- def self.dynamic_cast(obj, mod)
128
- if obj.is_a?(T::InterfaceWrapper)
129
- target_obj = obj.__target_obj_DO_NOT_USE
130
- target_obj.is_a?(mod) ? target_obj : nil
131
- elsif obj.is_a?(mod)
132
- obj
133
- else
134
- nil
135
- end
136
- end
137
-
138
- # Like dynamic_cast, but puts the result in its own wrapper if necessary.
139
- #
140
- # @param obj [Object] object to cast
141
- # @param mod [Module] type to cast `obj` to
142
- def self.wrapped_dynamic_cast(obj, mod)
143
- # Avoid unwrapping and creating an equivalent wrapper.
144
- if obj.is_a?(T::InterfaceWrapper) && obj.__interface_mod_DO_NOT_USE == mod
145
- return obj
146
- end
147
-
148
- cast_obj = dynamic_cast(obj, mod)
149
- if cast_obj.nil?
150
- nil
151
- elsif cast_obj.class == mod
152
- # Nothing to wrap, they want the full class
153
- cast_obj
154
- else
155
- new(cast_obj, mod)
156
- end
157
- end
158
-
159
- def self.self_methods
160
- @self_methods ||= self.instance_methods(false).to_set
161
- end
162
- end