steep 0.4.0 → 0.5.0

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 (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 }