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
data/lib/steep/errors.rb CHANGED
@@ -8,18 +8,49 @@ module Steep
8
8
  end
9
9
 
10
10
  def location_to_str
11
- "#{node.loc.expression.source_buffer.name}:#{node.loc.first_line}:#{node.loc.column}"
11
+ Rainbow("#{node.loc.expression.source_buffer.name}:#{node.loc.first_line}:#{node.loc.column}").red
12
+ end
13
+
14
+ def print_to(io)
15
+ source = node.loc.expression.source
16
+ io.puts "#{to_s} (#{Rainbow(source.split(/\n/).first).blue})"
17
+ end
18
+ end
19
+
20
+ module ResultPrinter
21
+ def print_result_to(io, level: 2)
22
+ indent = " " * level
23
+ result.trace.each do |s, t|
24
+ case s
25
+ when Interface::Method
26
+ io.puts "#{indent}#{s.name}(#{s.type_name}) <: #{t.name}(#{t.type_name})"
27
+ when Interface::MethodType
28
+ io.puts "#{indent}#{s} <: #{t} (#{s.location.name}:#{s.location.start_line})"
29
+ else
30
+ io.puts "#{indent}#{s} <: #{t}"
31
+ end
32
+ end
33
+ io.puts "#{indent} #{result.error.message}"
34
+ end
35
+
36
+ def print_to(io)
37
+ super
38
+ print_result_to io
12
39
  end
13
40
  end
14
41
 
15
42
  class IncompatibleAssignment < Base
16
43
  attr_reader :lhs_type
17
44
  attr_reader :rhs_type
45
+ attr_reader :result
46
+
47
+ include ResultPrinter
18
48
 
19
- def initialize(node:, lhs_type:, rhs_type:)
49
+ def initialize(node:, lhs_type:, rhs_type:, result:)
20
50
  super(node: node)
21
51
  @lhs_type = lhs_type
22
52
  @rhs_type = rhs_type
53
+ @result = result
23
54
  end
24
55
 
25
56
  def to_s
@@ -27,18 +58,66 @@ module Steep
27
58
  end
28
59
  end
29
60
 
61
+ class IncompatibleArguments < Base
62
+ attr_reader :node
63
+ attr_reader :receiver_type
64
+ attr_reader :method_type
65
+
66
+ def initialize(node:, receiver_type:, method_type:)
67
+ super(node: node)
68
+ @receiver_type = receiver_type
69
+ @method_type = method_type
70
+ end
71
+
72
+ def to_s
73
+ "#{location_to_str}: IncompatibleArguments: receiver=#{receiver_type}, method_type=#{method_type}"
74
+ end
75
+ end
76
+
30
77
  class ArgumentTypeMismatch < Base
31
- attr_reader :type
32
- attr_reader :method
78
+ attr_reader :node
79
+ attr_reader :expected
80
+ attr_reader :actual
81
+ attr_reader :receiver_type
33
82
 
34
- def initialize(node:, type:, method:)
83
+ def initialize(node:, receiver_type:, expected:, actual:)
35
84
  super(node: node)
36
- @type = type
37
- @method = method
85
+ @receiver_type = receiver_type
86
+ @expected = expected
87
+ @actual = actual
88
+ end
89
+
90
+ def to_s
91
+ "#{location_to_str}: ArgumentTypeMismatch: receiver=#{receiver_type}, expected=#{expected}, actual=#{actual}"
92
+ end
93
+ end
94
+
95
+ class IncompatibleBlockParameters < Base
96
+ attr_reader :node
97
+ attr_reader :method_type
98
+
99
+ def initialize(node:, method_type:)
100
+ super(node: node)
101
+ @method_type = method_type
102
+ end
103
+
104
+ def to_s
105
+ "#{location_to_str}: IncompatibleBlockParameters: method_type=#{method_type}"
106
+ end
107
+ end
108
+
109
+ class BlockParameterTypeMismatch < Base
110
+ attr_reader :expected
111
+ attr_reader :actual
112
+
113
+ def initialize(node:, expected:, actual:)
114
+ super(node: node)
115
+ @expected = expected
116
+ @actual = actual
38
117
  end
39
118
 
40
119
  def to_s
41
- "#{location_to_str}: ArgumentTypeMismatch: type=#{type}, method=#{method}"
120
+ "#{location_to_str}: BlockParameterTypeMismatch: expected=#{expected}, actual=#{actual}"
42
121
  end
43
122
  end
44
123
 
@@ -60,11 +139,15 @@ module Steep
60
139
  class ReturnTypeMismatch < Base
61
140
  attr_reader :expected
62
141
  attr_reader :actual
142
+ attr_reader :result
63
143
 
64
- def initialize(node:, expected:, actual:)
144
+ include ResultPrinter
145
+
146
+ def initialize(node:, expected:, actual:, result:)
65
147
  super(node: node)
66
148
  @expected = expected
67
149
  @actual = actual
150
+ @result = result
68
151
  end
69
152
 
70
153
  def to_s
@@ -73,24 +156,43 @@ module Steep
73
156
  end
74
157
 
75
158
  class UnexpectedBlockGiven < Base
76
- attr_reader :method
77
- attr_reader :type
159
+ attr_reader :method_type
78
160
 
79
- def initialize(node:, type:, method:)
161
+ def initialize(node:, method_type:)
80
162
  super(node: node)
81
- @type = type
82
- @method = method
163
+ @method_type = method_type
164
+ end
165
+
166
+ def to_s
167
+ "#{location_to_str}: UnexpectedBlockGiven: method_type=#{method_type.location&.source}"
168
+ end
169
+ end
170
+
171
+ class RequiredBlockMissing < Base
172
+ attr_reader :method_type
173
+
174
+ def initialize(node:, method_type:)
175
+ super(node: node)
176
+ @method_type = method_type
177
+ end
178
+
179
+ def to_s
180
+ "#{location_to_str}: RequiredBlockMissing: method_type=#{method_type.location&.source}"
83
181
  end
84
182
  end
85
183
 
86
184
  class BlockTypeMismatch < Base
87
185
  attr_reader :expected
88
186
  attr_reader :actual
187
+ attr_reader :result
89
188
 
90
- def initialize(node:, expected:, actual:)
189
+ include ResultPrinter
190
+
191
+ def initialize(node:, expected:, actual:, result:)
91
192
  super(node: node)
92
193
  @expected = expected
93
194
  @actual = actual
195
+ @result = result
94
196
  end
95
197
 
96
198
  def to_s
@@ -101,28 +203,103 @@ module Steep
101
203
  class BreakTypeMismatch < Base
102
204
  attr_reader :expected
103
205
  attr_reader :actual
206
+ attr_reader :result
104
207
 
105
- def initialize(node:, expected:, actual:)
208
+ include ResultPrinter
209
+
210
+ def initialize(node:, expected:, actual:, result:)
106
211
  super(node: node)
107
212
  @expected = expected
108
213
  @actual = actual
214
+ @result = result
215
+ end
216
+
217
+ def to_s
218
+ "#{location_to_str}: BreakTypeMismatch: expected=#{expected}, actual=#{actual}"
219
+ end
220
+ end
221
+
222
+ class UnexpectedJump < Base
223
+ def to_s
224
+ "#{location_to_str}: UnexpectedJump"
225
+ end
226
+ end
227
+
228
+ class UnexpectedJumpValue < Base
229
+ def to_s
230
+ "#{location_to_str}: UnexpectedJumpValue"
109
231
  end
110
232
  end
111
233
 
112
- class MethodParameterTypeMismatch < Base
234
+ class MethodArityMismatch < Base
113
235
  def to_s
114
- "#{location_to_str}: MethodParameterTypeMismatch: method=#{node.children[0]}"
236
+ "#{location_to_str}: MethodArityMismatch: method=#{node.children[0]}"
237
+ end
238
+ end
239
+
240
+ class IncompatibleMethodTypeAnnotation < Base
241
+ attr_reader :interface_method
242
+ attr_reader :annotation_method
243
+ attr_reader :result
244
+
245
+ include ResultPrinter
246
+
247
+ def initialize(node:, interface_method:, annotation_method:, result:)
248
+ super(node: node)
249
+ @interface_method = interface_method
250
+ @annotation_method = annotation_method
251
+ @result = result
252
+ end
253
+
254
+ def to_s
255
+ "#{location_to_str}: IncompatibleMethodTypeAnnotation: interface_method=#{interface_method.type_name}.#{interface_method.name}, annotation_method=#{annotation_method.name}"
256
+ end
257
+ end
258
+
259
+ class MethodDefinitionWithOverloading < Base
260
+ attr_reader :method
261
+
262
+ def initialize(node:, method:)
263
+ super(node: node)
264
+ @method = method
265
+ end
266
+
267
+ def to_s
268
+ "#{location_to_str}: MethodDefinitionWithOverloading: method=#{method.name}, types=#{method.types.join(" | ")}"
269
+ end
270
+ end
271
+
272
+ class MethodReturnTypeAnnotationMismatch < Base
273
+ attr_reader :method_type
274
+ attr_reader :annotation_type
275
+ attr_reader :result
276
+
277
+ include ResultPrinter
278
+
279
+ def initialize(node:, method_type:, annotation_type:, result:)
280
+ super(node: node)
281
+ @method_type = method_type
282
+ @annotation_type = annotation_type
283
+ @result = result
284
+ end
285
+
286
+ def to_s
287
+ "#{location_to_str}: MethodReturnTypeAnnotationMismatch: method_type=#{method_type.return_type}, annotation_type=#{annotation_type}"
115
288
  end
116
289
  end
117
290
 
118
291
  class MethodBodyTypeMismatch < Base
119
292
  attr_reader :expected
120
293
  attr_reader :actual
294
+ attr_reader :result
121
295
 
122
- def initialize(node:, expected:, actual:)
296
+ include ResultPrinter
297
+
298
+ def initialize(node:, expected:, actual:, result:)
123
299
  super(node: node)
124
300
  @expected = expected
125
301
  @actual = actual
302
+ @result = result
126
303
  end
127
304
 
128
305
  def to_s
@@ -194,6 +371,19 @@ module Steep
194
371
  end
195
372
  end
196
373
 
374
+ class UnknownConstantAssigned < Base
375
+ attr_reader :type
376
+
377
+ def initialize(node:, type:)
378
+ super(node: node)
379
+ @type = type
380
+ end
381
+
382
+ def to_s
383
+ "#{location_to_str}: UnknownConstantAssigned: type=#{type}"
384
+ end
385
+ end
386
+
197
387
  class FallbackAny < Base
198
388
  def initialize(node:)
199
389
  @node = node
@@ -203,5 +393,87 @@ module Steep
203
393
  "#{location_to_str}: FallbackAny"
204
394
  end
205
395
  end
396
+
397
+ class UnsatisfiableConstraint < Base
398
+ attr_reader :method_type
399
+ attr_reader :var
400
+ attr_reader :sub_type
401
+ attr_reader :super_type
402
+ attr_reader :result
403
+
404
+ def initialize(node:, method_type:, var:, sub_type:, super_type:, result:)
405
+ super(node: node)
406
+ @method_type = method_type
407
+ @var = var
408
+ @sub_type = sub_type
409
+ @super_type = super_type
410
+ @result = result
411
+ end
412
+
413
+ include ResultPrinter
414
+
415
+ def to_s
416
+ "#{location_to_str}: UnsatisfiableConstraint: method_type=#{method_type}, constraint=#{sub_type} <: '#{var} <: #{super_type}"
417
+ end
418
+ end
419
+
420
+ class IncompatibleAnnotation < Base
421
+ attr_reader :var_name
422
+ attr_reader :result
423
+ attr_reader :relation
424
+
425
+ def initialize(node:, var_name:, result:, relation:)
426
+ super(node: node)
427
+ @var_name = var_name
428
+ @result = result
429
+ @relation = relation
430
+ end
431
+
432
+ include ResultPrinter
433
+
434
+ def to_s
435
+ "#{location_to_str}: IncompatibleAnnotation: var_name=#{var_name}, #{relation}"
436
+ end
437
+ end
438
+
439
+ class IncompatibleTypeCase < Base
440
+ attr_reader :var_name
441
+ attr_reader :result
442
+ attr_reader :relation
443
+
444
+ def initialize(node:, var_name:, result:, relation:)
445
+ super(node: node)
446
+ @var_name = var_name
447
+ @result = result
448
+ @relation = relation
449
+ end
450
+
451
+ include ResultPrinter
452
+
453
+ def to_s
454
+ "#{location_to_str}: IncompatibleTypeCase: var_name=#{var_name}, #{relation}"
455
+ end
456
+ end
457
+
458
+ class ElseOnExhaustiveCase < Base
459
+ def initialize(node:, type:)
460
+ def to_s
461
+ "#{location_to_str}: ElseOnExhaustiveCase: type=#{type}"
462
+ end
463
+ end
464
+ end
465
+
466
+ class UnexpectedSplat < Base
467
+ attr_reader :type
468
+
469
+ def initialize(node:, type:)
470
+ super(node: node)
471
+ @type = type
472
+ end
473
+
474
+ def to_s
475
+ "#{location_to_str}: UnexpectedSplat: type=#{type}"
476
+ end
477
+ end
206
478
  end
207
479
  end
@@ -0,0 +1,44 @@
1
+ module Steep
2
+ module Interface
3
+ class Abstract
4
+ attr_reader :name
5
+ attr_reader :kind
6
+ attr_reader :params
7
+ attr_reader :methods
8
+ attr_reader :supers
9
+ attr_reader :ivar_chains
10
+
11
+ def initialize(name:, params:, methods:, supers:, ivar_chains:)
12
+ @name = name
13
+ @params = params
14
+ @methods = methods
15
+ @supers = supers
16
+ @ivar_chains = ivar_chains
17
+ end
18
+
19
+ def ivars
20
+ @ivars ||= ivar_chains.transform_values(&:type)
21
+ end
22
+
23
+ def ==(other)
24
+ other.is_a?(self.class) &&
25
+ other.name == name &&
26
+ other.params == params &&
27
+ other.methods == methods &&
28
+ other.supers == supers &&
29
+ other.ivars == ivars
30
+ end
31
+
32
+ def instantiate(type:, args:, instance_type:, module_type:)
33
+ Steep.logger.debug("type=#{type}, self=#{name}, args=#{args}, params=#{params}")
34
+ subst = Substitution.build(params, args, instance_type: instance_type, module_type: module_type, self_type: type)
35
+
36
+ Instantiated.new(
37
+ type: type,
38
+ methods: methods.transform_values {|method| method.subst(subst) },
39
+ ivar_chains: ivar_chains.transform_values {|chain| chain.subst(subst) }
40
+ )
41
+ end
42
+ end
43
+ end
44
+ end