sorbet-runtime 0.5.11144 → 0.5.11264

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sorbet-runtime.rb +1 -1
  3. data/lib/types/compatibility_patches.rb +1 -1
  4. data/lib/types/configuration.rb +1 -1
  5. data/lib/types/private/abstract/declare.rb +4 -5
  6. data/lib/types/private/caller_utils.rb +21 -0
  7. data/lib/types/private/methods/_methods.rb +35 -30
  8. data/lib/types/private/methods/call_validation.rb +16 -2
  9. data/lib/types/private/methods/call_validation_2_6.rb +518 -0
  10. data/lib/types/private/methods/call_validation_2_7.rb +518 -0
  11. data/lib/types/private/methods/decl_builder.rb +1 -1
  12. data/lib/types/private/methods/signature.rb +10 -2
  13. data/lib/types/private/methods/signature_validation.rb +12 -6
  14. data/lib/types/private/sealed.rb +6 -6
  15. data/lib/types/private/types/not_typed.rb +4 -0
  16. data/lib/types/private/types/string_holder.rb +4 -0
  17. data/lib/types/private/types/type_alias.rb +4 -0
  18. data/lib/types/private/types/void.rb +4 -0
  19. data/lib/types/props/_props.rb +2 -2
  20. data/lib/types/props/decorator.rb +8 -7
  21. data/lib/types/props/has_lazily_specialized_methods.rb +2 -0
  22. data/lib/types/props/pretty_printable.rb +1 -1
  23. data/lib/types/props/private/deserializer_generator.rb +4 -1
  24. data/lib/types/props/private/setter_factory.rb +129 -69
  25. data/lib/types/props/serializable.rb +7 -1
  26. data/lib/types/types/anything.rb +4 -0
  27. data/lib/types/types/attached_class.rb +4 -0
  28. data/lib/types/types/base.rb +6 -0
  29. data/lib/types/types/class_of.rb +4 -0
  30. data/lib/types/types/enum.rb +4 -0
  31. data/lib/types/types/fixed_array.rb +19 -12
  32. data/lib/types/types/fixed_hash.rb +16 -9
  33. data/lib/types/types/intersection.rb +13 -6
  34. data/lib/types/types/noreturn.rb +4 -0
  35. data/lib/types/types/proc.rb +18 -8
  36. data/lib/types/types/self_type.rb +4 -0
  37. data/lib/types/types/simple.rb +9 -0
  38. data/lib/types/types/t_enum.rb +4 -0
  39. data/lib/types/types/type_parameter.rb +4 -0
  40. data/lib/types/types/type_variable.rb +4 -0
  41. data/lib/types/types/typed_array.rb +6 -1
  42. data/lib/types/types/typed_class.rb +21 -4
  43. data/lib/types/types/typed_enumerable.rb +19 -12
  44. data/lib/types/types/typed_enumerator.rb +1 -3
  45. data/lib/types/types/typed_enumerator_chain.rb +1 -3
  46. data/lib/types/types/typed_enumerator_lazy.rb +1 -3
  47. data/lib/types/types/typed_hash.rb +17 -7
  48. data/lib/types/types/typed_range.rb +1 -3
  49. data/lib/types/types/typed_set.rb +1 -3
  50. data/lib/types/types/union.rb +12 -5
  51. data/lib/types/types/untyped.rb +4 -0
  52. data/lib/types/utils.rb +6 -4
  53. metadata +16 -30
  54. data/lib/types/interface_wrapper.rb +0 -162
@@ -20,6 +20,10 @@ module T::Types
20
20
  @name = name
21
21
  end
22
22
 
23
+ def build_type
24
+ nil
25
+ end
26
+
23
27
  def self.make(name)
24
28
  cached = Private.cached_entry(name)
25
29
  return cached if cached
@@ -19,6 +19,10 @@ module T::Types
19
19
  @variance = variance
20
20
  end
21
21
 
22
+ def build_type
23
+ nil
24
+ end
25
+
22
26
  def valid?(obj)
23
27
  true
24
28
  end
@@ -5,7 +5,7 @@ module T::Types
5
5
  class TypedArray < TypedEnumerable
6
6
  # overrides Base
7
7
  def name
8
- "T::Array[#{@type.name}]"
8
+ "T::Array[#{type.name}]"
9
9
  end
10
10
 
11
11
  def underlying_class
@@ -60,6 +60,11 @@ module T::Types
60
60
  obj.is_a?(Array)
61
61
  end
62
62
 
63
+ def freeze
64
+ build_type # force lazy initialization before freezing the object
65
+ super
66
+ end
67
+
63
68
  module Private
64
69
  INSTANCE = Untyped.new.freeze
65
70
  end
@@ -3,15 +3,22 @@
3
3
 
4
4
  module T::Types
5
5
  class TypedClass < T::Types::Base
6
- attr_reader :type
7
-
8
6
  def initialize(type)
9
- @type = T::Utils.coerce(type)
7
+ @inner_type = type
8
+ end
9
+
10
+ def type
11
+ @type ||= T::Utils.coerce(@inner_type)
12
+ end
13
+
14
+ def build_type
15
+ type
16
+ nil
10
17
  end
11
18
 
12
19
  # overrides Base
13
20
  def name
14
- "T::Class[#{@type.name}]"
21
+ "T::Class[#{type.name}]"
15
22
  end
16
23
 
17
24
  def underlying_class
@@ -67,6 +74,11 @@ module T::Types
67
74
  super(T.untyped)
68
75
  end
69
76
 
77
+ def freeze
78
+ build_type # force lazy initialization before freezing the object
79
+ super
80
+ end
81
+
70
82
  module Private
71
83
  INSTANCE = Untyped.new.freeze
72
84
  end
@@ -77,6 +89,11 @@ module T::Types
77
89
  super(T.anything)
78
90
  end
79
91
 
92
+ def freeze
93
+ build_type # force lazy initialization before freezing the object
94
+ super
95
+ end
96
+
80
97
  module Private
81
98
  INSTANCE = Anything.new.freeze
82
99
  end
@@ -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
@@ -165,7 +172,7 @@ module T::Types
165
172
  if T::Configuration::AT_LEAST_RUBY_2_7
166
173
  Object.instance_method(:class).bind_call(obj)
167
174
  else
168
- Object.instance_method(:class).bind(obj).call
175
+ Object.instance_method(:class).bind(obj).call # rubocop:disable Performance/BindCall
169
176
  end
170
177
  end
171
178
  end
@@ -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
@@ -4,6 +4,7 @@
4
4
  module T::Utils
5
5
  module Private
6
6
  def self.coerce_and_check_module_types(val, check_val, check_module_type)
7
+ # rubocop:disable Style/CaseLikeIf
7
8
  if val.is_a?(T::Types::Base)
8
9
  if val.is_a?(T::Private::Types::TypeAlias)
9
10
  val.aliased_type
@@ -31,6 +32,7 @@ module T::Utils
31
32
  raise "Invalid value for type constraint. Must be an #{T::Types::Base}, a " \
32
33
  "class/module, or an array. Got a `#{val.class}`."
33
34
  end
35
+ # rubocop:enable Style/CaseLikeIf
34
36
  end
35
37
  end
36
38
 
@@ -79,8 +81,8 @@ module T::Utils
79
81
  end
80
82
 
81
83
  # Unwraps all the sigs.
82
- def self.run_all_sig_blocks
83
- T::Private::Methods.run_all_sig_blocks
84
+ def self.run_all_sig_blocks(force_type_init: true)
85
+ T::Private::Methods.run_all_sig_blocks(force_type_init: force_type_init)
84
86
  end
85
87
 
86
88
  # Return the underlying type for a type alias. Otherwise returns type.
@@ -173,7 +175,7 @@ module T::Utils
173
175
  def self.get_type_info(prop_type)
174
176
  if prop_type.is_a?(T::Types::Union)
175
177
  non_nilable_type = prop_type.unwrap_nilable
176
- if non_nilable_type&.is_a?(T::Types::Simple)
178
+ if non_nilable_type.is_a?(T::Types::Simple)
177
179
  non_nilable_type = non_nilable_type.raw_type
178
180
  end
179
181
  TypeInfo.new(true, non_nilable_type)
@@ -188,7 +190,7 @@ module T::Utils
188
190
  def self.get_underlying_type(prop_type)
189
191
  if prop_type.is_a?(T::Types::Union)
190
192
  non_nilable_type = prop_type.unwrap_nilable
191
- if non_nilable_type&.is_a?(T::Types::Simple)
193
+ if non_nilable_type.is_a?(T::Types::Simple)
192
194
  non_nilable_type = non_nilable_type.raw_type
193
195
  end
194
196
  non_nilable_type || prop_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.11264
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-01 00:00:00.000000000 Z
11
+ date: 2024-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -56,30 +56,30 @@ dependencies:
56
56
  name: rubocop
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 0.90.0
61
+ version: 1.57.1
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 0.90.0
68
+ version: 1.57.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rubocop-performance
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 1.8.0
75
+ version: 1.13.2
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 1.8.0
82
+ version: 1.13.2
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: concurrent-ruby
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -122,20 +122,6 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
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
125
  - !ruby/object:Gem::Dependency
140
126
  name: subprocess
141
127
  requirement: !ruby/object:Gem::Requirement
@@ -151,7 +137,7 @@ dependencies:
151
137
  - !ruby/object:Gem::Version
152
138
  version: 1.5.3
153
139
  description: Sorbet's runtime type checking component
154
- email:
140
+ email:
155
141
  executables: []
156
142
  extensions: []
157
143
  extra_rdoc_files: []
@@ -165,12 +151,12 @@ files:
165
151
  - lib/types/enum.rb
166
152
  - lib/types/generic.rb
167
153
  - lib/types/helpers.rb
168
- - lib/types/interface_wrapper.rb
169
154
  - lib/types/non_forcing_constants.rb
170
155
  - lib/types/private/abstract/data.rb
171
156
  - lib/types/private/abstract/declare.rb
172
157
  - lib/types/private/abstract/hooks.rb
173
158
  - lib/types/private/abstract/validate.rb
159
+ - lib/types/private/caller_utils.rb
174
160
  - lib/types/private/casts.rb
175
161
  - lib/types/private/class_utils.rb
176
162
  - lib/types/private/compiler.rb
@@ -249,7 +235,7 @@ licenses:
249
235
  - Apache-2.0
250
236
  metadata:
251
237
  source_code_uri: https://github.com/sorbet/sorbet
252
- post_install_message:
238
+ post_install_message:
253
239
  rdoc_options: []
254
240
  require_paths:
255
241
  - lib
@@ -264,8 +250,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
264
250
  - !ruby/object:Gem::Version
265
251
  version: '0'
266
252
  requirements: []
267
- rubygems_version: 3.3.7
268
- signing_key:
253
+ rubygems_version: 3.5.3
254
+ signing_key:
269
255
  specification_version: 4
270
256
  summary: Sorbet runtime
271
257
  test_files: []
@@ -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