typeprof 0.5.3 → 0.8.0

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