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
@@ -1305,29 +1305,39 @@ module Steep
|
|
1305
1305
|
var = node.children[0]
|
1306
1306
|
rhs = node.children[1]
|
1307
1307
|
|
1308
|
-
|
1308
|
+
if SPECIAL_LVAR_NAMES.include?(var)
|
1309
|
+
synthesize(rhs)
|
1310
|
+
add_typing(node, type: AST::Builtin.any_type)
|
1311
|
+
else
|
1312
|
+
var_type = context.type_env[var]
|
1309
1313
|
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1314
|
+
if var_type
|
1315
|
+
type, constr = check(rhs, var_type) do |expected_type, actual_type, result|
|
1316
|
+
typing.add_error(
|
1317
|
+
Diagnostic::Ruby::IncompatibleAssignment.new(
|
1318
|
+
node: node,
|
1319
|
+
lhs_type: expected_type,
|
1320
|
+
rhs_type: actual_type,
|
1321
|
+
result: result
|
1322
|
+
)
|
1318
1323
|
)
|
1319
|
-
|
1324
|
+
end
|
1325
|
+
else
|
1326
|
+
type, constr = synthesize(rhs)
|
1320
1327
|
end
|
1321
|
-
else
|
1322
|
-
type, constr = synthesize(rhs)
|
1323
|
-
end
|
1324
1328
|
|
1325
|
-
|
1329
|
+
constr.add_typing(node, type: type)
|
1330
|
+
end
|
1326
1331
|
end
|
1327
1332
|
|
1328
1333
|
when :restarg
|
1329
1334
|
yield_self do
|
1330
1335
|
var = node.children[0]
|
1336
|
+
|
1337
|
+
if SPECIAL_LVAR_NAMES.include?(var)
|
1338
|
+
return add_typing(node, type: AST::Builtin.any_type)
|
1339
|
+
end
|
1340
|
+
|
1331
1341
|
type = context.type_env[var]
|
1332
1342
|
|
1333
1343
|
unless type
|
@@ -1344,6 +1354,11 @@ module Steep
|
|
1344
1354
|
when :kwrestarg
|
1345
1355
|
yield_self do
|
1346
1356
|
var = node.children[0]
|
1357
|
+
|
1358
|
+
if SPECIAL_LVAR_NAMES.include?(var)
|
1359
|
+
return add_typing(node, type: AST::Builtin.any_type)
|
1360
|
+
end
|
1361
|
+
|
1347
1362
|
type = context.type_env[var]
|
1348
1363
|
unless type
|
1349
1364
|
if context.method_context&.method_type
|
@@ -2893,6 +2908,8 @@ module Steep
|
|
2893
2908
|
_, constr = constr.gvasgn(asgn_node, type)
|
2894
2909
|
when :mlhs
|
2895
2910
|
constr = (constr.type_masgn_type(asgn_node, type, masgn: masgn, optional: optional) or return)
|
2911
|
+
else
|
2912
|
+
_, constr = constr.synthesize_children(asgn_node).add_typing(asgn_node, type: AST::Builtin.any_type)
|
2896
2913
|
end
|
2897
2914
|
|
2898
2915
|
if node.type == :splat
|
@@ -3046,6 +3063,7 @@ module Steep
|
|
3046
3063
|
end
|
3047
3064
|
else
|
3048
3065
|
parent_type, constr = synthesize(parent_node).to_ary
|
3066
|
+
parent_type = expand_self(parent_type)
|
3049
3067
|
parent_type = deep_expand_alias(parent_type)
|
3050
3068
|
|
3051
3069
|
case parent_type
|
@@ -3284,7 +3302,14 @@ module Steep
|
|
3284
3302
|
|
3285
3303
|
if call && constr
|
3286
3304
|
case method_name.to_s
|
3287
|
-
when "[]="
|
3305
|
+
when "[]="
|
3306
|
+
if test_send_node(node) {|_, _, _, loc| !loc.dot }
|
3307
|
+
last_arg = arguments.last or raise
|
3308
|
+
if typing.has_type?(last_arg)
|
3309
|
+
call = call.with_return_type(typing.type_of(node: last_arg))
|
3310
|
+
end
|
3311
|
+
end
|
3312
|
+
when /\w=\Z/
|
3288
3313
|
last_arg = arguments.last or raise
|
3289
3314
|
if typing.has_type?(last_arg)
|
3290
3315
|
call = call.with_return_type(typing.type_of(node: last_arg))
|
@@ -3292,7 +3317,7 @@ module Steep
|
|
3292
3317
|
end
|
3293
3318
|
|
3294
3319
|
if call.is_a?(TypeInference::MethodCall::Typed)
|
3295
|
-
if (pure_call, type = constr.context.type_env.pure_method_calls
|
3320
|
+
if (pure_call, type = constr.context.type_env.pure_method_calls.fetch(node, nil))
|
3296
3321
|
if type
|
3297
3322
|
call = pure_call.update(node: node, return_type: type)
|
3298
3323
|
constr.add_typing(node, type: call.return_type)
|
@@ -3345,12 +3370,14 @@ module Steep
|
|
3345
3370
|
method_name: method_name,
|
3346
3371
|
method_types: method.method_types
|
3347
3372
|
)
|
3373
|
+
decls = method.method_types.each_with_object(Set[]) {|type, decls| decls.merge(type.method_decls) }
|
3348
3374
|
call = TypeInference::MethodCall::Error.new(
|
3349
3375
|
node: node,
|
3350
3376
|
context: context.call_context,
|
3351
3377
|
method_name: method_name,
|
3352
3378
|
receiver_type: receiver_type,
|
3353
|
-
errors: errors
|
3379
|
+
errors: errors,
|
3380
|
+
method_decls: decls
|
3354
3381
|
)
|
3355
3382
|
end
|
3356
3383
|
|
@@ -3665,6 +3692,23 @@ module Steep
|
|
3665
3692
|
end
|
3666
3693
|
end
|
3667
3694
|
|
3695
|
+
non_arity_errors = fails.reject do |call, _|
|
3696
|
+
if call.is_a?(TypeInference::MethodCall::Error)
|
3697
|
+
call.errors.any? do |error|
|
3698
|
+
error.is_a?(Diagnostic::Ruby::UnexpectedBlockGiven) ||
|
3699
|
+
error.is_a?(Diagnostic::Ruby::RequiredBlockMissing) ||
|
3700
|
+
error.is_a?(Diagnostic::Ruby::UnexpectedPositionalArgument) ||
|
3701
|
+
error.is_a?(Diagnostic::Ruby::InsufficientPositionalArguments) ||
|
3702
|
+
error.is_a?(Diagnostic::Ruby::UnexpectedKeywordArgument) ||
|
3703
|
+
error.is_a?(Diagnostic::Ruby::InsufficientKeywordArguments)
|
3704
|
+
end
|
3705
|
+
end
|
3706
|
+
end
|
3707
|
+
|
3708
|
+
unless non_arity_errors.empty?
|
3709
|
+
fails = non_arity_errors
|
3710
|
+
end
|
3711
|
+
|
3668
3712
|
if fails.one?
|
3669
3713
|
call, constr = fails[0]
|
3670
3714
|
|
@@ -367,6 +367,32 @@ module Steep
|
|
367
367
|
[truthy_result, falsy_result]
|
368
368
|
end
|
369
369
|
end
|
370
|
+
|
371
|
+
when AST::Types::Logic::ArgIsAncestor
|
372
|
+
if receiver && (arg = arguments[0])
|
373
|
+
receiver_type = typing.type_of(node: receiver)
|
374
|
+
arg_type = factory.deep_expand_alias(typing.type_of(node: arg))
|
375
|
+
|
376
|
+
if arg_type.is_a?(AST::Types::Name::Singleton)
|
377
|
+
truthy_type = arg_type
|
378
|
+
falsy_type = receiver_type
|
379
|
+
truthy_env, falsy_env = refine_node_type(
|
380
|
+
env: env,
|
381
|
+
node: receiver,
|
382
|
+
truthy_type: truthy_type,
|
383
|
+
falsy_type: falsy_type
|
384
|
+
)
|
385
|
+
|
386
|
+
truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
|
387
|
+
truthy_result.unreachable! unless truthy_type
|
388
|
+
|
389
|
+
falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
|
390
|
+
falsy_result.unreachable! unless falsy_type
|
391
|
+
|
392
|
+
[truthy_result, falsy_result]
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
370
396
|
when AST::Types::Logic::Not
|
371
397
|
if receiver
|
372
398
|
truthy_result, falsy_result = evaluate_node(env: env, node: receiver)
|
@@ -453,7 +453,7 @@ module Steep
|
|
453
453
|
has_error = false
|
454
454
|
|
455
455
|
keywords.each do |keyword|
|
456
|
-
rest_types << keyword_params.requireds[keyword] || keyword_params.optionals[keyword]
|
456
|
+
rest_types << (keyword_params.requireds[keyword] || keyword_params.optionals[keyword])
|
457
457
|
has_error = true
|
458
458
|
end
|
459
459
|
keywords.clear
|
data/lib/steep/version.rb
CHANGED
data/lib/steep.rb
CHANGED
@@ -23,9 +23,6 @@ require "rbs"
|
|
23
23
|
|
24
24
|
require "steep/path_helper"
|
25
25
|
|
26
|
-
require "steep/shims/filter_map"
|
27
|
-
require "steep/shims/symbol_start_with"
|
28
|
-
|
29
26
|
require "steep/thread_waiter"
|
30
27
|
require "steep/equatable"
|
31
28
|
require "steep/method_name"
|
@@ -113,6 +110,7 @@ require "steep/services/stats_calculator"
|
|
113
110
|
require "steep/services/file_loader"
|
114
111
|
require "steep/services/goto_service"
|
115
112
|
|
113
|
+
require "steep/server/delay_queue"
|
116
114
|
require "steep/server/lsp_formatter"
|
117
115
|
require "steep/server/change_buffer"
|
118
116
|
require "steep/server/base_worker"
|
@@ -52,6 +52,11 @@ module Steep
|
|
52
52
|
def initialize: (?location: untyped?) -> void
|
53
53
|
end
|
54
54
|
|
55
|
+
# A type for `Class#<` or `Class#<=` call results.
|
56
|
+
class ArgIsAncestor < Base
|
57
|
+
def initialize: (?location: untyped?) -> void
|
58
|
+
end
|
59
|
+
|
55
60
|
# A type with truthy/falsy type environment.
|
56
61
|
class Env < Base
|
57
62
|
attr_reader truthy: TypeInference::TypeEnv
|
data/sig/steep/ast/types.rbs
CHANGED
@@ -6,7 +6,7 @@ module Steep
|
|
6
6
|
| Intersection | Record | Tuple | Union
|
7
7
|
| Name::Alias | Name::Instance | Name::Interface | Name::Singleton
|
8
8
|
| Proc | Var
|
9
|
-
| Logic::Not | Logic::ReceiverIsNil | Logic::ReceiverIsNotNil | Logic::ReceiverIsArg | Logic::ArgIsReceiver | Logic::ArgEqualsReceiver | Logic::Env
|
9
|
+
| Logic::Not | Logic::ReceiverIsNil | Logic::ReceiverIsNotNil | Logic::ReceiverIsArg | Logic::ArgIsReceiver | Logic::ArgEqualsReceiver | Logic::ArgIsAncestor | Logic::Env
|
10
10
|
|
11
11
|
# Variables and special types that is subject for substitution
|
12
12
|
#
|
data/sig/steep/cli.rbs
CHANGED
@@ -98,19 +98,19 @@ module Steep
|
|
98
98
|
end
|
99
99
|
|
100
100
|
class UnresolvedOverloading < Base
|
101
|
-
attr_reader node:
|
101
|
+
attr_reader node (): Parser::AST::Node
|
102
102
|
|
103
|
-
attr_reader receiver_type:
|
103
|
+
attr_reader receiver_type: AST::Types::t
|
104
104
|
|
105
|
-
attr_reader method_name:
|
105
|
+
attr_reader method_name: Symbol
|
106
106
|
|
107
|
-
attr_reader method_types:
|
107
|
+
attr_reader method_types: Array[Interface::MethodType]
|
108
108
|
|
109
|
-
def initialize: (node:
|
109
|
+
def initialize: (node: Parser::AST::Node, receiver_type: AST::Types::t, method_name: Symbol, method_types: Array[Interface::MethodType]) -> void
|
110
110
|
|
111
|
-
def header_line: () ->
|
111
|
+
def header_line: () -> String
|
112
112
|
|
113
|
-
def detail_lines: () ->
|
113
|
+
def detail_lines: () -> String
|
114
114
|
end
|
115
115
|
|
116
116
|
class ArgumentTypeMismatch < Base
|
@@ -1,22 +1,44 @@
|
|
1
1
|
module Steep
|
2
2
|
class Project
|
3
|
+
# `Pattern` class represents a pair of *positive* and *negative* patterns that may match with a pathname
|
4
|
+
#
|
5
|
+
# ```rb
|
6
|
+
# pat = Pattern.new(patterns: ["app/models"], ignores: ["app/models/account.rb"], ext: ".rbs")
|
7
|
+
#
|
8
|
+
# pat =~ "app/models/group.rb" # => true
|
9
|
+
# pat =~ "app/models/account.rb" # => false
|
10
|
+
# ```
|
11
|
+
#
|
12
|
+
# The pattern may be:
|
13
|
+
#
|
14
|
+
# 1. Directory name pattern -- `lib`, or
|
15
|
+
# 2. *Glob* pattern -- `foo/**/bar.rb`
|
16
|
+
#
|
3
17
|
class Pattern
|
18
|
+
# Positive patterns, which is tested with `fnmatch`
|
4
19
|
attr_reader patterns: Array[String]
|
5
20
|
|
21
|
+
# Negative patterns, which is tested with `fnmatch`
|
6
22
|
attr_reader ignores: Array[String]
|
7
23
|
|
24
|
+
# Positive *dir name* pattern constructed from `#patterns`, which is tested with `start_with?`
|
8
25
|
attr_reader prefixes: Array[String]
|
9
26
|
|
27
|
+
# Negative *dir name* pattern constructed from `#ignores`, which is tested with `start_with?`
|
10
28
|
attr_reader ignore_prefixes: Array[String]
|
11
29
|
|
12
30
|
attr_reader ext: String
|
13
31
|
|
14
32
|
def initialize: (patterns: Array[String], ext: String, ?ignores: Array[String]) -> void
|
15
33
|
|
34
|
+
# Returns `true` if given path matches to *positive* pattern, but doesn't match to *negative* pattern
|
35
|
+
#
|
16
36
|
def =~: (Pathname | String path) -> bool
|
17
37
|
|
38
|
+
# Returns true if given `Pathname` matches to *positive* pattern
|
18
39
|
def match?: (Pathname path) -> bool
|
19
40
|
|
41
|
+
# Returns true if given `Pathname` matches to *negative* pattern
|
20
42
|
def ignore?: (Pathname path) -> bool
|
21
43
|
|
22
44
|
def test_string: (Pathname path, Array[String] patterns, Array[String] prefixes) -> bool
|
@@ -27,6 +27,10 @@ module Steep
|
|
27
27
|
# Load changes from a request with `DidChangeTextDocumentParams` into `buffered_changes`
|
28
28
|
#
|
29
29
|
def collect_changes: (untyped request) -> void
|
30
|
+
|
31
|
+
# Reset the content of `uri` to `text`
|
32
|
+
#
|
33
|
+
def reset_change: (uri: String, text: String) -> void
|
30
34
|
end
|
31
35
|
end
|
32
36
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Steep
|
2
|
+
module Server
|
3
|
+
# DelayQueue provides a queue that delays running given job
|
4
|
+
#
|
5
|
+
# 1. The `delay` is specific to a DelayQueue instance, not job specific
|
6
|
+
# 2. It executes only the last job
|
7
|
+
#
|
8
|
+
# ```ruby
|
9
|
+
# queue = DelayQueue.new(delay: 0.5)
|
10
|
+
# queue.execute { pp 1 }
|
11
|
+
# queue.execute { pp 2 }
|
12
|
+
# queue.execute { pp 3 }
|
13
|
+
#
|
14
|
+
# # => Will print only `3`, and the jobs printing `1` and `2` will be discarded
|
15
|
+
# ```
|
16
|
+
#
|
17
|
+
# The job will run on `#thread`.
|
18
|
+
#
|
19
|
+
class DelayQueue
|
20
|
+
attr_reader delay: Float
|
21
|
+
|
22
|
+
attr_reader thread: Thread
|
23
|
+
|
24
|
+
attr_reader queue: Thread::Queue
|
25
|
+
|
26
|
+
attr_reader last_task: Proc
|
27
|
+
|
28
|
+
def initialize: (delay: Float) -> void
|
29
|
+
|
30
|
+
# The `#execute` method is not thread safe
|
31
|
+
#
|
32
|
+
# You should synchronize yourself if you want to call the method from multiple threads.
|
33
|
+
#
|
34
|
+
def execute: () { () -> void } -> void
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/sig/steep/server/master.rbs
CHANGED
@@ -225,6 +225,8 @@ module Steep
|
|
225
225
|
|
226
226
|
attr_accessor typecheck_automatically: bool
|
227
227
|
|
228
|
+
attr_reader start_type_checking_queue: DelayQueue
|
229
|
+
|
228
230
|
def initialize: (project: Project, reader: untyped, writer: untyped, interaction_worker: WorkerProcess?, typecheck_workers: Array[WorkerProcess], ?queue: Thread::Queue) -> void
|
229
231
|
|
230
232
|
# Start the Steep language server
|
@@ -252,6 +254,8 @@ module Steep
|
|
252
254
|
|
253
255
|
def work_done_progress_supported?: () -> bool
|
254
256
|
|
257
|
+
def file_system_watcher_supported?: () -> bool
|
258
|
+
|
255
259
|
def process_message_from_client: (untyped message) -> void
|
256
260
|
|
257
261
|
def process_message_from_worker: (untyped message, worker: WorkerProcess) -> void
|
@@ -1,17 +1,41 @@
|
|
1
1
|
module Steep
|
2
2
|
module Services
|
3
3
|
class StatsCalculator
|
4
|
-
SuccessStats
|
4
|
+
class SuccessStats
|
5
|
+
attr_reader target: Project::Target
|
5
6
|
|
6
|
-
|
7
|
+
attr_reader path: Pathname
|
7
8
|
|
8
|
-
|
9
|
+
attr_reader typed_calls_count: Integer
|
9
10
|
|
10
|
-
|
11
|
+
attr_reader untyped_calls_count: Integer
|
11
12
|
|
12
|
-
|
13
|
+
attr_reader error_calls_count: Integer
|
13
14
|
|
14
|
-
|
15
|
+
def initialize: (target: Project::Target, path: Pathname, typed_calls_count: Integer, untyped_calls_count: Integer, error_calls_count: Integer) -> void
|
16
|
+
|
17
|
+
def as_json: () -> Hash[Symbol, untyped]
|
18
|
+
end
|
19
|
+
|
20
|
+
class ErrorStats
|
21
|
+
attr_reader target: Project::Target
|
22
|
+
|
23
|
+
attr_reader path: Pathname
|
24
|
+
|
25
|
+
def initialize: (target: Project::Target, path: Pathname) -> void
|
26
|
+
|
27
|
+
def as_json: () -> Hash[Symbol, untyped]
|
28
|
+
end
|
29
|
+
|
30
|
+
type stats = SuccessStats | ErrorStats
|
31
|
+
|
32
|
+
attr_reader service: TypeCheckService
|
33
|
+
|
34
|
+
def initialize: (service: TypeCheckService) -> void
|
35
|
+
|
36
|
+
def project: () -> Project
|
37
|
+
|
38
|
+
def calc_stats: (Project::Target target, file: TypeCheckService::SourceFile) -> stats
|
15
39
|
end
|
16
40
|
end
|
17
41
|
end
|
@@ -112,9 +112,22 @@ module Steep
|
|
112
112
|
|
113
113
|
def format_constant_name: (TypeName) -> String
|
114
114
|
|
115
|
+
def resolve_used_name: (TypeName) -> TypeName?
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
# Yield type names defined in the environment
|
120
|
+
#
|
121
|
+
# * Yields an absolute type name if it is defined in the environment
|
122
|
+
# * Yields an relative type name if it is imported with `use` declerative
|
123
|
+
#
|
124
|
+
# Alias classes/modules and types under them are yielded.
|
125
|
+
#
|
115
126
|
def each_type_name: () { (TypeName) -> void } -> void
|
116
127
|
| () -> Enumerator[TypeName, void]
|
117
128
|
|
129
|
+
def each_type_name_under: (TypeName module_name, TypeName normalized_name, table: Hash[Namespace, Array[TypeName]]) { (TypeName) -> void } -> void
|
130
|
+
|
118
131
|
def each_outer_module: (?Resolver::context) { (Namespace) -> void } -> Namespace
|
119
132
|
| () -> Enumerator[Namespace, void]
|
120
133
|
end
|
@@ -66,6 +66,11 @@ module Steep
|
|
66
66
|
|
67
67
|
def validate_one_global: (Symbol name, RBS::Environment::GlobalEntry) -> void
|
68
68
|
|
69
|
+
# Validate type alias
|
70
|
+
#
|
71
|
+
# 1. Make sure the outer namespace of given `name` exists
|
72
|
+
# 2. Make sure the type alias is valid with respect to `RBS::Validator`
|
73
|
+
#
|
69
74
|
def validate_one_alias: (RBS::TypeName name, ?RBS::Environment::TypeAliasEntry entry) -> void
|
70
75
|
|
71
76
|
def validate_one_class_decl: (RBS::TypeName) -> void
|
@@ -123,7 +123,7 @@ module Steep
|
|
123
123
|
# Returns nil if there is no path.
|
124
124
|
def hole_path: (AST::Types::t `type`, ?Array[AST::Types::t] path) -> Array[AST::Types::t]?
|
125
125
|
|
126
|
-
def Relation: [T <
|
126
|
+
def Relation: [T < Relation::_Subject] (T sub, T sup) -> Relation[T]
|
127
127
|
end
|
128
128
|
end
|
129
129
|
end
|
@@ -1,6 +1,16 @@
|
|
1
1
|
module Steep
|
2
2
|
module Subtyping
|
3
|
-
class Relation[out Subject <
|
3
|
+
class Relation[out Subject < _Subject]
|
4
|
+
interface _Subject
|
5
|
+
def hash: () -> Integer
|
6
|
+
|
7
|
+
def is_a?: (Module) -> bool
|
8
|
+
|
9
|
+
def class: () -> Class
|
10
|
+
|
11
|
+
def !: () -> bool
|
12
|
+
end
|
13
|
+
|
4
14
|
attr_reader sub_type: Subject
|
5
15
|
|
6
16
|
attr_reader super_type: Subject
|
@@ -45,7 +45,7 @@ module Steep
|
|
45
45
|
@failure: bool
|
46
46
|
|
47
47
|
# Returns `false` if no future `#add` changes the result.
|
48
|
-
def add: [T <
|
48
|
+
def add: [T < Relation::_Subject] (*Relation[T] relations) { (Relation[T]) -> t? } -> bool
|
49
49
|
|
50
50
|
# Returns `false` if no future `#add` changes the result.
|
51
51
|
def add_result: (t?) -> bool
|
@@ -271,7 +271,7 @@ module Steep
|
|
271
271
|
def calculate_interface: (AST::Types::t `type`, private: bool) -> Interface::Shape?
|
272
272
|
| (AST::Types::t `type`, Symbol method_name, private: bool) -> Interface::Shape::Entry?
|
273
273
|
|
274
|
-
def expand_self: (
|
274
|
+
def expand_self: (AST::Types::t `type`) -> AST::Types::t
|
275
275
|
|
276
276
|
SPECIAL_METHOD_NAMES: Hash[Symbol, Set[method_name]]
|
277
277
|
|
@@ -98,31 +98,27 @@
|
|
98
98
|
- range:
|
99
99
|
start:
|
100
100
|
line: 10
|
101
|
-
character:
|
101
|
+
character: 12
|
102
102
|
end:
|
103
103
|
line: 10
|
104
|
-
character:
|
104
|
+
character: 28
|
105
105
|
severity: ERROR
|
106
106
|
message: |-
|
107
|
-
Cannot
|
108
|
-
|
109
|
-
|
110
|
-
| () -> ::Enumerator[::Integer, ::Array[untyped]]
|
111
|
-
code: Ruby::UnresolvedOverloading
|
107
|
+
Cannot pass a value of type `::Proc` as a block-pass-argument of type `^(::Integer) -> U(3)`
|
108
|
+
::Proc <: ^(::Integer) -> U(3)
|
109
|
+
code: Ruby::BlockTypeMismatch
|
112
110
|
- range:
|
113
111
|
start:
|
114
112
|
line: 11
|
115
|
-
character:
|
113
|
+
character: 12
|
116
114
|
end:
|
117
115
|
line: 11
|
118
|
-
character:
|
116
|
+
character: 20
|
119
117
|
severity: ERROR
|
120
118
|
message: |-
|
121
|
-
Cannot
|
122
|
-
|
123
|
-
|
124
|
-
| () -> ::Enumerator[::Integer, ::Array[untyped]]
|
125
|
-
code: Ruby::UnresolvedOverloading
|
119
|
+
Cannot pass a value of type `::Proc` as a block-pass-argument of type `^(::Integer) -> U(4)`
|
120
|
+
::Proc <: ^(::Integer) -> U(4)
|
121
|
+
code: Ruby::BlockTypeMismatch
|
126
122
|
- file: e.rb
|
127
123
|
diagnostics:
|
128
124
|
- range:
|
@@ -10,11 +10,11 @@
|
|
10
10
|
character: 3
|
11
11
|
severity: ERROR
|
12
12
|
message: |-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
code: Ruby::
|
13
|
+
Unsatisfiable constraint `::String <: U(1) <: ::Hash[::Symbol, ::String]` is generated through (U(1)) { (::Integer, U(1)) -> untyped } -> U(1)
|
14
|
+
::String <: ::Hash[::Symbol, ::String]
|
15
|
+
::Object <: ::Hash[::Symbol, ::String]
|
16
|
+
::BasicObject <: ::Hash[::Symbol, ::String]
|
17
|
+
code: Ruby::UnsatisfiableConstraint
|
18
18
|
- file: b.rb
|
19
19
|
diagnostics:
|
20
20
|
- range:
|
@@ -40,8 +40,8 @@
|
|
40
40
|
character: 3
|
41
41
|
severity: ERROR
|
42
42
|
message: |-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
code: Ruby::
|
43
|
+
Unsatisfiable constraint `::Array[untyped] <: U(3) <: ::String` is generated through (U(3)) { (::Integer, U(3)) -> untyped } -> U(3)
|
44
|
+
::Array[untyped] <: ::String
|
45
|
+
::Object <: ::String
|
46
|
+
::BasicObject <: ::String
|
47
|
+
code: Ruby::UnsatisfiableConstraint
|
@@ -102,20 +102,9 @@
|
|
102
102
|
message: |-
|
103
103
|
Cannot find compatible overloading of method `Integer` of type `::Object`
|
104
104
|
Method types:
|
105
|
-
def Integer: ((::
|
106
|
-
| (::
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
line: 26
|
111
|
-
character: 0
|
112
|
-
end:
|
113
|
-
line: 26
|
114
|
-
character: 12
|
115
|
-
severity: ERROR
|
116
|
-
message: |-
|
117
|
-
Cannot find compatible overloading of method `Integer` of type `::Object`
|
118
|
-
Method types:
|
119
|
-
def Integer: ((::Numeric | ::String), ?exception: bool) -> ::Integer
|
120
|
-
| (::String, ?::Integer, ?exception: bool) -> ::Integer
|
105
|
+
def Integer: ((::_ToInt | ::_ToI), ?exception: true) -> ::Integer
|
106
|
+
| ((::_ToInt | ::_ToI), exception: bool) -> (::Integer | nil)
|
107
|
+
| (::string, ?::int, ?exception: true) -> ::Integer
|
108
|
+
| (::string, ?::int, exception: bool) -> (::Integer | nil)
|
109
|
+
| (untyped, ?untyped, exception: false) -> nil
|
121
110
|
code: Ruby::UnresolvedOverloading
|
@@ -0,0 +1 @@
|
|
1
|
+
1.foo()
|