rbs 3.4.4 → 3.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +12 -4
  3. data/.github/workflows/dependabot.yml +26 -0
  4. data/.github/workflows/ruby.yml +14 -1
  5. data/CHANGELOG.md +87 -1
  6. data/README.md +5 -3
  7. data/Rakefile +20 -3
  8. data/Steepfile +1 -1
  9. data/core/enumerator.rbs +1 -1
  10. data/core/float.rbs +2 -1
  11. data/core/gc.rbs +272 -150
  12. data/core/integer.rbs +6 -4
  13. data/core/io/wait.rbs +4 -4
  14. data/core/io.rbs +10 -3
  15. data/core/kernel.rbs +8 -7
  16. data/core/module.rbs +17 -4
  17. data/core/proc.rbs +1 -1
  18. data/core/range.rbs +2 -2
  19. data/core/rational.rbs +2 -1
  20. data/core/regexp.rbs +101 -90
  21. data/core/ruby_vm.rbs +107 -103
  22. data/core/rubygems/rubygems.rbs +1 -1
  23. data/core/set.rbs +13 -7
  24. data/core/string.rbs +3 -3
  25. data/core/symbol.rbs +2 -1
  26. data/core/thread.rbs +1 -1
  27. data/core/time.rbs +24 -4
  28. data/docs/architecture.md +110 -0
  29. data/docs/gem.md +0 -1
  30. data/docs/syntax.md +5 -1
  31. data/ext/rbs_extension/constants.c +2 -0
  32. data/ext/rbs_extension/constants.h +1 -0
  33. data/ext/rbs_extension/lexer.c +1338 -1341
  34. data/ext/rbs_extension/lexer.h +2 -0
  35. data/ext/rbs_extension/lexer.re +2 -3
  36. data/ext/rbs_extension/lexstate.c +5 -1
  37. data/ext/rbs_extension/location.c +80 -70
  38. data/ext/rbs_extension/location.h +25 -5
  39. data/ext/rbs_extension/parser.c +149 -43
  40. data/ext/rbs_extension/parserstate.c +12 -1
  41. data/ext/rbs_extension/parserstate.h +9 -0
  42. data/ext/rbs_extension/ruby_objs.c +13 -3
  43. data/ext/rbs_extension/ruby_objs.h +1 -0
  44. data/lib/rbs/cli/validate.rb +2 -2
  45. data/lib/rbs/cli.rb +4 -6
  46. data/lib/rbs/collection/config.rb +1 -1
  47. data/lib/rbs/collection/sources/git.rb +1 -6
  48. data/lib/rbs/definition_builder/method_builder.rb +1 -1
  49. data/lib/rbs/definition_builder.rb +8 -8
  50. data/lib/rbs/diff.rb +1 -1
  51. data/lib/rbs/environment_loader.rb +2 -1
  52. data/lib/rbs/errors.rb +0 -14
  53. data/lib/rbs/location_aux.rb +6 -1
  54. data/lib/rbs/parser/lex_result.rb +15 -0
  55. data/lib/rbs/parser/token.rb +23 -0
  56. data/lib/rbs/parser_aux.rb +12 -5
  57. data/lib/rbs/prototype/helpers.rb +22 -12
  58. data/lib/rbs/prototype/rb.rb +38 -4
  59. data/lib/rbs/prototype/rbi.rb +30 -20
  60. data/lib/rbs/test/errors.rb +19 -14
  61. data/lib/rbs/test/tester.rb +1 -1
  62. data/lib/rbs/test/type_check.rb +95 -16
  63. data/lib/rbs/types.rb +112 -13
  64. data/lib/rbs/unit_test/spy.rb +1 -1
  65. data/lib/rbs/version.rb +1 -1
  66. data/rbs.gemspec +7 -2
  67. data/sig/environment_loader.rbs +1 -1
  68. data/sig/errors.rbs +1 -1
  69. data/sig/manifest.yaml +0 -1
  70. data/sig/method_types.rbs +3 -3
  71. data/sig/parser.rbs +28 -0
  72. data/sig/prototype/helpers.rbs +4 -0
  73. data/sig/prototype/rbi.rbs +2 -0
  74. data/sig/types.rbs +54 -4
  75. data/sig/variance_calculator.rbs +2 -2
  76. data/stdlib/csv/0/csv.rbs +4 -1
  77. data/stdlib/fileutils/0/fileutils.rbs +1 -1
  78. data/stdlib/net-http/0/net-http.rbs +29 -27
  79. data/stdlib/socket/0/socket.rbs +2 -2
  80. data/stdlib/timeout/0/timeout.rbs +6 -0
  81. data/stdlib/uri/0/generic.rbs +2 -2
  82. data/stdlib/uri/0/http.rbs +2 -2
  83. data/stdlib/uri/0/mailto.rbs +84 -0
  84. metadata +7 -9
  85. data/Gemfile +0 -30
  86. data/Gemfile.lock +0 -117
  87. data/lib/rbs/parser_compat/lexer_error.rb +0 -6
  88. data/lib/rbs/parser_compat/located_value.rb +0 -7
  89. data/lib/rbs/parser_compat/semantics_error.rb +0 -6
  90. data/lib/rbs/parser_compat/syntax_error.rb +0 -6
@@ -630,12 +630,12 @@ module RBS
630
630
  end
631
631
 
632
632
  # @type var accessibility: RBS::Definition::accessibility
633
- accessibility = if method.name == :initialize
634
- :private
635
- else
636
- method.accessibility
637
- end
638
-
633
+ accessibility =
634
+ if original.instance? && [:initialize, :initialize_copy, :initialize_clone, :initialize_dup, :respond_to_missing?].include?(method.name)
635
+ :private
636
+ else
637
+ method.accessibility
638
+ end
639
639
  # Skip setting up `super_method` if `implemented_in` is `nil`, that means the type doesn't have implementation.
640
640
  # This typically happens if the type is an interface.
641
641
  if implemented_in
@@ -669,7 +669,7 @@ module RBS
669
669
  ]
670
670
  ),
671
671
  block: nil,
672
- location: nil
672
+ location: original.location
673
673
  )
674
674
  else
675
675
  # getter
@@ -677,7 +677,7 @@ module RBS
677
677
  type_params: [],
678
678
  type: Types::Function.empty(attr_type),
679
679
  block: nil,
680
- location: nil
680
+ location: original.location
681
681
  )
682
682
  end
683
683
 
data/lib/rbs/diff.rb CHANGED
@@ -83,7 +83,7 @@ module RBS
83
83
  manifest_pathname = dir_pathname / 'manifest.yaml'
84
84
  if manifest_pathname.exist?
85
85
  manifest = YAML.safe_load(manifest_pathname.read)
86
- if manifest['dependencies']
86
+ if manifest && manifest['dependencies']
87
87
  manifest['dependencies'].each do |dependency|
88
88
  loader.add(library: dependency['name'], version: nil)
89
89
  end
@@ -14,7 +14,8 @@ module RBS
14
14
 
15
15
  include FileFinder
16
16
 
17
- Library = _ = Struct.new(:name, :version, keyword_init: true)
17
+ class Library < Struct.new(:name, :version, keyword_init: true)
18
+ end
18
19
 
19
20
  attr_reader :core_root
20
21
  attr_reader :repository
data/lib/rbs/errors.rb CHANGED
@@ -62,20 +62,6 @@ module RBS
62
62
 
63
63
  super "#{Location.to_string location}: Syntax error: #{error_message}, token=`#{location.source}` (#{token_type})"
64
64
  end
65
-
66
- def error_value
67
- RBS.print_warning {
68
- "#{self.class.name}#error_value is deprecated and will be deleted in RBS 2.0. Consider using `location.source` instead."
69
- }
70
- location.source
71
- end
72
-
73
- def token_str
74
- RBS.print_warning {
75
- "#{self.class.name}#token_str is deprecated and will be deleted in RBS 2.0. Consider using `token_type` instead."
76
- }
77
- token_type
78
- end
79
65
  end
80
66
 
81
67
  class InvalidTypeApplicationError < DefinitionError
@@ -5,7 +5,12 @@ module RBS
5
5
  def inspect
6
6
  rks = each_required_key.to_a
7
7
  ops = each_optional_key.to_a.map {|x| "?#{x}" }
8
- "#<#{self.class}:#{self.__id__} buffer=#{buffer.name}, start=#{start_line}:#{start_column}, pos=#{start_pos}...#{end_pos}, children=#{(rks + ops).join(",")} source='#{source.lines.first&.chomp}'>"
8
+ src = if source.length <= 1
9
+ source.inspect
10
+ else
11
+ source.each_line.first&.chomp&.inspect
12
+ end
13
+ "#<#{self.class}:#{self.__id__} buffer=#{buffer.name}, start=#{start_line}:#{start_column}, pos=#{start_pos}...#{end_pos}, children=#{(rks + ops).join(",")} source=#{src}>"
9
14
  end
10
15
 
11
16
  def self.new(buffer_ = nil, start_pos_ = nil, end_pos_ = nil, buffer: nil, start_pos: nil, end_pos: nil)
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBS
4
+ class Parser
5
+ class LexResult
6
+ attr_reader :buffer
7
+ attr_reader :value
8
+
9
+ def initialize(buffer:, value:)
10
+ @buffer = buffer
11
+ @value = value
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBS
4
+ class Parser
5
+ class Token
6
+ attr_reader :type
7
+ attr_reader :location
8
+
9
+ def initialize(type:, location:)
10
+ @type = type
11
+ @location = location
12
+ end
13
+
14
+ def value
15
+ @location.source
16
+ end
17
+
18
+ def comment?
19
+ @type == :tCOMMENT || @type == :tLINECOMMENT
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "parser/lex_result"
4
+ require_relative "parser/token"
5
+
3
6
  module RBS
4
7
  class Parser
5
8
  def self.parse_type(source, range: 0..., variables: [], require_eof: false)
@@ -19,6 +22,15 @@ module RBS
19
22
  [buf, dirs, decls]
20
23
  end
21
24
 
25
+ def self.lex(source)
26
+ buf = buffer(source)
27
+ list = _lex(buf, buf.last_position)
28
+ value = list.map do |type, location|
29
+ Token.new(type: type, location: location)
30
+ end
31
+ LexResult.new(buffer: buf, value: value)
32
+ end
33
+
22
34
  def self.buffer(source)
23
35
  case source
24
36
  when String
@@ -28,11 +40,6 @@ module RBS
28
40
  end
29
41
  end
30
42
 
31
- autoload :SyntaxError, "rbs/parser_compat/syntax_error"
32
- autoload :SemanticsError, "rbs/parser_compat/semantics_error"
33
- autoload :LexerError, "rbs/parser_compat/lexer_error"
34
- autoload :LocatedValue, "rbs/parser_compat/located_value"
35
-
36
43
  KEYWORDS = %w(
37
44
  bool
38
45
  bot
@@ -37,13 +37,9 @@ module RBS
37
37
  end
38
38
  end
39
39
 
40
- method_block = Types::Block.new(
41
- required: required,
42
- type: Types::Function.empty(untyped),
43
- self_type: nil
44
- )
45
-
46
40
  if yields
41
+ function = Types::Function.empty(untyped)
42
+
47
43
  yields.each do |yield_node|
48
44
  array_content = yield_node.children[0]&.children&.compact || []
49
45
 
@@ -54,9 +50,9 @@ module RBS
54
50
  [array_content, nil]
55
51
  end
56
52
 
57
- if (diff = positionals.size - method_block.type.required_positionals.size) > 0
53
+ if (diff = positionals.size - function.required_positionals.size) > 0
58
54
  diff.times do
59
- method_block.type.required_positionals << Types::Function::Param.new(
55
+ function.required_positionals << Types::Function::Param.new(
60
56
  type: untyped,
61
57
  name: nil
62
58
  )
@@ -67,7 +63,7 @@ module RBS
67
63
  keywords.children[0].children.each_slice(2) do |key_node, value_node|
68
64
  if key_node
69
65
  key = key_node.children[0]
70
- method_block.type.required_keywords[key] ||=
66
+ function.required_keywords[key] ||=
71
67
  Types::Function::Param.new(
72
68
  type: untyped,
73
69
  name: nil
@@ -76,10 +72,13 @@ module RBS
76
72
  end
77
73
  end
78
74
  end
75
+ else
76
+ function = Types::UntypedFunction.new(return_type: untyped)
79
77
  end
80
- end
81
78
 
82
- method_block
79
+
80
+ Types::Block.new(required: required, type: function, self_type: nil)
81
+ end
83
82
  end
84
83
 
85
84
  def each_child(node, &block)
@@ -109,7 +108,7 @@ module RBS
109
108
  def keyword_hash?(node)
110
109
  if node && node.type == :HASH
111
110
  node.children[0].children.compact.each_slice(2).all? {|key, _|
112
- key.type == :LIT && key.children[0].is_a?(Symbol)
111
+ symbol_literal_node?(key)
113
112
  }
114
113
  else
115
114
  false
@@ -122,6 +121,17 @@ module RBS
122
121
  args_node&.children || [0, nil, nil, nil, 0, nil, nil, nil, nil, nil]
123
122
  end
124
123
 
124
+ def symbol_literal_node?(node)
125
+ case node.type
126
+ when :LIT
127
+ if node.children[0].is_a?(Symbol)
128
+ node.children[0]
129
+ end
130
+ when :SYM
131
+ node.children[0]
132
+ end
133
+ end
134
+
125
135
  def untyped
126
136
  @untyped ||= Types::Bases::Any.new(location: nil)
127
137
  end
@@ -5,7 +5,7 @@ module RBS
5
5
  class RB
6
6
  include Helpers
7
7
 
8
- Context = _ = Struct.new(:module_function, :singleton, :namespace, :in_def, keyword_init: true) do
8
+ class Context < Struct.new(:module_function, :singleton, :namespace, :in_def, keyword_init: true)
9
9
  # @implements Context
10
10
 
11
11
  def self.initial(namespace: Namespace.root)
@@ -461,6 +461,8 @@ module RBS
461
461
 
462
462
  def literal_to_symbol(node)
463
463
  case node.type
464
+ when :SYM
465
+ node.children[0]
464
466
  when :LIT
465
467
  node.children[0] if node.children[0].is_a?(Symbol)
466
468
  when :STR
@@ -495,7 +497,7 @@ module RBS
495
497
  end
496
498
 
497
499
  if rest
498
- rest_name = rest == :* ? nil : rest # # For `def f(...) end` syntax
500
+ rest_name = rest == :* ? nil : rest # `def f(...)` syntax has `*` name
499
501
  fun = fun.update(rest_positionals: Types::Function::Param.new(name: rest_name, type: untyped))
500
502
  end
501
503
 
@@ -518,7 +520,9 @@ module RBS
518
520
  end
519
521
 
520
522
  if kwrest && kwrest.children.any?
521
- fun = fun.update(rest_keywords: Types::Function::Param.new(name: kwrest.children[0], type: untyped))
523
+ kwrest_name = kwrest.children[0] #: Symbol?
524
+ kwrest_name = nil if kwrest_name == :** # `def f(...)` syntax has `**` name
525
+ fun = fun.update(rest_keywords: Types::Function::Param.new(name: kwrest_name, type: untyped))
522
526
  end
523
527
 
524
528
  fun
@@ -574,9 +578,16 @@ module RBS
574
578
  end
575
579
  when :DSTR, :XSTR
576
580
  BuiltinNames::String.instance_type
581
+ when :SYM
582
+ lit = node.children[0]
583
+ if lit.to_s.ascii_only?
584
+ Types::Literal.new(literal: lit, location: nil)
585
+ else
586
+ BuiltinNames::Symbol.instance_type
587
+ end
577
588
  when :DSYM
578
589
  BuiltinNames::Symbol.instance_type
579
- when :DREGX
590
+ when :DREGX, :REGX
580
591
  BuiltinNames::Regexp.instance_type
581
592
  when :TRUE
582
593
  Types::Literal.new(literal: true, location: nil)
@@ -584,6 +595,14 @@ module RBS
584
595
  Types::Literal.new(literal: false, location: nil)
585
596
  when :NIL
586
597
  Types::Bases::Nil.new(location: nil)
598
+ when :INTEGER
599
+ Types::Literal.new(literal: node.children[0], location: nil)
600
+ when :FLOAT
601
+ BuiltinNames::Float.instance_type
602
+ when :RATIONAL, :IMAGINARY
603
+ lit = node.children[0]
604
+ type_name = TypeName.new(name: lit.class.name.to_sym, namespace: Namespace.root)
605
+ Types::ClassInstance.new(name: type_name, args: [], location: nil)
587
606
  when :LIT
588
607
  lit = node.children[0]
589
608
  case lit
@@ -595,6 +614,11 @@ module RBS
595
614
  end
596
615
  when Integer
597
616
  Types::Literal.new(literal: lit, location: nil)
617
+ when String
618
+ # For Ruby <=3.3 which generates `LIT` node for string literals inside Hash literal.
619
+ # "a" => STR node
620
+ # { "a" => nil } => LIT node
621
+ Types::Literal.new(literal: lit, location: nil)
598
622
  else
599
623
  type_name = TypeName.new(name: lit.class.name.to_sym, namespace: Namespace.root)
600
624
  Types::ClassInstance.new(name: type_name, args: [], location: nil)
@@ -686,6 +710,14 @@ module RBS
686
710
 
687
711
  def param_type(node, default: Types::Bases::Any.new(location: nil))
688
712
  case node.type
713
+ when :INTEGER
714
+ BuiltinNames::Integer.instance_type
715
+ when :FLOAT
716
+ BuiltinNames::Float.instance_type
717
+ when :RATIONAL
718
+ Types::ClassInstance.new(name: TypeName("::Rational"), args: [], location: nil)
719
+ when :IMAGINARY
720
+ Types::ClassInstance.new(name: TypeName("::Complex"), args: [], location: nil)
689
721
  when :LIT
690
722
  case node.children[0]
691
723
  when Symbol
@@ -697,6 +729,8 @@ module RBS
697
729
  else
698
730
  default
699
731
  end
732
+ when :SYM
733
+ BuiltinNames::Symbol.instance_type
700
734
  when :STR, :DSTR
701
735
  BuiltinNames::String.instance_type
702
736
  when :NIL
@@ -3,6 +3,8 @@
3
3
  module RBS
4
4
  module Prototype
5
5
  class RBI
6
+ include Helpers
7
+
6
8
  attr_reader :decls
7
9
  attr_reader :modules
8
10
  attr_reader :last_sig
@@ -218,11 +220,11 @@ module RBS
218
220
  if (send = node.children.last) && send.type == :FCALL && send.children[0] == :type_member
219
221
  unless each_arg(send.children[1]).any? {|node|
220
222
  node.type == :HASH &&
221
- each_arg(node.children[0]).each_slice(2).any? {|a, _| a.type == :LIT && a.children[0] == :fixed }
223
+ each_arg(node.children[0]).each_slice(2).any? {|a, _| symbol_literal_node?(a) == :fixed }
222
224
  }
223
225
  # @type var variance: AST::TypeParam::variance?
224
- if (a0 = each_arg(send.children[1]).to_a[0]) && a0.type == :LIT
225
- variance = case a0.children[0]
226
+ if (a0 = each_arg(send.children[1]).to_a[0]) && (v = symbol_literal_node?(a0))
227
+ variance = case v
226
228
  when :out
227
229
  :covariant
228
230
  when :in
@@ -315,14 +317,18 @@ module RBS
315
317
  Types::Function::Param.new(name: name, type: type)
316
318
  end
317
319
 
318
- method_type.update(type: method_type.type.update(required_positionals: required_positionals))
320
+ if method_type.type.is_a?(RBS::Types::Function)
321
+ method_type.update(type: method_type.type.update(required_positionals: required_positionals))
322
+ else
323
+ method_type
324
+ end
319
325
  end
320
326
  when :type_parameters
321
327
  type_params = []
322
328
 
323
329
  each_arg args do |node|
324
- if node.type == :LIT
325
- type_params << node.children[0]
330
+ if name = symbol_literal_node?(node)
331
+ type_params << name
326
332
  end
327
333
  end
328
334
 
@@ -444,18 +450,22 @@ module RBS
444
450
  end
445
451
  end
446
452
 
447
- method_type.update(
448
- type: method_type.type.update(
449
- required_positionals: required_positionals,
450
- optional_positionals: optional_positionals,
451
- rest_positionals: rest_positionals,
452
- trailing_positionals: trailing_positionals,
453
- required_keywords: required_keywords,
454
- optional_keywords: optional_keywords,
455
- rest_keywords: rest_keywords
456
- ),
457
- block: method_block
458
- )
453
+ if method_type.type.is_a?(Types::Function)
454
+ method_type.update(
455
+ type: method_type.type.update(
456
+ required_positionals: required_positionals,
457
+ optional_positionals: optional_positionals,
458
+ rest_positionals: rest_positionals,
459
+ trailing_positionals: trailing_positionals,
460
+ required_keywords: required_keywords,
461
+ optional_keywords: optional_keywords,
462
+ rest_keywords: rest_keywords
463
+ ),
464
+ block: method_block
465
+ )
466
+ else
467
+ method_type
468
+ end
459
469
  end
460
470
 
461
471
  def type_of(type_node, variables:)
@@ -613,8 +623,8 @@ module RBS
613
623
  each_arg(node.children[0]).each_slice(2) do |var, type|
614
624
  var or raise
615
625
 
616
- if var.type == :LIT && type
617
- hash[var.children[0]] = type
626
+ if (name = symbol_literal_node?(var)) && type
627
+ hash[name] = type
618
628
  end
619
629
  end
620
630
 
@@ -40,32 +40,37 @@ module RBS
40
40
  end
41
41
  end
42
42
 
43
- def self.to_string(error)
44
- name = if error.klass.singleton_class?
45
- inspect_(error.klass).sub(/\A#<Class:(.*)>\z/, '\1')
43
+ def self.method_tag(error)
44
+ if error.klass.singleton_class?
45
+ name = inspect_(error.klass).sub(/\A#<Class:(.*)>\z/, '\1')
46
+ method_name = ".#{error.method_name}"
46
47
  else
47
- error.klass.name
48
+ name = error.klass.name
49
+ method_name = "##{error.method_name}"
48
50
  end
49
- method = "#{name}#{error.method_name}"
51
+ "[#{name}#{method_name}]"
52
+ end
53
+
54
+ def self.to_string(error)
50
55
  case error
51
56
  when ArgumentTypeError
52
- "[#{method}] ArgumentTypeError: expected #{format_param error.param} but given `#{inspect_(error.value)}`"
57
+ "#{method_tag(error)} ArgumentTypeError: expected #{format_param error.param} but given `#{inspect_(error.value)}`"
53
58
  when BlockArgumentTypeError
54
- "[#{method}] BlockArgumentTypeError: expected #{format_param error.param} but given `#{inspect_(error.value)}`"
59
+ "#{method_tag(error)} BlockArgumentTypeError: expected #{format_param error.param} but given `#{inspect_(error.value)}`"
55
60
  when ArgumentError
56
- "[#{method}] ArgumentError: expected method type #{error.method_type}"
61
+ "#{method_tag(error)} ArgumentError: expected method type #{error.method_type}"
57
62
  when BlockArgumentError
58
- "[#{method}] BlockArgumentError: expected method type #{error.method_type}"
63
+ "#{method_tag(error)} BlockArgumentError: expected method type #{error.method_type}"
59
64
  when ReturnTypeError
60
- "[#{method}] ReturnTypeError: expected `#{error.type}` but returns `#{inspect_(error.value)}`"
65
+ "#{method_tag(error)} ReturnTypeError: expected `#{error.type}` but returns `#{inspect_(error.value)}`"
61
66
  when BlockReturnTypeError
62
- "[#{method}] BlockReturnTypeError: expected `#{error.type}` but returns `#{inspect_(error.value)}`"
67
+ "#{method_tag(error)} BlockReturnTypeError: expected `#{error.type}` but returns `#{inspect_(error.value)}`"
63
68
  when UnexpectedBlockError
64
- "[#{method}] UnexpectedBlockError: unexpected block is given for `#{error.method_type}`"
69
+ "#{method_tag(error)} UnexpectedBlockError: unexpected block is given for `#{error.method_type}`"
65
70
  when MissingBlockError
66
- "[#{method}] MissingBlockError: required block is missing for `#{error.method_type}`"
71
+ "#{method_tag(error)} MissingBlockError: required block is missing for `#{error.method_type}`"
67
72
  when UnresolvedOverloadingError
68
- "[#{method}] UnresolvedOverloadingError: couldn't find a suitable overloading"
73
+ "#{method_tag(error)} UnresolvedOverloadingError: couldn't find a suitable overloading"
69
74
  else
70
75
  raise "Unexpected error: #{inspect_(error)}"
71
76
  end
@@ -149,7 +149,7 @@ module RBS
149
149
  method = definition.methods[method_name]
150
150
  if method
151
151
  RBS.logger.debug { "Type checking `#{self_class}#{format_method_name(method_name)}`..."}
152
- errors = check.overloaded_call(method, format_method_name(method_name), trace, errors: [])
152
+ errors = check.overloaded_call(method, method_name, trace, errors: [])
153
153
 
154
154
  if errors.empty?
155
155
  RBS.logger.debug { "No type error detected 👏" }
@@ -35,22 +35,24 @@ module RBS
35
35
  if es.size == 1
36
36
  errors.push(*es[0])
37
37
  else
38
+ error = Errors::UnresolvedOverloadingError.new(
39
+ klass: self_class,
40
+ method_name: method_name,
41
+ method_types: method.method_types
42
+ )
38
43
  RBS.logger.warn do
39
- message = +"[#{self_class}#{method_name}] UnresolvedOverloadingError "
44
+ tag = Errors.method_tag(error)
45
+ message = +"#{tag} UnresolvedOverloadingError "
40
46
  message << method.method_types.zip(es).map do |method_type, es|
41
47
  msg = +"method_type=`#{method_type}`"
42
48
  details = es.map do |e|
43
- "\"#{Errors.to_string(e).sub("[#{e.klass.name}#{e.method_name}] ", "") }\""
49
+ "\"#{Errors.to_string(e).sub("#{tag} ", "") }\""
44
50
  end.join(', ')
45
51
  msg << " details=[#{details}]"
46
52
  end.join(', ')
47
53
  message
48
54
  end
49
- errors << Errors::UnresolvedOverloadingError.new(
50
- klass: self_class,
51
- method_name: method_name,
52
- method_types: method.method_types
53
- )
55
+ errors << error
54
56
  end
55
57
 
56
58
  errors
@@ -281,19 +283,22 @@ module RBS
281
283
  end
282
284
  end
283
285
 
284
- each_sample(values).all? do |v|
286
+ value_check = values.empty? || each_sample(values).all? do |v|
285
287
  if v.size == 1
286
288
  # Only one block argument.
287
289
  value(v[0], type.args[0]) || value(v, type.args[0])
288
290
  else
289
291
  value(v, type.args[0])
290
292
  end
291
- end &&
292
- if ret.equal?(self)
293
- type.args[1].is_a?(Types::Bases::Bottom)
294
- else
295
- value(ret, type.args[1])
296
- end
293
+ end
294
+
295
+ return_check = if ret.equal?(self)
296
+ type.args[1].is_a?(Types::Bases::Bottom)
297
+ else
298
+ value(ret, type.args[1])
299
+ end
300
+
301
+ value_check && return_check
297
302
  end
298
303
  else
299
304
  Test.call(val, IS_AP, klass)
@@ -308,8 +313,15 @@ module RBS
308
313
  val.is_a?(singleton_class)
309
314
  when Types::Interface
310
315
  if (definition = builder.build_interface(type.name.absolute!))
311
- definition.methods.each_key.all? do |method_name|
312
- Test.call(val, RESPOND_TOP, method_name)
316
+ definition.methods.each.all? do |method_name, method|
317
+ next false unless Test.call(val, RESPOND_TOP, method_name)
318
+
319
+ meth = Test.call(val, METHOD, method_name)
320
+ method.defs.all? do |type_def|
321
+ type_def.member.overloads.all? do |overload|
322
+ callable_argument?(meth.parameters, overload.method_type)
323
+ end
324
+ end
313
325
  end
314
326
  end
315
327
  when Types::Variable
@@ -336,6 +348,73 @@ module RBS
336
348
  false
337
349
  end
338
350
  end
351
+
352
+ private
353
+
354
+ def callable_argument?(parameters, method_type)
355
+ fun = method_type.type
356
+ take_has_rest = !!parameters.find { |(op, _)| op == :rest }
357
+
358
+ fun.required_positionals.each do
359
+ op, _ = parameters.first
360
+ return false if op.nil? || op == :keyreq || op == :key || op == :keyrest
361
+ parameters.shift if op == :req || op == :opt
362
+ end
363
+
364
+ fun.optional_positionals.each do
365
+ op, _ = parameters.first
366
+ return false if op.nil? || op == :req || op == :keyreq || op == :key || op == :keyrest
367
+ parameters.shift if op == :opt
368
+ end
369
+
370
+ if fun.rest_positionals
371
+ op, _ = parameters.shift
372
+ return false if op.nil? || op != :rest
373
+ end
374
+
375
+ fun.trailing_positionals.each do
376
+ op, _ = parameters.first
377
+ return false if !take_has_rest && (op.nil? || op == :keyreq || op == :key || op == :keyrest)
378
+ index = parameters.find_index { |(op, _)| op == :req }
379
+ parameters.delete_at(index) if index
380
+ end
381
+
382
+ if fun.has_keyword?
383
+ return false if !take_has_rest && parameters.empty?
384
+
385
+ fun.required_keywords.each do |name, _|
386
+ return false if !take_has_rest && parameters.empty?
387
+ index = parameters.find_index { |(op, n)| (op == :keyreq || op == :key) && n == name }
388
+ parameters.delete_at(index) if index
389
+ end
390
+
391
+ if !fun.optional_keywords.empty?
392
+ fun.optional_keywords.each do |name, _|
393
+ return false if !take_has_rest && parameters.empty?
394
+ index = parameters.find_index { |(op, n)| op == :key && n == name }
395
+ parameters.delete_at(index) if index
396
+ end
397
+ op, _ = parameters.first
398
+ return false if op == :req
399
+ end
400
+
401
+ if fun.rest_keywords
402
+ op, _ = parameters.first
403
+ return false if (!take_has_rest && op.nil?)
404
+ # f(a) allows (Integer, a: Integer)
405
+ return false if op == :req && fun.required_keywords.empty?
406
+ end
407
+
408
+ op, _ = parameters.first
409
+ return true if (op == :req || op == :opt) && parameters.length == 1
410
+ end
411
+
412
+ # rest required arguments
413
+ op, _ = parameters.first
414
+ return false if op == :req || op == :keyreq
415
+
416
+ true
417
+ end
339
418
  end
340
419
  end
341
420
  end