sorbet-runtime 0.5.10439 → 0.5.11120

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sorbet-runtime.rb +7 -1
  3. data/lib/types/_types.rb +57 -3
  4. data/lib/types/compatibility_patches.rb +4 -2
  5. data/lib/types/enum.rb +6 -1
  6. data/lib/types/generic.rb +2 -0
  7. data/lib/types/private/abstract/declare.rb +10 -9
  8. data/lib/types/private/casts.rb +4 -1
  9. data/lib/types/private/class_utils.rb +13 -6
  10. data/lib/types/private/methods/_methods.rb +37 -12
  11. data/lib/types/private/methods/call_validation.rb +104 -5
  12. data/lib/types/private/methods/call_validation_2_6.rb +68 -60
  13. data/lib/types/private/methods/call_validation_2_7.rb +68 -60
  14. data/lib/types/private/methods/decl_builder.rb +21 -6
  15. data/lib/types/private/methods/signature.rb +63 -38
  16. data/lib/types/private/methods/signature_validation.rb +68 -6
  17. data/lib/types/private/runtime_levels.rb +19 -0
  18. data/lib/types/private/types/not_typed.rb +2 -0
  19. data/lib/types/private/types/simple_pair_union.rb +55 -0
  20. data/lib/types/private/types/void.rb +29 -23
  21. data/lib/types/props/_props.rb +2 -2
  22. data/lib/types/props/custom_type.rb +2 -2
  23. data/lib/types/props/decorator.rb +41 -36
  24. data/lib/types/props/has_lazily_specialized_methods.rb +2 -2
  25. data/lib/types/props/pretty_printable.rb +45 -83
  26. data/lib/types/props/private/setter_factory.rb +1 -1
  27. data/lib/types/props/serializable.rb +17 -9
  28. data/lib/types/props/type_validation.rb +5 -2
  29. data/lib/types/struct.rb +2 -2
  30. data/lib/types/types/anything.rb +31 -0
  31. data/lib/types/types/base.rb +15 -1
  32. data/lib/types/types/class_of.rb +11 -0
  33. data/lib/types/types/enum.rb +1 -1
  34. data/lib/types/types/fixed_array.rb +13 -0
  35. data/lib/types/types/fixed_hash.rb +22 -0
  36. data/lib/types/types/intersection.rb +1 -1
  37. data/lib/types/types/noreturn.rb +0 -1
  38. data/lib/types/types/simple.rb +27 -4
  39. data/lib/types/types/type_parameter.rb +19 -0
  40. data/lib/types/types/typed_array.rb +29 -0
  41. data/lib/types/types/typed_class.rb +85 -0
  42. data/lib/types/types/typed_enumerable.rb +7 -0
  43. data/lib/types/types/typed_enumerator_chain.rb +41 -0
  44. data/lib/types/types/union.rb +50 -14
  45. data/lib/types/utils.rb +41 -33
  46. metadata +14 -10
@@ -11,26 +11,28 @@ module T::Private::Methods::CallValidation
11
11
  raise 'Should have used create_validator_procedure_fast'
12
12
  end
13
13
  # trampoline to reduce stack frame size
14
- if method_sig.arg_types.empty?
14
+ arg_types = method_sig.arg_types
15
+ case arg_types.length
16
+ when 0
15
17
  create_validator_method_fast0(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type)
16
- elsif method_sig.arg_types.length == 1
18
+ when 1
17
19
  create_validator_method_fast1(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type,
18
- method_sig.arg_types[0][1].raw_type)
19
- elsif method_sig.arg_types.length == 2
20
+ arg_types[0][1].raw_type)
21
+ when 2
20
22
  create_validator_method_fast2(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type,
21
- method_sig.arg_types[0][1].raw_type,
22
- method_sig.arg_types[1][1].raw_type)
23
- elsif method_sig.arg_types.length == 3
23
+ arg_types[0][1].raw_type,
24
+ arg_types[1][1].raw_type)
25
+ when 3
24
26
  create_validator_method_fast3(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type,
25
- method_sig.arg_types[0][1].raw_type,
26
- method_sig.arg_types[1][1].raw_type,
27
- method_sig.arg_types[2][1].raw_type)
28
- elsif method_sig.arg_types.length == 4
27
+ arg_types[0][1].raw_type,
28
+ arg_types[1][1].raw_type,
29
+ arg_types[2][1].raw_type)
30
+ when 4
29
31
  create_validator_method_fast4(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type,
30
- method_sig.arg_types[0][1].raw_type,
31
- method_sig.arg_types[1][1].raw_type,
32
- method_sig.arg_types[2][1].raw_type,
33
- method_sig.arg_types[3][1].raw_type)
32
+ arg_types[0][1].raw_type,
33
+ arg_types[1][1].raw_type,
34
+ arg_types[2][1].raw_type,
35
+ arg_types[3][1].raw_type)
34
36
  else
35
37
  raise 'should not happen'
36
38
  end
@@ -343,26 +345,28 @@ module T::Private::Methods::CallValidation
343
345
 
344
346
  def self.create_validator_procedure_fast(mod, original_method, method_sig, original_visibility)
345
347
  # trampoline to reduce stack frame size
346
- if method_sig.arg_types.empty?
348
+ arg_types = method_sig.arg_types
349
+ case arg_types.length
350
+ when 0
347
351
  create_validator_procedure_fast0(mod, original_method, method_sig, original_visibility)
348
- elsif method_sig.arg_types.length == 1
352
+ when 1
349
353
  create_validator_procedure_fast1(mod, original_method, method_sig, original_visibility,
350
- method_sig.arg_types[0][1].raw_type)
351
- elsif method_sig.arg_types.length == 2
354
+ arg_types[0][1].raw_type)
355
+ when 2
352
356
  create_validator_procedure_fast2(mod, original_method, method_sig, original_visibility,
353
- method_sig.arg_types[0][1].raw_type,
354
- method_sig.arg_types[1][1].raw_type)
355
- elsif method_sig.arg_types.length == 3
357
+ arg_types[0][1].raw_type,
358
+ arg_types[1][1].raw_type)
359
+ when 3
356
360
  create_validator_procedure_fast3(mod, original_method, method_sig, original_visibility,
357
- method_sig.arg_types[0][1].raw_type,
358
- method_sig.arg_types[1][1].raw_type,
359
- method_sig.arg_types[2][1].raw_type)
360
- elsif method_sig.arg_types.length == 4
361
+ arg_types[0][1].raw_type,
362
+ arg_types[1][1].raw_type,
363
+ arg_types[2][1].raw_type)
364
+ when 4
361
365
  create_validator_procedure_fast4(mod, original_method, method_sig, original_visibility,
362
- method_sig.arg_types[0][1].raw_type,
363
- method_sig.arg_types[1][1].raw_type,
364
- method_sig.arg_types[2][1].raw_type,
365
- method_sig.arg_types[3][1].raw_type)
366
+ arg_types[0][1].raw_type,
367
+ arg_types[1][1].raw_type,
368
+ arg_types[2][1].raw_type,
369
+ arg_types[3][1].raw_type)
366
370
  else
367
371
  raise 'should not happen'
368
372
  end
@@ -608,26 +612,28 @@ module T::Private::Methods::CallValidation
608
612
  raise 'Should have used create_validator_procedure_medium'
609
613
  end
610
614
  # trampoline to reduce stack frame size
611
- if method_sig.arg_types.empty?
615
+ arg_types = method_sig.arg_types
616
+ case arg_types.length
617
+ when 0
612
618
  create_validator_method_medium0(mod, original_method, method_sig, original_visibility, method_sig.return_type)
613
- elsif method_sig.arg_types.length == 1
619
+ when 1
614
620
  create_validator_method_medium1(mod, original_method, method_sig, original_visibility, method_sig.return_type,
615
- method_sig.arg_types[0][1])
616
- elsif method_sig.arg_types.length == 2
621
+ arg_types[0][1])
622
+ when 2
617
623
  create_validator_method_medium2(mod, original_method, method_sig, original_visibility, method_sig.return_type,
618
- method_sig.arg_types[0][1],
619
- method_sig.arg_types[1][1])
620
- elsif method_sig.arg_types.length == 3
624
+ arg_types[0][1],
625
+ arg_types[1][1])
626
+ when 3
621
627
  create_validator_method_medium3(mod, original_method, method_sig, original_visibility, method_sig.return_type,
622
- method_sig.arg_types[0][1],
623
- method_sig.arg_types[1][1],
624
- method_sig.arg_types[2][1])
625
- elsif method_sig.arg_types.length == 4
628
+ arg_types[0][1],
629
+ arg_types[1][1],
630
+ arg_types[2][1])
631
+ when 4
626
632
  create_validator_method_medium4(mod, original_method, method_sig, original_visibility, method_sig.return_type,
627
- method_sig.arg_types[0][1],
628
- method_sig.arg_types[1][1],
629
- method_sig.arg_types[2][1],
630
- method_sig.arg_types[3][1])
633
+ arg_types[0][1],
634
+ arg_types[1][1],
635
+ arg_types[2][1],
636
+ arg_types[3][1])
631
637
  else
632
638
  raise 'should not happen'
633
639
  end
@@ -940,26 +946,28 @@ module T::Private::Methods::CallValidation
940
946
 
941
947
  def self.create_validator_procedure_medium(mod, original_method, method_sig, original_visibility)
942
948
  # trampoline to reduce stack frame size
943
- if method_sig.arg_types.empty?
949
+ arg_types = method_sig.arg_types
950
+ case arg_types.length
951
+ when 0
944
952
  create_validator_procedure_medium0(mod, original_method, method_sig, original_visibility)
945
- elsif method_sig.arg_types.length == 1
953
+ when 1
946
954
  create_validator_procedure_medium1(mod, original_method, method_sig, original_visibility,
947
- method_sig.arg_types[0][1])
948
- elsif method_sig.arg_types.length == 2
955
+ arg_types[0][1])
956
+ when 2
949
957
  create_validator_procedure_medium2(mod, original_method, method_sig, original_visibility,
950
- method_sig.arg_types[0][1],
951
- method_sig.arg_types[1][1])
952
- elsif method_sig.arg_types.length == 3
958
+ arg_types[0][1],
959
+ arg_types[1][1])
960
+ when 3
953
961
  create_validator_procedure_medium3(mod, original_method, method_sig, original_visibility,
954
- method_sig.arg_types[0][1],
955
- method_sig.arg_types[1][1],
956
- method_sig.arg_types[2][1])
957
- elsif method_sig.arg_types.length == 4
962
+ arg_types[0][1],
963
+ arg_types[1][1],
964
+ arg_types[2][1])
965
+ when 4
958
966
  create_validator_procedure_medium4(mod, original_method, method_sig, original_visibility,
959
- method_sig.arg_types[0][1],
960
- method_sig.arg_types[1][1],
961
- method_sig.arg_types[2][1],
962
- method_sig.arg_types[3][1])
967
+ arg_types[0][1],
968
+ arg_types[1][1],
969
+ arg_types[2][1],
970
+ arg_types[3][1])
963
971
  else
964
972
  raise 'should not happen'
965
973
  end
@@ -11,26 +11,28 @@ module T::Private::Methods::CallValidation
11
11
  raise 'Should have used create_validator_procedure_fast'
12
12
  end
13
13
  # trampoline to reduce stack frame size
14
- if method_sig.arg_types.empty?
14
+ arg_types = method_sig.arg_types
15
+ case arg_types.length
16
+ when 0
15
17
  create_validator_method_fast0(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type)
16
- elsif method_sig.arg_types.length == 1
18
+ when 1
17
19
  create_validator_method_fast1(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type,
18
- method_sig.arg_types[0][1].raw_type)
19
- elsif method_sig.arg_types.length == 2
20
+ arg_types[0][1].raw_type)
21
+ when 2
20
22
  create_validator_method_fast2(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type,
21
- method_sig.arg_types[0][1].raw_type,
22
- method_sig.arg_types[1][1].raw_type)
23
- elsif method_sig.arg_types.length == 3
23
+ arg_types[0][1].raw_type,
24
+ arg_types[1][1].raw_type)
25
+ when 3
24
26
  create_validator_method_fast3(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type,
25
- method_sig.arg_types[0][1].raw_type,
26
- method_sig.arg_types[1][1].raw_type,
27
- method_sig.arg_types[2][1].raw_type)
28
- elsif method_sig.arg_types.length == 4
27
+ arg_types[0][1].raw_type,
28
+ arg_types[1][1].raw_type,
29
+ arg_types[2][1].raw_type)
30
+ when 4
29
31
  create_validator_method_fast4(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type,
30
- method_sig.arg_types[0][1].raw_type,
31
- method_sig.arg_types[1][1].raw_type,
32
- method_sig.arg_types[2][1].raw_type,
33
- method_sig.arg_types[3][1].raw_type)
32
+ arg_types[0][1].raw_type,
33
+ arg_types[1][1].raw_type,
34
+ arg_types[2][1].raw_type,
35
+ arg_types[3][1].raw_type)
34
36
  else
35
37
  raise 'should not happen'
36
38
  end
@@ -343,26 +345,28 @@ module T::Private::Methods::CallValidation
343
345
 
344
346
  def self.create_validator_procedure_fast(mod, original_method, method_sig, original_visibility)
345
347
  # trampoline to reduce stack frame size
346
- if method_sig.arg_types.empty?
348
+ arg_types = method_sig.arg_types
349
+ case arg_types.length
350
+ when 0
347
351
  create_validator_procedure_fast0(mod, original_method, method_sig, original_visibility)
348
- elsif method_sig.arg_types.length == 1
352
+ when 1
349
353
  create_validator_procedure_fast1(mod, original_method, method_sig, original_visibility,
350
- method_sig.arg_types[0][1].raw_type)
351
- elsif method_sig.arg_types.length == 2
354
+ arg_types[0][1].raw_type)
355
+ when 2
352
356
  create_validator_procedure_fast2(mod, original_method, method_sig, original_visibility,
353
- method_sig.arg_types[0][1].raw_type,
354
- method_sig.arg_types[1][1].raw_type)
355
- elsif method_sig.arg_types.length == 3
357
+ arg_types[0][1].raw_type,
358
+ arg_types[1][1].raw_type)
359
+ when 3
356
360
  create_validator_procedure_fast3(mod, original_method, method_sig, original_visibility,
357
- method_sig.arg_types[0][1].raw_type,
358
- method_sig.arg_types[1][1].raw_type,
359
- method_sig.arg_types[2][1].raw_type)
360
- elsif method_sig.arg_types.length == 4
361
+ arg_types[0][1].raw_type,
362
+ arg_types[1][1].raw_type,
363
+ arg_types[2][1].raw_type)
364
+ when 4
361
365
  create_validator_procedure_fast4(mod, original_method, method_sig, original_visibility,
362
- method_sig.arg_types[0][1].raw_type,
363
- method_sig.arg_types[1][1].raw_type,
364
- method_sig.arg_types[2][1].raw_type,
365
- method_sig.arg_types[3][1].raw_type)
366
+ arg_types[0][1].raw_type,
367
+ arg_types[1][1].raw_type,
368
+ arg_types[2][1].raw_type,
369
+ arg_types[3][1].raw_type)
366
370
  else
367
371
  raise 'should not happen'
368
372
  end
@@ -608,26 +612,28 @@ module T::Private::Methods::CallValidation
608
612
  raise 'Should have used create_validator_procedure_medium'
609
613
  end
610
614
  # trampoline to reduce stack frame size
611
- if method_sig.arg_types.empty?
615
+ arg_types = method_sig.arg_types
616
+ case arg_types.length
617
+ when 0
612
618
  create_validator_method_medium0(mod, original_method, method_sig, original_visibility, method_sig.return_type)
613
- elsif method_sig.arg_types.length == 1
619
+ when 1
614
620
  create_validator_method_medium1(mod, original_method, method_sig, original_visibility, method_sig.return_type,
615
- method_sig.arg_types[0][1])
616
- elsif method_sig.arg_types.length == 2
621
+ arg_types[0][1])
622
+ when 2
617
623
  create_validator_method_medium2(mod, original_method, method_sig, original_visibility, method_sig.return_type,
618
- method_sig.arg_types[0][1],
619
- method_sig.arg_types[1][1])
620
- elsif method_sig.arg_types.length == 3
624
+ arg_types[0][1],
625
+ arg_types[1][1])
626
+ when 3
621
627
  create_validator_method_medium3(mod, original_method, method_sig, original_visibility, method_sig.return_type,
622
- method_sig.arg_types[0][1],
623
- method_sig.arg_types[1][1],
624
- method_sig.arg_types[2][1])
625
- elsif method_sig.arg_types.length == 4
628
+ arg_types[0][1],
629
+ arg_types[1][1],
630
+ arg_types[2][1])
631
+ when 4
626
632
  create_validator_method_medium4(mod, original_method, method_sig, original_visibility, method_sig.return_type,
627
- method_sig.arg_types[0][1],
628
- method_sig.arg_types[1][1],
629
- method_sig.arg_types[2][1],
630
- method_sig.arg_types[3][1])
633
+ arg_types[0][1],
634
+ arg_types[1][1],
635
+ arg_types[2][1],
636
+ arg_types[3][1])
631
637
  else
632
638
  raise 'should not happen'
633
639
  end
@@ -940,26 +946,28 @@ module T::Private::Methods::CallValidation
940
946
 
941
947
  def self.create_validator_procedure_medium(mod, original_method, method_sig, original_visibility)
942
948
  # trampoline to reduce stack frame size
943
- if method_sig.arg_types.empty?
949
+ arg_types = method_sig.arg_types
950
+ case arg_types.length
951
+ when 0
944
952
  create_validator_procedure_medium0(mod, original_method, method_sig, original_visibility)
945
- elsif method_sig.arg_types.length == 1
953
+ when 1
946
954
  create_validator_procedure_medium1(mod, original_method, method_sig, original_visibility,
947
- method_sig.arg_types[0][1])
948
- elsif method_sig.arg_types.length == 2
955
+ arg_types[0][1])
956
+ when 2
949
957
  create_validator_procedure_medium2(mod, original_method, method_sig, original_visibility,
950
- method_sig.arg_types[0][1],
951
- method_sig.arg_types[1][1])
952
- elsif method_sig.arg_types.length == 3
958
+ arg_types[0][1],
959
+ arg_types[1][1])
960
+ when 3
953
961
  create_validator_procedure_medium3(mod, original_method, method_sig, original_visibility,
954
- method_sig.arg_types[0][1],
955
- method_sig.arg_types[1][1],
956
- method_sig.arg_types[2][1])
957
- elsif method_sig.arg_types.length == 4
962
+ arg_types[0][1],
963
+ arg_types[1][1],
964
+ arg_types[2][1])
965
+ when 4
958
966
  create_validator_procedure_medium4(mod, original_method, method_sig, original_visibility,
959
- method_sig.arg_types[0][1],
960
- method_sig.arg_types[1][1],
961
- method_sig.arg_types[2][1],
962
- method_sig.arg_types[3][1])
967
+ arg_types[0][1],
968
+ arg_types[1][1],
969
+ arg_types[2][1],
970
+ arg_types[3][1])
963
971
  else
964
972
  raise 'should not happen'
965
973
  end
@@ -16,7 +16,6 @@ module T::Private::Methods
16
16
  end
17
17
 
18
18
  def initialize(mod, raw)
19
- # TODO RUBYPLAT-1278 - with ruby 2.5, use kwargs here
20
19
  @decl = Declaration.new(
21
20
  mod,
22
21
  ARG_NOT_PROVIDED, # params
@@ -32,15 +31,29 @@ module T::Private::Methods
32
31
  )
33
32
  end
34
33
 
35
- def params(**params)
34
+ def params(*unused_positional_params, **params)
36
35
  check_live!
37
36
  if !decl.params.equal?(ARG_NOT_PROVIDED)
38
37
  raise BuilderError.new("You can't call .params twice")
39
38
  end
40
39
 
40
+ if unused_positional_params.any?
41
+ some_or_only = params.any? ? "some" : "only"
42
+ raise BuilderError.new(<<~MSG)
43
+ 'params' was called with #{some_or_only} positional arguments, but it needs to be called with keyword arguments.
44
+ The keyword arguments' keys must match the name and order of the method's parameters.
45
+ MSG
46
+ end
47
+
41
48
  if params.empty?
42
- raise BuilderError.new("params expects keyword arguments")
49
+ raise BuilderError.new(<<~MSG)
50
+ 'params' was called without any arguments, but it needs to be called with keyword arguments.
51
+ The keyword arguments' keys must match the name and order of the method's parameters.
52
+
53
+ Omit 'params' entirely for methods with no parameters.
54
+ MSG
43
55
  end
56
+
44
57
  decl.params = params
45
58
 
46
59
  self
@@ -66,7 +79,7 @@ module T::Private::Methods
66
79
  raise BuilderError.new("You can't call .void after calling .returns.")
67
80
  end
68
81
 
69
- decl.returns = T::Private::Types::Void.new
82
+ decl.returns = T::Private::Types::Void::Private::INSTANCE
70
83
 
71
84
  self
72
85
  end
@@ -218,15 +231,17 @@ module T::Private::Methods
218
231
  decl.on_failure = nil
219
232
  end
220
233
  if decl.params.equal?(ARG_NOT_PROVIDED)
221
- decl.params = {}
234
+ decl.params = FROZEN_HASH
222
235
  end
223
236
  if decl.type_parameters.equal?(ARG_NOT_PROVIDED)
224
- decl.type_parameters = {}
237
+ decl.type_parameters = FROZEN_HASH
225
238
  end
226
239
 
227
240
  decl.finalized = true
228
241
 
229
242
  self
230
243
  end
244
+
245
+ FROZEN_HASH = {}.freeze
231
246
  end
232
247
  end
@@ -8,17 +8,20 @@ class T::Private::Methods::Signature
8
8
  :check_level, :parameters, :on_failure, :override_allow_incompatible,
9
9
  :defined_raw
10
10
 
11
+ UNNAMED_REQUIRED_PARAMETERS = [[:req]].freeze
12
+
11
13
  def self.new_untyped(method:, mode: T::Private::Methods::Modes.untyped, parameters: method.parameters)
12
- # Using `Untyped` ensures we'll get an error if we ever try validation on these.
13
- not_typed = T::Private::Types::NotTyped.new
14
+ # Using `NotTyped` ensures we'll get an error if we ever try validation on these.
15
+ not_typed = T::Private::Types::NotTyped::INSTANCE
14
16
  raw_return_type = not_typed
15
17
  # Map missing parameter names to "argN" positionally
16
18
  parameters = parameters.each_with_index.map do |(param_kind, param_name), index|
17
19
  [param_kind, param_name || "arg#{index}"]
18
20
  end
19
- raw_arg_types = parameters.map do |_param_kind, param_name|
20
- [param_name, not_typed]
21
- end.to_h
21
+ raw_arg_types = {}
22
+ parameters.each do |_, param_name|
23
+ raw_arg_types[param_name] = not_typed
24
+ end
22
25
 
23
26
  self.new(
24
27
  method: method,
@@ -36,8 +39,6 @@ class T::Private::Methods::Signature
36
39
  def initialize(method:, method_name:, raw_arg_types:, raw_return_type:, bind:, mode:, check_level:, on_failure:, parameters: method.parameters, override_allow_incompatible: false, defined_raw: false)
37
40
  @method = method
38
41
  @method_name = method_name
39
- @arg_types = []
40
- @kwarg_types = {}
41
42
  @block_type = nil
42
43
  @block_name = nil
43
44
  @rest_type = nil
@@ -48,8 +49,6 @@ class T::Private::Methods::Signature
48
49
  @bind = bind ? T::Utils.coerce(bind) : bind
49
50
  @mode = mode
50
51
  @check_level = check_level
51
- @req_arg_count = 0
52
- @req_kwarg_names = []
53
52
  @has_rest = false
54
53
  @has_keyrest = false
55
54
  @parameters = parameters
@@ -57,28 +56,40 @@ class T::Private::Methods::Signature
57
56
  @override_allow_incompatible = override_allow_incompatible
58
57
  @defined_raw = defined_raw
59
58
 
60
- declared_param_names = raw_arg_types.keys
59
+ # Use T.untyped in lieu of T.nilable to try to avoid unnecessary allocations.
60
+ arg_types = T.let(nil, T.untyped)
61
+ kwarg_types = T.let(nil, T.untyped)
62
+ req_arg_count = 0
63
+ req_kwarg_names = T.let(nil, T.untyped)
64
+
61
65
  # If sig params are declared but there is a single parameter with a missing name
62
66
  # **and** the method ends with a "=", assume it is a writer method generated
63
67
  # by attr_writer or attr_accessor
64
- writer_method = declared_param_names != [nil] && parameters == [[:req]] && method_name[-1] == "="
68
+ writer_method = !(raw_arg_types.size == 1 && raw_arg_types.key?(nil)) && parameters == UNNAMED_REQUIRED_PARAMETERS && method_name[-1] == "="
65
69
  # For writer methods, map the single parameter to the method name without the "=" at the end
66
70
  parameters = [[:req, method_name[0...-1].to_sym]] if writer_method
67
- param_names = parameters.map {|_, name| name}
68
- missing_names = param_names - declared_param_names
69
- extra_names = declared_param_names - param_names
70
- if !missing_names.empty?
71
+ is_name_missing = parameters.any? {|_, name| !raw_arg_types.key?(name)}
72
+ if is_name_missing
73
+ param_names = parameters.map {|_, name| name}
74
+ missing_names = param_names - raw_arg_types.keys
71
75
  raise "The declaration for `#{method.name}` is missing parameter(s): #{missing_names.join(', ')}"
72
- end
73
- if !extra_names.empty?
74
- raise "The declaration for `#{method.name}` has extra parameter(s): #{extra_names.join(', ')}"
76
+ elsif parameters.length == raw_arg_types.size
77
+ else
78
+ param_names = parameters.map {|_, name| name}
79
+ has_extra_names = parameters.count {|_, name| raw_arg_types.key?(name)} < raw_arg_types.size
80
+ if has_extra_names
81
+ extra_names = raw_arg_types.keys - param_names
82
+ raise "The declaration for `#{method.name}` has extra parameter(s): #{extra_names.join(', ')}"
83
+ end
75
84
  end
76
85
 
77
86
  if parameters.size != raw_arg_types.size
78
87
  raise "The declaration for `#{method.name}` has arguments with duplicate names"
79
88
  end
89
+ i = 0
90
+ raw_arg_types.each do |type_name, raw_type|
91
+ param_kind, param_name = parameters[i]
80
92
 
81
- parameters.zip(raw_arg_types) do |(param_kind, param_name), (type_name, raw_type)|
82
93
  if type_name != param_name
83
94
  hint = ""
84
95
  # Ruby reorders params so that required keyword arguments
@@ -92,15 +103,15 @@ class T::Private::Methods::Signature
92
103
  end
93
104
 
94
105
  raise "Parameter `#{type_name}` is declared out of order (declared as arg number " \
95
- "#{declared_param_names.index(type_name) + 1}, defined in the method as arg number " \
96
- "#{param_names.index(type_name) + 1}).#{hint}\nMethod: #{method_desc}"
106
+ "#{i + 1}, defined in the method as arg number " \
107
+ "#{parameters.index {|_, name| name == type_name} + 1}).#{hint}\nMethod: #{method_desc}"
97
108
  end
98
109
 
99
110
  type = T::Utils.coerce(raw_type)
100
111
 
101
112
  case param_kind
102
113
  when :req
103
- if @arg_types.length > @req_arg_count
114
+ if (arg_types ? arg_types.length : 0) > req_arg_count
104
115
  # Note that this is actually is supported by Ruby, but it would add complexity to
105
116
  # support it here, and I'm happy to discourage its use anyway.
106
117
  #
@@ -111,14 +122,14 @@ class T::Private::Methods::Signature
111
122
  # see this error. The simplest resolution is to rename your method.
112
123
  raise "Required params after optional params are not supported in method declarations. Method: #{method_desc}"
113
124
  end
114
- @arg_types << [param_name, type]
115
- @req_arg_count += 1
125
+ (arg_types ||= []) << [param_name, type]
126
+ req_arg_count += 1
116
127
  when :opt
117
- @arg_types << [param_name, type]
128
+ (arg_types ||= []) << [param_name, type]
118
129
  when :key, :keyreq
119
- @kwarg_types[param_name] = type
130
+ (kwarg_types ||= {})[param_name] = type
120
131
  if param_kind == :keyreq
121
- @req_kwarg_names << param_name
132
+ (req_kwarg_names ||= []) << param_name
122
133
  end
123
134
  when :block
124
135
  @block_name = param_name
@@ -134,7 +145,14 @@ class T::Private::Methods::Signature
134
145
  else
135
146
  raise "Unexpected param_kind: `#{param_kind}`. Method: #{method_desc}"
136
147
  end
148
+
149
+ i += 1
137
150
  end
151
+
152
+ @arg_types = arg_types || EMPTY_LIST
153
+ @kwarg_types = kwarg_types || EMPTY_HASH
154
+ @req_arg_count = req_arg_count
155
+ @req_kwarg_names = req_kwarg_names || EMPTY_LIST
138
156
  end
139
157
 
140
158
  attr_writer :method_name
@@ -179,15 +197,7 @@ class T::Private::Methods::Signature
179
197
  kwargs = EMPTY_HASH
180
198
  end
181
199
 
182
- arg_types = @arg_types
183
-
184
- if @has_rest
185
- rest_count = args_length - @arg_types.length
186
- rest_count = 0 if rest_count.negative?
187
-
188
- arg_types += [[@rest_name, @rest_type]] * rest_count
189
-
190
- elsif (args_length < @req_arg_count) || (args_length > @arg_types.length)
200
+ if !@has_rest && ((args_length < @req_arg_count) || (args_length > @arg_types.length))
191
201
  expected_str = @req_arg_count.to_s
192
202
  if @arg_types.length != @req_arg_count
193
203
  expected_str += "..#{@arg_types.length}"
@@ -197,10 +207,23 @@ class T::Private::Methods::Signature
197
207
 
198
208
  begin
199
209
  it = 0
200
- while it < args_length
201
- yield arg_types[it][0], args[it], arg_types[it][1]
210
+
211
+ # Process given pre-rest args. When there are no rest args,
212
+ # this is just the given number of args.
213
+ while it < args_length && it < @arg_types.length
214
+ yield @arg_types[it][0], args[it], @arg_types[it][1]
202
215
  it += 1
203
216
  end
217
+
218
+ if @has_rest
219
+ rest_count = args_length - @arg_types.length
220
+ rest_count = 0 if rest_count.negative?
221
+
222
+ rest_count.times do
223
+ yield @rest_name, args[it], @rest_type
224
+ it += 1
225
+ end
226
+ end
204
227
  end
205
228
 
206
229
  kwargs.each do |name, val|
@@ -208,6 +231,7 @@ class T::Private::Methods::Signature
208
231
  if !type && @has_keyrest
209
232
  type = @keyrest_type
210
233
  end
234
+
211
235
  yield name, val, type if type
212
236
  end
213
237
  end
@@ -221,5 +245,6 @@ class T::Private::Methods::Signature
221
245
  "#{@method} at #{loc}"
222
246
  end
223
247
 
248
+ EMPTY_LIST = [].freeze
224
249
  EMPTY_HASH = {}.freeze
225
250
  end