steep 1.5.3 → 1.6.0.pre.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|