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.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/lib/sorbet-runtime.rb +116 -0
  3. data/lib/types/_types.rb +285 -0
  4. data/lib/types/abstract_utils.rb +50 -0
  5. data/lib/types/boolean.rb +8 -0
  6. data/lib/types/compatibility_patches.rb +95 -0
  7. data/lib/types/configuration.rb +428 -0
  8. data/lib/types/enum.rb +349 -0
  9. data/lib/types/generic.rb +23 -0
  10. data/lib/types/helpers.rb +39 -0
  11. data/lib/types/interface_wrapper.rb +158 -0
  12. data/lib/types/non_forcing_constants.rb +51 -0
  13. data/lib/types/private/abstract/data.rb +36 -0
  14. data/lib/types/private/abstract/declare.rb +48 -0
  15. data/lib/types/private/abstract/hooks.rb +43 -0
  16. data/lib/types/private/abstract/validate.rb +128 -0
  17. data/lib/types/private/casts.rb +22 -0
  18. data/lib/types/private/class_utils.rb +111 -0
  19. data/lib/types/private/decl_state.rb +30 -0
  20. data/lib/types/private/final.rb +51 -0
  21. data/lib/types/private/methods/_methods.rb +460 -0
  22. data/lib/types/private/methods/call_validation.rb +1149 -0
  23. data/lib/types/private/methods/decl_builder.rb +228 -0
  24. data/lib/types/private/methods/modes.rb +16 -0
  25. data/lib/types/private/methods/signature.rb +196 -0
  26. data/lib/types/private/methods/signature_validation.rb +229 -0
  27. data/lib/types/private/mixins/mixins.rb +27 -0
  28. data/lib/types/private/retry.rb +10 -0
  29. data/lib/types/private/runtime_levels.rb +56 -0
  30. data/lib/types/private/sealed.rb +65 -0
  31. data/lib/types/private/types/not_typed.rb +23 -0
  32. data/lib/types/private/types/string_holder.rb +26 -0
  33. data/lib/types/private/types/type_alias.rb +26 -0
  34. data/lib/types/private/types/void.rb +34 -0
  35. data/lib/types/profile.rb +31 -0
  36. data/lib/types/props/_props.rb +161 -0
  37. data/lib/types/props/constructor.rb +40 -0
  38. data/lib/types/props/custom_type.rb +108 -0
  39. data/lib/types/props/decorator.rb +672 -0
  40. data/lib/types/props/errors.rb +8 -0
  41. data/lib/types/props/generated_code_validation.rb +268 -0
  42. data/lib/types/props/has_lazily_specialized_methods.rb +92 -0
  43. data/lib/types/props/optional.rb +81 -0
  44. data/lib/types/props/plugin.rb +37 -0
  45. data/lib/types/props/pretty_printable.rb +107 -0
  46. data/lib/types/props/private/apply_default.rb +170 -0
  47. data/lib/types/props/private/deserializer_generator.rb +165 -0
  48. data/lib/types/props/private/parser.rb +32 -0
  49. data/lib/types/props/private/serde_transform.rb +192 -0
  50. data/lib/types/props/private/serializer_generator.rb +77 -0
  51. data/lib/types/props/private/setter_factory.rb +134 -0
  52. data/lib/types/props/serializable.rb +330 -0
  53. data/lib/types/props/type_validation.rb +111 -0
  54. data/lib/types/props/utils.rb +59 -0
  55. data/lib/types/props/weak_constructor.rb +67 -0
  56. data/lib/types/runtime_profiled.rb +24 -0
  57. data/lib/types/sig.rb +30 -0
  58. data/lib/types/struct.rb +18 -0
  59. data/lib/types/types/attached_class.rb +37 -0
  60. data/lib/types/types/base.rb +151 -0
  61. data/lib/types/types/class_of.rb +38 -0
  62. data/lib/types/types/enum.rb +42 -0
  63. data/lib/types/types/fixed_array.rb +60 -0
  64. data/lib/types/types/fixed_hash.rb +59 -0
  65. data/lib/types/types/intersection.rb +37 -0
  66. data/lib/types/types/noreturn.rb +29 -0
  67. data/lib/types/types/proc.rb +51 -0
  68. data/lib/types/types/self_type.rb +35 -0
  69. data/lib/types/types/simple.rb +33 -0
  70. data/lib/types/types/t_enum.rb +38 -0
  71. data/lib/types/types/type_member.rb +7 -0
  72. data/lib/types/types/type_parameter.rb +23 -0
  73. data/lib/types/types/type_template.rb +7 -0
  74. data/lib/types/types/type_variable.rb +31 -0
  75. data/lib/types/types/typed_array.rb +34 -0
  76. data/lib/types/types/typed_enumerable.rb +161 -0
  77. data/lib/types/types/typed_enumerator.rb +36 -0
  78. data/lib/types/types/typed_hash.rb +43 -0
  79. data/lib/types/types/typed_range.rb +26 -0
  80. data/lib/types/types/typed_set.rb +36 -0
  81. data/lib/types/types/union.rb +56 -0
  82. data/lib/types/types/untyped.rb +29 -0
  83. data/lib/types/utils.rb +217 -0
  84. metadata +223 -0
@@ -0,0 +1,228 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ module T::Private::Methods
5
+ Declaration = Struct.new(:mod, :params, :returns, :bind, :mode, :checked, :finalized, :on_failure, :override_allow_incompatible, :type_parameters)
6
+
7
+ class DeclBuilder
8
+ attr_reader :decl
9
+
10
+ class BuilderError < StandardError; end
11
+
12
+ private def check_live!
13
+ if decl.finalized
14
+ raise BuilderError.new("You can't modify a signature declaration after it has been used.")
15
+ end
16
+ end
17
+
18
+ def initialize(mod)
19
+ # TODO RUBYPLAT-1278 - with ruby 2.5, use kwargs here
20
+ @decl = Declaration.new(
21
+ mod,
22
+ ARG_NOT_PROVIDED, # params
23
+ ARG_NOT_PROVIDED, # returns
24
+ ARG_NOT_PROVIDED, # bind
25
+ Modes.standard, # mode
26
+ ARG_NOT_PROVIDED, # checked
27
+ false, # finalized
28
+ ARG_NOT_PROVIDED, # on_failure
29
+ nil, # override_allow_incompatible
30
+ ARG_NOT_PROVIDED, # type_parameters
31
+ )
32
+ end
33
+
34
+ def params(params)
35
+ check_live!
36
+ if !decl.params.equal?(ARG_NOT_PROVIDED)
37
+ raise BuilderError.new("You can't call .params twice")
38
+ end
39
+
40
+ decl.params = params
41
+
42
+ self
43
+ end
44
+
45
+ def returns(type)
46
+ check_live!
47
+ if decl.returns.is_a?(T::Private::Types::Void)
48
+ raise BuilderError.new("You can't call .returns after calling .void.")
49
+ end
50
+ if !decl.returns.equal?(ARG_NOT_PROVIDED)
51
+ raise BuilderError.new("You can't call .returns multiple times in a signature.")
52
+ end
53
+
54
+ decl.returns = type
55
+
56
+ self
57
+ end
58
+
59
+ def void
60
+ check_live!
61
+ if !decl.returns.equal?(ARG_NOT_PROVIDED)
62
+ raise BuilderError.new("You can't call .void after calling .returns.")
63
+ end
64
+
65
+ decl.returns = T::Private::Types::Void.new
66
+
67
+ self
68
+ end
69
+
70
+ def bind(type)
71
+ check_live!
72
+ if !decl.bind.equal?(ARG_NOT_PROVIDED)
73
+ raise BuilderError.new("You can't call .bind multiple times in a signature.")
74
+ end
75
+
76
+ decl.bind = type
77
+
78
+ self
79
+ end
80
+
81
+ def checked(level)
82
+ check_live!
83
+
84
+ if !decl.checked.equal?(ARG_NOT_PROVIDED)
85
+ raise BuilderError.new("You can't call .checked multiple times in a signature.")
86
+ end
87
+ if level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
88
+ raise BuilderError.new("You can't use .checked(:never) with .on_failure because .on_failure will have no effect.")
89
+ end
90
+ if !T::Private::RuntimeLevels::LEVELS.include?(level)
91
+ raise BuilderError.new("Invalid `checked` level '#{level}'. Use one of: #{T::Private::RuntimeLevels::LEVELS}.")
92
+ end
93
+
94
+ decl.checked = level
95
+
96
+ self
97
+ end
98
+
99
+ def on_failure(*args)
100
+ check_live!
101
+
102
+ if !decl.on_failure.equal?(ARG_NOT_PROVIDED)
103
+ raise BuilderError.new("You can't call .on_failure multiple times in a signature.")
104
+ end
105
+ if decl.checked == :never
106
+ raise BuilderError.new("You can't use .on_failure with .checked(:never) because .on_failure will have no effect.")
107
+ end
108
+
109
+ decl.on_failure = args
110
+
111
+ self
112
+ end
113
+
114
+ def abstract
115
+ check_live!
116
+
117
+ case decl.mode
118
+ when Modes.standard
119
+ decl.mode = Modes.abstract
120
+ when Modes.abstract
121
+ raise BuilderError.new(".abstract cannot be repeated in a single signature")
122
+ else
123
+ raise BuilderError.new("`.abstract` cannot be combined with `.override` or `.overridable`.")
124
+ end
125
+
126
+ self
127
+ end
128
+
129
+ def final
130
+ check_live!
131
+ raise BuilderError.new("The syntax for declaring a method final is `sig(:final) {...}`, not `sig {final. ...}`")
132
+ end
133
+
134
+ def override(allow_incompatible: false)
135
+ check_live!
136
+
137
+ case decl.mode
138
+ when Modes.standard
139
+ decl.mode = Modes.override
140
+ decl.override_allow_incompatible = allow_incompatible
141
+ when Modes.override, Modes.overridable_override
142
+ raise BuilderError.new(".override cannot be repeated in a single signature")
143
+ when Modes.overridable
144
+ decl.mode = Modes.overridable_override
145
+ else
146
+ raise BuilderError.new("`.override` cannot be combined with `.abstract`.")
147
+ end
148
+
149
+ self
150
+ end
151
+
152
+ def overridable
153
+ check_live!
154
+
155
+ case decl.mode
156
+ when Modes.abstract
157
+ raise BuilderError.new("`.overridable` cannot be combined with `.#{decl.mode}`")
158
+ when Modes.override
159
+ decl.mode = Modes.overridable_override
160
+ when Modes.standard
161
+ decl.mode = Modes.overridable
162
+ when Modes.overridable, Modes.overridable_override
163
+ raise BuilderError.new(".overridable cannot be repeated in a single signature")
164
+ end
165
+
166
+ self
167
+ end
168
+
169
+ # Declares valid type paramaters which can be used with `T.type_parameter` in
170
+ # this `sig`.
171
+ #
172
+ # This is used for generic methods. Example usage:
173
+ #
174
+ # sig do
175
+ # type_parameters(:U)
176
+ # .params(blk: T.proc.params(arg0: Elem).returns(T.type_parameter(:U)))
177
+ # .returns(T::Array[T.type_parameter(:U)])
178
+ # end
179
+ # def map(&blk); end
180
+ def type_parameters(*names)
181
+ check_live!
182
+
183
+ names.each do |name|
184
+ raise BuilderError.new("not a symbol: #{name}") unless name.is_a?(Symbol)
185
+ end
186
+
187
+ if !decl.type_parameters.equal?(ARG_NOT_PROVIDED)
188
+ raise BuilderError.new("You can't call .type_parameters multiple times in a signature.")
189
+ end
190
+
191
+ decl.type_parameters = names
192
+
193
+ self
194
+ end
195
+
196
+ def finalize!
197
+ check_live!
198
+
199
+ if decl.returns.equal?(ARG_NOT_PROVIDED)
200
+ raise BuilderError.new("You must provide a return type; use the `.returns` or `.void` builder methods.")
201
+ end
202
+
203
+ if decl.bind.equal?(ARG_NOT_PROVIDED)
204
+ decl.bind = nil
205
+ end
206
+ if decl.checked.equal?(ARG_NOT_PROVIDED)
207
+ default_checked_level = T::Private::RuntimeLevels.default_checked_level
208
+ if default_checked_level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
209
+ raise BuilderError.new("To use .on_failure you must additionally call .checked(:tests) or .checked(:always), otherwise, the .on_failure has no effect.")
210
+ end
211
+ decl.checked = default_checked_level
212
+ end
213
+ if decl.on_failure.equal?(ARG_NOT_PROVIDED)
214
+ decl.on_failure = nil
215
+ end
216
+ if decl.params.equal?(ARG_NOT_PROVIDED)
217
+ decl.params = {}
218
+ end
219
+ if decl.type_parameters.equal?(ARG_NOT_PROVIDED)
220
+ decl.type_parameters = {}
221
+ end
222
+
223
+ decl.finalized = true
224
+
225
+ self
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ module T::Private::Methods::Modes
5
+ def self.standard; 'standard'; end
6
+ def self.abstract; 'abstract'; end
7
+ def self.overridable; 'overridable'; end
8
+ def self.override; 'override'; end
9
+ def self.overridable_override; 'overridable_override'; end
10
+ def self.untyped; 'untyped'; end
11
+ MODES = [self.standard, self.abstract, self.overridable, self.override, self.overridable_override, self.untyped]
12
+
13
+ OVERRIDABLE_MODES = [self.override, self.overridable, self.overridable_override, self.untyped, self.abstract]
14
+ OVERRIDE_MODES = [self.override, self.overridable_override]
15
+ NON_OVERRIDE_MODES = MODES - OVERRIDE_MODES
16
+ end
@@ -0,0 +1,196 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ class T::Private::Methods::Signature
5
+ attr_reader :method, :method_name, :arg_types, :kwarg_types, :block_type, :block_name,
6
+ :rest_type, :rest_name, :keyrest_type, :keyrest_name, :bind,
7
+ :return_type, :mode, :req_arg_count, :req_kwarg_names, :has_rest, :has_keyrest,
8
+ :check_level, :parameters, :on_failure, :override_allow_incompatible
9
+
10
+ def self.new_untyped(method:, mode: T::Private::Methods::Modes.untyped, parameters: method.parameters)
11
+ # Using `Untyped` ensures we'll get an error if we ever try validation on these.
12
+ not_typed = T::Private::Types::NotTyped.new
13
+ raw_return_type = not_typed
14
+ raw_arg_types = parameters.map do |_param_kind, param_name|
15
+ [param_name, not_typed]
16
+ end.to_h
17
+
18
+ self.new(
19
+ method: method,
20
+ method_name: method.name,
21
+ raw_arg_types: raw_arg_types,
22
+ raw_return_type: raw_return_type,
23
+ bind: nil,
24
+ mode: mode,
25
+ check_level: :never,
26
+ parameters: parameters,
27
+ on_failure: nil,
28
+ )
29
+ end
30
+
31
+ def initialize(method:, method_name:, raw_arg_types:, raw_return_type:, bind:, mode:, check_level:, parameters: method.parameters, on_failure:, override_allow_incompatible: false)
32
+ @method = method
33
+ @method_name = method_name
34
+ @arg_types = []
35
+ @kwarg_types = {}
36
+ @block_type = nil
37
+ @block_name = nil
38
+ @rest_type = nil
39
+ @rest_name = nil
40
+ @keyrest_type = nil
41
+ @keyrest_name = nil
42
+ @return_type = T::Utils.coerce(raw_return_type)
43
+ @bind = bind ? T::Utils.coerce(bind) : bind
44
+ @mode = mode
45
+ @check_level = check_level
46
+ @req_arg_count = 0
47
+ @req_kwarg_names = []
48
+ @has_rest = false
49
+ @has_keyrest = false
50
+ @parameters = parameters
51
+ @on_failure = on_failure
52
+ @override_allow_incompatible = override_allow_incompatible
53
+
54
+ declared_param_names = raw_arg_types.keys
55
+ # If sig params are declared but there is a single parameter with a missing name
56
+ # **and** the method ends with a "=", assume it is a writer method generated
57
+ # by attr_writer or attr_accessor
58
+ writer_method = declared_param_names != [nil] && parameters == [[:req]] && method_name[-1] == "="
59
+ # For writer methods, map the single parameter to the method name without the "=" at the end
60
+ parameters = [[:req, method_name[0...-1].to_sym]] if writer_method
61
+ param_names = parameters.map {|_, name| name}
62
+ missing_names = param_names - declared_param_names
63
+ extra_names = declared_param_names - param_names
64
+ if !missing_names.empty?
65
+ raise "The declaration for `#{method.name}` is missing parameter(s): #{missing_names.join(', ')}"
66
+ end
67
+ if !extra_names.empty?
68
+ raise "The declaration for `#{method.name}` has extra parameter(s): #{extra_names.join(', ')}"
69
+ end
70
+
71
+ parameters.zip(raw_arg_types) do |(param_kind, param_name), (type_name, raw_type)|
72
+ if type_name != param_name
73
+ hint = ""
74
+ # Ruby reorders params so that required keyword arguments
75
+ # always precede optional keyword arguments. We can't tell
76
+ # whether the culprit is the Ruby reordering or user error, so
77
+ # we error but include a note
78
+ if param_kind == :keyreq && parameters.any? {|k, _| k == :key}
79
+ hint = "\n\nNote: Any required keyword arguments must precede any optional keyword " \
80
+ "arguments. If your method declaration matches your `def`, try reordering any " \
81
+ "optional keyword parameters to the end of the method list."
82
+ end
83
+
84
+ raise "Parameter `#{type_name}` is declared out of order (declared as arg number " \
85
+ "#{declared_param_names.index(type_name) + 1}, defined in the method as arg number " \
86
+ "#{param_names.index(type_name) + 1}).#{hint}\nMethod: #{method_desc}"
87
+ end
88
+
89
+ type = T::Utils.coerce(raw_type)
90
+
91
+ case param_kind
92
+ when :req
93
+ if @arg_types.length > @req_arg_count
94
+ # Note that this is actually is supported by Ruby, but it would add complexity to
95
+ # support it here, and I'm happy to discourage its use anyway.
96
+ raise "Required params after optional params are not supported in method declarations. Method: #{method_desc}"
97
+ end
98
+ @arg_types << [param_name, type]
99
+ @req_arg_count += 1
100
+ when :opt
101
+ @arg_types << [param_name, type]
102
+ when :key, :keyreq
103
+ @kwarg_types[param_name] = type
104
+ if param_kind == :keyreq
105
+ @req_kwarg_names << param_name
106
+ end
107
+ when :block
108
+ @block_name = param_name
109
+ @block_type = type
110
+ when :rest
111
+ @has_rest = true
112
+ @rest_name = param_name
113
+ @rest_type = type
114
+ when :keyrest
115
+ @has_keyrest = true
116
+ @keyrest_name = param_name
117
+ @keyrest_type = type
118
+ else
119
+ raise "Unexpected param_kind: `#{param_kind}`. Method: #{method_desc}"
120
+ end
121
+ end
122
+ end
123
+
124
+ def arg_count
125
+ @arg_types.length
126
+ end
127
+
128
+ def kwarg_names
129
+ @kwarg_types.keys
130
+ end
131
+
132
+ def owner
133
+ @method.owner
134
+ end
135
+
136
+ def dsl_method
137
+ "#{@mode}_method"
138
+ end
139
+
140
+ # @return [Hash] a mapping like {arg_name: [val, type], ...}, for only those args actually present.
141
+ def each_args_value_type(args)
142
+ # Manually split out args and kwargs based on ruby's behavior. Do not try to implement this by
143
+ # getting ruby to determine the kwargs for you (e.g., by defining this method to take *args and
144
+ # **kwargs). That won't work, because ruby's behavior for determining kwargs is dependent on the
145
+ # the other parameters in the method definition, and our method definition here doesn't (and
146
+ # can't) match the definition of the method we're validating. In addition, Ruby has a bug that
147
+ # causes forwarding **kwargs to do the wrong thing: see https://bugs.ruby-lang.org/issues/10708
148
+ # and https://bugs.ruby-lang.org/issues/11860.
149
+ if (args.length > @req_arg_count) && (!@kwarg_types.empty? || @has_keyrest) && args[-1].is_a?(Hash)
150
+ kwargs = args[-1]
151
+ args = args[0...-1]
152
+ else
153
+ kwargs = EMPTY_HASH
154
+ end
155
+
156
+ arg_types = @arg_types
157
+
158
+ if @has_rest
159
+ arg_types += [[@rest_name, @rest_type]] * (args.length - @arg_types.length)
160
+
161
+ elsif (args.length < @req_arg_count) || (args.length > @arg_types.length)
162
+ expected_str = @req_arg_count.to_s
163
+ if @arg_types.length != @req_arg_count
164
+ expected_str += "..#{@arg_types.length}"
165
+ end
166
+ raise ArgumentError.new("wrong number of arguments (given #{args.length}, expected #{expected_str})")
167
+ end
168
+
169
+ begin
170
+ it = 0
171
+ while it < args.length
172
+ yield arg_types[it][0], args[it], arg_types[it][1]
173
+ it += 1
174
+ end
175
+ end
176
+
177
+ kwargs.each do |name, val|
178
+ type = @kwarg_types[name]
179
+ if !type && @has_keyrest
180
+ type = @keyrest_type
181
+ end
182
+ yield name, val, type if type
183
+ end
184
+ end
185
+
186
+ def method_desc
187
+ if @method.source_location
188
+ loc = @method.source_location.join(':')
189
+ else
190
+ loc = "<unknown location>"
191
+ end
192
+ "#{@method} at #{loc}"
193
+ end
194
+
195
+ EMPTY_HASH = {}.freeze
196
+ end
@@ -0,0 +1,229 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ module T::Private::Methods::SignatureValidation
5
+ Methods = T::Private::Methods
6
+ Modes = Methods::Modes
7
+
8
+ def self.validate(signature)
9
+ if signature.method_name == :initialize && signature.method.owner.is_a?(Class)
10
+ # Constructors are special. They look like overrides in terms of a super_method existing,
11
+ # but in practice, you never call them polymorphically. Conceptually, they're standard
12
+ # methods (this is consistent with how they're treated in other languages, e.g. Java)
13
+ if signature.mode != Modes.standard
14
+ raise "`initialize` should not use `.abstract` or `.implementation` or any other inheritance modifiers."
15
+ end
16
+ return
17
+ end
18
+
19
+ super_method = signature.method.super_method
20
+
21
+ if super_method && super_method.owner != signature.method.owner
22
+ Methods.maybe_run_sig_block_for_method(super_method)
23
+ super_signature = Methods.signature_for_method(super_method)
24
+
25
+ # If the super_method has any kwargs we can't build a
26
+ # Signature for it, so we'll just skip validation in that case.
27
+ if !super_signature && !super_method.parameters.select {|kind, _| kind == :rest || kind == :kwrest}.empty?
28
+ nil
29
+ else
30
+ # super_signature can be nil when we're overriding a method (perhaps a builtin) that didn't use
31
+ # one of the method signature helpers. Use an untyped signature so we can still validate
32
+ # everything but types.
33
+ #
34
+ # We treat these signatures as overridable, that way people can use `.override` with
35
+ # overrides of builtins. In the future we could try to distinguish when the method is a
36
+ # builtin and treat non-builtins as non-overridable (so you'd be forced to declare them with
37
+ # `.overridable`).
38
+ #
39
+ super_signature ||= Methods::Signature.new_untyped(method: super_method)
40
+
41
+ validate_override_mode(signature, super_signature)
42
+ validate_override_shape(signature, super_signature)
43
+ validate_override_types(signature, super_signature)
44
+ end
45
+ else
46
+ validate_non_override_mode(signature)
47
+ end
48
+ end
49
+
50
+ private_class_method def self.pretty_mode(signature)
51
+ if signature.mode == Modes.overridable_override
52
+ '.overridable.override'
53
+ else
54
+ ".#{signature.mode}"
55
+ end
56
+ end
57
+
58
+ def self.validate_override_mode(signature, super_signature)
59
+ case signature.mode
60
+ when *Modes::OVERRIDE_MODES
61
+ # Peaceful
62
+ when *Modes::NON_OVERRIDE_MODES
63
+ if super_signature.mode == Modes.standard
64
+ # Peaceful
65
+ elsif super_signature.mode == Modes.abstract
66
+ raise "You must use `.override` when overriding the abstract method `#{signature.method_name}`.\n" \
67
+ " Abstract definition: #{method_loc_str(super_signature.method)}\n" \
68
+ " Implementation definition: #{method_loc_str(signature.method)}\n"
69
+ elsif super_signature.mode != Modes.untyped
70
+ raise "You must use `.override` when overriding the existing method `#{signature.method_name}`.\n" \
71
+ " Parent definition: #{method_loc_str(super_signature.method)}\n" \
72
+ " Child definition: #{method_loc_str(signature.method)}\n"
73
+ end
74
+ else
75
+ raise "Unexpected mode: #{signature.mode}. Please report to #dev-productivity."
76
+ end
77
+ end
78
+
79
+ def self.validate_non_override_mode(signature)
80
+ case signature.mode
81
+ when Modes.override
82
+ if signature.method_name == :each && signature.method.owner < Enumerable
83
+ # Enumerable#each is the only method in Sorbet's RBI payload that defines an abstract method.
84
+ # Enumerable#each does not actually exist at runtime, but it is required to be implemented by
85
+ # any class which includes Enumerable. We want to declare Enumerable#each as abstract so that
86
+ # people can call it anything which implements the Enumerable interface, and so that it's a
87
+ # static error to forget to implement it.
88
+ #
89
+ # This is a one-off hack, and we should think carefully before adding more methods here.
90
+ nil
91
+ else
92
+ raise "You marked `#{signature.method_name}` as #{pretty_mode(signature)}, but that method doesn't already exist in this class/module to be overriden.\n" \
93
+ " Either check for typos and for missing includes or super classes to make the parent method shows up\n" \
94
+ " ... or remove #{pretty_mode(signature)} here: #{method_loc_str(signature.method)}\n"
95
+ end
96
+ when Modes.standard, *Modes::NON_OVERRIDE_MODES
97
+ # Peaceful
98
+ nil
99
+ else
100
+ raise "Unexpected mode: #{signature.mode}. Please report to #dev-productivity."
101
+ end
102
+
103
+ owner = signature.method.owner
104
+ if (signature.mode == Modes.abstract || Modes::OVERRIDABLE_MODES.include?(signature.mode)) &&
105
+ owner.singleton_class?
106
+ # Given a singleton class, we can check if it belongs to a
107
+ # module by looking at its superclass; given `module M`,
108
+ # `M.singleton_class.superclass == Module`, which is not true
109
+ # for any class.
110
+ if owner.superclass == Module
111
+ raise "Defining an overridable class method (via #{pretty_mode(signature)}) " \
112
+ "on a module is not allowed. Class methods on " \
113
+ "modules do not get inherited and thus cannot be overridden. For help, ask in " \
114
+ "#dev-productivity."
115
+ end
116
+ end
117
+ end
118
+
119
+ def self.validate_override_shape(signature, super_signature)
120
+ return if signature.override_allow_incompatible
121
+ return if super_signature.mode == Modes.untyped
122
+
123
+ method_name = signature.method_name
124
+ mode_verb = super_signature.mode == Modes.abstract ? 'implements' : 'overrides'
125
+
126
+ if !signature.has_rest && signature.arg_count < super_signature.arg_count
127
+ raise "Your definition of `#{method_name}` must accept at least #{super_signature.arg_count} " \
128
+ "positional arguments to be compatible with the method it #{mode_verb}: " \
129
+ "#{base_override_loc_str(signature, super_signature)}"
130
+ end
131
+
132
+ if !signature.has_rest && super_signature.has_rest
133
+ raise "Your definition of `#{method_name}` must have `*#{super_signature.rest_name}` " \
134
+ "to be compatible with the method it #{mode_verb}: " \
135
+ "#{base_override_loc_str(signature, super_signature)}"
136
+ end
137
+
138
+ if signature.req_arg_count > super_signature.req_arg_count
139
+ raise "Your definition of `#{method_name}` must have no more than #{super_signature.req_arg_count} " \
140
+ "required argument(s) to be compatible with the method it #{mode_verb}: " \
141
+ "#{base_override_loc_str(signature, super_signature)}"
142
+ end
143
+
144
+ if !signature.has_keyrest
145
+ # O(nm), but n and m are tiny here
146
+ missing_kwargs = super_signature.kwarg_names - signature.kwarg_names
147
+ if !missing_kwargs.empty?
148
+ raise "Your definition of `#{method_name}` is missing these keyword arg(s): #{missing_kwargs} " \
149
+ "which are defined in the method it #{mode_verb}: " \
150
+ "#{base_override_loc_str(signature, super_signature)}"
151
+ end
152
+ end
153
+
154
+ if !signature.has_keyrest && super_signature.has_keyrest
155
+ raise "Your definition of `#{method_name}` must have `**#{super_signature.keyrest_name}` " \
156
+ "to be compatible with the method it #{mode_verb}: " \
157
+ "#{base_override_loc_str(signature, super_signature)}"
158
+ end
159
+
160
+
161
+ # O(nm), but n and m are tiny here
162
+ extra_req_kwargs = signature.req_kwarg_names - super_signature.req_kwarg_names
163
+ if !extra_req_kwargs.empty?
164
+ raise "Your definition of `#{method_name}` has extra required keyword arg(s) " \
165
+ "#{extra_req_kwargs} relative to the method it #{mode_verb}, making it incompatible: " \
166
+ "#{base_override_loc_str(signature, super_signature)}"
167
+ end
168
+
169
+ if super_signature.block_name && !signature.block_name
170
+ raise "Your definition of `#{method_name}` must accept a block parameter to be compatible " \
171
+ "with the method it #{mode_verb}: " \
172
+ "#{base_override_loc_str(signature, super_signature)}"
173
+ end
174
+ end
175
+
176
+ def self.validate_override_types(signature, super_signature)
177
+ return if signature.override_allow_incompatible
178
+ return if super_signature.mode == Modes.untyped
179
+ return unless [signature, super_signature].all? do |sig|
180
+ sig.check_level == :always || (sig.check_level == :tests && T::Private::RuntimeLevels.check_tests?)
181
+ end
182
+ mode_noun = super_signature.mode == Modes.abstract ? 'implementation' : 'override'
183
+
184
+ # arg types must be contravariant
185
+ super_signature.arg_types.zip(signature.arg_types).each_with_index do |((_super_name, super_type), (name, type)), index|
186
+ if !super_type.subtype_of?(type)
187
+ raise "Incompatible type for arg ##{index + 1} (`#{name}`) in #{mode_noun} of method " \
188
+ "`#{signature.method_name}`:\n" \
189
+ "* Base: `#{super_type}` (in #{method_loc_str(super_signature.method)})\n" \
190
+ "* #{mode_noun.capitalize}: `#{type}` (in #{method_loc_str(signature.method)})\n" \
191
+ "(The types must be contravariant.)"
192
+ end
193
+ end
194
+
195
+ # kwarg types must be contravariant
196
+ super_signature.kwarg_types.each do |name, super_type|
197
+ type = signature.kwarg_types[name]
198
+ if !super_type.subtype_of?(type)
199
+ raise "Incompatible type for arg `#{name}` in #{mode_noun} of method `#{signature.method_name}`:\n" \
200
+ "* Base: `#{super_type}` (in #{method_loc_str(super_signature.method)})\n" \
201
+ "* #{mode_noun.capitalize}: `#{type}` (in #{method_loc_str(signature.method)})\n" \
202
+ "(The types must be contravariant.)"
203
+ end
204
+ end
205
+
206
+ # return types must be covariant
207
+ if !signature.return_type.subtype_of?(super_signature.return_type)
208
+ raise "Incompatible return type in #{mode_noun} of method `#{signature.method_name}`:\n" \
209
+ "* Base: `#{super_signature.return_type}` (in #{method_loc_str(super_signature.method)})\n" \
210
+ "* #{mode_noun.capitalize}: `#{signature.return_type}` (in #{method_loc_str(signature.method)})\n" \
211
+ "(The types must be covariant.)"
212
+ end
213
+ end
214
+
215
+ private_class_method def self.base_override_loc_str(signature, super_signature)
216
+ mode_noun = super_signature.mode == Modes.abstract ? 'Implementation' : 'Override'
217
+ "\n * Base definition: in #{method_loc_str(super_signature.method)}" \
218
+ "\n * #{mode_noun}: in #{method_loc_str(signature.method)}"
219
+ end
220
+
221
+ private_class_method def self.method_loc_str(method)
222
+ if method.source_location
223
+ loc = method.source_location.join(':')
224
+ else
225
+ loc = "<unknown location>"
226
+ end
227
+ "#{method.owner} at #{loc}"
228
+ end
229
+ end