steep 0.47.1 → 0.48.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -80,7 +80,7 @@ module Steep
80
80
  @vars = Set.new
81
81
 
82
82
  unknowns.each do |var|
83
- dictionary[var] = [Set.new, Set.new]
83
+ dictionary[var] = [Set.new, Set.new, Set.new]
84
84
  end
85
85
  end
86
86
 
@@ -101,8 +101,8 @@ module Steep
101
101
  end
102
102
  end
103
103
 
104
- def add(var, sub_type: nil, super_type: nil)
105
- subs, supers = dictionary[var]
104
+ def add(var, sub_type: nil, super_type: nil, skip: false)
105
+ subs, supers, skips = dictionary[var]
106
106
 
107
107
  if sub_type.is_a?(AST::Types::Logic::Base)
108
108
  sub_type = AST::Builtin.bool_type
@@ -113,11 +113,15 @@ module Steep
113
113
  end
114
114
 
115
115
  if super_type && !super_type.is_a?(AST::Types::Top)
116
- supers << eliminate_variable(super_type, to: AST::Types::Top.new)
116
+ type = eliminate_variable(super_type, to: AST::Types::Top.new)
117
+ supers << type
118
+ skips << type if skip
117
119
  end
118
120
 
119
121
  if sub_type && !sub_type.is_a?(AST::Types::Bot)
120
- subs << eliminate_variable(sub_type, to: AST::Types::Bot.new)
122
+ type = eliminate_variable(sub_type, to: AST::Types::Bot.new)
123
+ subs << type
124
+ skips << type if skip
121
125
  end
122
126
 
123
127
  super_fvs = supers.each.with_object(Set.new) do |type, fvs|
@@ -178,12 +182,20 @@ module Steep
178
182
  Set.new(dictionary.keys)
179
183
  end
180
184
 
185
+ def unknown!(var)
186
+ unless unknown?(var)
187
+ dictionary[var] = [Set.new, Set.new, Set.new]
188
+ end
189
+ end
190
+
181
191
  def empty?
182
192
  dictionary.keys.empty?
183
193
  end
184
194
 
185
- def upper_bound(var)
186
- _, upper_bound = dictionary[var]
195
+ def upper_bound(var, skip: false)
196
+ _, upper_bound, skips = dictionary[var]
197
+ upper_bound -= skips if skip
198
+
187
199
  case upper_bound.size
188
200
  when 0
189
201
  AST::Types::Top.new
@@ -194,8 +206,9 @@ module Steep
194
206
  end
195
207
  end
196
208
 
197
- def lower_bound(var)
198
- lower_bound, _ = dictionary[var]
209
+ def lower_bound(var, skip: false)
210
+ lower_bound, _, skips = dictionary[var]
211
+ lower_bound -= skips if skip
199
212
 
200
213
  case lower_bound.size
201
214
  when 0
@@ -207,40 +220,61 @@ module Steep
207
220
  end
208
221
  end
209
222
 
210
- def solution(checker, variance:, variables:, self_type:, instance_type:, class_type:)
223
+ Context = Struct.new(:variance, :self_type, :instance_type, :class_type, keyword_init: true)
224
+
225
+ def solution(checker, variance: nil, variables:, self_type: nil, instance_type: nil, class_type: nil, context: nil)
226
+ if context
227
+ raise if variance
228
+ raise if self_type
229
+ raise if instance_type
230
+ raise if class_type
231
+
232
+ variance = context.variance
233
+ self_type = context.self_type
234
+ instance_type = context.instance_type
235
+ class_type = context.class_type
236
+ end
237
+
211
238
  vars = []
212
239
  types = []
213
240
 
214
241
  dictionary.each_key do |var|
215
242
  if variables.include?(var)
216
243
  if has_constraint?(var)
217
- upper_bound = upper_bound(var)
218
- lower_bound = lower_bound(var)
219
- relation = Relation.new(sub_type: lower_bound, super_type: upper_bound)
244
+ relation = Relation.new(
245
+ sub_type: lower_bound(var, skip: false),
246
+ super_type: upper_bound(var, skip: false)
247
+ )
220
248
 
221
249
  checker.check(relation, self_type: self_type, instance_type: instance_type, class_type: class_type, constraints: self.class.empty).yield_self do |result|
222
250
  if result.success?
223
251
  vars << var
224
252
 
225
- type = case
226
- when variance.contravariant?(var)
227
- upper_bound
228
- when variance.covariant?(var)
229
- lower_bound
230
- else
231
- if lower_bound.level.join > upper_bound.level.join
232
- upper_bound
233
- else
234
- lower_bound
235
- end
236
- end
253
+ upper_bound = upper_bound(var, skip: true)
254
+ lower_bound = lower_bound(var, skip: true)
255
+
256
+ type =
257
+ case
258
+ when variance.contravariant?(var)
259
+ upper_bound
260
+ when variance.covariant?(var)
261
+ lower_bound
262
+ else
263
+ if lower_bound.level.join > upper_bound.level.join
264
+ upper_bound
265
+ else
266
+ lower_bound
267
+ end
268
+ end
237
269
 
238
270
  types << type
239
271
  else
240
- raise UnsatisfiableConstraint.new(var: var,
241
- sub_type: lower_bound,
242
- super_type: upper_bound,
243
- result: result)
272
+ raise UnsatisfiableConstraint.new(
273
+ var: var,
274
+ sub_type: result.relation.sub_type,
275
+ super_type: result.relation.super_type,
276
+ result: result
277
+ )
244
278
  end
245
279
  end
246
280
  else
@@ -254,7 +288,9 @@ module Steep
254
288
  end
255
289
 
256
290
  def has_constraint?(var)
257
- lower, upper = dictionary[var]
291
+ lower, upper, skips = dictionary[var]
292
+ lower -= skips
293
+ upper -= skips
258
294
  !lower.empty? || !upper.empty?
259
295
  end
260
296
 
@@ -23,6 +23,66 @@ module Steep
23
23
  "#{sub_type} <: #{super_type}"
24
24
  end
25
25
 
26
+ def to_ary
27
+ [sub_type, super_type]
28
+ end
29
+
30
+ def type?
31
+ !interface? && !method? && !function? && !params? && !block?
32
+ end
33
+
34
+ def interface?
35
+ sub_type.is_a?(Interface::Interface) && super_type.is_a?(Interface::Interface)
36
+ end
37
+
38
+ def method?
39
+ (sub_type.is_a?(Interface::Interface::Entry) || sub_type.is_a?(Interface::MethodType)) &&
40
+ (super_type.is_a?(Interface::Interface::Entry) || super_type.is_a?(Interface::MethodType))
41
+ end
42
+
43
+ def function?
44
+ sub_type.is_a?(Interface::Function) && super_type.is_a?(Interface::Function)
45
+ end
46
+
47
+ def params?
48
+ sub_type.is_a?(Interface::Function::Params) && super_type.is_a?(Interface::Function::Params)
49
+ end
50
+
51
+ def block?
52
+ (sub_type.is_a?(Interface::Block) || !sub_type) &&
53
+ (!super_type || super_type.is_a?(Interface::Block))
54
+ end
55
+
56
+ def assert_type(type)
57
+ unless __send__(:"#{type}?")
58
+ raise "#{type}? is expected but: sub_type=#{sub_type.class}, super_type=#{super_type.class}"
59
+ end
60
+ end
61
+
62
+ def type!
63
+ assert_type(:type)
64
+ end
65
+
66
+ def interface!
67
+ assert_type(:interface)
68
+ end
69
+
70
+ def method!
71
+ assert_type(:method)
72
+ end
73
+
74
+ def function!
75
+ assert_type(:function)
76
+ end
77
+
78
+ def params!
79
+ assert_type(:params)
80
+ end
81
+
82
+ def block!
83
+ assert_type(:block)
84
+ end
85
+
26
86
  def map
27
87
  self.class.new(
28
88
  sub_type: yield(sub_type),
@@ -2,6 +2,12 @@ module Steep
2
2
  module Subtyping
3
3
  module Result
4
4
  class Base
5
+ attr_reader :relation
6
+
7
+ def initialize(relation)
8
+ @relation = relation
9
+ end
10
+
5
11
  def failure?
6
12
  !success?
7
13
  end
@@ -21,18 +27,139 @@ module Steep
21
27
  self
22
28
  end
23
29
  end
30
+
31
+ def failure_path(path = [])
32
+ raise
33
+ end
24
34
  end
25
35
 
26
- class Success < Base
27
- attr_reader :constraints
36
+ class Skip < Base
37
+ def success?
38
+ false
39
+ end
40
+
41
+ def failure?
42
+ false
43
+ end
44
+
45
+ def failure_path(path = [])
46
+ raise
47
+ end
48
+ end
49
+
50
+ class Expand < Base
51
+ attr_reader :child
52
+
53
+ def initialize(relation, &block)
54
+ super relation
55
+ @child = yield relation
56
+
57
+ raise if @child == true
58
+ end
59
+
60
+ def success?
61
+ child.success?
62
+ end
28
63
 
29
- def initialize(constraints:)
30
- @constraints = constraints
64
+ def failure_path(path = [])
65
+ if child.failure?
66
+ path.unshift(self)
67
+ child.failure_path(path)
68
+ end
69
+ end
70
+ end
71
+
72
+ class All < Base
73
+ attr_reader :branches
74
+
75
+ def initialize(relation)
76
+ super relation
77
+ @branches = []
78
+ @failure = false
79
+ end
80
+
81
+ # Returns `false` if no future `#add` changes the result.
82
+ def add(*relations, &block)
83
+ relations.each do |relation|
84
+ if success?
85
+ result = yield(relation)
86
+ branches << result
87
+ else
88
+ # Already failed.
89
+ branches << Skip.new(relation)
90
+ end
91
+ end
92
+
93
+ # No need to test more branches if already failed.
94
+ success?
31
95
  end
32
96
 
97
+ def success?
98
+ !failure?
99
+ end
100
+
101
+ def failure?
102
+ @failure ||= branches.any?(&:failure?)
103
+ end
104
+
105
+ def failure_path(path = [])
106
+ if failure?
107
+ r = branches.find(&:failure?)
108
+ path.unshift(self)
109
+ r.failure_path(path)
110
+ end
111
+ end
112
+ end
113
+
114
+ class Any < Base
115
+ attr_reader :branches
116
+
117
+ def initialize(relation)
118
+ super relation
119
+ @branches = []
120
+ @success = false
121
+ end
122
+
123
+ # Returns `false` if no future `#add` changes the result.
124
+ def add(*relations, &block)
125
+ relations.each do |relation|
126
+ if failure?
127
+ result = yield(relation)
128
+ branches << result
129
+ else
130
+ # Already succeeded.
131
+ branches << Skip.new(relation)
132
+ end
133
+ end
134
+
135
+ # No need to test more branches if already succeeded.
136
+ failure?
137
+ end
138
+
139
+ def success?
140
+ @success ||= branches.any?(&:success?)
141
+ end
142
+
143
+ def failure_path(path = [])
144
+ if failure?
145
+ path.unshift(self)
146
+ if r = branches.find(&:failure?)
147
+ r.failure_path(path)
148
+ else
149
+ path
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ class Success < Base
33
156
  def success?
34
157
  true
35
158
  end
159
+
160
+ def failure_path(path = [])
161
+ nil
162
+ end
36
163
  end
37
164
 
38
165
  class Failure < Base
@@ -96,29 +223,76 @@ module Steep
96
223
  end
97
224
  end
98
225
 
226
+ class UnsatisfiedConstraints
227
+ attr_reader :error
228
+
229
+ def initialize(error)
230
+ @error = error
231
+ end
232
+
233
+ def var
234
+ error.var
235
+ end
236
+
237
+ def sub_type
238
+ error.sub_type
239
+ end
240
+
241
+ def super_type
242
+ error.super_type
243
+ end
244
+
245
+ def result
246
+ error.result
247
+ end
248
+
249
+ def message
250
+ "A constraint on #{var} cannot be solved: #{sub_type} <: #{super_type}"
251
+ end
252
+ end
253
+
99
254
  attr_reader :error
100
- attr_reader :trace
101
255
 
102
- def initialize(error:, trace:)
256
+ def initialize(relation, error)
257
+ super relation
103
258
  @error = error
104
- @trace = trace.dup
105
259
  end
106
260
 
107
261
  def success?
108
262
  false
109
263
  end
110
264
 
111
- def merge_trace(trace)
112
- if trace.empty?
113
- self
114
- else
115
- self.class.new(error: error,
116
- trace: trace + self.trace)
117
- end
265
+ def failure_path(path = [])
266
+ path.unshift(self)
267
+ path
268
+ end
269
+ end
270
+
271
+ module Helper
272
+ def Skip(relation)
273
+ Skip.new(relation)
274
+ end
275
+
276
+ def Expand(relation, &block)
277
+ Expand.new(relation, &block)
278
+ end
279
+
280
+ def All(relation, &block)
281
+ All.new(relation).tap(&block)
118
282
  end
119
283
 
120
- def drop(n)
121
- self.class.new(error: error, trace: trace.drop(n))
284
+ def Any(relation, &block)
285
+ Any.new(relation).tap(&block)
286
+ end
287
+
288
+ def Success(relation)
289
+ Success.new(relation)
290
+ end
291
+
292
+ alias success Success
293
+
294
+ def Failure(relation, error = nil)
295
+ Failure.new(relation, error || yield)
122
296
  end
123
297
  end
124
298
  end