steep 0.1.0.pre2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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