steep 0.1.0.pre2 → 0.1.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 (119) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +1 -1
  3. data/README.md +146 -33
  4. data/bin/smoke_runner.rb +43 -10
  5. data/lib/steep/ast/annotation/collection.rb +93 -0
  6. data/lib/steep/ast/annotation.rb +131 -0
  7. data/lib/steep/ast/buffer.rb +47 -0
  8. data/lib/steep/ast/location.rb +82 -0
  9. data/lib/steep/ast/method_type.rb +116 -0
  10. data/lib/steep/ast/signature/class.rb +33 -0
  11. data/lib/steep/ast/signature/const.rb +17 -0
  12. data/lib/steep/ast/signature/env.rb +123 -0
  13. data/lib/steep/ast/signature/extension.rb +21 -0
  14. data/lib/steep/ast/signature/gvar.rb +17 -0
  15. data/lib/steep/ast/signature/interface.rb +31 -0
  16. data/lib/steep/ast/signature/members.rb +71 -0
  17. data/lib/steep/ast/signature/module.rb +21 -0
  18. data/lib/steep/ast/type_params.rb +13 -0
  19. data/lib/steep/ast/types/any.rb +39 -0
  20. data/lib/steep/ast/types/bot.rb +39 -0
  21. data/lib/steep/ast/types/class.rb +35 -0
  22. data/lib/steep/ast/types/helper.rb +21 -0
  23. data/lib/steep/ast/types/instance.rb +39 -0
  24. data/lib/steep/ast/types/intersection.rb +74 -0
  25. data/lib/steep/ast/types/name.rb +124 -0
  26. data/lib/steep/ast/types/self.rb +39 -0
  27. data/lib/steep/ast/types/top.rb +39 -0
  28. data/lib/steep/ast/types/union.rb +74 -0
  29. data/lib/steep/ast/types/var.rb +57 -0
  30. data/lib/steep/ast/types/void.rb +35 -0
  31. data/lib/steep/cli.rb +28 -1
  32. data/lib/steep/drivers/annotations.rb +32 -0
  33. data/lib/steep/drivers/check.rb +53 -77
  34. data/lib/steep/drivers/scaffold.rb +303 -0
  35. data/lib/steep/drivers/utils/each_signature.rb +66 -0
  36. data/lib/steep/drivers/utils/validator.rb +115 -0
  37. data/lib/steep/drivers/validate.rb +39 -0
  38. data/lib/steep/errors.rb +291 -19
  39. data/lib/steep/interface/abstract.rb +44 -0
  40. data/lib/steep/interface/builder.rb +470 -0
  41. data/lib/steep/interface/instantiated.rb +126 -0
  42. data/lib/steep/interface/ivar_chain.rb +26 -0
  43. data/lib/steep/interface/method.rb +60 -0
  44. data/lib/steep/{interface.rb → interface/method_type.rb} +111 -100
  45. data/lib/steep/interface/substitution.rb +65 -0
  46. data/lib/steep/module_name.rb +116 -0
  47. data/lib/steep/parser.rb +1314 -814
  48. data/lib/steep/parser.y +536 -175
  49. data/lib/steep/source.rb +220 -25
  50. data/lib/steep/subtyping/check.rb +673 -0
  51. data/lib/steep/subtyping/constraints.rb +275 -0
  52. data/lib/steep/subtyping/relation.rb +41 -0
  53. data/lib/steep/subtyping/result.rb +126 -0
  54. data/lib/steep/subtyping/trace.rb +48 -0
  55. data/lib/steep/subtyping/variable_occurrence.rb +49 -0
  56. data/lib/steep/subtyping/variable_variance.rb +69 -0
  57. data/lib/steep/type_construction.rb +1630 -524
  58. data/lib/steep/type_inference/block_params.rb +100 -0
  59. data/lib/steep/type_inference/constant_env.rb +55 -0
  60. data/lib/steep/type_inference/send_args.rb +222 -0
  61. data/lib/steep/type_inference/type_env.rb +226 -0
  62. data/lib/steep/type_name.rb +27 -7
  63. data/lib/steep/typing.rb +4 -0
  64. data/lib/steep/version.rb +1 -1
  65. data/lib/steep.rb +71 -16
  66. data/smoke/and/a.rb +4 -2
  67. data/smoke/array/a.rb +4 -5
  68. data/smoke/array/b.rb +4 -4
  69. data/smoke/block/a.rb +2 -2
  70. data/smoke/block/a.rbi +2 -0
  71. data/smoke/block/b.rb +15 -0
  72. data/smoke/case/a.rb +3 -3
  73. data/smoke/class/a.rb +3 -3
  74. data/smoke/class/b.rb +0 -2
  75. data/smoke/class/d.rb +2 -2
  76. data/smoke/class/e.rb +1 -1
  77. data/smoke/class/f.rb +2 -2
  78. data/smoke/class/g.rb +8 -0
  79. data/smoke/const/a.rb +3 -3
  80. data/smoke/dstr/a.rb +1 -1
  81. data/smoke/ensure/a.rb +22 -0
  82. data/smoke/enumerator/a.rb +6 -6
  83. data/smoke/enumerator/b.rb +22 -0
  84. data/smoke/extension/a.rb +2 -2
  85. data/smoke/extension/b.rb +3 -3
  86. data/smoke/extension/c.rb +1 -1
  87. data/smoke/hello/hello.rb +2 -2
  88. data/smoke/if/a.rb +4 -2
  89. data/smoke/kwbegin/a.rb +8 -0
  90. data/smoke/literal/a.rb +5 -5
  91. data/smoke/method/a.rb +5 -5
  92. data/smoke/method/a.rbi +4 -0
  93. data/smoke/method/b.rb +29 -0
  94. data/smoke/module/a.rb +3 -3
  95. data/smoke/module/a.rbi +9 -0
  96. data/smoke/module/b.rb +2 -2
  97. data/smoke/module/c.rb +1 -1
  98. data/smoke/module/d.rb +5 -0
  99. data/smoke/module/e.rb +13 -0
  100. data/smoke/module/f.rb +13 -0
  101. data/smoke/rescue/a.rb +62 -0
  102. data/smoke/super/a.rb +2 -2
  103. data/smoke/type_case/a.rb +35 -0
  104. data/smoke/yield/a.rb +2 -2
  105. data/stdlib/builtin.rbi +463 -24
  106. data/steep.gemspec +3 -2
  107. metadata +91 -29
  108. data/lib/steep/annotation.rb +0 -223
  109. data/lib/steep/signature/class.rb +0 -450
  110. data/lib/steep/signature/extension.rb +0 -51
  111. data/lib/steep/signature/interface.rb +0 -49
  112. data/lib/steep/types/any.rb +0 -31
  113. data/lib/steep/types/class.rb +0 -27
  114. data/lib/steep/types/instance.rb +0 -27
  115. data/lib/steep/types/merge.rb +0 -32
  116. data/lib/steep/types/name.rb +0 -57
  117. data/lib/steep/types/union.rb +0 -42
  118. data/lib/steep/types/var.rb +0 -38
  119. data/lib/steep/types.rb +0 -4
@@ -0,0 +1,470 @@
1
+ module Steep
2
+ module Interface
3
+ class Builder
4
+ class RecursiveDefinitionError < StandardError
5
+ attr_reader :chain
6
+
7
+ def initialize(type_name)
8
+ @chain = [type_name].compact
9
+ super "Recursive inheritance/mixin"
10
+ end
11
+
12
+ def to_s
13
+ super + " #{chain.join(" ~> ")}"
14
+ end
15
+ end
16
+
17
+ attr_reader :signatures
18
+ attr_reader :cache
19
+
20
+ def initialize(signatures:)
21
+ @cache = {}
22
+ @signatures = signatures
23
+ end
24
+
25
+ def absolute_type_name(type_name, current:)
26
+ if current
27
+ begin
28
+ case type_name
29
+ when TypeName::Instance
30
+ type_name.map_module_name {|name|
31
+ signatures.find_class_or_module(name, current_module: current).name
32
+ }
33
+ when TypeName::Module
34
+ type_name.map_module_name {|name|
35
+ signatures.find_module(name, current_module: current).name
36
+ }
37
+ when TypeName::Class
38
+ type_name.map_module_name {|name|
39
+ signatures.find_class(name, current_module: current).name
40
+ }
41
+ else
42
+ type_name
43
+ end
44
+ rescue => exn
45
+ STDERR.puts "Cannot find absolute type name: #{exn.inspect}"
46
+ type_name
47
+ end
48
+ else
49
+ type_name.map_module_name(&:absolute!)
50
+ end
51
+ end
52
+
53
+ def absolute_type(type, current:)
54
+ case type
55
+ when AST::Types::Name
56
+ AST::Types::Name.new(
57
+ name: absolute_type_name(type.name, current: current),
58
+ args: type.args.map {|ty| absolute_type(ty, current: current) },
59
+ location: type.location
60
+ )
61
+ when AST::Types::Union
62
+ AST::Types::Union.build(
63
+ types: type.types.map {|ty| absolute_type(ty, current: current) },
64
+ location: type.location
65
+ )
66
+ when AST::Types::Intersection
67
+ AST::Types::Intersection.build(
68
+ types: type.types.map {|ty| absolute_type(ty, current: current) },
69
+ location: type.location
70
+ )
71
+ else
72
+ type
73
+ end
74
+ end
75
+
76
+ def build(type_name, current: nil, with_initialize: false)
77
+ type_name = absolute_type_name(type_name, current: current)
78
+ cache_key = [type_name, with_initialize]
79
+ cached = cache[cache_key]
80
+
81
+ case cached
82
+ when nil
83
+ begin
84
+ cache[cache_key] = type_name
85
+
86
+ interface = case type_name
87
+ when TypeName::Instance
88
+ instance_to_interface(signatures.find_class_or_module(type_name.name), with_initialize: with_initialize)
89
+ when TypeName::Module
90
+ module_to_interface(signatures.find_module(type_name.name))
91
+ when TypeName::Class
92
+ class_to_interface(signatures.find_class_or_module(type_name.name),
93
+ constructor: type_name.constructor)
94
+ when TypeName::Interface
95
+ interface_to_interface(type_name.name,
96
+ signatures.find_interface(type_name.name))
97
+ else
98
+ raise "Unexpected type_name: #{type_name.inspect}"
99
+ end
100
+
101
+ cache[cache_key]= interface
102
+ rescue RecursiveDefinitionError => exn
103
+ exn.chain.unshift(type_name)
104
+ raise
105
+ end
106
+ when TypeName::Base
107
+ raise RecursiveDefinitionError, type_name
108
+ else
109
+ cached
110
+ end
111
+ end
112
+
113
+ def merge_mixin(type_name, args, methods:, ivars:, supers:, current:)
114
+ mixed = block_given? ? yield : build(type_name, current: current)
115
+
116
+ supers.push(*mixed.supers)
117
+ instantiated = mixed.instantiate(
118
+ type: AST::Types::Self.new,
119
+ args: args,
120
+ instance_type: AST::Types::Instance.new,
121
+ module_type: AST::Types::Class.new
122
+ )
123
+
124
+ methods.merge!(instantiated.methods) do |_, super_method, new_method|
125
+ if super_method.include_in_chain?(new_method)
126
+ super_method
127
+ else
128
+ new_method.with_super(super_method)
129
+ end
130
+ end
131
+
132
+ merge_ivars ivars, instantiated.ivars
133
+ end
134
+
135
+ def add_method(type_name, method, methods:)
136
+ super_method = methods[method.name]
137
+ new_method = Method.new(
138
+ type_name: type_name,
139
+ name: method.name,
140
+ types: method.types.map do |method_type|
141
+ method_type_to_method_type(method_type, current: type_name.name)
142
+ end,
143
+ super_method: super_method,
144
+ attributes: method.attributes
145
+ )
146
+
147
+ methods[method.name] = if super_method&.include_in_chain?(new_method)
148
+ super_method
149
+ else
150
+ new_method
151
+ end
152
+ end
153
+
154
+ def class_to_interface(sig, constructor:)
155
+ type_name = TypeName::Class.new(name: sig.name, constructor: constructor)
156
+
157
+ supers = []
158
+ methods = {
159
+ new: Method.new(
160
+ type_name: TypeName::Class.new(name: "Builtin", constructor: true),
161
+ name: :new,
162
+ types: [
163
+ MethodType.new(type_params: [],
164
+ params: Params.empty,
165
+ block: nil,
166
+ return_type: AST::Types::Instance.new,
167
+ location: nil
168
+ )
169
+ ],
170
+ super_method: nil,
171
+ attributes: []
172
+ )
173
+ }
174
+
175
+ klass = build(TypeName::Instance.new(name: ModuleName.parse("::Class")))
176
+ instantiated = klass.instantiate(
177
+ type: AST::Types::Self.new,
178
+ args: [AST::Types::Instance.new],
179
+ instance_type: AST::Types::Instance.new,
180
+ module_type: AST::Types::Class.new
181
+ )
182
+ methods.merge!(instantiated.methods)
183
+
184
+ unless sig.name == ModuleName.parse("::BasicObject")
185
+ super_class_name = sig.super_class&.name&.absolute! || ModuleName.parse("::Object")
186
+ merge_mixin(TypeName::Class.new(name: super_class_name, constructor: constructor),
187
+ [],
188
+ methods: methods,
189
+ ivars: {},
190
+ supers: supers,
191
+ current: sig.name)
192
+ end
193
+
194
+ sig.members.each do |member|
195
+ case member
196
+ when AST::Signature::Members::Include
197
+ merge_mixin(TypeName::Module.new(name: member.name),
198
+ [],
199
+ methods: methods,
200
+ supers: supers,
201
+ ivars: {},
202
+ current: sig.name)
203
+ when AST::Signature::Members::Extend
204
+ merge_mixin(TypeName::Instance.new(name: member.name),
205
+ member.args.map {|type| absolute_type(type, current: sig.name) },
206
+ methods: methods,
207
+ ivars: {},
208
+ supers: supers,
209
+ current: sig.name)
210
+ end
211
+ end
212
+
213
+ sig.members.each do |member|
214
+ case member
215
+ when AST::Signature::Members::Method
216
+ case
217
+ when member.module_method?
218
+ add_method(type_name, member, methods: methods)
219
+ when member.instance_method? && member.name == :initialize
220
+ if constructor
221
+ methods[:new] = Method.new(
222
+ type_name: type_name,
223
+ name: :new,
224
+ types: member.types.map do |method_type_sig|
225
+ method_type = method_type_to_method_type(method_type_sig, current: sig.name).with(return_type: AST::Types::Instance.new)
226
+ args = (sig.params&.variables || []) + method_type.type_params
227
+
228
+ method_type.with(
229
+ type_params: args,
230
+ return_type: AST::Types::Instance.new
231
+ )
232
+ end,
233
+ super_method: nil,
234
+ attributes: []
235
+ )
236
+ end
237
+ end
238
+ end
239
+ end
240
+
241
+ unless constructor
242
+ methods.delete(:new)
243
+ end
244
+
245
+ Abstract.new(
246
+ name: type_name,
247
+ params: [],
248
+ methods: methods,
249
+ supers: supers,
250
+ ivar_chains: {}
251
+ )
252
+ end
253
+
254
+ def module_to_interface(sig)
255
+ type_name = TypeName::Module.new(name: sig.name)
256
+
257
+ supers = [sig.self_type].compact.map {|type| absolute_type(type, current: nil) }
258
+ methods = {}
259
+
260
+ module_instance = build(TypeName::Instance.new(name: ModuleName.parse("::Module")))
261
+ instantiated = module_instance.instantiate(
262
+ type: AST::Types::Self.new,
263
+ args: [],
264
+ instance_type: AST::Types::Instance.new,
265
+ module_type: AST::Types::Class.new
266
+ )
267
+ methods.merge!(instantiated.methods)
268
+
269
+ sig.members.each do |member|
270
+ case member
271
+ when AST::Signature::Members::Include
272
+ merge_mixin(TypeName::Module.new(name: member.name),
273
+ member.args.map {|type| absolute_type(type, current: sig.name) },
274
+ methods: methods,
275
+ ivars: {},
276
+ supers: supers,
277
+ current: sig.name)
278
+ when AST::Signature::Members::Extend
279
+ merge_mixin(TypeName::Instance.new(name: member.name),
280
+ member.args.map {|type| absolute_type(type, current: sig.name) },
281
+ methods: methods,
282
+ ivars: {},
283
+ supers: supers,
284
+ current: sig.name)
285
+ end
286
+ end
287
+
288
+ sig.members.each do |member|
289
+ case member
290
+ when AST::Signature::Members::Method
291
+ if member.module_method?
292
+ add_method(type_name, member, methods: methods)
293
+ end
294
+ end
295
+ end
296
+
297
+ Abstract.new(
298
+ name: type_name,
299
+ params: [],
300
+ methods: methods,
301
+ supers: supers,
302
+ ivar_chains: {}
303
+ )
304
+ end
305
+
306
+ def instance_to_interface(sig, with_initialize:)
307
+ type_name = TypeName::Instance.new(name: sig.name)
308
+
309
+ params = sig.params&.variables || []
310
+ supers = []
311
+ methods = {}
312
+ ivar_chains = {}
313
+
314
+ if sig.is_a?(AST::Signature::Class)
315
+ unless sig.name == ModuleName.parse("::BasicObject")
316
+ super_class_name = sig.super_class&.name || ModuleName.parse("::Object")
317
+ super_class_interface = build(TypeName::Instance.new(name: super_class_name), current: nil)
318
+
319
+ supers.push(*super_class_interface.supers)
320
+ instantiated = super_class_interface.instantiate(
321
+ type: AST::Types::Self.new,
322
+ args: (sig.super_class&.args || []).map {|type| absolute_type(type, current: nil) },
323
+ instance_type: AST::Types::Instance.new,
324
+ module_type: AST::Types::Class.new
325
+ )
326
+
327
+ methods.merge!(instantiated.methods)
328
+ merge_ivars(ivar_chains, instantiated.ivars)
329
+ end
330
+ end
331
+
332
+ if sig.is_a?(AST::Signature::Module)
333
+ if sig.self_type
334
+ supers << sig.self_type
335
+ end
336
+ end
337
+
338
+ sig.members.each do |member|
339
+ case member
340
+ when AST::Signature::Members::Include
341
+ merge_mixin(TypeName::Instance.new(name: member.name),
342
+ member.args.map {|type| absolute_type(type, current: sig.name) },
343
+ methods: methods,
344
+ ivars: ivar_chains,
345
+ supers: supers,
346
+ current: sig.name)
347
+ end
348
+ end
349
+
350
+ sig.members.each do |member|
351
+ case member
352
+ when AST::Signature::Members::Method
353
+ if member.instance_method?
354
+ if with_initialize || member.name != :initialize
355
+ add_method(type_name, member, methods: methods)
356
+ end
357
+ end
358
+ when AST::Signature::Members::Ivar
359
+ merge_ivars(ivar_chains,
360
+ { member.name => absolute_type(member.type, current: sig.name) })
361
+ end
362
+ end
363
+
364
+ signatures.find_extensions(sig.name).each do |ext|
365
+ ext.members.each do |member|
366
+ case member
367
+ when AST::Signature::Members::Method
368
+ if member.instance_method?
369
+ add_method(type_name, member, methods: methods)
370
+ end
371
+ end
372
+ end
373
+ end
374
+
375
+ Abstract.new(
376
+ name: type_name,
377
+ params: params,
378
+ methods: methods,
379
+ supers: supers,
380
+ ivar_chains: ivar_chains
381
+ )
382
+ end
383
+
384
+ def merge_ivars(dest, new_vars)
385
+ new_vars.each do |name, new_type|
386
+ dest[name] = IvarChain.new(type: new_type, parent: dest[name])
387
+ end
388
+ end
389
+
390
+ def interface_to_interface(_, sig)
391
+ type_name = TypeName::Interface.new(name: sig.name)
392
+
393
+ variables = sig.params&.variables || []
394
+ methods = sig.methods.each.with_object({}) do |method, methods|
395
+ methods[method.name] = Method.new(
396
+ type_name: type_name,
397
+ name: method.name,
398
+ types: method.types.map do |method_type|
399
+ method_type_to_method_type(method_type, current: nil)
400
+ end,
401
+ super_method: nil,
402
+ attributes: []
403
+ )
404
+ end
405
+
406
+ Abstract.new(
407
+ name: type_name,
408
+ params: variables,
409
+ methods: methods,
410
+ supers: [],
411
+ ivar_chains: {}
412
+ )
413
+ end
414
+
415
+ def method_type_to_method_type(method_type, current:)
416
+ type_params = method_type.type_params&.variables || []
417
+ params = params_to_params(method_type.params, current: current)
418
+ block = method_type.block && Block.new(
419
+ params: params_to_params(method_type.block.params, current: current),
420
+ return_type: absolute_type(method_type.block.return_type, current: current)
421
+ )
422
+
423
+ MethodType.new(
424
+ type_params: type_params,
425
+ return_type: absolute_type(method_type.return_type, current: current),
426
+ block: block,
427
+ params: params,
428
+ location: method_type.location
429
+ )
430
+ end
431
+
432
+ def params_to_params(params, current:)
433
+ required = []
434
+ optional = []
435
+ rest = nil
436
+ required_keywords = {}
437
+ optional_keywords = {}
438
+ rest_keywords = nil
439
+
440
+ while params
441
+ case params
442
+ when AST::MethodType::Params::Required
443
+ required << absolute_type(params.type, current: current)
444
+ when AST::MethodType::Params::Optional
445
+ optional << absolute_type(params.type, current: current)
446
+ when AST::MethodType::Params::Rest
447
+ rest = absolute_type(params.type, current: current)
448
+ when AST::MethodType::Params::RequiredKeyword
449
+ required_keywords[params.name] = absolute_type(params.type, current: current)
450
+ when AST::MethodType::Params::OptionalKeyword
451
+ optional_keywords[params.name] = absolute_type(params.type, current: current)
452
+ when AST::MethodType::Params::RestKeyword
453
+ rest_keywords = absolute_type(params.type, current: current)
454
+ break
455
+ end
456
+ params = params.next_params
457
+ end
458
+
459
+ Params.new(
460
+ required: required,
461
+ optional: optional,
462
+ rest: rest,
463
+ required_keywords: required_keywords,
464
+ optional_keywords: optional_keywords,
465
+ rest_keywords: rest_keywords
466
+ )
467
+ end
468
+ end
469
+ end
470
+ end
@@ -0,0 +1,126 @@
1
+ module Steep
2
+ module Interface
3
+ class Instantiated
4
+ attr_reader :type
5
+ attr_reader :methods
6
+ attr_reader :ivar_chains
7
+
8
+ def initialize(type:, methods:, ivar_chains:)
9
+ @type = type
10
+ @methods = methods
11
+ @ivar_chains = ivar_chains
12
+ end
13
+
14
+ def ivars
15
+ @ivars ||= ivar_chains.transform_values(&:type)
16
+ end
17
+
18
+ def ==(other)
19
+ other.is_a?(self.class) && other.type == type && other.params == params && other.methods == methods && other.ivars == ivars
20
+ end
21
+
22
+ class InvalidMethodOverrideError < StandardError
23
+ attr_reader :type
24
+ attr_reader :current_method
25
+ attr_reader :super_method
26
+ attr_reader :result
27
+
28
+ def initialize(type:, current_method:, super_method:, result:)
29
+ @type = type
30
+ @current_method = current_method
31
+ @super_method = super_method
32
+ @result = result
33
+
34
+ super "Invalid override of `#{current_method.name}` in #{type}: definition in #{current_method.type_name} is not compatible with its super (#{super_method.type_name})"
35
+ end
36
+ end
37
+
38
+ class InvalidIvarOverrideError < StandardError
39
+ attr_reader :type
40
+ attr_reader :ivar_name
41
+ attr_reader :current_ivar_type
42
+ attr_reader :super_ivar_type
43
+
44
+ def initialize(type:, ivar_name:, current_ivar_type:, super_ivar_type:)
45
+ @type = type
46
+ @ivar_name = ivar_name
47
+ @current_ivar_type = current_ivar_type
48
+ @super_ivar_type = super_ivar_type
49
+
50
+ super "Invalid override of `#{ivar_name}` in #{type}: #{current_ivar_type} is not compatible with #{super_ivar_type}"
51
+ end
52
+ end
53
+
54
+ def validate(check)
55
+ methods.each do |_, method|
56
+ validate_method(check, method)
57
+ end
58
+
59
+ ivar_chains.each do |name, chain|
60
+ validate_chain(check, name, chain)
61
+ end
62
+ end
63
+
64
+ def validate_chain(check, name, chain)
65
+ return unless chain.parent
66
+
67
+ this_type = chain.type
68
+ super_type = chain.parent.type
69
+
70
+ case
71
+ when this_type.is_a?(AST::Types::Any) && super_type.is_a?(AST::Types::Any)
72
+ # ok
73
+ else
74
+ relation = Subtyping::Relation.new(sub_type: this_type, super_type: super_type)
75
+
76
+ result1 = check.check(relation, constraints: Subtyping::Constraints.empty)
77
+ result2 = check.check(relation.flip, constraints: Subtyping::Constraints.empty)
78
+
79
+ if result1.failure? || result2.failure? || this_type.is_a?(AST::Types::Any) || super_type.is_a?(AST::Types::Any)
80
+ raise InvalidIvarOverrideError.new(type: self.type, ivar_name: name, current_ivar_type: this_type, super_ivar_type: super_type)
81
+ end
82
+ end
83
+
84
+ validate_chain(check, name, chain.parent)
85
+ end
86
+
87
+ def validate_method(check, method)
88
+ if method.super_method
89
+ result = check.check_method(method.name,
90
+ method,
91
+ method.super_method,
92
+ assumption: Set.new,
93
+ trace: Subtyping::Trace.new,
94
+ constraints: Subtyping::Constraints.empty)
95
+
96
+ if result.success?
97
+ validate_method(check, method.super_method)
98
+ else
99
+ raise InvalidMethodOverrideError.new(type: type,
100
+ current_method: method,
101
+ super_method: method.super_method,
102
+ result: result)
103
+ end
104
+ end
105
+ end
106
+
107
+ def select_method_type(&block)
108
+ self.class.new(
109
+ type: type,
110
+ methods: methods.each.with_object({}) do |(name, method), methods|
111
+ methods[name] = Method.new(
112
+ type_name: method.type_name,
113
+ name: method.name,
114
+ types: method.types.select(&block),
115
+ super_method: method.super_method,
116
+ attributes: method.attributes,
117
+ )
118
+ end.reject do |_, method|
119
+ method.types.empty?
120
+ end,
121
+ ivar_chains: ivar_chains
122
+ )
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,26 @@
1
+ module Steep
2
+ module Interface
3
+ class IvarChain
4
+ attr_reader :type
5
+ attr_reader :parent
6
+
7
+ def initialize(type:, parent: nil)
8
+ @type = type
9
+ @parent = parent
10
+ end
11
+
12
+ def ==(other)
13
+ other.is_a?(IvarChain) &&
14
+ type == type &&
15
+ parent == parent
16
+ end
17
+
18
+ def subst(s)
19
+ self.class.new(
20
+ type: type.subst(s),
21
+ parent: parent&.subst(s)
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,60 @@
1
+ module Steep
2
+ module Interface
3
+ class Method
4
+ attr_reader :type_name
5
+ attr_reader :name
6
+ attr_reader :super_method
7
+ attr_reader :types
8
+ attr_reader :attributes
9
+
10
+ def initialize(type_name:, name:, types:, super_method:, attributes:)
11
+ @type_name = type_name
12
+ @name = name
13
+ @types = types
14
+ @super_method = super_method
15
+ @attributes = attributes
16
+ end
17
+
18
+ def ==(other)
19
+ other.is_a?(Method) &&
20
+ other.type_name == type_name &&
21
+ other.name == name &&
22
+ other.types == types &&
23
+ other.super_method == super_method &&
24
+ other.attributes == attributes
25
+ end
26
+
27
+ def closed?
28
+ types.all?(&:closed?)
29
+ end
30
+
31
+ def subst(s)
32
+ self.class.new(
33
+ type_name: type_name,
34
+ name: name,
35
+ types: types.map {|type| type.subst(s) },
36
+ super_method: super_method&.subst(s),
37
+ attributes: attributes
38
+ )
39
+ end
40
+
41
+ def with_super(super_method)
42
+ self.class.new(
43
+ type_name: type_name,
44
+ name: name,
45
+ types: types,
46
+ super_method: super_method,
47
+ attributes: attributes
48
+ )
49
+ end
50
+
51
+ def include_in_chain?(method)
52
+ (method.type_name == type_name &&
53
+ method.name == name &&
54
+ method.types == types &&
55
+ method.attributes == attributes) ||
56
+ super_method&.include_in_chain?(method)
57
+ end
58
+ end
59
+ end
60
+ end