typeprof 0.5.3 → 0.8.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 (208) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +6 -4
  3. data/doc/doc.ja.md +3 -4
  4. data/doc/doc.md +3 -4
  5. data/lib/typeprof/analyzer.rb +248 -166
  6. data/lib/typeprof/arguments.rb +12 -6
  7. data/lib/typeprof/builtin.rb +123 -23
  8. data/lib/typeprof/cli.rb +33 -34
  9. data/lib/typeprof/config.rb +6 -4
  10. data/lib/typeprof/container-type.rb +175 -112
  11. data/lib/typeprof/export.rb +23 -17
  12. data/lib/typeprof/import.rb +58 -53
  13. data/lib/typeprof/method.rb +59 -125
  14. data/lib/typeprof/type.rb +26 -14
  15. data/lib/typeprof/version.rb +1 -1
  16. data/smoke/alias.rb +1 -0
  17. data/smoke/any1.rb +1 -0
  18. data/smoke/any2.rb +1 -0
  19. data/smoke/arguments.rb +1 -0
  20. data/smoke/arguments2.rb +1 -0
  21. data/smoke/array-each.rb +1 -0
  22. data/smoke/array-each2.rb +1 -0
  23. data/smoke/array-each3.rb +2 -1
  24. data/smoke/array-ltlt.rb +1 -0
  25. data/smoke/array-ltlt2.rb +1 -0
  26. data/smoke/array-map.rb +1 -0
  27. data/smoke/array-map2.rb +1 -0
  28. data/smoke/array-map3.rb +1 -0
  29. data/smoke/array-mul.rb +1 -0
  30. data/smoke/array-plus1.rb +1 -0
  31. data/smoke/array-pop.rb +1 -0
  32. data/smoke/array-range-aref.rb +71 -0
  33. data/smoke/array-replace.rb +1 -0
  34. data/smoke/array-s-aref.rb +1 -0
  35. data/smoke/array1.rb +1 -0
  36. data/smoke/array10.rb +1 -0
  37. data/smoke/array11.rb +2 -1
  38. data/smoke/array12.rb +1 -0
  39. data/smoke/array13.rb +1 -0
  40. data/smoke/array14.rb +1 -0
  41. data/smoke/array2.rb +1 -0
  42. data/smoke/array4.rb +1 -0
  43. data/smoke/array5.rb +1 -0
  44. data/smoke/array6.rb +3 -2
  45. data/smoke/array7.rb +1 -0
  46. data/smoke/array8.rb +1 -1
  47. data/smoke/array9.rb +1 -0
  48. data/smoke/autoload.rb +14 -0
  49. data/smoke/backtrace.rb +1 -0
  50. data/smoke/block-ambiguous.rb +1 -0
  51. data/smoke/block-args1-rest.rb +1 -0
  52. data/smoke/block-args1.rb +1 -0
  53. data/smoke/block-args2-rest.rb +1 -0
  54. data/smoke/block-args2.rb +4 -3
  55. data/smoke/block-args3-rest.rb +1 -0
  56. data/smoke/block-args3.rb +5 -4
  57. data/smoke/block-blockarg.rb +2 -1
  58. data/smoke/block-kwarg.rb +1 -0
  59. data/smoke/block1.rb +1 -0
  60. data/smoke/block10.rb +1 -0
  61. data/smoke/block11.rb +1 -0
  62. data/smoke/block12.rb +1 -0
  63. data/smoke/block14.rb +1 -0
  64. data/smoke/block2.rb +1 -0
  65. data/smoke/block4.rb +1 -0
  66. data/smoke/block5.rb +2 -1
  67. data/smoke/block6.rb +1 -0
  68. data/smoke/block7.rb +1 -0
  69. data/smoke/block8.rb +1 -0
  70. data/smoke/block9.rb +1 -0
  71. data/smoke/blown.rb +1 -0
  72. data/smoke/break1.rb +1 -0
  73. data/smoke/break2.rb +1 -0
  74. data/smoke/case.rb +1 -0
  75. data/smoke/case2.rb +1 -0
  76. data/smoke/class_method3.rb +2 -0
  77. data/smoke/constant2.rb +2 -2
  78. data/smoke/constant3.rb +1 -0
  79. data/smoke/constant4.rb +1 -0
  80. data/smoke/context-sensitive1.rb +1 -0
  81. data/smoke/cvar.rb +1 -0
  82. data/smoke/define_method.rb +16 -0
  83. data/smoke/define_method2.rb +18 -0
  84. data/smoke/demo.rb +1 -0
  85. data/smoke/demo1.rb +1 -0
  86. data/smoke/demo10.rb +1 -0
  87. data/smoke/demo11.rb +1 -0
  88. data/smoke/demo2.rb +1 -0
  89. data/smoke/demo3.rb +1 -0
  90. data/smoke/demo5.rb +1 -1
  91. data/smoke/demo7.rb +1 -0
  92. data/smoke/demo8.rb +1 -0
  93. data/smoke/demo9.rb +2 -1
  94. data/smoke/dummy-execution1.rb +1 -0
  95. data/smoke/ensure1.rb +1 -0
  96. data/smoke/enumerator.rb +1 -0
  97. data/smoke/expandarray1.rb +1 -0
  98. data/smoke/expandarray2.rb +1 -0
  99. data/smoke/flow1.rb +1 -0
  100. data/smoke/flow2.rb +1 -0
  101. data/smoke/flow3.rb +1 -0
  102. data/smoke/flow5.rb +1 -0
  103. data/smoke/flow6.rb +1 -0
  104. data/smoke/flow7.rb +1 -0
  105. data/smoke/flow8.rb +1 -0
  106. data/smoke/freeze.rb +1 -0
  107. data/smoke/function.rb +1 -0
  108. data/smoke/gvar.rb +1 -0
  109. data/smoke/gvar2.rb +1 -0
  110. data/smoke/hash-fetch.rb +1 -0
  111. data/smoke/hash-merge-bang.rb +1 -0
  112. data/smoke/hash1.rb +3 -1
  113. data/smoke/hash2.rb +1 -0
  114. data/smoke/hash3.rb +1 -0
  115. data/smoke/hash4.rb +2 -1
  116. data/smoke/inheritance2.rb +2 -2
  117. data/smoke/initialize.rb +1 -0
  118. data/smoke/int_times.rb +1 -0
  119. data/smoke/integer.rb +1 -0
  120. data/smoke/ivar.rb +1 -0
  121. data/smoke/ivar2.rb +1 -1
  122. data/smoke/kernel-class.rb +2 -1
  123. data/smoke/keyword1.rb +1 -0
  124. data/smoke/keyword2.rb +1 -0
  125. data/smoke/keyword3.rb +1 -0
  126. data/smoke/keyword4.rb +1 -0
  127. data/smoke/keyword5.rb +1 -0
  128. data/smoke/kwrest.rb +12 -0
  129. data/smoke/kwrest.rbs +3 -0
  130. data/smoke/kwsplat1.rb +2 -1
  131. data/smoke/kwsplat2.rb +1 -0
  132. data/smoke/manual-rbs.rb +1 -0
  133. data/smoke/manual-rbs2.rb +1 -0
  134. data/smoke/masgn1.rb +1 -0
  135. data/smoke/masgn2.rb +1 -0
  136. data/smoke/masgn3.rb +1 -0
  137. data/smoke/method_in_branch.rb +1 -0
  138. data/smoke/method_missing.rb +28 -0
  139. data/smoke/multiple-superclass.rb +1 -1
  140. data/smoke/next1.rb +1 -0
  141. data/smoke/next2.rb +1 -0
  142. data/smoke/object-send1.rb +1 -0
  143. data/smoke/once.rb +1 -0
  144. data/smoke/optional1.rb +1 -0
  145. data/smoke/optional2.rb +1 -0
  146. data/smoke/optional3.rb +1 -0
  147. data/smoke/parameterizedd-self.rb +3 -2
  148. data/smoke/parameterizedd-self2.rb +15 -0
  149. data/smoke/pathname1.rb +1 -0
  150. data/smoke/pathname2.rb +1 -0
  151. data/smoke/pattern-match1.rb +1 -0
  152. data/smoke/pattern-match2.rb +1 -0
  153. data/smoke/proc.rb +1 -0
  154. data/smoke/proc2.rb +1 -0
  155. data/smoke/proc3.rb +1 -0
  156. data/smoke/proc4.rb +1 -0
  157. data/smoke/range.rb +1 -0
  158. data/smoke/rbs-alias.rb +1 -0
  159. data/smoke/rbs-attr.rb +3 -2
  160. data/smoke/rbs-attr2.rb +11 -0
  161. data/smoke/rbs-attr2.rbs +3 -0
  162. data/smoke/rbs-extend.rb +1 -0
  163. data/smoke/rbs-interface.rb +1 -0
  164. data/smoke/rbs-proc1.rb +1 -0
  165. data/smoke/rbs-proc2.rb +1 -0
  166. data/smoke/rbs-proc3.rb +1 -0
  167. data/smoke/rbs-record.rb +1 -0
  168. data/smoke/rbs-tyvar.rb +1 -0
  169. data/smoke/rbs-tyvar2.rb +1 -0
  170. data/smoke/rbs-tyvar3.rb +1 -0
  171. data/smoke/rbs-tyvar5.rb +1 -0
  172. data/smoke/rbs-tyvar6.rb +18 -0
  173. data/smoke/rbs-tyvar6.rbs +12 -0
  174. data/smoke/rbs-tyvar7.rb +12 -0
  175. data/smoke/rbs-tyvar7.rbs +7 -0
  176. data/smoke/rbs-vars.rb +1 -2
  177. data/smoke/redo1.rb +1 -0
  178. data/smoke/redo2.rb +1 -0
  179. data/smoke/req-keyword.rb +1 -0
  180. data/smoke/rescue1.rb +1 -0
  181. data/smoke/rescue2.rb +1 -0
  182. data/smoke/respond_to.rb +1 -0
  183. data/smoke/rest-farg.rb +1 -0
  184. data/smoke/rest1.rb +1 -0
  185. data/smoke/rest2.rb +1 -0
  186. data/smoke/rest3.rb +1 -0
  187. data/smoke/rest4.rb +1 -0
  188. data/smoke/rest5.rb +1 -0
  189. data/smoke/rest6.rb +1 -0
  190. data/smoke/retry1.rb +1 -0
  191. data/smoke/return.rb +1 -0
  192. data/smoke/step.rb +1 -0
  193. data/smoke/string-split.rb +1 -0
  194. data/smoke/struct.rb +2 -2
  195. data/smoke/struct2.rb +1 -0
  196. data/smoke/super1.rb +1 -0
  197. data/smoke/super4.rb +43 -0
  198. data/smoke/super5.rb +36 -0
  199. data/smoke/svar1.rb +1 -0
  200. data/smoke/symbol-proc.rb +1 -0
  201. data/smoke/tap1.rb +1 -0
  202. data/smoke/toplevel.rb +1 -0
  203. data/smoke/two-map.rb +1 -0
  204. data/smoke/type_var.rb +1 -0
  205. data/smoke/typed_method.rb +1 -0
  206. data/smoke/uninitialize-var.rb +1 -0
  207. data/smoke/union-recv.rb +2 -2
  208. metadata +18 -2
@@ -91,9 +91,9 @@ module TypeProf
91
91
  def conv_class(namespace, class_def, inner_classes)
92
92
  @scratch.namespace = namespace
93
93
 
94
- if class_def.superclass
95
- omit = @class_defs[class_def.superclass].klass_obj == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
96
- superclass = omit ? nil : @scratch.get_class_name(@class_defs[class_def.superclass].klass_obj)
94
+ if class_def.klass_obj.superclass != :__root__ && class_def.klass_obj.superclass
95
+ omit = class_def.klass_obj.superclass == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
96
+ superclass = omit ? nil : @scratch.get_class_name(class_def.klass_obj.superclass)
97
97
  end
98
98
 
99
99
  @scratch.namespace = class_def.name
@@ -105,12 +105,12 @@ module TypeProf
105
105
  consts[name] = ty.screen_name(@scratch)
106
106
  end
107
107
 
108
- included_mods = class_def.modules[false].filter_map do |mod_def, absolute_paths|
108
+ included_mods = class_def.modules[false].filter_map do |mod_def, _type_args, absolute_paths|
109
109
  next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
110
110
  Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
111
111
  end
112
112
 
113
- extended_mods = class_def.modules[true].filter_map do |mod_def, absolute_paths|
113
+ extended_mods = class_def.modules[true].filter_map do |mod_def, _type_args, absolute_paths|
114
114
  next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
115
115
  Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
116
116
  end
@@ -135,11 +135,12 @@ module TypeProf
135
135
  method_name = ctx.mid
136
136
  method_name = "self.#{ method_name }" if singleton
137
137
 
138
- iseq_methods[method_name] ||= []
139
- iseq_methods[method_name] << @scratch.show_method_signature(ctx)
138
+ iseq_methods[method_name] ||= [true, []]
139
+ iseq_methods[method_name][0] &&= mdef.pub_meth
140
+ iseq_methods[method_name][1] << @scratch.show_method_signature(ctx)
140
141
  end
141
142
  when AttrMethodDef
142
- next if Config.check_dir_filter(mdef.absolute_path) == :exclude
143
+ next if !mdef.absolute_path || Config.check_dir_filter(mdef.absolute_path) == :exclude
143
144
  mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
144
145
  method_name = mid
145
146
  method_name = "self.#{ mid }" if singleton
@@ -168,12 +169,14 @@ module TypeProf
168
169
  next unless var.to_s.start_with?("@")
169
170
  var = "self.#{ var }" if singleton
170
171
  next if attr_methods[[singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]
171
- [var, ty.screen_name(@scratch), entry.rbs_declared]
172
+ next if entry.rbs_declared
173
+ [var, ty.screen_name(@scratch)]
172
174
  end.compact
173
175
 
174
176
  cvars = cvars.map do |var, entry|
175
177
  next if entry.absolute_paths.all? {|path| Config.check_dir_filter(path) == :exclude }
176
- [var, entry.type.screen_name(@scratch), entry.rbs_declared]
178
+ next if entry.rbs_declared
179
+ [var, entry.type.screen_name(@scratch)]
177
180
  end.compact
178
181
 
179
182
  if !class_def.absolute_path || Config.check_dir_filter(class_def.absolute_path) == :exclude
@@ -277,14 +280,12 @@ module TypeProf
277
280
  output.puts indent + " extend #{ mod }"
278
281
  first = false
279
282
  end
280
- class_data.ivars.each do |var, ty, rbs_declared|
281
- s = rbs_declared ? "# " : " "
282
- output.puts indent + s + "#{ var } : #{ ty }" unless var.start_with?("_")
283
+ class_data.ivars.each do |var, ty|
284
+ output.puts indent + " #{ var } : #{ ty }" unless var.start_with?("_")
283
285
  first = false
284
286
  end
285
- class_data.cvars.each do |var, ty, rbs_declared|
286
- s = rbs_declared ? "# " : " "
287
- output.puts indent + s + "#{ var } : #{ ty }"
287
+ class_data.cvars.each do |var, ty|
288
+ output.puts indent + " #{ var } : #{ ty }"
288
289
  first = false
289
290
  end
290
291
  class_data.attr_methods.each do |(method_name, hidden), (kind, ty)|
@@ -296,8 +297,13 @@ module TypeProf
296
297
  output.puts indent + "# def #{ method_name } : #{ sigs }"
297
298
  first = false
298
299
  end
299
- class_data.iseq_methods.each do |method_name, sigs|
300
+ prev_pub_meth = true
301
+ class_data.iseq_methods.each do |method_name, (pub_meth, sigs)|
300
302
  sigs = sigs.sort.join("\n" + indent + " " * (method_name.size + 7) + "| ")
303
+ if prev_pub_meth != pub_meth
304
+ output.puts indent + " #{ pub_meth ? "public" : "private" }"
305
+ prev_pub_meth = pub_meth
306
+ end
301
307
  output.puts indent + " def #{ method_name } : #{ sigs }"
302
308
  first = false
303
309
  end
@@ -100,14 +100,19 @@ module TypeProf
100
100
  json = {}
101
101
 
102
102
  each_class_decl do |name, decls|
103
- super_class_name = get_super_class_name(name, decls)
104
103
  klass = conv_type_name(name)
105
- superclass = super_class_name ? conv_type_name(super_class_name) : nil
104
+ super_class_name, super_class_args = get_super_class(name, decls)
105
+ if super_class_name
106
+ name = conv_type_name(super_class_name)
107
+ type_args = super_class_args.map {|type| conv_type(type) }
108
+ superclass = [name, type_args]
109
+ end
106
110
 
107
111
  type_params = nil
108
112
  included_modules = []
109
113
  extended_modules = []
110
114
  methods = {}
115
+ attr_methods = {}
111
116
  ivars = {}
112
117
  cvars = {}
113
118
  rbs_sources = {}
@@ -143,15 +148,15 @@ module TypeProf
143
148
  end
144
149
  when RBS::AST::Members::AttrReader
145
150
  ty = conv_type(member.type)
146
- methods[[false, member.name]] = attr_reader_def(ty)
151
+ attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty)
147
152
  when RBS::AST::Members::AttrWriter
148
153
  ty = conv_type(member.type)
149
- methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
154
+ attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty)
150
155
  when RBS::AST::Members::AttrAccessor
151
156
  ty = conv_type(member.type)
152
- methods[[false, member.name]] = attr_reader_def(ty)
153
- methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
157
+ attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty)
154
158
  when RBS::AST::Members::Alias
159
+ # XXX: an alias to attr methods?
155
160
  if member.instance?
156
161
  method_def = methods[[false, member.old_name]]
157
162
  methods[[false, member.new_name]] = method_def if method_def
@@ -165,7 +170,8 @@ module TypeProf
165
170
  name = member.name
166
171
  if name.kind == :class
167
172
  mod = conv_type_name(name)
168
- included_modules << mod
173
+ type_args = member.args.map {|type| conv_type(type) }
174
+ included_modules << [mod, type_args]
169
175
  else
170
176
  # including an interface is not supported yet
171
177
  end
@@ -174,7 +180,8 @@ module TypeProf
174
180
  name = member.name
175
181
  if name.kind == :class
176
182
  mod = conv_type_name(name)
177
- extended_modules << mod
183
+ type_args = member.args.map {|type| conv_type(type) }
184
+ extended_modules << [mod, type_args]
178
185
  else
179
186
  # extending a module with an interface is not supported yet
180
187
  end
@@ -205,6 +212,7 @@ module TypeProf
205
212
  included_modules: included_modules,
206
213
  extended_modules: extended_modules,
207
214
  methods: methods,
215
+ attr_methods: attr_methods,
208
216
  ivars: ivars,
209
217
  cvars: cvars,
210
218
  rbs_sources: rbs_sources,
@@ -231,7 +239,7 @@ module TypeProf
231
239
  @all_env.class_decls[name].decls.each do |decl|
232
240
  decl = decl.decl
233
241
  next if decl.is_a?(RBS::AST::Declarations::Module)
234
- each_ancestor(decl) {|name| queue << [:visit, name] }
242
+ each_reference(decl) {|name| queue << [:visit, name] }
235
243
  end
236
244
  queue << [:visit, name.namespace.to_type_name] if !name.namespace.empty?
237
245
  end
@@ -246,24 +254,29 @@ module TypeProf
246
254
  end
247
255
  end
248
256
 
249
- def each_ancestor(decl, &blk)
257
+ def each_reference(decl, &blk)
250
258
  yield decl.name
251
- super_class = decl.super_class || RBS::BuiltinNames::Object
259
+ if decl.super_class
260
+ name = decl.super_class.name
261
+ else
262
+ name = RBS::BuiltinNames::Object.name
263
+ end
252
264
  return if decl.name == RBS::BuiltinNames::BasicObject.name
253
- return if decl.name == super_class.name
254
- @all_env.class_decls[super_class.name].decls.each do |decl|
255
- each_ancestor(decl.decl, &blk)
265
+ return if decl.name == name
266
+ @all_env.class_decls[name].decls.each do |decl|
267
+ each_reference(decl.decl, &blk)
256
268
  end
257
269
  end
258
270
 
259
- def get_super_class_name(name, decls)
271
+ def get_super_class(name, decls)
260
272
  return nil if name == RBS::BuiltinNames::BasicObject.name
261
273
 
262
274
  decls.each do |decl|
263
275
  decl = decl.decl
264
276
  case decl
265
277
  when RBS::AST::Declarations::Class
266
- return decl.super_class.name if decl.super_class
278
+ super_class = decl.super_class
279
+ return super_class.name, super_class.args if super_class
267
280
  when RBS::AST::Declarations::Module, RBS::AST::Declarations::Interface
268
281
  return nil
269
282
  else
@@ -271,7 +284,7 @@ module TypeProf
271
284
  end
272
285
  end
273
286
 
274
- return RBS::BuiltinNames::Object.name
287
+ return RBS::BuiltinNames::Object.name, []
275
288
  end
276
289
 
277
290
  def conv_method_def(rbs_method_types)
@@ -290,7 +303,7 @@ module TypeProf
290
303
  opt_kw_tys = func.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
291
304
  req_kw_tys = func.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
292
305
  rest_kw_ty = func.rest_keywords
293
- raise NotImplementedError if rest_kw_ty # XXX
306
+ rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty
294
307
 
295
308
  ret_ty = conv_type(func.return_type)
296
309
 
@@ -307,32 +320,12 @@ module TypeProf
307
320
  }
308
321
  end
309
322
 
310
- def attr_reader_def(ty)
311
- [{
312
- type_params: [],
313
- lead_tys: [],
314
- opt_tys: [],
315
- rest_ty: nil,
316
- req_kw_tys: {},
317
- opt_kw_tys: {},
318
- rest_kw_ty: nil,
319
- blk: nil,
320
- ret_ty: ty,
321
- }]
322
- end
323
-
324
- def attr_writer_def(ty)
325
- [{
326
- type_params: [],
327
- lead_tys: [ty],
328
- opt_tys: [],
329
- rest_ty: nil,
330
- req_kw_tys: {},
331
- opt_kw_tys: {},
332
- rest_kw_ty: nil,
333
- blk: nil,
334
- ret_ty: ty,
335
- }]
323
+ def attr_method_def(kind, name, ty)
324
+ {
325
+ kind: kind,
326
+ ivar: name,
327
+ ty: ty,
328
+ }
336
329
  end
337
330
 
338
331
  def conv_block(rbs_block)
@@ -467,8 +460,8 @@ module TypeProf
467
460
  def import(explicit = false)
468
461
  classes = @json[:classes].map do |classpath, cdef|
469
462
  type_params = cdef[:type_params]
470
- superclass = cdef[:superclass]
471
- members = cdef[:members]
463
+ superclass, superclass_type_args = cdef[:superclass]
464
+ members = cdef[:members]
472
465
 
473
466
  name = classpath.last
474
467
  superclass = path_to_klass(superclass) if superclass
@@ -492,23 +485,27 @@ module TypeProf
492
485
  end
493
486
  end
494
487
 
495
- [klass, members]
488
+ [klass, superclass_type_args, members]
496
489
  end
497
490
 
498
- classes.each do |klass, members|
491
+ classes.each do |klass, superclass_type_args, members|
492
+ @scratch.add_superclass_type_args!(klass, superclass_type_args&.map {|ty| conv_type(ty) })
499
493
  included_modules = members[:included_modules]
500
494
  extended_modules = members[:extended_modules]
501
495
  methods = members[:methods]
496
+ attr_methods = members[:attr_methods]
502
497
  ivars = members[:ivars]
503
498
  cvars = members[:cvars]
504
499
  rbs_sources = members[:rbs_sources]
505
500
 
506
- included_modules.each do |mod|
507
- @scratch.include_module(klass, path_to_klass(mod), false, nil)
501
+ included_modules.each do |mod, type_args|
502
+ type_args = type_args&.map {|ty| conv_type(ty) }
503
+ @scratch.include_module(klass, path_to_klass(mod), type_args, false, nil)
508
504
  end
509
505
 
510
- extended_modules.each do |mod|
511
- @scratch.include_module(klass, path_to_klass(mod), true, nil)
506
+ extended_modules.each do |mod, type_args|
507
+ type_args = type_args&.map {|ty| conv_type(ty) }
508
+ @scratch.include_module(klass, path_to_klass(mod), type_args, true, nil)
512
509
  end
513
510
 
514
511
  methods.each do |(singleton, method_name), mdef|
@@ -517,6 +514,14 @@ module TypeProf
517
514
  @scratch.add_method(klass, method_name, singleton, mdef)
518
515
  end
519
516
 
517
+ attr_methods.each do |(singleton, method_name), mdef|
518
+ kind = mdef[:kind]
519
+ ivar = mdef[:ivar]
520
+ ty = conv_type(mdef[:ty]).remove_type_vars
521
+ @scratch.add_attr_method(klass, nil, ivar, :"@#{ ivar }", kind)
522
+ @scratch.add_ivar_write!(Type::Instance.new(klass), :"@#{ ivar }", ty, nil)
523
+ end
524
+
520
525
  ivars.each do |ivar_name, ty|
521
526
  ty = conv_type(ty).remove_type_vars
522
527
  @scratch.add_ivar_write!(Type::Instance.new(klass), ivar_name, ty, nil)
@@ -583,7 +588,7 @@ module TypeProf
583
588
  req, lead_tys, opt_tys, ret_ty = blk
584
589
  lead_tys = lead_tys.map {|ty| conv_type(ty) }
585
590
  opt_tys = opt_tys.map {|ty| conv_type(ty) }
586
- msig = MethodSignature.new(lead_tys, opt_tys, nil, nil, nil, nil, nil)
591
+ msig = MethodSignature.new(lead_tys, opt_tys, nil, [], {}, nil, Type.nil)
587
592
  ret_ty = conv_type(ret_ty)
588
593
  ret = [Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Builtin[:proc])]
589
594
  ret << Type.nil unless req
@@ -4,12 +4,16 @@ module TypeProf
4
4
  end
5
5
 
6
6
  class ISeqMethodDef < MethodDef
7
- def initialize(iseq, cref)
7
+ def initialize(iseq, cref, outer_ep, pub_meth)
8
8
  @iseq = iseq
9
9
  raise if iseq.nil?
10
10
  @cref = cref
11
+ @outer_ep = outer_ep
12
+ @pub_meth = pub_meth
11
13
  end
12
14
 
15
+ attr_accessor :pub_meth
16
+
13
17
  def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
14
18
  recv = recv.base_type while recv.respond_to?(:base_type)
15
19
  recv = scratch.globalize_type(recv, caller_env, caller_ep)
@@ -25,8 +29,8 @@ module TypeProf
25
29
  end
26
30
 
27
31
  nctx = Context.new(@iseq, @cref, mid)
28
- callee_ep = ExecutionPoint.new(nctx, 0, nil)
29
- nenv = Env.new(StaticEnv.new(recv, blk_ty, false), locals, [], Utils::HashWrapper.new({}))
32
+ callee_ep = ExecutionPoint.new(nctx, 0, @outer_ep)
33
+ nenv = Env.new(StaticEnv.new(recv, blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
30
34
  alloc_site = AllocationSite.new(callee_ep)
31
35
  locals.each_with_index do |ty, i|
32
36
  alloc_site2 = alloc_site.add_id(i)
@@ -44,6 +48,14 @@ module TypeProf
44
48
  end
45
49
 
46
50
  def do_check_send(msig, recv, mid, ep, scratch)
51
+ klass, singleton = recv.method_dispatch_info
52
+ cur_subst = {}
53
+ direct_method = true
54
+ scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
55
+ direct_method &&= direct
56
+ cur_subst = Type.merge_substitution(cur_subst, subst)
57
+ end
58
+
47
59
  lead_num = @iseq.fargs_format[:lead_num] || 0
48
60
  post_num = @iseq.fargs_format[:post_num] || 0
49
61
  rest_start = @iseq.fargs_format[:rest_start]
@@ -67,7 +79,8 @@ module TypeProf
67
79
  post_start = @iseq.fargs_format[:post_start]
68
80
  rest_start = @iseq.fargs_format[:rest_start]
69
81
  kw_start = @iseq.fargs_format[:kwbits]
70
- kw_start -= @iseq.fargs_format[:keyword].size if kw_start
82
+ keyword = @iseq.fargs_format[:keyword]
83
+ kw_start -= keyword.size if kw_start
71
84
  kw_rest = @iseq.fargs_format[:kwrest]
72
85
  block_start = @iseq.fargs_format[:block_start]
73
86
 
@@ -77,18 +90,20 @@ module TypeProf
77
90
  callee_ep = ExecutionPoint.new(ctx, 0, nil)
78
91
 
79
92
  locals = [Type.nil] * @iseq.locals.size
80
- nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false), locals, [], Utils::HashWrapper.new({}))
93
+ nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
81
94
  alloc_site = AllocationSite.new(callee_ep)
82
95
  idx = 0
83
96
  msig.lead_tys.each_with_index do |ty, i|
84
97
  alloc_site2 = alloc_site.add_id(idx += 1)
85
98
  # nenv is top-level, so it is okay to call Type#localize directly
99
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
86
100
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
87
101
  nenv = nenv.local_update(i, ty)
88
102
  end
89
103
  if msig.opt_tys
90
104
  msig.opt_tys.each_with_index do |ty, i|
91
105
  alloc_site2 = alloc_site.add_id(idx += 1)
106
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
92
107
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
93
108
  nenv = nenv.local_update(lead_num + i, ty)
94
109
  end
@@ -96,19 +111,27 @@ module TypeProf
96
111
  if msig.rest_ty
97
112
  alloc_site2 = alloc_site.add_id(idx += 1)
98
113
  ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
114
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
99
115
  nenv, rest_ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
100
116
  nenv = nenv.local_update(rest_start, rest_ty)
101
117
  end
102
118
  if msig.post_tys
103
119
  msig.post_tys.each_with_index do |ty, i|
104
120
  alloc_site2 = alloc_site.add_id(idx += 1)
121
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
105
122
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
106
123
  nenv = nenv.local_update(post_start + i, ty)
107
124
  end
108
125
  end
109
126
  if msig.kw_tys
110
- msig.kw_tys.each_with_index do |(_, key, ty), i|
127
+ msig.kw_tys.each do |_, key, ty|
128
+ i = keyword.index(key)
129
+ unless i
130
+ # warn
131
+ next
132
+ end
111
133
  alloc_site2 = alloc_site.add_id(key)
134
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
112
135
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
113
136
  nenv = nenv.local_update(kw_start + i, ty)
114
137
  end
@@ -116,6 +139,7 @@ module TypeProf
116
139
  if msig.kw_rest_ty
117
140
  ty = msig.kw_rest_ty
118
141
  alloc_site2 = alloc_site.add_id(:**)
142
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
119
143
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
120
144
  nenv = nenv.local_update(kw_rest, ty)
121
145
  end
@@ -170,6 +194,15 @@ module TypeProf
170
194
 
171
195
  def do_send(recv_orig, mid, aargs, caller_ep, caller_env, scratch, &ctn)
172
196
  recv = scratch.globalize_type(recv_orig, caller_env, caller_ep)
197
+
198
+ klass, singleton = recv_orig.method_dispatch_info
199
+ cur_subst = {}
200
+ direct_method = true
201
+ scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
202
+ direct_method &&= direct
203
+ cur_subst = Type.merge_substitution(cur_subst, subst)
204
+ end
205
+
173
206
  found = false
174
207
  aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
175
208
  @sig_rets.each do |msig, ret_ty|
@@ -178,56 +211,15 @@ module TypeProf
178
211
  # XXX: support self type in msig
179
212
  subst = aargs.consistent_with_method_signature?(msig)
180
213
  next unless subst
214
+
215
+ if direct_method && recv_orig.is_a?(Type::Local)
216
+ ncaller_env = recv_orig.update_container_elem_type(subst, ncaller_env, caller_ep, scratch)
217
+ end
218
+
219
+ subst = Type.merge_substitution(subst, cur_subst)
181
220
  # need to check self tyvar?
182
221
  subst[Type::Var.new(:self)] = recv
183
- case
184
- when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
185
- tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
186
- tyvars.each_with_index do |tyvar, idx|
187
- ty = subst[tyvar]
188
- if ty
189
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
190
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
191
- elems.update(idx, ty)
192
- end
193
- end
194
- end
195
- tyvars.zip(recv.elems.elems) do |tyvar, elem|
196
- if subst[tyvar]
197
- subst[tyvar] = subst[tyvar].union(elem)
198
- else
199
- subst[tyvar] = elem
200
- end
201
- end
202
- when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
203
- tyvar_elem = Type::Var.new(:Elem)
204
- if subst[tyvar_elem]
205
- ty = subst[tyvar_elem]
206
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
207
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
208
- elems.update(nil, ty)
209
- end
210
- end
211
- subst.merge!({ tyvar_elem => recv.elems.squash })
212
- when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
213
- tyvar_k = Type::Var.new(:K)
214
- tyvar_v = Type::Var.new(:V)
215
- k_ty0, v_ty0 = recv.elems.squash
216
- if subst[tyvar_k] && subst[tyvar_v]
217
- k_ty = subst[tyvar_k]
218
- v_ty = subst[tyvar_v]
219
- k_ty0 = k_ty0.union(k_ty)
220
- v_ty0 = v_ty0.union(v_ty)
221
- alloc_site = AllocationSite.new(caller_ep)
222
- ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
223
- ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
224
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
225
- elems.update(k_ty, v_ty)
226
- end
227
- end
228
- # XXX: need to heuristically replace ret type Hash[K, V] with self, instead of conversative type?
229
- subst.merge!({ tyvar_k => k_ty0, tyvar_v => v_ty0 })
230
- end
222
+
231
223
  found = true
232
224
  if aargs.blk_ty.is_a?(Type::Proc)
233
225
  #raise NotImplementedError unless aargs.blk_ty.block_body.is_a?(ISeqBlock) # XXX
@@ -235,91 +227,33 @@ module TypeProf
235
227
  dummy_ep = ExecutionPoint.new(dummy_ctx, -1, caller_ep)
236
228
  s_recv = recv
237
229
  s_recv = s_recv.base_type while s_recv.respond_to?(:base_type)
238
- dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false), [], [], Utils::HashWrapper.new({}))
230
+ dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false, true), [], [], Utils::HashWrapper.new({}))
239
231
  if msig.blk_ty.is_a?(Type::Proc)
240
232
  scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn)
241
- nfargs = msig.blk_ty.block_body.msig
233
+ bsig = msig.blk_ty.block_body.msig
242
234
  alloc_site = AllocationSite.new(caller_ep).add_id(self)
243
- nlead_tys = (nfargs.lead_tys + nfargs.opt_tys).map.with_index do |ty, i|
244
- if recv.is_a?(Type::Array)
245
- tyvar_elem = Type::Var.new(:Elem)
246
- ty = ty.substitute(subst.merge({ tyvar_elem => recv.elems.squash_or_any }), Config.options[:type_depth_limit])
247
- else
248
- ty = ty.substitute(subst, Config.options[:type_depth_limit])
249
- end
250
- ty = ty.remove_type_vars
251
- alloc_site2 = alloc_site.add_id(i)
252
- dummy_env, ty = scratch.localize_type(ty, dummy_env, dummy_ep, alloc_site2)
235
+ nlead_tys = (bsig.lead_tys + bsig.opt_tys).map.with_index do |ty, i|
236
+ ty = ty.substitute(subst, Config.options[:type_depth_limit]).remove_type_vars
237
+ dummy_env, ty = scratch.localize_type(ty, dummy_env, dummy_ep, alloc_site.add_id(i))
253
238
  ty
254
239
  end
255
- 0.upto(nfargs.opt_tys.size) do |n|
256
- naargs = ActualArguments.new(nlead_tys[0, nfargs.lead_tys.size + n], nil, {}, Type.nil) # XXX: support block to block?
240
+ 0.upto(bsig.opt_tys.size) do |n|
241
+ naargs = ActualArguments.new(nlead_tys[0, bsig.lead_tys.size + n], nil, {}, Type.nil) # XXX: support block to block?
257
242
  scratch.do_invoke_block(aargs.blk_ty, naargs, dummy_ep, dummy_env) do |blk_ret_ty, _ep, _env|
258
243
  subst2 = Type.match?(blk_ret_ty, msig.blk_ty.block_body.ret_ty)
259
244
  if subst2
260
245
  subst2 = Type.merge_substitution(subst, subst2)
261
- case
262
- when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
263
- tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
264
- tyvars.each_with_index do |tyvar, idx|
265
- ty = subst2[tyvar]
266
- if ty
267
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
268
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
269
- elems.update(idx, ty)
270
- end
271
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
272
- end
273
- end
274
- tyvars.zip(recv.elems.elems) do |tyvar, elem|
275
- if subst2[tyvar]
276
- subst2[tyvar] = subst2[tyvar].union(elem)
277
- else
278
- subst2[tyvar] = elem
279
- end
280
- end
281
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
282
- when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
283
- tyvar_elem = Type::Var.new(:Elem)
284
- if subst2[tyvar_elem]
285
- ty = subst2[tyvar_elem]
286
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
287
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
288
- elems.update(nil, ty)
289
- end
290
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
291
- end
292
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
293
- when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
294
- tyvar_k = Type::Var.new(:K)
295
- tyvar_v = Type::Var.new(:V)
296
- k_ty0, v_ty0 = recv.elems.squash
297
- if subst2[tyvar_k] && subst2[tyvar_v]
298
- k_ty = subst2[tyvar_k]
299
- v_ty = subst2[tyvar_v]
300
- k_ty0 = k_ty0.union(k_ty)
301
- v_ty0 = v_ty0.union(v_ty)
302
- alloc_site = AllocationSite.new(caller_ep)
303
- ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
304
- ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
305
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
306
- elems.update(k_ty, v_ty)
307
- end
308
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
309
- end
310
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
311
- else
312
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
246
+ if direct_method && recv_orig.is_a?(Type::Local)
247
+ ncaller_env = recv_orig.update_container_elem_type(subst2, ncaller_env, caller_ep, scratch)
248
+ scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
313
249
  end
250
+ ret_ty2 = ret_ty.substitute(subst2, Config.options[:type_depth_limit]).remove_type_vars
314
251
  else
315
- # raise "???"
316
- # XXX: need warning
317
- ret_ty = Type.any
252
+ ret_ty2 = Type.any
318
253
  end
319
- ret_ty = ret_ty.remove_type_vars
320
254
  # XXX: check the return type from the block
321
255
  # sig.blk_ty.block_body.ret_ty.eql?(_ret_ty) ???
322
- scratch.add_return_value!(dummy_ctx, ret_ty)
256
+ scratch.add_return_value!(dummy_ctx, ret_ty2)
323
257
  end
324
258
  # scratch.add_return_value!(dummy_ctx, ret_ty) ?
325
259
  # This makes `def foo; 1.times { return "str" }; end` return Integer|String