steep 1.8.0.dev.2 → 1.8.0.pre.1

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/bin/mem_graph.rb +67 -0
  4. data/bin/mem_prof.rb +102 -0
  5. data/bin/stackprof_test.rb +19 -0
  6. data/bin/steep-check.rb +251 -0
  7. data/lib/steep/annotation_parser.rb +1 -1
  8. data/lib/steep/ast/builtin.rb +5 -5
  9. data/lib/steep/ast/node/type_application.rb +7 -6
  10. data/lib/steep/ast/types/any.rb +1 -9
  11. data/lib/steep/ast/types/boolean.rb +8 -16
  12. data/lib/steep/ast/types/bot.rb +2 -10
  13. data/lib/steep/ast/types/class.rb +1 -13
  14. data/lib/steep/ast/types/factory.rb +101 -85
  15. data/lib/steep/ast/types/instance.rb +1 -13
  16. data/lib/steep/ast/types/intersection.rb +8 -15
  17. data/lib/steep/ast/types/literal.rb +2 -8
  18. data/lib/steep/ast/types/logic.rb +3 -24
  19. data/lib/steep/ast/types/name.rb +5 -16
  20. data/lib/steep/ast/types/nil.rb +3 -12
  21. data/lib/steep/ast/types/proc.rb +4 -13
  22. data/lib/steep/ast/types/record.rb +21 -12
  23. data/lib/steep/ast/types/self.rb +1 -13
  24. data/lib/steep/ast/types/shared_instance.rb +11 -0
  25. data/lib/steep/ast/types/top.rb +1 -9
  26. data/lib/steep/ast/types/tuple.rb +4 -10
  27. data/lib/steep/ast/types/union.rb +10 -15
  28. data/lib/steep/ast/types/var.rb +4 -13
  29. data/lib/steep/ast/types/void.rb +2 -10
  30. data/lib/steep/diagnostic/ruby.rb +4 -4
  31. data/lib/steep/drivers/check.rb +11 -14
  32. data/lib/steep/drivers/checkfile.rb +8 -10
  33. data/lib/steep/drivers/stats.rb +17 -13
  34. data/lib/steep/drivers/utils/driver_helper.rb +24 -3
  35. data/lib/steep/drivers/watch.rb +3 -3
  36. data/lib/steep/interface/builder.rb +162 -138
  37. data/lib/steep/interface/method_type.rb +12 -20
  38. data/lib/steep/interface/shape.rb +66 -10
  39. data/lib/steep/interface/substitution.rb +2 -0
  40. data/lib/steep/interface/type_param.rb +20 -7
  41. data/lib/steep/located_value.rb +20 -0
  42. data/lib/steep/server/change_buffer.rb +5 -7
  43. data/lib/steep/server/custom_methods.rb +61 -0
  44. data/lib/steep/server/delay_queue.rb +8 -1
  45. data/lib/steep/server/interaction_worker.rb +10 -5
  46. data/lib/steep/server/lsp_formatter.rb +8 -6
  47. data/lib/steep/server/master.rb +193 -140
  48. data/lib/steep/server/type_check_worker.rb +18 -19
  49. data/lib/steep/server/work_done_progress.rb +64 -0
  50. data/lib/steep/services/completion_provider.rb +24 -22
  51. data/lib/steep/services/goto_service.rb +3 -2
  52. data/lib/steep/services/hover_provider/ruby.rb +7 -6
  53. data/lib/steep/services/signature_help_provider.rb +7 -6
  54. data/lib/steep/services/signature_service.rb +1 -1
  55. data/lib/steep/services/type_check_service.rb +3 -3
  56. data/lib/steep/signature/validator.rb +17 -20
  57. data/lib/steep/subtyping/check.rb +105 -55
  58. data/lib/steep/subtyping/constraints.rb +11 -15
  59. data/lib/steep/type_construction.rb +100 -100
  60. data/lib/steep/type_inference/block_params.rb +6 -6
  61. data/lib/steep/type_inference/logic_type_interpreter.rb +11 -7
  62. data/lib/steep/type_inference/method_call.rb +3 -3
  63. data/lib/steep/type_inference/method_params.rb +1 -1
  64. data/lib/steep/type_inference/send_args.rb +1 -1
  65. data/lib/steep/typing.rb +158 -102
  66. data/lib/steep/version.rb +1 -1
  67. data/lib/steep.rb +28 -3
  68. data/steep.gemspec +2 -2
  69. metadata +16 -9
  70. data/lib/steep/type_inference/context_array.rb +0 -112
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eff62e36ae34f76bafc5eb5ec8425ba373dd9ab64ae880537d65b96b4581970c
4
- data.tar.gz: b0dc7b3d10b83a0e188a211f40c3a91eb3e146138da328079c84639b92c87bb8
3
+ metadata.gz: c87015f545300c9c126b0121aa9534db083c157fbd791b7117006b6683bdc05d
4
+ data.tar.gz: 6bb606ac1b4cc9cdd6364745c02f878714cdf2ca2d61079376a3ea50fbf4b9ba
5
5
  SHA512:
6
- metadata.gz: 6e5d7e9e19bf782a8a03842eed077030a9f72eeb5f570ef23110658916f2d4c93c1090e3f3f6017957c80ef1a74c4c7a33bbc295316fe4afb47309cf47c2bcac
7
- data.tar.gz: 66a14f3ec60c294a90e85bde099eb40224f22a99493f121bd8378e288affd7ad32a7ee8e1aff23915dd373768c4a35657fd92e14c7afe9e9cbe244c18d36d96c
6
+ metadata.gz: 4787c76c6049f2e1a2a9856d26dd0157419a2f4258a185559d0fe676500380089d75b30f916e353836f0e6af4eab16e2d977a9be5798bcfae1d13f8902d21491
7
+ data.tar.gz: 462bb7747747fd5a34bf3205cd71d94f22beb4efd4407e5e59fbc31c049583b8350cdac262591319ad2ed09d802d94e3ff42d2f9c54ba0addff5547c7258f898
data/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.8.0.pre.1 (2024-09-17)
4
+
5
+ ### Type checker core
6
+
7
+ * Fix some subtyping problems ([#1221](https://github.com/soutaro/steep/pull/1221))
8
+ * Support optional keys in record types ([#1223](https://github.com/soutaro/steep/pull/1223))
9
+ * Revert implicit generic upper bound ([#1220](https://github.com/soutaro/steep/pull/1220))
10
+ * Improve generics ([#1216](https://github.com/soutaro/steep/pull/1216))
11
+ * Delete meta data from `MethodType` and `Types::*` ([#1201](https://github.com/soutaro/steep/pull/1201))
12
+ * Delete `ContextArray` ([#1199](https://github.com/soutaro/steep/pull/1199))
13
+ * Fix shape calculation error ([#1197](https://github.com/soutaro/steep/pull/1197))
14
+ * Skip `#:` syntax in `Data.define` and `Struct.new` ([#1196](https://github.com/soutaro/steep/pull/1196))
15
+ * Support literals for Rational and Complex ([#1178](https://github.com/soutaro/steep/pull/1178))
16
+ * Ignore type assertions on arguments/receiver on `def`/`defs` ([#1179](https://github.com/soutaro/steep/pull/1179))
17
+ * Ignore `#:` annotation on `attr_*` calls ([#1176](https://github.com/soutaro/steep/pull/1176))
18
+
19
+ ### Commandline tool
20
+
21
+ * Improve performance when there are many files ([#1184](https://github.com/soutaro/steep/pull/1184))
22
+ * Fix type errors ([#1183](https://github.com/soutaro/steep/pull/1183))
23
+
24
+ ### Language server
25
+
26
+ * Make type checking a LSP request, not a LSP notification ([#1218](https://github.com/soutaro/steep/pull/1218))
27
+ * No `timeout: nil` ([#1217](https://github.com/soutaro/steep/pull/1217))
28
+ * Print `loading project` message via LSP ([#1213](https://github.com/soutaro/steep/pull/1213))
29
+ * Load files in main process ([#1206](https://github.com/soutaro/steep/pull/1206))
30
+
31
+ ### Miscellaneous
32
+
33
+ * Drop Ruby 3.0 ([#1225](https://github.com/soutaro/steep/pull/1225))
34
+ * Add `bin/steep-check` for profiling ([#1198](https://github.com/soutaro/steep/pull/1198))
35
+
3
36
  ## 1.7.1 (2024-06-12)
4
37
 
5
38
  ### Type checker core
data/bin/mem_graph.rb ADDED
@@ -0,0 +1,67 @@
1
+ class MemGraph
2
+ attr_reader :edges
3
+
4
+ attr_reader :checked
5
+
6
+ attr_reader :generation
7
+
8
+ def initialize(generation)
9
+ @generation = generation
10
+ @edges = []
11
+ @checked = Set.new.compare_by_identity
12
+ @checked << self
13
+ @checked << edges
14
+ @checked << checked
15
+ end
16
+
17
+ IVARS = Object.instance_method(:instance_variables)
18
+ IVGET = Object.instance_method(:instance_variable_get)
19
+
20
+ def traverse(object)
21
+ return if checked.include?(object)
22
+ checked << object
23
+
24
+ case object
25
+ when Array
26
+ object.each do |value|
27
+ insert_edge(object, value)
28
+ traverse(value)
29
+ end
30
+ when Hash
31
+ object.each do |key, value|
32
+ insert_edge(object, key)
33
+ insert_edge(object, value)
34
+
35
+ traverse(key)
36
+ traverse(value)
37
+ end
38
+ else
39
+ IVARS.bind_call(object).each do |name|
40
+ if name.is_a?(Symbol)
41
+ value = IVGET.bind_call(object, name)
42
+ traverse(value)
43
+ insert_edge(object, value)
44
+ else
45
+ STDERR.puts "Unexpected instance variable name: #{name} in #{object.class}"
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ def insert_edge(source, dest)
52
+ case dest
53
+ when Integer, Symbol, nil, true, false, Float
54
+ else
55
+ edges << [
56
+ "#{source.class}(#{source.__id__})",
57
+ "#{dest.class}(#{dest.__id__})",
58
+ ]
59
+ end
60
+ end
61
+
62
+ def dot
63
+ "digraph G {\n" + edges.uniq.map do |source, dest|
64
+ " #{source} -> #{dest};"
65
+ end.join("\n") + "}"
66
+ end
67
+ end
data/bin/mem_prof.rb ADDED
@@ -0,0 +1,102 @@
1
+ require "objspace"
2
+
3
+ class MemProf
4
+ attr_reader :generation
5
+
6
+ def initialize
7
+ end
8
+
9
+ def self.trace(io: STDOUT, &block)
10
+ profiler = MemProf.new
11
+ profiler.start
12
+
13
+ begin
14
+ ret = yield
15
+ rescue
16
+ ObjectSpace.trace_object_allocations_stop
17
+ ObjectSpace.trace_object_allocations_clear
18
+ raise
19
+ end
20
+
21
+ allocated, retained, collected = profiler.stop
22
+
23
+ counts = {}
24
+ collected.each do |id, entry|
25
+ counts[entry] ||= 0
26
+ counts[entry] += 1
27
+ end
28
+
29
+ counts.keys.sort_by {|entry| -counts[entry] }.take(200).each do |entry|
30
+ count = counts.fetch(entry)
31
+ io.puts "#{entry[0]},#{entry[1]},#{entry[2]},#{count}"
32
+ end
33
+
34
+ STDERR.puts "Total allocated: #{allocated.size}"
35
+ STDERR.puts "Total retained: #{retained.size}"
36
+ STDERR.puts "Total collected: #{collected.size}"
37
+
38
+ ret
39
+ end
40
+
41
+ def start
42
+ GC.disable
43
+ 3.times { GC.start }
44
+ GC.start
45
+
46
+ @generation = GC.count
47
+ ObjectSpace.trace_object_allocations_start
48
+ end
49
+
50
+ def stop
51
+ ObjectSpace.trace_object_allocations_stop
52
+
53
+ allocated = objects()
54
+ retained = {}
55
+
56
+ GC.enable
57
+ GC.start
58
+ GC.start
59
+ GC.start
60
+
61
+ ObjectSpace.each_object do |obj|
62
+ next unless ObjectSpace.allocation_generation(obj) == generation
63
+ if o = allocated[obj.__id__]
64
+ retained[obj.__id__] = o
65
+ end
66
+ end
67
+
68
+ # ObjectSpace.trace_object_allocations_clear
69
+
70
+ collected = {}
71
+ allocated.each do |id, state|
72
+ collected[id] = state unless retained.key?(id)
73
+ end
74
+
75
+ [allocated, retained, collected]
76
+ end
77
+
78
+ def objects(hash = {})
79
+ ObjectSpace.each_object do |obj|
80
+ next unless ObjectSpace.allocation_generation(obj) == generation
81
+
82
+ file = ObjectSpace.allocation_sourcefile(obj) || "(no name)"
83
+ line = ObjectSpace.allocation_sourceline(obj)
84
+ klass = object_class(obj)
85
+
86
+ hash[obj.__id__] = [file, line, klass]
87
+ end
88
+
89
+ hash
90
+ end
91
+
92
+ KERNEL_CLASS_METHOD = Kernel.instance_method(:class)
93
+ def object_class(obj)
94
+ klass = obj.class rescue nil
95
+
96
+ unless Class === klass
97
+ # attempt to determine the true Class when .class returns something other than a Class
98
+ klass = KERNEL_CLASS_METHOD.bind_call(obj)
99
+ end
100
+ klass
101
+ end
102
+ end
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "stackprof"
4
+
5
+ mode = (ENV["STEEP_STACKPROF_MODE"] || :cpu).to_sym
6
+ out = ENV["STEEP_STACKPROF_OUT"] || "tmp/stackprof-#{mode}-test.dump"
7
+ interval = ENV["STEEP_STACKPROF_INTERVAL"]&.to_i || 1000
8
+
9
+ STDERR.puts "Running profiler: mode => #{mode}, out => #{out}"
10
+ StackProf.run(mode: mode, out: out, raw: true, interval: interval) do
11
+ # 10.times do
12
+ # 1_000.times do
13
+ # Array.new(1_000_000)
14
+ # end
15
+ # sleep 0.1
16
+ # end
17
+
18
+ sleep 5
19
+ end
@@ -0,0 +1,251 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pathname'
4
+
5
+ $LOAD_PATH << Pathname(__dir__) + "../lib"
6
+
7
+ require 'steep'
8
+ require "fileutils"
9
+ require "optparse"
10
+
11
+ puts <<MESSAGE
12
+ This is a single-threaded and one-process type checker for profiling.
13
+ It runs really slow because it's not parallelized, but it's easier to profiling and analyzing the result.
14
+
15
+ $ bundle exec bin/steep-check --target=app
16
+ $ bundle exec bin/steep-check --target=app files...
17
+
18
+ MESSAGE
19
+
20
+ steep_file_path = Pathname("Steepfile")
21
+ target_name = nil #: Symbol?
22
+ profile_mode = :none #: Symbol?
23
+
24
+ OptionParser.new do |opts|
25
+ opts.on("--steepfile=FILE") do |file|
26
+ steep_file_path = Pathname(file)
27
+ end
28
+ opts.on("--target=TARGET") do |target|
29
+ target_name = target.to_sym
30
+ end
31
+ opts.on("--profile=MODE", "vernier, memory, stackprof, none, majo, memory2, dumpall") do |mode|
32
+ profile_mode = mode.to_sym
33
+ end
34
+ end.parse!(ARGV)
35
+
36
+ command_line_args = ARGV.dup
37
+
38
+ class Command
39
+ include Steep
40
+
41
+ attr_reader :project, :target
42
+
43
+ def initialize(steep_file_path:, target_name:)
44
+ @project = Project.new(steepfile_path: steep_file_path).tap do |project|
45
+ Project::DSL.parse(project, steep_file_path.read, filename: steep_file_path.to_s)
46
+ end
47
+
48
+ if target_name
49
+ @target = project.targets.find { _1.name == target_name}
50
+ else
51
+ @target = project.targets[0]
52
+ end
53
+
54
+ unless target
55
+ raise "!! Cannot find a target with #{target_name}: targets=[#{project.targets.map(&:name).join(", ")}]"
56
+ end
57
+ end
58
+
59
+ def load_signatures()
60
+ file_loader = Steep::Services::FileLoader.new(base_dir: project.base_dir)
61
+
62
+ signature_files = {}
63
+ file_loader.each_path_in_patterns(target.signature_pattern) do |path|
64
+ signature_files[path] = path.read
65
+ end
66
+
67
+ target.options.load_collection_lock
68
+
69
+ signature_service = Steep::Project::Target.construct_env_loader(options: target.options, project: project).yield_self do |loader|
70
+ Steep::Services::SignatureService.load_from(loader)
71
+ end
72
+
73
+ env = signature_service.latest_env
74
+
75
+ new_decls = Set[]
76
+
77
+ signature_files.each do |path, content|
78
+ buffer = RBS::Buffer.new(name: path.to_s, content: content)
79
+ buffer, dirs, decls = RBS::Parser.parse_signature(buffer)
80
+ env.add_signature(buffer: buffer, directives: dirs, decls: decls)
81
+ new_decls.merge(decls)
82
+ end
83
+
84
+ env.resolve_type_names(only: new_decls)
85
+ end
86
+
87
+ def type_check_files(command_line_args, env)
88
+ file_loader = Steep::Services::FileLoader.new(base_dir: project.base_dir)
89
+
90
+ source_files = {}
91
+ file_loader.each_path_in_patterns(target.source_pattern, command_line_args) do |path|
92
+ source_files[path] = path.read
93
+ end
94
+
95
+ definition_builder = RBS::DefinitionBuilder.new(env: env)
96
+ factory = AST::Types::Factory.new(builder: definition_builder)
97
+ builder = Interface::Builder.new(factory)
98
+ subtyping = Subtyping::Check.new(builder: builder)
99
+
100
+ typings = {}
101
+
102
+ source_files.each do |path, content|
103
+ source = Source.parse(content, path: path, factory: factory)
104
+
105
+ self_type = AST::Builtin::Object.instance_type
106
+
107
+ annotations = source.annotations(block: source.node, factory: factory, context: nil)
108
+ resolver = RBS::Resolver::ConstantResolver.new(builder: factory.definition_builder)
109
+ const_env = TypeInference::ConstantEnv.new(factory: factory, context: nil, resolver: resolver)
110
+
111
+ type_env = TypeInference::TypeEnvBuilder.new(
112
+ TypeInference::TypeEnvBuilder::Command::ImportGlobalDeclarations.new(factory),
113
+ TypeInference::TypeEnvBuilder::Command::ImportInstanceVariableAnnotations.new(annotations),
114
+ TypeInference::TypeEnvBuilder::Command::ImportConstantAnnotations.new(annotations),
115
+ TypeInference::TypeEnvBuilder::Command::ImportLocalVariableAnnotations.new(annotations)
116
+ ).build(TypeInference::TypeEnv.new(const_env))
117
+
118
+ context = TypeInference::Context.new(
119
+ block_context: nil,
120
+ method_context: nil,
121
+ module_context: TypeInference::Context::ModuleContext.new(
122
+ instance_type: AST::Builtin::Object.instance_type,
123
+ module_type: AST::Builtin::Object.module_type,
124
+ implement_name: nil,
125
+ nesting: nil,
126
+ class_name: AST::Builtin::Object.module_name,
127
+ instance_definition: factory.definition_builder.build_instance(AST::Builtin::Object.module_name),
128
+ module_definition: factory.definition_builder.build_singleton(AST::Builtin::Object.module_name)
129
+ ),
130
+ break_context: nil,
131
+ self_type: self_type,
132
+ type_env: type_env,
133
+ call_context: TypeInference::MethodCall::TopLevelContext.new(),
134
+ variable_context: TypeInference::Context::TypeVariableContext.empty
135
+ )
136
+
137
+ typing = Typing.new(source: source, root_context: context, cursor: nil)
138
+ construction = TypeConstruction.new(checker: subtyping, source: source, annotations: annotations, context: context, typing: typing)
139
+
140
+ construction.synthesize(source.node)
141
+ typings[path] = typing
142
+ end
143
+
144
+ typings
145
+ end
146
+ end
147
+
148
+ command = Command.new(steep_file_path: Pathname.pwd + steep_file_path, target_name: target_name)
149
+
150
+ puts ">> Loading RBS files..."
151
+ env = command.load_signatures()
152
+
153
+ puts ">> Type checking files with #{profile_mode}..."
154
+
155
+ typings = nil
156
+
157
+ GC.start(immediate_sweep: true, immediate_mark: true, full_mark: true)
158
+ # GC.config[:rgengc_allow_major_gc] = false
159
+
160
+ case profile_mode
161
+ when :vernier
162
+ require "vernier"
163
+ out = Pathname.pwd + "tmp/typecheck-#{Process.pid}.vernier.json"
164
+ puts ">> Profiling with vernier: #{out}"
165
+ Vernier.profile(out: out.to_s) do
166
+ typings = command.type_check_files(command_line_args, env)
167
+ end
168
+
169
+ when :memory
170
+ require 'memory_profiler'
171
+ out = Pathname.pwd + "tmp/typecheck-#{Process.pid}.memory.txt"
172
+ puts ">> Profiling with memory_profiler: #{out}"
173
+ classes = nil
174
+ report = MemoryProfiler.report(trace: classes) do
175
+ typings = command.type_check_files(command_line_args, env)
176
+ end
177
+ report.pretty_print(to_file: out, detailed_report: true, scale_bytes: true, retained_strings: false, allocated_strings: false)
178
+
179
+ when :memory2
180
+ require_relative 'mem_prof'
181
+ out = Pathname.pwd + "tmp/typecheck-#{Process.pid}.memory2.csv"
182
+ puts ">> Profiling with mem_prof: #{out}"
183
+ generation = nil
184
+ out.open("w") do |io|
185
+ MemProf.trace(io: io) do
186
+ generation = GC.count
187
+ typings = command.type_check_files(command_line_args, env)
188
+ end
189
+ end
190
+
191
+ require_relative 'mem_graph'
192
+ graph = MemGraph.new(generation)
193
+ ObjectSpace.each_object do |obj|
194
+ if ObjectSpace.allocation_generation(obj) == generation
195
+ graph.traverse(obj)
196
+ end
197
+ end
198
+ (Pathname.pwd + "objects-#{Process.pid}.dot").write(graph.dot)
199
+
200
+ when :stackprof
201
+ require "stackprof"
202
+ out = Pathname.pwd + "tmp/typecheck-#{Process.pid}.stackprof"
203
+ puts ">> Profiling with stackprof: #{out}"
204
+ StackProf.run(out: out, raw: true, interval: 1000) do
205
+ typings = command.type_check_files(command_line_args, env)
206
+ end
207
+
208
+ when :majo
209
+ require "majo"
210
+ out = Pathname.pwd + "tmp/typecheck-#{Process.pid}.majo.csv"
211
+ puts ">> Profiling with majo: #{out}"
212
+
213
+ result = Majo.run do
214
+ typings = command.type_check_files(command_line_args, env)
215
+ end
216
+
217
+ out.open("w") do |io|
218
+ result.report(out: io, formatter: :csv)
219
+ end
220
+
221
+ when :dumpall
222
+ require "objspace"
223
+ out = Pathname.pwd + "tmp/dumpall-#{Process.pid}.json"
224
+ puts ">> Profiling with dumpall: #{out}"
225
+ ObjectSpace.trace_object_allocations_start
226
+ typings = command.type_check_files(command_line_args, env)
227
+ out.open('w+') do |io|
228
+ ObjectSpace.dump_all(output: io)
229
+ end
230
+
231
+ when :none
232
+
233
+ pp rbs_method_types: ObjectSpace.each_object(RBS::MethodType).count
234
+ GC.start(immediate_sweep: true, immediate_mark: true, full_mark: true)
235
+
236
+ pp defs: ObjectSpace.each_object(RBS::AST::Members::MethodDefinition).count
237
+ pp aliases: ObjectSpace.each_object(RBS::AST::Members::Alias).count
238
+ pp attr_reader: ObjectSpace.each_object(RBS::AST::Members::AttrReader).count
239
+ pp attr_writer: ObjectSpace.each_object(RBS::AST::Members::AttrWriter).count
240
+ pp attr_accessor: ObjectSpace.each_object(RBS::AST::Members::AttrAccessor).count
241
+
242
+ Steep.measure("type check", level: :fatal) do
243
+ GC.disable
244
+ typings = command.type_check_files(command_line_args, env)
245
+
246
+ pp steep_method_types: ObjectSpace.each_object(Steep::Interface::MethodType).count, rbs_method_types: ObjectSpace.each_object(RBS::MethodType).count
247
+ pp any: ObjectSpace.each_object(Steep::AST::Types::Any).count, void: ObjectSpace.each_object(Steep::AST::Types::Void).count, self: ObjectSpace.each_object(Steep::AST::Types::Self).count
248
+ end
249
+ end
250
+
251
+ typings.size
@@ -91,7 +91,7 @@ module Steep
91
91
  name = match[:name] or raise
92
92
  type = match[:type] or raise
93
93
 
94
- method_type = factory.method_type(RBS::Parser.parse_method_type(type) || raise, method_decls: Set[])
94
+ method_type = factory.method_type(RBS::Parser.parse_method_type(type) || raise)
95
95
 
96
96
  AST::Annotation::MethodType.new(name: name.to_sym,
97
97
  type: method_type,
@@ -67,23 +67,23 @@ module Steep
67
67
  Proc = Type.new("::Proc")
68
68
 
69
69
  def self.nil_type
70
- AST::Types::Nil.new
70
+ AST::Types::Nil.instance
71
71
  end
72
72
 
73
73
  def self.any_type
74
- AST::Types::Any.new
74
+ AST::Types::Any.instance
75
75
  end
76
76
 
77
77
  def self.bool_type
78
- AST::Types::Boolean.new
78
+ AST::Types::Boolean.instance
79
79
  end
80
80
 
81
81
  def self.bottom_type
82
- AST::Types::Bot.new
82
+ AST::Types::Bot.instance
83
83
  end
84
84
 
85
85
  def self.top_type
86
- AST::Types::Top.new
86
+ AST::Types::Top.instance
87
87
  end
88
88
 
89
89
  def self.optional(type)
@@ -27,14 +27,15 @@ module Steep
27
27
  def types(context, subtyping, type_vars)
28
28
  resolver = RBS::Resolver::TypeNameResolver.new(subtyping.factory.env)
29
29
 
30
- # @type var types: Array[Types::t]
30
+ # @type var types: Array[LocatedValue[Types::t]]
31
31
  types = []
32
32
 
33
33
  loc = type_location
34
34
 
35
35
  while true
36
- ty = RBS::Parser.parse_type(loc.buffer, range: loc.range, variables: type_vars) or break
37
- ty = ty.map_type_name {|name| resolver.resolve(name, context: context) || name.absolute! }
36
+ rbs_ty = RBS::Parser.parse_type(loc.buffer, range: loc.range, variables: type_vars) or break
37
+ rbs_loc = rbs_ty.location or raise
38
+ ty = rbs_ty.map_type_name {|name| resolver.resolve(name, context: context) || name.absolute! }
38
39
 
39
40
  validator = Signature::Validator.new(checker: subtyping)
40
41
  validator.rescue_validation_errors do
@@ -46,11 +47,11 @@ module Steep
46
47
  end
47
48
 
48
49
  ty = subtyping.factory.type(ty)
49
- types << ty
50
+ types << LocatedValue.new(value: ty, location: rbs_loc)
50
51
 
51
- match = RBS::Location.new(loc.buffer, ty.location.end_pos, type_location.end_pos).source.match(/\A\s*,\s*/) or break
52
+ match = RBS::Location.new(loc.buffer, rbs_loc.end_pos, type_location.end_pos).source.match(/\A\s*,\s*/) or break
52
53
  offset = match.length
53
- loc = RBS::Location.new(loc.buffer, ty.location.end_pos + offset, type_location.end_pos)
54
+ loc = RBS::Location.new(loc.buffer, rbs_loc.end_pos + offset, type_location.end_pos)
54
55
  end
55
56
 
56
57
  types
@@ -2,11 +2,7 @@ module Steep
2
2
  module AST
3
3
  module Types
4
4
  class Any
5
- attr_reader :location
6
-
7
- def initialize(location: nil)
8
- @location = location
9
- end
5
+ extend SharedInstance
10
6
 
11
7
  def ==(other)
12
8
  other.is_a?(Any)
@@ -33,10 +29,6 @@ module Steep
33
29
  def level
34
30
  [1]
35
31
  end
36
-
37
- def with_location(new_location)
38
- self.class.new(location: new_location)
39
- end
40
32
  end
41
33
  end
42
34
  end
@@ -2,12 +2,8 @@ module Steep
2
2
  module AST
3
3
  module Types
4
4
  class Boolean
5
- attr_reader :location
6
-
7
- def initialize(location: nil)
8
- @location = location
9
- end
10
-
5
+ extend SharedInstance
6
+
11
7
  def ==(other)
12
8
  other.is_a?(Boolean)
13
9
  end
@@ -34,17 +30,13 @@ module Steep
34
30
  [0]
35
31
  end
36
32
 
37
- def with_location(new_location)
38
- self.class.new(location: new_location)
39
- end
40
-
41
33
  def back_type
42
- Union.build(types:
43
- [
44
- Builtin::TrueClass.instance_type,
45
- Builtin::FalseClass.instance_type
46
- ],
47
- location: location)
34
+ Union.build(
35
+ types: [
36
+ Builtin::TrueClass.instance_type,
37
+ Builtin::FalseClass.instance_type
38
+ ]
39
+ )
48
40
  end
49
41
  end
50
42
  end
@@ -2,12 +2,8 @@ module Steep
2
2
  module AST
3
3
  module Types
4
4
  class Bot
5
- attr_reader :location
6
-
7
- def initialize(location: nil)
8
- @location = location
9
- end
10
-
5
+ extend SharedInstance
6
+
11
7
  def ==(other)
12
8
  other.is_a?(Bot)
13
9
  end
@@ -33,10 +29,6 @@ module Steep
33
29
  def level
34
30
  [2]
35
31
  end
36
-
37
- def with_location(new_location)
38
- self.class.new(location: new_location)
39
- end
40
32
  end
41
33
  end
42
34
  end
@@ -2,15 +2,7 @@ module Steep
2
2
  module AST
3
3
  module Types
4
4
  class Class
5
- attr_reader :location
6
-
7
- def initialize(location: nil)
8
- @location = location
9
- end
10
-
11
- def self.instance
12
- @instance ||= new()
13
- end
5
+ extend SharedInstance
14
6
 
15
7
  def to_s
16
8
  "class"
@@ -45,10 +37,6 @@ module Steep
45
37
  def level
46
38
  [0]
47
39
  end
48
-
49
- def with_location(new_location)
50
- self.class.new(location: new_location)
51
- end
52
40
  end
53
41
  end
54
42
  end