steep 1.5.3 → 1.6.0.pre.2
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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby-windows.yml +1 -2
- data/.github/workflows/ruby.yml +1 -2
- data/CHANGELOG.md +46 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +37 -10
- data/gemfile_steep/Gemfile.lock +3 -3
- data/lib/steep/ast/types/logic.rb +6 -0
- data/lib/steep/cli.rb +39 -19
- data/lib/steep/diagnostic/ruby.rb +4 -4
- data/lib/steep/interface/builder.rb +9 -0
- data/lib/steep/path_helper.rb +2 -0
- data/lib/steep/project/pattern.rb +1 -1
- data/lib/steep/server/change_buffer.rb +9 -0
- data/lib/steep/server/delay_queue.rb +41 -0
- data/lib/steep/server/interaction_worker.rb +4 -2
- data/lib/steep/server/master.rb +106 -10
- data/lib/steep/server/type_check_worker.rb +10 -3
- data/lib/steep/services/completion_provider.rb +2 -2
- data/lib/steep/services/stats_calculator.rb +2 -2
- data/lib/steep/services/type_name_completion.rb +86 -15
- data/lib/steep/signature/validator.rb +9 -2
- data/lib/steep/subtyping/check.rb +24 -18
- data/lib/steep/type_construction.rb +61 -17
- data/lib/steep/type_inference/logic_type_interpreter.rb +26 -0
- data/lib/steep/type_inference/method_params.rb +1 -1
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +1 -3
- data/sig/shims/language-server_protocol.rbs +12 -0
- data/sig/steep/ast/types/logic.rbs +5 -0
- data/sig/steep/ast/types.rbs +1 -1
- data/sig/steep/cli.rbs +2 -0
- data/sig/steep/diagnostic/ruby.rbs +7 -7
- data/sig/steep/project/pattern.rbs +22 -0
- data/sig/steep/server/change_buffer.rbs +4 -0
- data/sig/steep/server/delay_queue.rbs +37 -0
- data/sig/steep/server/master.rbs +4 -0
- data/sig/steep/services/stats_calculator.rbs +30 -6
- data/sig/steep/services/type_name_completion.rbs +13 -0
- data/sig/steep/signature/validator.rbs +5 -0
- data/sig/steep/subtyping/check.rbs +1 -1
- data/sig/steep/subtyping/relation.rbs +11 -1
- data/sig/steep/subtyping/result.rbs +1 -1
- data/sig/steep/type_construction.rbs +1 -1
- data/smoke/block/test_expectations.yml +10 -14
- data/smoke/enumerator/test_expectations.yml +10 -10
- data/smoke/integer/test_expectations.yml +5 -16
- data/smoke/regression/hello world.rb +1 -0
- data/smoke/regression/test_expectations.yml +12 -0
- data/steep.gemspec +1 -1
- metadata +8 -7
- data/lib/steep/shims/filter_map.rb +0 -30
- data/lib/steep/shims/symbol_start_with.rb +0 -18
data/lib/steep/server/master.rb
CHANGED
@@ -402,6 +402,7 @@ module Steep
|
|
402
402
|
|
403
403
|
attr_reader :initialize_params
|
404
404
|
attr_accessor :typecheck_automatically
|
405
|
+
attr_reader :start_type_checking_queue
|
405
406
|
|
406
407
|
def initialize(project:, reader:, writer:, interaction_worker:, typecheck_workers:, queue: Queue.new)
|
407
408
|
@project = project
|
@@ -416,6 +417,7 @@ module Steep
|
|
416
417
|
|
417
418
|
@controller = TypeCheckController.new(project: project)
|
418
419
|
@result_controller = ResultController.new()
|
420
|
+
@start_type_checking_queue = DelayQueue.new(delay: 0.1)
|
419
421
|
end
|
420
422
|
|
421
423
|
def start
|
@@ -488,6 +490,8 @@ module Steep
|
|
488
490
|
Steep.logger.info { "Processing SendMessageJob: dest=#{job.dest.name}, method=#{job.message[:method] || "-"}, id=#{job.message[:id] || "-"}" }
|
489
491
|
job.dest << job.message
|
490
492
|
end
|
493
|
+
when Proc
|
494
|
+
job.call()
|
491
495
|
end
|
492
496
|
end
|
493
497
|
end
|
@@ -529,6 +533,10 @@ module Steep
|
|
529
533
|
initialize_params&.dig(:capabilities, :window, :workDoneProgress) ? true : false
|
530
534
|
end
|
531
535
|
|
536
|
+
def file_system_watcher_supported?
|
537
|
+
initialize_params&.dig(:capabilities, :workspace, :didChangeWatchedFiles, :dynamicRegistration) || false
|
538
|
+
end
|
539
|
+
|
532
540
|
def process_message_from_client(message)
|
533
541
|
Steep.logger.info "Processing message from client: method=#{message[:method]}, id=#{message[:id]}"
|
534
542
|
id = message[:id]
|
@@ -551,7 +559,6 @@ module Steep
|
|
551
559
|
capabilities: LSP::Interface::ServerCapabilities.new(
|
552
560
|
text_document_sync: LSP::Interface::TextDocumentSyncOptions.new(
|
553
561
|
change: LSP::Constant::TextDocumentSyncKind::INCREMENTAL,
|
554
|
-
save: LSP::Interface::SaveOptions.new(include_text: false),
|
555
562
|
open_close: true
|
556
563
|
),
|
557
564
|
hover_provider: {
|
@@ -575,6 +582,52 @@ module Steep
|
|
575
582
|
)
|
576
583
|
}
|
577
584
|
)
|
585
|
+
|
586
|
+
if file_system_watcher_supported?
|
587
|
+
patterns = [] #: Array[String]
|
588
|
+
project.targets.each do |target|
|
589
|
+
target.source_pattern.patterns.each do |pat|
|
590
|
+
path = project.base_dir + pat
|
591
|
+
patterns << path.to_s unless path.directory?
|
592
|
+
end
|
593
|
+
target.source_pattern.prefixes.each do |pat|
|
594
|
+
path = project.base_dir + pat
|
595
|
+
patterns << (path + "**/*.rb").to_s unless path.file?
|
596
|
+
end
|
597
|
+
target.signature_pattern.patterns.each do |pat|
|
598
|
+
path = project.base_dir + pat
|
599
|
+
patterns << path.to_s unless path.directory?
|
600
|
+
end
|
601
|
+
target.signature_pattern.prefixes.each do |pat|
|
602
|
+
path = project.base_dir + pat
|
603
|
+
patterns << (path + "**/*.rbs").to_s unless path.file?
|
604
|
+
end
|
605
|
+
end
|
606
|
+
patterns.sort!
|
607
|
+
patterns.uniq!
|
608
|
+
|
609
|
+
Steep.logger.info { "Setting up didChangeWatchedFiles with pattern: #{patterns.inspect}" }
|
610
|
+
|
611
|
+
job_queue << SendMessageJob.to_client(
|
612
|
+
message: {
|
613
|
+
id: SecureRandom.uuid,
|
614
|
+
method: "client/registerCapability",
|
615
|
+
params: {
|
616
|
+
registrations: [
|
617
|
+
{
|
618
|
+
id: SecureRandom.uuid,
|
619
|
+
method: "workspace/didChangeWatchedFiles",
|
620
|
+
registerOptions: {
|
621
|
+
watchers: patterns.map do |pattern|
|
622
|
+
{ globPattern: pattern }
|
623
|
+
end
|
624
|
+
}
|
625
|
+
}
|
626
|
+
]
|
627
|
+
}
|
628
|
+
}
|
629
|
+
)
|
630
|
+
end
|
578
631
|
end
|
579
632
|
end
|
580
633
|
|
@@ -585,28 +638,71 @@ module Steep
|
|
585
638
|
end
|
586
639
|
end
|
587
640
|
|
641
|
+
when "workspace/didChangeWatchedFiles"
|
642
|
+
message[:params][:changes].each do |change|
|
643
|
+
uri = change[:uri]
|
644
|
+
type = change[:type]
|
645
|
+
|
646
|
+
path = PathHelper.to_pathname(uri) or next
|
647
|
+
|
648
|
+
controller.push_changes(path)
|
649
|
+
|
650
|
+
case type
|
651
|
+
when 1, 2
|
652
|
+
content = path.read
|
653
|
+
when 4
|
654
|
+
# Deleted
|
655
|
+
content = ""
|
656
|
+
end
|
657
|
+
|
658
|
+
broadcast_notification({
|
659
|
+
method: "$/file/reset",
|
660
|
+
params: { uri: uri, content: content }
|
661
|
+
})
|
662
|
+
end
|
663
|
+
|
664
|
+
if typecheck_automatically
|
665
|
+
start_type_checking_queue.execute do
|
666
|
+
job_queue.push(
|
667
|
+
-> do
|
668
|
+
last_request = current_type_check_request
|
669
|
+
if request = controller.make_request(last_request: last_request)
|
670
|
+
start_type_check(request, last_request: last_request, start_progress: request.total > 10)
|
671
|
+
end
|
672
|
+
end
|
673
|
+
)
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|
588
677
|
when "textDocument/didChange"
|
589
678
|
if path = pathname(message[:params][:textDocument][:uri])
|
590
679
|
broadcast_notification(message)
|
591
680
|
controller.push_changes(path)
|
592
|
-
end
|
593
681
|
|
594
|
-
when "textDocument/didSave"
|
595
|
-
if path = pathname(message[:params][:textDocument][:uri])
|
596
682
|
if typecheck_automatically
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
683
|
+
start_type_checking_queue.execute do
|
684
|
+
job_queue.push(
|
685
|
+
-> do
|
686
|
+
last_request = current_type_check_request
|
687
|
+
if request = controller.make_request(last_request: last_request)
|
688
|
+
start_type_check(request, last_request: last_request, start_progress: request.total > 10)
|
689
|
+
end
|
690
|
+
end
|
602
691
|
)
|
603
692
|
end
|
604
693
|
end
|
605
694
|
end
|
606
695
|
|
607
696
|
when "textDocument/didOpen"
|
608
|
-
|
697
|
+
uri = message[:params][:textDocument][:uri]
|
698
|
+
text = message[:params][:textDocument][:text]
|
699
|
+
|
700
|
+
if path = pathname(uri)
|
609
701
|
controller.update_priority(open: path)
|
702
|
+
broadcast_notification({
|
703
|
+
method: "$/file/reset",
|
704
|
+
params: { uri: uri, content: text }
|
705
|
+
})
|
610
706
|
end
|
611
707
|
|
612
708
|
when "textDocument/didClose"
|
@@ -70,8 +70,15 @@ module Steep
|
|
70
70
|
when "initialize"
|
71
71
|
load_files(project: project, commandline_args: commandline_args)
|
72
72
|
writer.write({ id: request[:id], result: nil})
|
73
|
+
|
73
74
|
when "textDocument/didChange"
|
74
75
|
collect_changes(request)
|
76
|
+
|
77
|
+
when "$/file/reset"
|
78
|
+
uri = request[:params][:uri]
|
79
|
+
text = request[:params][:content]
|
80
|
+
reset_change(uri: uri, text: text)
|
81
|
+
|
75
82
|
when "workspace/symbol"
|
76
83
|
query = request[:params][:query]
|
77
84
|
queue << WorkspaceSymbolJob.new(id: request[:id], query: query)
|
@@ -165,7 +172,7 @@ module Steep
|
|
165
172
|
writer.write(
|
166
173
|
method: :"textDocument/publishDiagnostics",
|
167
174
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
168
|
-
uri: Steep::PathHelper.to_uri(job.path),
|
175
|
+
uri: Steep::PathHelper.to_uri(job.path).to_s,
|
169
176
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
|
170
177
|
)
|
171
178
|
)
|
@@ -183,7 +190,7 @@ module Steep
|
|
183
190
|
writer.write(
|
184
191
|
method: :"textDocument/publishDiagnostics",
|
185
192
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
186
|
-
uri: Steep::PathHelper.to_uri(job.path),
|
193
|
+
uri: Steep::PathHelper.to_uri(job.path).to_s,
|
187
194
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
188
195
|
)
|
189
196
|
)
|
@@ -202,7 +209,7 @@ module Steep
|
|
202
209
|
writer.write(
|
203
210
|
method: :"textDocument/publishDiagnostics",
|
204
211
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
205
|
-
uri: Steep::PathHelper.to_uri(job.path),
|
212
|
+
uri: Steep::PathHelper.to_uri(job.path).to_s,
|
206
213
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
207
214
|
)
|
208
215
|
)
|
@@ -115,7 +115,7 @@ module Steep
|
|
115
115
|
when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
|
116
116
|
entry.decl
|
117
117
|
else
|
118
|
-
raise
|
118
|
+
raise "absolute_type_name=#{absolute_type_name}, relative_type_name=#{relative_type_name}"
|
119
119
|
end
|
120
120
|
else
|
121
121
|
raise
|
@@ -663,7 +663,7 @@ module Steep
|
|
663
663
|
if parent
|
664
664
|
case parent.type
|
665
665
|
when :const
|
666
|
-
const_name = typing.source_index.reference(constant_node: parent)
|
666
|
+
const_name = typing.source_index.reference(constant_node: parent) or raise "Unknown node in source_index: #{parent}"
|
667
667
|
consts = context.type_env.constant_env.children(const_name)
|
668
668
|
end
|
669
669
|
else
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Steep
|
2
2
|
module Services
|
3
3
|
class StatsCalculator
|
4
|
-
SuccessStats
|
4
|
+
class SuccessStats < Struct.new(:target, :path, :typed_calls_count, :untyped_calls_count, :error_calls_count, keyword_init: true)
|
5
5
|
def as_json
|
6
6
|
{
|
7
7
|
type: "success",
|
@@ -14,7 +14,7 @@ module Steep
|
|
14
14
|
}
|
15
15
|
end
|
16
16
|
end
|
17
|
-
ErrorStats
|
17
|
+
class ErrorStats < Struct.new(:target, :path, keyword_init: true)
|
18
18
|
def as_json
|
19
19
|
{
|
20
20
|
type: "error",
|
@@ -31,15 +31,20 @@ module Steep
|
|
31
31
|
|
32
32
|
case prefix
|
33
33
|
when /\A((::\w+[A-Z])+(::)?)/
|
34
|
-
|
34
|
+
namespace = $1 or raise
|
35
|
+
NamespacePrefix.new(RBS::Namespace.parse(namespace.reverse), namespace.size)
|
35
36
|
when /\A::/
|
36
37
|
NamespacePrefix.new(RBS::Namespace.root, 2)
|
37
38
|
when /\A(\w*[A-Za-z_])((::\w+[A-Z])+(::)?)/
|
38
|
-
|
39
|
+
namespace = $1 or raise
|
40
|
+
identifier = $2 or raise
|
41
|
+
NamespacedIdentPrefix.new(RBS::Namespace.parse(identifier.reverse), namespace.reverse, namespace.size + identifier.size)
|
39
42
|
when /\A(\w*[A-Za-z_])::/
|
40
|
-
|
43
|
+
namespace = $1 or raise
|
44
|
+
NamespacedIdentPrefix.new(RBS::Namespace.root, namespace.reverse, namespace.size + 2)
|
41
45
|
when /\A(\w*[A-Za-z_])/
|
42
|
-
|
46
|
+
identifier = $1 or raise
|
47
|
+
RawIdentPrefix.new(identifier.reverse)
|
43
48
|
end
|
44
49
|
end
|
45
50
|
end
|
@@ -92,36 +97,97 @@ module Steep
|
|
92
97
|
if block
|
93
98
|
env = self.env
|
94
99
|
|
100
|
+
table = {} #: Hash[RBS::Namespace, Array[RBS::TypeName]]
|
101
|
+
env.class_decls.each_key do |type_name|
|
102
|
+
yield(type_name)
|
103
|
+
(table[type_name.namespace] ||= []) << type_name
|
104
|
+
end
|
105
|
+
env.type_alias_decls.each_key do |type_name|
|
106
|
+
yield(type_name)
|
107
|
+
(table[type_name.namespace] ||= []) << type_name
|
108
|
+
end
|
109
|
+
env.interface_decls.each_key do |type_name|
|
110
|
+
yield(type_name)
|
111
|
+
(table[type_name.namespace] ||= []) << type_name
|
112
|
+
end
|
113
|
+
env.class_alias_decls.each_key do |type_name|
|
114
|
+
yield(type_name)
|
115
|
+
(table[type_name.namespace] ||= []) << type_name
|
116
|
+
end
|
117
|
+
|
118
|
+
env.class_alias_decls.each_key do |alias_name|
|
119
|
+
normalized_name = env.normalize_module_name?(alias_name) or next
|
120
|
+
each_type_name_under(alias_name, normalized_name, table: table, &block)
|
121
|
+
end
|
122
|
+
|
123
|
+
resolve_pairs = [] #: Array[[RBS::TypeName, RBS::TypeName]]
|
124
|
+
|
95
125
|
map.instance_eval do
|
96
126
|
@map.each_key do |name|
|
97
127
|
relative_name = RBS::TypeName.new(name: name, namespace: RBS::Namespace.empty)
|
98
128
|
if absolute_name = resolve?(relative_name)
|
99
129
|
if env.type_name?(absolute_name)
|
100
130
|
# Yields only if the relative type name resolves to existing absolute type name
|
101
|
-
|
131
|
+
resolve_pairs << [relative_name, absolute_name]
|
102
132
|
end
|
103
133
|
end
|
104
134
|
end
|
105
135
|
end
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
136
|
+
|
137
|
+
resolve_pairs.each do |use_name, absolute_name|
|
138
|
+
yield use_name
|
139
|
+
each_type_name_under(use_name, absolute_name, table: table, &block)
|
140
|
+
end
|
110
141
|
else
|
111
142
|
enum_for :each_type_name
|
112
143
|
end
|
113
144
|
end
|
114
145
|
|
146
|
+
def each_type_name_under(module_name, normalized_name, table:, &block)
|
147
|
+
if children = table.fetch(normalized_name.to_namespace, nil)
|
148
|
+
module_namespace = module_name.to_namespace
|
149
|
+
|
150
|
+
children.each do |normalized_child_name|
|
151
|
+
child_name = RBS::TypeName.new(namespace: module_namespace, name: normalized_child_name.name)
|
152
|
+
|
153
|
+
yield child_name
|
154
|
+
|
155
|
+
if normalized_child_name.class?
|
156
|
+
each_type_name_under(child_name, env.normalize_module_name(normalized_child_name), table: table, &block)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def resolve_used_name(name)
|
163
|
+
return nil if name.absolute?
|
164
|
+
|
165
|
+
case
|
166
|
+
when resolved = map.resolve?(name)
|
167
|
+
resolved
|
168
|
+
when name.namespace.empty?
|
169
|
+
nil
|
170
|
+
else
|
171
|
+
if resolved_parent = resolve_used_name(name.namespace.to_type_name)
|
172
|
+
resolved_name = RBS::TypeName.new(namespace: resolved_parent.to_namespace, name: name.name)
|
173
|
+
if env.normalize_type_name?(resolved_name)
|
174
|
+
resolved_name
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
115
180
|
def resolve_name_in_context(name)
|
116
|
-
if resolved_name =
|
181
|
+
if resolved_name = resolve_used_name(name)
|
117
182
|
return [resolved_name, name]
|
118
183
|
end
|
119
184
|
|
120
185
|
name.absolute? or raise
|
186
|
+
normalized_name = env.normalize_type_name?(name) or raise "Cannot normalize given type name `#{name}`"
|
121
187
|
|
122
188
|
name.namespace.path.reverse_each.inject(RBS::TypeName.new(namespace: RBS::Namespace.empty, name: name.name)) do |relative_name, component|
|
123
189
|
if type_name_resolver.resolve(relative_name, context: context) == name
|
124
|
-
return [
|
190
|
+
return [normalized_name, relative_name]
|
125
191
|
end
|
126
192
|
|
127
193
|
RBS::TypeName.new(
|
@@ -130,10 +196,10 @@ module Steep
|
|
130
196
|
)
|
131
197
|
end
|
132
198
|
|
133
|
-
if type_name_resolver.resolve(name.relative!, context: context) == name && !
|
134
|
-
[
|
199
|
+
if type_name_resolver.resolve(name.relative!, context: context) == name && !resolve_used_name(name.relative!)
|
200
|
+
[normalized_name, name.relative!]
|
135
201
|
else
|
136
|
-
[
|
202
|
+
[normalized_name, name]
|
137
203
|
end
|
138
204
|
end
|
139
205
|
|
@@ -144,7 +210,12 @@ module Steep
|
|
144
210
|
type_name.split.any? {|sym| sym.to_s.downcase.include?(prefix.ident.downcase) }
|
145
211
|
end
|
146
212
|
when Prefix::NamespacedIdentPrefix
|
147
|
-
absolute_namespace =
|
213
|
+
absolute_namespace =
|
214
|
+
if prefix.namespace.empty?
|
215
|
+
RBS::Namespace.root
|
216
|
+
else
|
217
|
+
type_name_resolver.resolve(prefix.namespace.to_type_name, context: context)&.to_namespace || prefix.namespace
|
218
|
+
end
|
148
219
|
|
149
220
|
each_type_name.filter do|name|
|
150
221
|
name.namespace == absolute_namespace &&
|
@@ -112,10 +112,11 @@ module Steep
|
|
112
112
|
type.args
|
113
113
|
]
|
114
114
|
when RBS::Types::Alias
|
115
|
-
|
115
|
+
type_name = env.normalize_type_name?(type.name) or return
|
116
|
+
entry = env.type_alias_decls[type_name]
|
116
117
|
|
117
118
|
[
|
118
|
-
|
119
|
+
type_name,
|
119
120
|
entry.decl.type_params,
|
120
121
|
type.args
|
121
122
|
]
|
@@ -520,6 +521,12 @@ module Steep
|
|
520
521
|
def validate_one_alias(name, entry = env.type_alias_decls[name])
|
521
522
|
rescue_validation_errors(name) do
|
522
523
|
Steep.logger.debug "Validating alias `#{name}`..."
|
524
|
+
|
525
|
+
unless name.namespace.empty?
|
526
|
+
outer = name.namespace.to_type_name
|
527
|
+
builder.validate_type_name(outer, entry.decl.location&.aref(:name))
|
528
|
+
end
|
529
|
+
|
523
530
|
upper_bounds = entry.decl.type_params.each.with_object({}) do |param, bounds|
|
524
531
|
bounds[param.name] = factory.type_opt(param.upper_bound)
|
525
532
|
end
|
@@ -79,11 +79,11 @@ module Steep
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def instance_type
|
82
|
-
@instance_type
|
82
|
+
@instance_type || AST::Types::Instance.instance
|
83
83
|
end
|
84
84
|
|
85
85
|
def class_type
|
86
|
-
@class_type
|
86
|
+
@class_type || AST::Types::Class.instance
|
87
87
|
end
|
88
88
|
|
89
89
|
def constraints
|
@@ -193,7 +193,7 @@ module Steep
|
|
193
193
|
bounds = cache_bounds(relation)
|
194
194
|
fvs = relation.sub_type.free_variables + relation.super_type.free_variables
|
195
195
|
cached = cache[relation, @self_type, @instance_type, @class_type, bounds]
|
196
|
-
if cached && fvs.none? {|var| constraints.unknown?(var) }
|
196
|
+
if cached && fvs.none? {|var| var.is_a?(Symbol) && constraints.unknown?(var) }
|
197
197
|
cached
|
198
198
|
else
|
199
199
|
if assumptions.member?(relation)
|
@@ -212,7 +212,8 @@ module Steep
|
|
212
212
|
|
213
213
|
def cache_bounds(relation)
|
214
214
|
vars = relation.sub_type.free_variables + relation.super_type.free_variables
|
215
|
-
vars.each.with_object({}) do |var, hash|
|
215
|
+
vars.each.with_object({}) do |var, hash| #$ Hash[Symbol, AST::Types::t]
|
216
|
+
next unless var.is_a?(Symbol)
|
216
217
|
if upper_bound = variable_upper_bound(var)
|
217
218
|
hash[var] = upper_bound
|
218
219
|
end
|
@@ -232,7 +233,7 @@ module Steep
|
|
232
233
|
when AST::Types::Literal
|
233
234
|
type.value == true
|
234
235
|
else
|
235
|
-
AST::Builtin::TrueClass.instance_type?(type)
|
236
|
+
AST::Builtin::TrueClass.instance_type?(type) ? true : false
|
236
237
|
end
|
237
238
|
end
|
238
239
|
|
@@ -241,7 +242,7 @@ module Steep
|
|
241
242
|
when AST::Types::Literal
|
242
243
|
type.value == false
|
243
244
|
else
|
244
|
-
AST::Builtin::FalseClass.instance_type?(type)
|
245
|
+
AST::Builtin::FalseClass.instance_type?(type) ? true : false
|
245
246
|
end
|
246
247
|
end
|
247
248
|
|
@@ -410,7 +411,7 @@ module Steep
|
|
410
411
|
class_type: class_type,
|
411
412
|
variable_bounds: variable_upper_bounds
|
412
413
|
)
|
413
|
-
) or
|
414
|
+
) or return Failure(relation, Result::Failure::UnknownPairError.new(relation: relation))
|
414
415
|
}
|
415
416
|
)
|
416
417
|
end
|
@@ -492,7 +493,7 @@ module Steep
|
|
492
493
|
Failure(relation, Result::Failure::UnknownPairError.new(relation: relation))
|
493
494
|
end
|
494
495
|
|
495
|
-
when relation.sub_type.is_a?(AST::Types::Tuple) && AST::Builtin::Array.instance_type?(relation.super_type)
|
496
|
+
when relation.sub_type.is_a?(AST::Types::Tuple) && (super_type = AST::Builtin::Array.instance_type?(relation.super_type))
|
496
497
|
Expand(relation) do
|
497
498
|
tuple_element_type =
|
498
499
|
AST::Types::Union.build(
|
@@ -500,7 +501,7 @@ module Steep
|
|
500
501
|
location: relation.sub_type.location
|
501
502
|
)
|
502
503
|
|
503
|
-
check_type(Relation.new(sub_type: tuple_element_type, super_type:
|
504
|
+
check_type(Relation.new(sub_type: tuple_element_type, super_type: super_type.args[0]))
|
504
505
|
end
|
505
506
|
|
506
507
|
when relation.sub_type.is_a?(AST::Types::Record) && relation.super_type.is_a?(AST::Types::Record)
|
@@ -549,9 +550,7 @@ module Steep
|
|
549
550
|
end
|
550
551
|
|
551
552
|
when relation.super_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.sub_type)
|
552
|
-
|
553
|
-
|
554
|
-
when relation.sub_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.super_type)
|
553
|
+
# NilClass <: nil
|
555
554
|
Success(relation)
|
556
555
|
|
557
556
|
when relation.sub_type.is_a?(AST::Types::Literal)
|
@@ -742,10 +741,17 @@ module Steep
|
|
742
741
|
args = sub_type.type_params.map {|type_param| AST::Types::Var.fresh(type_param.name) }
|
743
742
|
args.each {|arg| constraints.unknown!(arg.name) }
|
744
743
|
|
745
|
-
upper_bounds = {}
|
746
|
-
relations = [] #: Array[Relation]
|
744
|
+
upper_bounds = {} #: Hash[Symbol, AST::Types::t]
|
745
|
+
relations = [] #: Array[Relation[AST::Types::t]]
|
747
746
|
|
748
747
|
args.zip(sub_type.type_params, super_type.type_params).each do |arg, sub_param, sup_param|
|
748
|
+
# @type var arg: AST::Types::Var
|
749
|
+
# @type var sub_param: Interface::TypeParam?
|
750
|
+
# @type var super_param: Interface::TypeParam?
|
751
|
+
|
752
|
+
sub_param or raise
|
753
|
+
sup_param or raise
|
754
|
+
|
749
755
|
sub_ub = sub_param.upper_bound
|
750
756
|
sup_ub = sup_param.upper_bound
|
751
757
|
|
@@ -927,7 +933,7 @@ module Steep
|
|
927
933
|
|
928
934
|
sub_params, super_params = relation
|
929
935
|
|
930
|
-
pairs = []
|
936
|
+
pairs = [] #: Array[[AST::Types::t, AST::Types::t]]
|
931
937
|
|
932
938
|
sub_flat = sub_params.flat_unnamed_params
|
933
939
|
sup_flat = super_params.flat_unnamed_params
|
@@ -939,7 +945,7 @@ module Steep
|
|
939
945
|
return failure unless sub_params.rest
|
940
946
|
|
941
947
|
while sub_flat.size > 0
|
942
|
-
sub_type = sub_flat.shift
|
948
|
+
sub_type = sub_flat.shift or raise
|
943
949
|
sup_type = sup_flat.shift
|
944
950
|
|
945
951
|
if sup_type
|
@@ -955,7 +961,7 @@ module Steep
|
|
955
961
|
|
956
962
|
when sub_params.rest
|
957
963
|
while sub_flat.size > 0
|
958
|
-
sub_type = sub_flat.shift
|
964
|
+
sub_type = sub_flat.shift or raise
|
959
965
|
sup_type = sup_flat.shift
|
960
966
|
|
961
967
|
if sup_type
|
@@ -972,7 +978,7 @@ module Steep
|
|
972
978
|
end
|
973
979
|
when sub_params.required.size + sub_params.optional.size >= super_params.required.size + super_params.optional.size
|
974
980
|
while sub_flat.size > 0
|
975
|
-
sub_type = sub_flat.shift
|
981
|
+
sub_type = sub_flat.shift or raise
|
976
982
|
sup_type = sup_flat.shift
|
977
983
|
|
978
984
|
if sup_type
|