steep-relaxed 1.9.3.3

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 (165) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.gitmodules +0 -0
  4. data/CHANGELOG.md +1032 -0
  5. data/LICENSE +21 -0
  6. data/README.md +260 -0
  7. data/Rakefile +227 -0
  8. data/STDGEM_DEPENDENCIES.txt +59 -0
  9. data/Steepfile +68 -0
  10. data/bin/console +14 -0
  11. data/bin/generate-diagnostics-docs.rb +112 -0
  12. data/bin/mem_graph.rb +67 -0
  13. data/bin/mem_prof.rb +102 -0
  14. data/bin/output_rebaseline.rb +34 -0
  15. data/bin/output_test.rb +60 -0
  16. data/bin/rbs +20 -0
  17. data/bin/rbs-inline +19 -0
  18. data/bin/setup +9 -0
  19. data/bin/stackprof_test.rb +19 -0
  20. data/bin/steep +19 -0
  21. data/bin/steep-check.rb +251 -0
  22. data/bin/steep-prof +16 -0
  23. data/doc/narrowing.md +195 -0
  24. data/doc/shape.md +194 -0
  25. data/exe/steep +18 -0
  26. data/guides/README.md +5 -0
  27. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +126 -0
  28. data/guides/src/getting-started/getting-started.md +163 -0
  29. data/guides/src/nil-optional/nil-optional.md +195 -0
  30. data/lib/steep/annotation_parser.rb +199 -0
  31. data/lib/steep/ast/annotation/collection.rb +172 -0
  32. data/lib/steep/ast/annotation.rb +137 -0
  33. data/lib/steep/ast/builtin.rb +104 -0
  34. data/lib/steep/ast/ignore.rb +148 -0
  35. data/lib/steep/ast/node/type_application.rb +88 -0
  36. data/lib/steep/ast/node/type_assertion.rb +81 -0
  37. data/lib/steep/ast/types/any.rb +35 -0
  38. data/lib/steep/ast/types/boolean.rb +45 -0
  39. data/lib/steep/ast/types/bot.rb +35 -0
  40. data/lib/steep/ast/types/class.rb +43 -0
  41. data/lib/steep/ast/types/factory.rb +557 -0
  42. data/lib/steep/ast/types/helper.rb +40 -0
  43. data/lib/steep/ast/types/instance.rb +42 -0
  44. data/lib/steep/ast/types/intersection.rb +93 -0
  45. data/lib/steep/ast/types/literal.rb +59 -0
  46. data/lib/steep/ast/types/logic.rb +84 -0
  47. data/lib/steep/ast/types/name.rb +128 -0
  48. data/lib/steep/ast/types/nil.rb +41 -0
  49. data/lib/steep/ast/types/proc.rb +117 -0
  50. data/lib/steep/ast/types/record.rb +79 -0
  51. data/lib/steep/ast/types/self.rb +43 -0
  52. data/lib/steep/ast/types/shared_instance.rb +11 -0
  53. data/lib/steep/ast/types/top.rb +35 -0
  54. data/lib/steep/ast/types/tuple.rb +60 -0
  55. data/lib/steep/ast/types/union.rb +97 -0
  56. data/lib/steep/ast/types/var.rb +65 -0
  57. data/lib/steep/ast/types/void.rb +35 -0
  58. data/lib/steep/cli.rb +401 -0
  59. data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
  60. data/lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb +28 -0
  61. data/lib/steep/diagnostic/helper.rb +18 -0
  62. data/lib/steep/diagnostic/lsp_formatter.rb +78 -0
  63. data/lib/steep/diagnostic/result_printer2.rb +48 -0
  64. data/lib/steep/diagnostic/ruby.rb +1221 -0
  65. data/lib/steep/diagnostic/signature.rb +570 -0
  66. data/lib/steep/drivers/annotations.rb +52 -0
  67. data/lib/steep/drivers/check.rb +339 -0
  68. data/lib/steep/drivers/checkfile.rb +210 -0
  69. data/lib/steep/drivers/diagnostic_printer.rb +105 -0
  70. data/lib/steep/drivers/init.rb +66 -0
  71. data/lib/steep/drivers/langserver.rb +56 -0
  72. data/lib/steep/drivers/print_project.rb +113 -0
  73. data/lib/steep/drivers/stats.rb +203 -0
  74. data/lib/steep/drivers/utils/driver_helper.rb +143 -0
  75. data/lib/steep/drivers/utils/jobs_option.rb +26 -0
  76. data/lib/steep/drivers/vendor.rb +27 -0
  77. data/lib/steep/drivers/watch.rb +194 -0
  78. data/lib/steep/drivers/worker.rb +58 -0
  79. data/lib/steep/equatable.rb +23 -0
  80. data/lib/steep/expectations.rb +228 -0
  81. data/lib/steep/index/rbs_index.rb +350 -0
  82. data/lib/steep/index/signature_symbol_provider.rb +185 -0
  83. data/lib/steep/index/source_index.rb +167 -0
  84. data/lib/steep/interface/block.rb +103 -0
  85. data/lib/steep/interface/builder.rb +843 -0
  86. data/lib/steep/interface/function.rb +1090 -0
  87. data/lib/steep/interface/method_type.rb +330 -0
  88. data/lib/steep/interface/shape.rb +239 -0
  89. data/lib/steep/interface/substitution.rb +159 -0
  90. data/lib/steep/interface/type_param.rb +115 -0
  91. data/lib/steep/located_value.rb +20 -0
  92. data/lib/steep/method_name.rb +42 -0
  93. data/lib/steep/module_helper.rb +24 -0
  94. data/lib/steep/node_helper.rb +273 -0
  95. data/lib/steep/path_helper.rb +30 -0
  96. data/lib/steep/project/dsl.rb +268 -0
  97. data/lib/steep/project/group.rb +31 -0
  98. data/lib/steep/project/options.rb +63 -0
  99. data/lib/steep/project/pattern.rb +59 -0
  100. data/lib/steep/project/target.rb +92 -0
  101. data/lib/steep/project.rb +78 -0
  102. data/lib/steep/rake_task.rb +132 -0
  103. data/lib/steep/range_extension.rb +29 -0
  104. data/lib/steep/server/base_worker.rb +97 -0
  105. data/lib/steep/server/change_buffer.rb +73 -0
  106. data/lib/steep/server/custom_methods.rb +77 -0
  107. data/lib/steep/server/delay_queue.rb +45 -0
  108. data/lib/steep/server/interaction_worker.rb +492 -0
  109. data/lib/steep/server/lsp_formatter.rb +455 -0
  110. data/lib/steep/server/master.rb +922 -0
  111. data/lib/steep/server/target_group_files.rb +205 -0
  112. data/lib/steep/server/type_check_controller.rb +366 -0
  113. data/lib/steep/server/type_check_worker.rb +303 -0
  114. data/lib/steep/server/work_done_progress.rb +64 -0
  115. data/lib/steep/server/worker_process.rb +176 -0
  116. data/lib/steep/services/completion_provider.rb +802 -0
  117. data/lib/steep/services/content_change.rb +61 -0
  118. data/lib/steep/services/file_loader.rb +74 -0
  119. data/lib/steep/services/goto_service.rb +441 -0
  120. data/lib/steep/services/hover_provider/rbs.rb +88 -0
  121. data/lib/steep/services/hover_provider/ruby.rb +221 -0
  122. data/lib/steep/services/hover_provider/singleton_methods.rb +20 -0
  123. data/lib/steep/services/path_assignment.rb +46 -0
  124. data/lib/steep/services/signature_help_provider.rb +202 -0
  125. data/lib/steep/services/signature_service.rb +428 -0
  126. data/lib/steep/services/stats_calculator.rb +68 -0
  127. data/lib/steep/services/type_check_service.rb +394 -0
  128. data/lib/steep/services/type_name_completion.rb +236 -0
  129. data/lib/steep/signature/validator.rb +651 -0
  130. data/lib/steep/source/ignore_ranges.rb +69 -0
  131. data/lib/steep/source.rb +691 -0
  132. data/lib/steep/subtyping/cache.rb +30 -0
  133. data/lib/steep/subtyping/check.rb +1113 -0
  134. data/lib/steep/subtyping/constraints.rb +341 -0
  135. data/lib/steep/subtyping/relation.rb +101 -0
  136. data/lib/steep/subtyping/result.rb +324 -0
  137. data/lib/steep/subtyping/variable_variance.rb +89 -0
  138. data/lib/steep/test.rb +9 -0
  139. data/lib/steep/thread_waiter.rb +43 -0
  140. data/lib/steep/type_construction.rb +5183 -0
  141. data/lib/steep/type_inference/block_params.rb +416 -0
  142. data/lib/steep/type_inference/case_when.rb +303 -0
  143. data/lib/steep/type_inference/constant_env.rb +56 -0
  144. data/lib/steep/type_inference/context.rb +195 -0
  145. data/lib/steep/type_inference/logic_type_interpreter.rb +613 -0
  146. data/lib/steep/type_inference/method_call.rb +193 -0
  147. data/lib/steep/type_inference/method_params.rb +531 -0
  148. data/lib/steep/type_inference/multiple_assignment.rb +194 -0
  149. data/lib/steep/type_inference/send_args.rb +712 -0
  150. data/lib/steep/type_inference/type_env.rb +341 -0
  151. data/lib/steep/type_inference/type_env_builder.rb +138 -0
  152. data/lib/steep/typing.rb +321 -0
  153. data/lib/steep/version.rb +3 -0
  154. data/lib/steep.rb +369 -0
  155. data/manual/annotations.md +181 -0
  156. data/manual/ignore.md +20 -0
  157. data/manual/ruby-diagnostics.md +1879 -0
  158. data/sample/Steepfile +22 -0
  159. data/sample/lib/conference.rb +49 -0
  160. data/sample/lib/length.rb +35 -0
  161. data/sample/sig/conference.rbs +42 -0
  162. data/sample/sig/generics.rbs +15 -0
  163. data/sample/sig/length.rbs +34 -0
  164. data/steep-relaxed.gemspec +56 -0
  165. metadata +340 -0
@@ -0,0 +1,330 @@
1
+ module Steep
2
+ module Interface
3
+ class MethodType
4
+ attr_reader :type_params
5
+ attr_reader :type
6
+ attr_reader :block
7
+
8
+ def initialize(type_params:, type:, block:)
9
+ @type_params = type_params
10
+ @type = type
11
+ @block = block
12
+ end
13
+
14
+ def ==(other)
15
+ other.is_a?(self.class) &&
16
+ other.type_params == type_params &&
17
+ other.type == type &&
18
+ other.block == block
19
+ end
20
+
21
+ alias eql? ==
22
+
23
+ def hash
24
+ type_params.hash ^ type.hash ^ block.hash
25
+ end
26
+
27
+ def free_variables
28
+ @fvs ||= Set.new.tap do |set|
29
+ set.merge(type.free_variables)
30
+ if block
31
+ set.merge(block.free_variables)
32
+ end
33
+ set.subtract(type_params.map(&:name))
34
+ end
35
+ end
36
+
37
+ def subst(s)
38
+ return self if s.empty?
39
+ return self if each_type.none? {|t| s.apply?(t) }
40
+
41
+ if type_params.any? {|param| s.key?(param.name) }
42
+ s_ = s.except(type_params.map(&:name))
43
+ else
44
+ s_ = s
45
+ end
46
+
47
+ ty = type.subst(s_)
48
+ bl = block&.subst(s_)
49
+
50
+ if ty == type && bl == block
51
+ self
52
+ else
53
+ self.class.new(type_params: type_params, type: ty, block: bl)
54
+ end
55
+ end
56
+
57
+ def each_type(&block)
58
+ if block
59
+ type.each_type(&block)
60
+ if block()
61
+ yield(block().self_type) if block().self_type
62
+ block().type.params&.each_type(&block)
63
+ yield(block().type.return_type)
64
+ end
65
+ else
66
+ enum_for :each_type
67
+ end
68
+ end
69
+
70
+ def instantiate(s)
71
+ self.class.new(type_params: [],
72
+ type: type.subst(s),
73
+ block: block&.subst(s))
74
+ end
75
+
76
+ def with(type_params: self.type_params, type: self.type, block: self.block)
77
+ self.class.new(type_params: type_params,
78
+ type: type,
79
+ block: block)
80
+ end
81
+
82
+ def to_s
83
+ type_params = !self.type_params.empty? ? "[#{self.type_params.join(", ")}] " : ""
84
+ params = type.params.to_s
85
+ return_type = type.return_type
86
+ block = self.block ? " #{self.block}" : ""
87
+
88
+ "#{type_params}#{params}#{block} -> #{return_type}"
89
+ end
90
+
91
+ def map_type(&block)
92
+ self.class.new(type_params: type_params,
93
+ type: type.map_type(&block),
94
+ block: self.block&.yield_self {|blk| blk.map_type(&block) })
95
+ end
96
+
97
+ # Returns a new method type which can be used for the method implementation type of both `self` and `other`.
98
+ #
99
+ def unify_overload(other)
100
+ type_params_1, s1 = TypeParam.rename(self.type_params)
101
+ type_params_2, s2 = TypeParam.rename(other.type_params)
102
+ type_params = type_params_1 + type_params_2
103
+
104
+ block =
105
+ case
106
+ when (b = self.block) && (ob = other.block)
107
+ b.subst(s1) + ob.subst(s2)
108
+ when b = self.block
109
+ b.to_optional.subst(s1)
110
+ when ob = other.block
111
+ ob.to_optional.subst(s2)
112
+ end
113
+
114
+ self.class.new(
115
+ type_params: type_params,
116
+ type: Function.new(
117
+ params: type.params && other.type.params ? type.params.subst(s1) + other.type.params.subst(s2) : nil,
118
+ return_type: AST::Types::Union.build(
119
+ types: [type.return_type.subst(s1), other.type.return_type.subst(s2)]
120
+ ),
121
+ location: nil
122
+ ),
123
+ block: block
124
+ )
125
+ end
126
+
127
+ def +(other)
128
+ unify_overload(other)
129
+ end
130
+
131
+ def equals_modulo_type_params?(other)
132
+ case
133
+ when self.type_params.empty? && other.type_params.empty?
134
+ self == other
135
+ when self.type_params.size == other.type_params.size
136
+ new_names = self.type_params.map(&:name)
137
+
138
+ self_params, self_subst = TypeParam.rename(self.type_params, self.type_params.map(&:name), new_names)
139
+ other_params, other_subst = TypeParam.rename(other.type_params, other.type_params.map(&:name), new_names)
140
+
141
+ self_params == other_params && self.instantiate(self_subst) == other.instantiate(other_subst)
142
+ else
143
+ false
144
+ end
145
+ end
146
+
147
+ def self.union(type1, type2, check)
148
+ try_type_params(
149
+ type1,
150
+ type2,
151
+ check,
152
+ -> (t1, t2) { t1 | t2 },
153
+ -> (original, generated) { Subtyping::Relation.new(sub_type: original, super_type: generated) }
154
+ )
155
+ end
156
+
157
+ def self.intersection(type1, type2, check)
158
+ try_type_params(
159
+ type1,
160
+ type2,
161
+ check,
162
+ -> (t1, t2) { t1 & t2 },
163
+ -> (original, generated) { Subtyping::Relation.new(sub_type: generated, super_type: original) }
164
+ )
165
+ end
166
+
167
+ def self.try_type_params(type1, type2, check, generate, relation)
168
+ return type1 if type1.equals_modulo_type_params?(type2)
169
+
170
+ case
171
+ when type1.type_params.empty? && type2.type_params.empty?
172
+ generate[type1, type2]
173
+ when type1.type_params.empty?
174
+ if mt = generate[type1, type2.with(type_params: [])]
175
+ mt.with(type_params: type2.type_params)
176
+ end
177
+ when type2.type_params.empty?
178
+ if mt = generate[type1.with(type_params: []), type2]
179
+ mt.with(type_params: type1.type_params)
180
+ end
181
+ when type1.type_params.size == type2.type_params.size
182
+ params1, s1 = TypeParam.rename(type1.type_params)
183
+ params2, s2 = TypeParam.rename(type2.type_params)
184
+
185
+ type1_ = type1.instantiate(s1)
186
+ type2_ = type2.instantiate(s2)
187
+ if mt = generate[type1_, type2_]
188
+ check.push_variable_bounds(params1 + params2) do
189
+ variables = type1.type_params.map(&:name) + type2.type_params.map(&:name)
190
+ constraints = Subtyping::Constraints.new(unknowns: variables)
191
+
192
+ check.with_context(self_type: AST::Builtin.any_type, instance_type: AST::Builtin.any_type, class_type: AST::Builtin.any_type, constraints: constraints) do
193
+ result1 = check.check_method_type(:__method_on_type1, relation[type1.with(type_params: []), mt])
194
+ result2 = check.check_method_type(:__method_on_type2, relation[type2.with(type_params: []), mt])
195
+
196
+ if result1.success? && result2.success?
197
+ unless type1.type_params.map(&:name).zip(type2.type_params.map(&:name)).all? {|pair|
198
+ constraints.upper_bound(pair[0]) == constraints.upper_bound(pair[1] || raise) &&
199
+ constraints.lower_bound(pair[0]) == constraints.lower_bound(pair[1] || raise)
200
+ }
201
+ return
202
+ end
203
+
204
+ params2_, s2_ = TypeParam.rename(type2.type_params, type2.type_params.map(&:name), type1.type_params.map(&:name))
205
+ if mt_ = generate[type1.with(type_params: []), type2.instantiate(s2_)]
206
+ mt_.with(
207
+ type_params: type1.type_params.map.with_index {|param1, index|
208
+ param2 = params2_[index] or raise
209
+ ub1 = param1.upper_bound
210
+ ub2 = param2.upper_bound
211
+
212
+ case
213
+ when ub1 && ub2
214
+ param1.update(upper_bound: AST::Types::Union.build(types: [ub1, ub2]))
215
+ when ub2
216
+ param1.update(upper_bound: ub2)
217
+ else
218
+ param1
219
+ end
220
+ }
221
+ )
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
229
+
230
+ def |(other)
231
+ return self if other == self
232
+
233
+ params = self.type.params & other.type.params or return
234
+ block =
235
+ case
236
+ when (b = block()) && (ob = other.block)
237
+ self_type =
238
+ case
239
+ when (self_self = b.self_type) && (other_self = ob.self_type)
240
+ AST::Types::Union.build(types: [self_self, other_self])
241
+ when b.self_type || ob.self_type
242
+ AST::Types::Bot.instance
243
+ else
244
+ nil
245
+ end
246
+
247
+ if b.type.params && ob.type.params
248
+ # Return when the two block parameters are imcompatible.
249
+ return unless b.type.params & ob.type.params
250
+ block_params = b.type.params | ob.type.params or return
251
+ else
252
+ block_params = b.type.params || ob.type.params
253
+ end
254
+
255
+ block_return_type = AST::Types::Intersection.build(types: [b.type.return_type, ob.type.return_type])
256
+ block_type = Function.new(params: block_params, return_type: block_return_type, location: nil)
257
+
258
+ Block.new(
259
+ type: block_type,
260
+ optional: b.optional && ob.optional,
261
+ self_type: self_type
262
+ )
263
+ when (b = block()) && b.optional?
264
+ b
265
+ when other.block && other.block.optional?
266
+ other.block
267
+ when !self.block && !other.block
268
+ nil
269
+ else
270
+ return
271
+ end
272
+ return_type = AST::Types::Union.build(types: [self.type.return_type, other.type.return_type])
273
+
274
+ MethodType.new(
275
+ type_params: [],
276
+ type: Function.new(params: params, return_type: return_type, location: nil),
277
+ block: block
278
+ )
279
+ end
280
+
281
+ def &(other)
282
+ return self if self == other
283
+
284
+ if self.type.params && other.type.params
285
+ params = self.type.params | other.type.params or return
286
+ else
287
+ params = self.type.params || other.type.params
288
+ end
289
+
290
+ block =
291
+ case
292
+ when (b = self.block) && (ob = other.block)
293
+ self_type =
294
+ case
295
+ when (self_self = b.self_type) && (other_self = ob.self_type)
296
+ AST::Types::Intersection.build(types: [self_self, other_self])
297
+ when b.self_type || ob.self_type
298
+ AST::Types::Top.instance
299
+ else
300
+ nil
301
+ end
302
+
303
+ block_params = b.type.params & ob.type.params or return
304
+ block_return_type = AST::Types::Union.build(types: [b.type.return_type, ob.type.return_type])
305
+ block_type = Function.new(params: block_params, return_type: block_return_type, location: nil)
306
+ Block.new(
307
+ type: block_type,
308
+ optional: b.optional || ob.optional,
309
+ self_type: self_type
310
+ )
311
+ else
312
+ self.block || other.block
313
+ end
314
+
315
+ return_type = AST::Types::Intersection.build(types: [self.type.return_type, other.type.return_type])
316
+
317
+ MethodType.new(
318
+ type_params: [],
319
+ type: Function.new(params: params, return_type: return_type, location: nil),
320
+ block: block
321
+ )
322
+ end
323
+
324
+ def accept_one_arg?
325
+ return false if block && block.required?
326
+ type.accept_one_arg?
327
+ end
328
+ end
329
+ end
330
+ end
@@ -0,0 +1,239 @@
1
+ module Steep
2
+ module Interface
3
+ class Shape
4
+ class MethodOverload
5
+ attr_reader :method_type
6
+
7
+ attr_reader :method_defs
8
+
9
+ def initialize(method_type, defs)
10
+ @method_type = method_type
11
+ @method_defs = defs.sort_by do |defn|
12
+ buf = +""
13
+
14
+ if loc = defn.type.location
15
+ buf << loc.buffer.name.to_s
16
+ buf << ":"
17
+ buf << loc.start_pos.to_s
18
+ end
19
+
20
+ buf
21
+ end
22
+ @method_defs.uniq!
23
+ end
24
+
25
+ def subst(s)
26
+ overload = MethodOverload.new(method_type.subst(s), [])
27
+ overload.method_defs.replace(method_defs)
28
+ overload
29
+ end
30
+
31
+ def method_decls(name)
32
+ method_defs.map do |defn|
33
+ type_name = defn.implemented_in || defn.defined_in
34
+
35
+ if name == :new && defn.member.is_a?(RBS::AST::Members::MethodDefinition) && defn.member.name == :initialize
36
+ method_name = SingletonMethodName.new(type_name: type_name, method_name: name)
37
+ else
38
+ method_name =
39
+ if defn.member.kind == :singleton
40
+ SingletonMethodName.new(type_name: defn.defined_in, method_name: name)
41
+ else
42
+ # Call the `self?` method an instance method, because the definition is done with instance method definition, not with singleton method
43
+ InstanceMethodName.new(type_name: defn.defined_in, method_name: name)
44
+ end
45
+ end
46
+
47
+ TypeInference::MethodCall::MethodDecl.new(method_def: defn, method_name: method_name)
48
+ end
49
+ end
50
+ end
51
+
52
+ class Entry
53
+ attr_reader :method_name
54
+
55
+ def initialize(overloads: nil, private_method:, method_name:, &block)
56
+ @overloads = overloads
57
+ @generator = block
58
+ @private_method = private_method
59
+ @method_name = method_name
60
+ end
61
+
62
+ def force
63
+ unless @overloads
64
+ @overloads = @generator&.call
65
+ @generator = nil
66
+ end
67
+ end
68
+
69
+ def overloads
70
+ force
71
+ @overloads or raise
72
+ end
73
+
74
+ def method_types
75
+ overloads.map(&:method_type)
76
+ end
77
+
78
+ def has_method_type?
79
+ force
80
+ @overloads ? true : false
81
+ end
82
+
83
+ def to_s
84
+ if @generator
85
+ "<< Lazy entry >>"
86
+ else
87
+ "{ #{method_types.join(" || ")} }"
88
+ end
89
+ end
90
+
91
+ def private_method?
92
+ @private_method
93
+ end
94
+
95
+ def public_method?
96
+ !private_method?
97
+ end
98
+ end
99
+
100
+ class Methods
101
+ attr_reader :substs, :methods, :resolved_methods
102
+
103
+ include Enumerable
104
+
105
+ def initialize(substs:, methods:)
106
+ @substs = substs
107
+ @methods = methods
108
+ @resolved_methods = {}
109
+ end
110
+
111
+ def key?(name)
112
+ if entry = methods.fetch(name, nil)
113
+ entry.has_method_type?
114
+ else
115
+ false
116
+ end
117
+ end
118
+
119
+ def []=(name, entry)
120
+ resolved_methods[name] = nil
121
+ methods[name] = entry
122
+ end
123
+
124
+ def [](name)
125
+ return nil unless key?(name)
126
+
127
+ resolved_methods[name] ||= begin
128
+ entry = methods.fetch(name)
129
+ Entry.new(
130
+ method_name: name,
131
+ overloads: entry.overloads.map do |overload|
132
+ overload.subst(subst)
133
+ end,
134
+ private_method: entry.private_method?
135
+ )
136
+ end
137
+ end
138
+
139
+ def each(&block)
140
+ if block
141
+ methods.each_key do |name|
142
+ entry = self[name] or next
143
+ yield [name, entry]
144
+ end
145
+ else
146
+ enum_for :each
147
+ end
148
+ end
149
+
150
+ def each_name(&block)
151
+ if block
152
+ each do |name, _|
153
+ yield name
154
+ end
155
+ else
156
+ enum_for :each_name
157
+ end
158
+ end
159
+
160
+ def subst
161
+ @subst ||= begin
162
+ substs.each_with_object(Substitution.empty) do |s, ss|
163
+ ss.merge!(s, overwrite: true)
164
+ end
165
+ end
166
+ end
167
+
168
+ def push_substitution(subst)
169
+ Methods.new(substs: [*substs, subst], methods: methods)
170
+ end
171
+
172
+ def merge!(other, &block)
173
+ other.each do |name, entry|
174
+ if block && (old_entry = methods[name])
175
+ methods[name] = yield(name, old_entry, entry)
176
+ else
177
+ methods[name] = entry
178
+ end
179
+ end
180
+ end
181
+
182
+ def public_methods
183
+ Methods.new(
184
+ substs: substs,
185
+ methods: methods.reject {|_, entry| entry.private_method? }
186
+ )
187
+ end
188
+ end
189
+
190
+ attr_reader :type
191
+ attr_reader :methods
192
+
193
+ def initialize(type:, private:, methods: nil)
194
+ @type = type
195
+ @private = private
196
+ @methods = methods || Methods.new(substs: [], methods: {})
197
+ end
198
+
199
+ def to_s
200
+ "#<#{self.class.name}: type=#{type}, private?=#{@private}, methods={#{methods.each_name.sort.join(", ")}}"
201
+ end
202
+
203
+ def update(type: self.type, methods: self.methods)
204
+ _ = self.class.new(type: type, private: private?, methods: methods)
205
+ end
206
+
207
+ def subst(s, type: nil)
208
+ ty =
209
+ if type
210
+ type
211
+ else
212
+ self.type.subst(s)
213
+ end
214
+
215
+ Shape.new(type: ty, private: private?, methods: methods.push_substitution(s))
216
+ end
217
+
218
+ def private?
219
+ @private
220
+ end
221
+
222
+ def public?
223
+ !private?
224
+ end
225
+
226
+ def public_shape
227
+ if public?
228
+ self
229
+ else
230
+ @public_shape ||= Shape.new(
231
+ type: type,
232
+ private: false,
233
+ methods: methods.public_methods
234
+ )
235
+ end
236
+ end
237
+ end
238
+ end
239
+ end