steep 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/LICENSE +21 -0
  4. data/bin/smoke_runner.rb +3 -0
  5. data/lib/steep/ast/annotation/collection.rb +120 -43
  6. data/lib/steep/ast/annotation.rb +5 -10
  7. data/lib/steep/ast/location.rb +1 -1
  8. data/lib/steep/ast/method_type.rb +3 -1
  9. data/lib/steep/ast/signature/alias.rb +19 -0
  10. data/lib/steep/ast/signature/env.rb +9 -0
  11. data/lib/steep/ast/signature/members.rb +4 -0
  12. data/lib/steep/ast/types/proc.rb +79 -0
  13. data/lib/steep/ast/types/void.rb +4 -0
  14. data/lib/steep/cli.rb +2 -1
  15. data/lib/steep/drivers/check.rb +4 -1
  16. data/lib/steep/errors.rb +13 -0
  17. data/lib/steep/interface/builder.rb +90 -47
  18. data/lib/steep/interface/instantiated.rb +1 -1
  19. data/lib/steep/interface/method.rb +8 -0
  20. data/lib/steep/interface/method_type.rb +40 -13
  21. data/lib/steep/parser.rb +1098 -1043
  22. data/lib/steep/parser.y +94 -36
  23. data/lib/steep/source.rb +5 -6
  24. data/lib/steep/subtyping/check.rb +162 -47
  25. data/lib/steep/subtyping/variable_occurrence.rb +2 -2
  26. data/lib/steep/subtyping/variable_variance.rb +3 -3
  27. data/lib/steep/type_construction.rb +630 -300
  28. data/lib/steep/type_inference/block_params.rb +186 -35
  29. data/lib/steep/type_inference/send_args.rb +12 -3
  30. data/lib/steep/type_inference/type_env.rb +10 -4
  31. data/lib/steep/type_name.rb +6 -0
  32. data/lib/steep/typing.rb +21 -2
  33. data/lib/steep/version.rb +1 -1
  34. data/lib/steep.rb +2 -0
  35. data/smoke/alias/a.rb +19 -0
  36. data/smoke/alias/a.rbi +10 -0
  37. data/smoke/alias/b.rb +7 -0
  38. data/smoke/alias/c.rb +10 -0
  39. data/smoke/array/c.rb +7 -0
  40. data/smoke/block/c.rb +10 -0
  41. data/smoke/block/c.rbi +3 -0
  42. data/smoke/block/d.rb +15 -0
  43. data/smoke/class/c.rb +1 -1
  44. data/smoke/class/e.rb +1 -1
  45. data/smoke/class/h.rb +15 -0
  46. data/smoke/class/h.rbi +7 -0
  47. data/smoke/class/i.rb +17 -0
  48. data/smoke/class/i.rbi +9 -0
  49. data/smoke/extension/a.rbi +4 -0
  50. data/smoke/extension/d.rb +2 -0
  51. data/smoke/hash/a.rb +17 -0
  52. data/smoke/hash/b.rb +7 -0
  53. data/smoke/implements/a.rb +2 -2
  54. data/smoke/initialize/a.rb +1 -1
  55. data/smoke/lambda/a.rb +11 -0
  56. data/smoke/literal/b.rb +9 -0
  57. data/smoke/literal/literal_methods.rbi +4 -0
  58. data/smoke/method/c.rb +5 -0
  59. data/smoke/regression/array.rb +7 -0
  60. data/smoke/regression/hash.rb +7 -0
  61. data/smoke/regression/set_divide.rb +16 -0
  62. data/smoke/self/a.rb +2 -2
  63. data/stdlib/builtin.rbi +151 -1
  64. data/steep.gemspec +1 -0
  65. metadata +30 -4
@@ -15,7 +15,7 @@ module Steep
15
15
  end
16
16
 
17
17
  def ==(other)
18
- other.is_a?(Param) && other.var == var && other.type == type && other.value == value && other.node == node
18
+ other.is_a?(self.class) && other.var == var && other.type == type && other.value == value && other.node == node
19
19
  end
20
20
 
21
21
  alias eql? ==
@@ -25,72 +25,223 @@ module Steep
25
25
  end
26
26
  end
27
27
 
28
- attr_reader :params
29
- attr_reader :rest
28
+ attr_reader :leading_params
29
+ attr_reader :optional_params
30
+ attr_reader :rest_param
31
+ attr_reader :trailing_params
30
32
 
31
- def initialize(params:, rest:)
32
- @params = params
33
- @rest = rest
33
+ def initialize(leading_params:, optional_params:, rest_param:, trailing_params:)
34
+ @leading_params = leading_params
35
+ @optional_params = optional_params
36
+ @rest_param = rest_param
37
+ @trailing_params = trailing_params
38
+ end
39
+
40
+ def params
41
+ [].tap do |params|
42
+ params.push *leading_params
43
+ params.push *optional_params
44
+ params.push rest_param if rest_param
45
+ params.push *trailing_params
46
+ end
34
47
  end
35
48
 
36
49
  def self.from_node(node, annotations:)
37
- params = []
38
- rest = nil
50
+ leading_params = []
51
+ optional_params = []
52
+ rest_param = nil
53
+ trailing_params = []
54
+
55
+ default_params = leading_params
39
56
 
40
57
  node.children.each do |arg|
41
58
  var = arg.children.first
42
- type = annotations.lookup_var_type(var.name)
59
+ type = annotations.var_type(lvar: var.name)
43
60
 
44
61
  case arg.type
45
62
  when :arg, :procarg0
46
- params << Param.new(var: var, type: type, value: nil, node: arg)
63
+ default_params << Param.new(var: var, type: type, value: nil, node: arg)
47
64
  when :optarg
48
- params << Param.new(var: var, type: type, value: arg.children.last, node: arg)
65
+ default_params = trailing_params
66
+ optional_params << Param.new(var: var, type: type, value: arg.children.last, node: arg)
49
67
  when :restarg
50
- rest = Param.new(var: var, type: type, value: nil, node: arg)
68
+ default_params = trailing_params
69
+ rest_param = Param.new(var: var, type: type, value: nil, node: arg)
51
70
  end
52
71
  end
53
72
 
54
73
  new(
55
- params: params,
56
- rest: rest
74
+ leading_params: leading_params,
75
+ optional_params: optional_params,
76
+ rest_param: rest_param,
77
+ trailing_params: trailing_params
78
+ )
79
+ end
80
+
81
+ def params_type(hint: nil)
82
+ params_type0(hint: hint) or params_type0(hint: nil)
83
+ end
84
+
85
+ def params_type0(hint:)
86
+ if hint
87
+ case
88
+ when leading_params.size == hint.required.size
89
+ leadings = leading_params.map.with_index do |param, index|
90
+ param.type || hint.required[index]
91
+ end
92
+ when !hint.rest && hint.optional.empty? && leading_params.size > hint.required.size
93
+ leadings = leading_params.take(hint.required.size).map.with_index do |param, index|
94
+ param.type || hint.required[index]
95
+ end
96
+ when !hint.rest && hint.optional.empty? && leading_params.size < hint.required.size
97
+ leadings = leading_params.map.with_index do |param, index|
98
+ param.type || hint.required[index]
99
+ end + hint.required.drop(leading_params.size)
100
+ else
101
+ return nil
102
+ end
103
+
104
+ case
105
+ when optional_params.size == hint.optional.size
106
+ optionals = optional_params.map.with_index do |param, index|
107
+ param.type || hint.optional[index]
108
+ end
109
+ when !hint.rest && optional_params.size > hint.optional.size
110
+ optionals = optional_params.take(hint.optional.size).map.with_index do |param, index|
111
+ param.type || hint.optional[index]
112
+ end
113
+ when !hint.rest && optional_params.size < hint.optional.size
114
+ optionals = optional_params.map.with_index do |param, index|
115
+ param.type || hint.optional[index]
116
+ end + hint.optional.drop(optional_params.size)
117
+ else
118
+ return nil
119
+ end
120
+
121
+ if rest_param && hint.rest
122
+ rest = rest_param.type&.yield_self {|ty| ty.args&.first } || hint.rest
123
+ else
124
+ rest = hint.rest
125
+ end
126
+ else
127
+ leadings = leading_params.map {|param| param.type || AST::Types::Any.new }
128
+ optionals = optional_params.map {|param| param.type || AST::Types::Any.new }
129
+ rest = rest_param&.yield_self {|param| param.type.args[0] }
130
+ end
131
+
132
+ Interface::Params.new(
133
+ required: leadings,
134
+ optional: optionals,
135
+ rest: rest,
136
+ required_keywords: {},
137
+ optional_keywords: {},
138
+ rest_keywords: nil
57
139
  )
58
140
  end
59
141
 
60
142
  def zip(params_type)
143
+ if trailing_params.any?
144
+ Steep.logger.error "Block definition with trailing required parameters are not supported yet"
145
+ end
146
+
61
147
  [].tap do |zip|
62
- types = params_type.flat_unnamed_params
63
- params.each do |param|
64
- type = types.shift&.last || params_type.rest || AST::Types::Any.new
148
+ if expandable_params?(params_type) && expandable?
149
+ type = params_type.required[0]
150
+
151
+ case
152
+ when array?(type)
153
+ type_arg = type.args[0]
154
+ params.each do |param|
155
+ unless param == rest_param
156
+ zip << [param, AST::Types::Union.build(types: [type_arg, AST::Types::Nil.new])]
157
+ else
158
+ zip << [param, AST::Types::Name.new_instance(name: "::Array", args: [type_arg])]
159
+ end
160
+ end
161
+ when type.is_a?(AST::Types::Tuple)
162
+ types = type.types.dup
163
+ (leading_params + optional_params).each do |param|
164
+ ty = types.shift
165
+ if ty
166
+ zip << [param, ty]
167
+ else
168
+ zip << [param, AST::Types::Nil.new]
169
+ end
170
+ end
65
171
 
66
- if type
67
- zip << [param, type]
172
+ if rest_param
173
+ if types.any?
174
+ union = AST::Types::Union.build(types: types)
175
+ zip << [rest_param, AST::Types::Name.new_instance(name: "::Array", args: [union])]
176
+ else
177
+ zip << [rest_param, AST::Types::Nil.new]
178
+ end
179
+ end
180
+ end
181
+ else
182
+ types = params_type.flat_unnamed_params
183
+
184
+ (leading_params + optional_params).each do |param|
185
+ type = types.shift&.last || params_type.rest
186
+
187
+ if type
188
+ zip << [param, type]
189
+ else
190
+ zip << [param, AST::Types::Nil.new]
191
+ end
68
192
  end
69
- end
70
193
 
71
- if rest
72
- if types.empty?
73
- array = AST::Types::Name.new_instance(
74
- name: :Array,
75
- args: [params_type.rest || AST::Types::Any.new]
76
- )
77
- zip << [rest, array]
78
- else
79
- union = AST::Types::Union.build(types: types.map(&:last) + [params_type.rest])
80
- array = AST::Types::Name.new_instance(
81
- name: :Array,
82
- args: [union]
83
- )
84
- zip << [rest, array]
194
+ if rest_param
195
+ if types.empty?
196
+ array = AST::Types::Name.new_instance(
197
+ name: "::Array",
198
+ args: [params_type.rest || AST::Types::Any.new]
199
+ )
200
+ zip << [rest_param, array]
201
+ else
202
+ union = AST::Types::Union.build(types: types.map(&:last) + [params_type.rest])
203
+ array = AST::Types::Name.new_instance(
204
+ name: "::Array",
205
+ args: [union]
206
+ )
207
+ zip << [rest_param, array]
208
+ end
85
209
  end
86
210
  end
87
211
  end
88
212
  end
89
213
 
214
+ def array?(type)
215
+ type.is_a?(AST::Types::Name) &&
216
+ type.name.is_a?(TypeName::Instance) &&
217
+ type.name.name.name == "Array" && type.name.name.absolute?
218
+ end
219
+
220
+ def expandable_params?(params_type)
221
+ if params_type.flat_unnamed_params.size == 1
222
+ case (type = params_type.required.first)
223
+ when AST::Types::Tuple
224
+ true
225
+ when AST::Types::Name
226
+ array?(type)
227
+ end
228
+ end
229
+ end
230
+
231
+ def expandable?
232
+ case
233
+ when leading_params.size + trailing_params.size > 1
234
+ true
235
+ when (leading_params.any? || trailing_params.any?) && rest_param
236
+ true
237
+ when params.size == 1 && params[0].node.type == :arg
238
+ true
239
+ end
240
+ end
241
+
90
242
  def each(&block)
91
243
  if block_given?
92
244
  params.each &block
93
- yield rest if rest
94
245
  else
95
246
  enum_for :each
96
247
  end
@@ -3,15 +3,24 @@ module Steep
3
3
  class SendArgs
4
4
  attr_reader :args
5
5
  attr_reader :kw_args
6
+ attr_reader :block_pass_arg
6
7
 
7
- def initialize(args:, kw_args:)
8
+ def initialize(args:, kw_args:, block_pass_arg:)
8
9
  @args = args
9
10
  @kw_args = kw_args
11
+ @block_pass_arg = block_pass_arg
10
12
  end
11
13
 
12
14
  def self.from_nodes(nodes)
15
+ nodes = nodes.dup
16
+
13
17
  args = []
14
18
  last_hash = nil
19
+ block_pass_arg = nil
20
+
21
+ if nodes.last&.type == :block_pass
22
+ block_pass_arg = nodes.pop
23
+ end
15
24
 
16
25
  nodes.each do |node|
17
26
  if last_hash
@@ -34,7 +43,7 @@ module Steep
34
43
  end
35
44
  end
36
45
 
37
- new(args: args, kw_args: last_hash)
46
+ new(args: args, kw_args: last_hash, block_pass_arg: block_pass_arg)
38
47
  end
39
48
 
40
49
  def self.kw_args?(node)
@@ -72,7 +81,7 @@ module Steep
72
81
  end
73
82
  end
74
83
 
75
- def zip(params)
84
+ def zip(params, block)
76
85
  Set.new(
77
86
  [].tap do |pairs|
78
87
  consumed_keywords = Set.new
@@ -28,14 +28,14 @@ module Steep
28
28
 
29
29
  def self.build(annotations:, signatures:, subtyping:, const_env:)
30
30
  new(subtyping: subtyping, const_env: const_env).tap do |env|
31
- annotations.var_types.each do |name, annot|
32
- env.set(lvar: name, type: subtyping.builder.absolute_type(annot.type, current: const_env.current_namespace))
31
+ annotations.lvar_types.each do |name, type|
32
+ env.set(lvar: name, type: type)
33
33
  end
34
34
  annotations.ivar_types.each do |name, type|
35
- env.set(ivar: name, type: subtyping.builder.absolute_type(type, current: const_env.current_namespace))
35
+ env.set(ivar: name, type: type)
36
36
  end
37
37
  annotations.const_types.each do |name, type|
38
- env.set(const: name, type: subtyping.builder.absolute_type(type, current: const_env.current_namespace))
38
+ env.set(const: name, type: type)
39
39
  end
40
40
  signatures.globals.each do |name, annot|
41
41
  type = subtyping.builder.absolute_type(annot.type, current: nil)
@@ -195,6 +195,9 @@ module Steep
195
195
  end
196
196
 
197
197
  def assert_assign(var_type:, lhs_type:)
198
+ var_type = subtyping.expand_alias(var_type)
199
+ lhs_type = subtyping.expand_alias(lhs_type)
200
+
198
201
  relation = Subtyping::Relation.new(sub_type: lhs_type, super_type: var_type)
199
202
  constraints = Subtyping::Constraints.new(unknowns: Set.new)
200
203
 
@@ -212,6 +215,9 @@ module Steep
212
215
  end
213
216
 
214
217
  def assert_annotation(name, annotated_type:, original_type:)
218
+ annotated_type = subtyping.expand_alias(annotated_type)
219
+ original_type = subtyping.expand_alias(original_type)
220
+
215
221
  relation = Subtyping::Relation.new(sub_type: annotated_type, super_type: original_type)
216
222
  constraints = Subtyping::Constraints.new(unknowns: Set.new)
217
223
 
@@ -83,5 +83,11 @@ module Steep
83
83
  end
84
84
 
85
85
  class Instance < Base; end
86
+
87
+ class Alias < Base
88
+ def map_module_name
89
+ self
90
+ end
91
+ end
86
92
  end
87
93
  end
data/lib/steep/typing.rb CHANGED
@@ -5,9 +5,15 @@ module Steep
5
5
  attr_reader :nodes
6
6
  attr_reader :var_typing
7
7
  attr_reader :parent
8
+ attr_reader :parent_last_update
9
+ attr_reader :last_update
10
+ attr_reader :should_update
8
11
 
9
- def initialize(parent: nil)
12
+ def initialize(parent: nil, parent_last_update: parent&.last_update)
10
13
  @parent = parent
14
+ @parent_last_update = parent_last_update
15
+ @last_update = parent&.last_update || 0
16
+ @should_update = false
11
17
 
12
18
  @errors = []
13
19
  @nodes = {}
@@ -23,6 +29,11 @@ module Steep
23
29
  typing[node.__id__] = type
24
30
  nodes[node.__id__] = node
25
31
 
32
+ if should_update
33
+ @last_update += 1
34
+ @should_update = false
35
+ end
36
+
26
37
  type
27
38
  end
28
39
 
@@ -65,7 +76,14 @@ module Steep
65
76
  end
66
77
 
67
78
  def new_child
68
- yield self.class.new(parent: self)
79
+ child = self.class.new(parent: self)
80
+ @should_update = true
81
+
82
+ if block_given?
83
+ yield child
84
+ else
85
+ child
86
+ end
69
87
  end
70
88
 
71
89
  def each_typing
@@ -76,6 +94,7 @@ module Steep
76
94
 
77
95
  def save!
78
96
  raise "Unexpected save!" unless parent
97
+ raise "Parent modified since new_child" unless parent.last_update == parent_last_update
79
98
 
80
99
  each_typing do |node, type|
81
100
  parent.add_typing(node, type)
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
data/lib/steep.rb CHANGED
@@ -25,6 +25,7 @@ require "steep/ast/types/nil"
25
25
  require "steep/ast/types/literal"
26
26
  require "steep/ast/types/boolean"
27
27
  require "steep/ast/types/tuple"
28
+ require "steep/ast/types/proc"
28
29
  require "steep/ast/method_type"
29
30
  require "steep/ast/type_params"
30
31
  require "steep/ast/signature/class"
@@ -35,6 +36,7 @@ require "steep/ast/signature/interface"
35
36
  require "steep/ast/signature/env"
36
37
  require "steep/ast/signature/const"
37
38
  require "steep/ast/signature/gvar"
39
+ require "steep/ast/signature/alias"
38
40
  require "steep/ast/annotation"
39
41
  require "steep/ast/annotation/collection"
40
42
  require "steep/ast/buffer"
data/smoke/alias/a.rb ADDED
@@ -0,0 +1,19 @@
1
+ # @type var x: foo
2
+ x = ""
3
+
4
+ # !expects NoMethodError: type=foo, method=+
5
+ x + 123
6
+
7
+ # @type var y: bar<Integer>
8
+ y = x
9
+ y = []
10
+
11
+ # @type var z: Symbol
12
+ case x
13
+ when String
14
+ # !expects IncompatibleAssignment: lhs_type=::Symbol, rhs_type=::String
15
+ z = x
16
+ when Integer
17
+ # !expects IncompatibleAssignment: lhs_type=::Symbol, rhs_type=::Integer
18
+ z = x
19
+ end
data/smoke/alias/a.rbi ADDED
@@ -0,0 +1,10 @@
1
+ type foo = String | Integer
2
+ type bar<'a> = Array<'a> | foo
3
+ type baz = [String, Symbol]
4
+
5
+ type name = :foo | :bar
6
+
7
+ class AliasMethodArg
8
+ def foo: (name) -> Integer
9
+ | (Symbol) -> String
10
+ end
data/smoke/alias/b.rb ADDED
@@ -0,0 +1,7 @@
1
+ # @type var a: baz
2
+
3
+ a = ["", :foo]
4
+
5
+ # @type var x: Integer
6
+ # !expects IncompatibleAssignment: lhs_type=::Integer, rhs_type=String
7
+ x = a[0]
data/smoke/alias/c.rb ADDED
@@ -0,0 +1,10 @@
1
+ # @type var x: String
2
+
3
+ # !expects IncompatibleAssignment: lhs_type=::String, rhs_type=::Integer
4
+ x = AliasMethodArg.new.foo(:foo)
5
+
6
+ # @type var name: name
7
+ name = :bar
8
+
9
+ # !expects IncompatibleAssignment: lhs_type=::String, rhs_type=::Integer
10
+ x = AliasMethodArg.new.foo(name)
data/smoke/array/c.rb ADDED
@@ -0,0 +1,7 @@
1
+ # @type var x: Array<String?>
2
+
3
+ x = ["foo"]
4
+ x = [nil]
5
+
6
+ # !expects IncompatibleAssignment: lhs_type=::Array<(::String | nil)>, rhs_type=::Array<::Integer>
7
+ x = [1]
data/smoke/block/c.rb ADDED
@@ -0,0 +1,10 @@
1
+ class OptionalBlock
2
+ def optional_block
3
+ yield
4
+ 30
5
+ end
6
+ end
7
+
8
+ OptionalBlock.new.optional_block()
9
+ OptionalBlock.new.optional_block() { :foo }
10
+
data/smoke/block/c.rbi ADDED
@@ -0,0 +1,3 @@
1
+ class OptionalBlock
2
+ def optional_block: ?{ () -> void } -> Integer
3
+ end
data/smoke/block/d.rb ADDED
@@ -0,0 +1,15 @@
1
+ # @type var a: ^(Integer) -> String
2
+ a = -> (x) { x.to_s }
3
+
4
+ # @type var b: Array<Float>
5
+
6
+ # !expects IncompatibleAssignment: lhs_type=::Array<::Float>, rhs_type=::Array<::String>
7
+ b = [1,2,3].map(&a)
8
+
9
+ # !expects IncompatibleAssignment: lhs_type=::Array<::Float>, rhs_type=::Array<::String>
10
+ b = [1,2,3].map(&:to_s)
11
+
12
+ # !expects* BlockTypeMismatch:
13
+ [1,2,3].map(&:no_such_method)
14
+ # !expects* BlockTypeMismatch:
15
+ [1,2,3].map(&:floor)
data/smoke/class/c.rb CHANGED
@@ -1,4 +1,4 @@
1
- # !expects UnexpectedDynamicMethod: module=B, method=type
1
+ # !expects UnexpectedDynamicMethod: module=::B, method=type
2
2
  class B
3
3
  # @implements B
4
4
 
data/smoke/class/e.rb CHANGED
@@ -6,7 +6,7 @@ class C
6
6
  end
7
7
 
8
8
  def bar
9
- # !expects NoMethodError: type=C.class noconstructor, method=new
9
+ # !expects NoMethodError: type=::C.class noconstructor, method=new
10
10
  self.class.new
11
11
  end
12
12
  end
data/smoke/class/h.rb ADDED
@@ -0,0 +1,15 @@
1
+ class WithSingletonConstructor
2
+ # @dynamic foo
3
+ attr_reader :foo
4
+
5
+ def initialize(foo:)
6
+ @foo = foo
7
+ end
8
+
9
+ def self.create()
10
+ new(foo: "hoge")
11
+ end
12
+
13
+ new(foo: "hoge")
14
+ create()
15
+ end
data/smoke/class/h.rbi ADDED
@@ -0,0 +1,7 @@
1
+ class WithSingletonConstructor
2
+ attr_reader foo: String
3
+
4
+ def initialize: (foo: String) -> any
5
+ def self.create: -> instance
6
+ end
7
+
data/smoke/class/i.rb ADDED
@@ -0,0 +1,17 @@
1
+ class IncompatibleChild
2
+ def foo(arg)
3
+ # @type var x: Symbol
4
+ # !expects IncompatibleAssignment: lhs_type=::Symbol, rhs_type=::Integer
5
+ x = super()
6
+
7
+ "123"
8
+ end
9
+
10
+ def initialize()
11
+ # !expects IncompatibleArguments: receiver=::IncompatibleChild, method_type=(name: ::String) -> any
12
+ super()
13
+
14
+ # !expects IncompatibleZuper: method=initialize
15
+ super
16
+ end
17
+ end
data/smoke/class/i.rbi ADDED
@@ -0,0 +1,9 @@
1
+ class IncompatibleSuper
2
+ def foo: () -> Integer
3
+ def initialize: (name: String) -> any
4
+ end
5
+
6
+ class IncompatibleChild <: IncompatibleSuper
7
+ def initialize: () -> any
8
+ def (incompatible) foo: (Object) -> String
9
+ end
@@ -3,6 +3,10 @@ extension Object (X)
3
3
  def f: -> Object
4
4
  end
5
5
 
6
+ extension Kernel (X)
7
+ def self.new_module_method: () -> void
8
+ end
9
+
6
10
  class Foo
7
11
  def f: -> String
8
12
  end
@@ -0,0 +1,2 @@
1
+ Foo.new_module_method()
2
+ Object.new_module_method()
data/smoke/hash/a.rb ADDED
@@ -0,0 +1,17 @@
1
+ { foo: "bar" }.each do |x, y|
2
+ # @type var x1: Symbol
3
+ # @type var y1: String
4
+
5
+ x1 = x
6
+ y1 = y
7
+ end
8
+
9
+ { foo: "bar" }.each.with_index do |x, y|
10
+ # @type var a: Symbol
11
+ # @type var b: String
12
+ # @type var c: Integer
13
+
14
+ a = x[0]
15
+ b = x[1]
16
+ c = y
17
+ end
data/smoke/hash/b.rb ADDED
@@ -0,0 +1,7 @@
1
+ # @type var x: Hash<Symbol, String?>
2
+
3
+ x = { foo: "foo" }
4
+ x = { foo: nil }
5
+
6
+ # !expects IncompatibleAssignment: lhs_type=::Hash<::Symbol, (::String | nil)>, rhs_type=::Hash<::Symbol, ::Integer>
7
+ x = { foo: 3 }
@@ -1,5 +1,5 @@
1
- # !expects@+2 MethodDefinitionMissing: module=A, method=baz
2
- # !expects MethodDefinitionMissing: module=A, method=self.bar
1
+ # !expects@+2 MethodDefinitionMissing: module=::A, method=baz
2
+ # !expects MethodDefinitionMissing: module=::A, method=self.bar
3
3
  class A
4
4
  # @implements A
5
5
 
@@ -6,7 +6,7 @@ class A
6
6
  end
7
7
 
8
8
  def foo()
9
- # !expects NoMethodError: type=A, method=initialize
9
+ # !expects NoMethodError: type=::A, method=initialize
10
10
  initialize()
11
11
  end
12
12
  end
data/smoke/lambda/a.rb ADDED
@@ -0,0 +1,11 @@
1
+ # @type var a: Integer
2
+
3
+ # !expects IncompatibleAssignment: lhs_type=::Integer, rhs_type=::String
4
+ a = -> (x, y) do
5
+ # @type var x: String
6
+ # @type var y: String
7
+ x + y
8
+ end["foo", "bar"]
9
+
10
+ # !expects NoMethodError: type=::Object, method=lambda
11
+ b = lambda {|x| x + 1 }