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
@@ -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()
|