steep 1.0.2 → 1.1.0.pre.1
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.yml +5 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +22 -3
- data/Gemfile +6 -3
- data/Gemfile.lock +12 -16
- data/Gemfile.steep +3 -0
- data/Gemfile.steep.lock +49 -0
- data/Rakefile +5 -0
- data/Steepfile +6 -1
- data/bin/setup +2 -0
- data/bin/steep +19 -0
- data/lib/steep/ast/types/factory.rb +1 -1
- data/lib/steep/diagnostic/ruby.rb +49 -3
- data/lib/steep/diagnostic/signature.rb +18 -0
- data/lib/steep/drivers/watch.rb +3 -1
- data/lib/steep/method_name.rb +9 -3
- data/lib/steep/node_helper.rb +49 -0
- data/lib/steep/services/completion_provider.rb +22 -15
- data/lib/steep/services/hover_provider/ruby.rb +30 -12
- data/lib/steep/services/type_check_service.rb +12 -12
- data/lib/steep/shims/symbol_start_with.rb +18 -0
- data/lib/steep/signature/validator.rb +19 -0
- data/lib/steep/subtyping/constraints.rb +43 -14
- data/lib/steep/type_construction.rb +666 -746
- data/lib/steep/type_inference/constant_env.rb +0 -2
- data/lib/steep/type_inference/context.rb +23 -17
- data/lib/steep/type_inference/logic_type_interpreter.rb +210 -119
- data/lib/steep/type_inference/method_call.rb +80 -6
- data/lib/steep/type_inference/multiple_assignment.rb +189 -0
- data/lib/steep/type_inference/type_env.rb +271 -120
- data/lib/steep/type_inference/type_env_builder.rb +138 -0
- data/lib/steep/typing.rb +2 -0
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +4 -3
- data/rbs_collection.steep.lock.yaml +112 -0
- data/rbs_collection.steep.yaml +19 -0
- data/sample/sig/conference.rbs +8 -0
- data/sig/shims/parser/source/map.rbs +146 -0
- data/sig/shims/parser/source/range.rbs +237 -0
- data/sig/shims/parser.rbs +17 -0
- data/sig/steep/ast/annotation/collection.rbs +75 -0
- data/sig/steep/ast/annotation.rbs +126 -0
- data/sig/steep/ast/builtin.rbs +69 -0
- data/sig/steep/ast/type_params.rbs +11 -0
- data/sig/steep/ast/types/any.rbs +29 -0
- data/sig/steep/ast/types/boolean.rbs +31 -0
- data/sig/steep/ast/types/bot.rbs +29 -0
- data/sig/steep/ast/types/class.rbs +29 -0
- data/sig/steep/ast/types/factory.rbs +76 -0
- data/sig/steep/ast/types/helper.rbs +19 -0
- data/sig/steep/ast/types/instance.rbs +29 -0
- data/sig/steep/ast/types/intersection.rbs +35 -0
- data/sig/steep/ast/types/literal.rbs +33 -0
- data/sig/steep/ast/types/logic.rbs +78 -0
- data/sig/steep/ast/types/name.rbs +71 -0
- data/sig/steep/ast/types/nil.rbs +31 -0
- data/sig/steep/ast/types/proc.rbs +46 -0
- data/sig/steep/ast/types/record.rbs +38 -0
- data/sig/steep/ast/types/self.rbs +29 -0
- data/sig/steep/ast/types/top.rbs +29 -0
- data/sig/steep/ast/types/tuple.rbs +34 -0
- data/sig/steep/ast/types/union.rbs +38 -0
- data/sig/steep/ast/types/var.rbs +37 -0
- data/sig/steep/ast/types/void.rbs +29 -0
- data/sig/steep/ast/types.rbs +37 -0
- data/sig/steep/diagnostic/deprecated/unknown_constant_assigned.rbs +15 -0
- data/sig/steep/diagnostic/helper.rbs +9 -0
- data/sig/steep/diagnostic/lsp_formatter.rbs +29 -0
- data/sig/steep/diagnostic/ruby.rbs +494 -0
- data/sig/steep/diagnostic/signature.rbs +215 -0
- data/sig/steep/interface/block.rbs +35 -0
- data/sig/steep/interface/function.rbs +253 -0
- data/sig/steep/interface/interface.rbs +23 -0
- data/sig/steep/interface/method_type.rbs +55 -0
- data/sig/steep/interface/substitution.rbs +53 -0
- data/sig/steep/interface/type_param.rbs +35 -0
- data/sig/steep/method_name.rbs +26 -0
- data/sig/steep/module_helper.rbs +7 -0
- data/sig/steep/node_helper.rbs +11 -0
- data/sig/steep/project/dsl.rbs +94 -0
- data/sig/steep/project/options.rbs +15 -0
- data/sig/steep/project/pattern.rbs +25 -0
- data/sig/steep/project/target.rbs +25 -0
- data/sig/steep/project.rbs +19 -0
- data/sig/steep/services/completion_provider.rbs +123 -0
- data/sig/steep/services/content_change.rbs +35 -0
- data/sig/steep/services/file_loader.rbs +13 -0
- data/sig/steep/services/goto_service.rbs +45 -0
- data/sig/steep/services/hover_provider/rbs.rbs +21 -0
- data/sig/steep/services/hover_provider/ruby.rbs +109 -0
- data/sig/steep/services/hover_provider/singleton_methods.rbs +11 -0
- data/sig/steep/services/path_assignment.rbs +21 -0
- data/sig/steep/services/signature_service.rbs +91 -0
- data/sig/steep/services/stats_calculator.rbs +17 -0
- data/sig/steep/services/type_check_service.rbs +93 -0
- data/sig/steep/source.rbs +55 -0
- data/sig/steep/subtyping/cache.rbs +17 -0
- data/sig/steep/subtyping/check.rbs +93 -0
- data/sig/steep/subtyping/constraints.rbs +111 -0
- data/sig/steep/subtyping/relation.rbs +51 -0
- data/sig/steep/subtyping/result.rbs +157 -0
- data/sig/steep/subtyping/variable_variance.rbs +23 -0
- data/sig/steep/type_construction.rbs +285 -0
- data/sig/steep/type_inference/block_params.rbs +52 -0
- data/sig/steep/type_inference/constant_env.rbs +27 -0
- data/sig/steep/type_inference/context.rbs +137 -0
- data/sig/steep/type_inference/logic_type_interpreter.rbs +72 -0
- data/sig/steep/type_inference/method_call.rbs +124 -0
- data/sig/steep/type_inference/method_params.rbs +104 -0
- data/sig/steep/type_inference/multiple_assignment.rbs +76 -0
- data/sig/steep/type_inference/type_env.rbs +158 -0
- data/sig/steep/type_inference/type_env_builder.rbs +77 -0
- data/sig/steep/typing.rbs +68 -0
- data/sig/steep.rbs +31 -0
- data/smoke/class/f.rb +1 -0
- data/smoke/class/test_expectations.yml +2 -2
- data/smoke/diagnostics/test_expectations.yml +4 -2
- metadata +90 -6
- data/lib/steep/type_inference/local_variable_type_env.rb +0 -249
- data/lib/steep/type_inference/logic.rb +0 -161
@@ -0,0 +1,285 @@
|
|
1
|
+
module Steep
|
2
|
+
class TypeConstruction
|
3
|
+
class Pair
|
4
|
+
attr_reader type: AST::Types::t
|
5
|
+
|
6
|
+
attr_reader constr: TypeConstruction
|
7
|
+
|
8
|
+
def initialize: (type: AST::Types::t, constr: TypeConstruction) -> void
|
9
|
+
|
10
|
+
def with: (?type: AST::Types::t, ?constr: TypeConstruction) -> Pair
|
11
|
+
|
12
|
+
def +: (Pair other) -> Pair
|
13
|
+
|
14
|
+
def context: () -> TypeInference::Context
|
15
|
+
|
16
|
+
def to_ary: () -> [AST::Types::t, TypeConstruction, TypeInference::Context]
|
17
|
+
end
|
18
|
+
|
19
|
+
include NodeHelper
|
20
|
+
|
21
|
+
attr_reader checker: Subtyping::Check
|
22
|
+
|
23
|
+
attr_reader source: Source
|
24
|
+
|
25
|
+
attr_reader annotations: AST::Annotation::Collection
|
26
|
+
|
27
|
+
attr_reader typing: Typing
|
28
|
+
|
29
|
+
attr_reader context: TypeInference::Context
|
30
|
+
|
31
|
+
def module_context: () -> TypeInference::Context::ModuleContext?
|
32
|
+
|
33
|
+
def method_context: () -> TypeInference::Context::MethodContext?
|
34
|
+
|
35
|
+
def block_context: () -> TypeInference::Context::BlockContext?
|
36
|
+
|
37
|
+
def break_context: () -> TypeInference::Context::BreakContext?
|
38
|
+
|
39
|
+
def self_type: () -> untyped
|
40
|
+
|
41
|
+
def variable_context: () -> TypeInference::Context::TypeVariableContext
|
42
|
+
|
43
|
+
def initialize: (checker: untyped, source: untyped, annotations: untyped, typing: untyped, context: untyped) -> void
|
44
|
+
|
45
|
+
def with_new_typing: (Typing typing) -> TypeConstruction
|
46
|
+
|
47
|
+
def with_updated_context: (?type_env: TypeInference::TypeEnv) -> TypeConstruction
|
48
|
+
|
49
|
+
def with: (?annotations: untyped, ?context: TypeInference::Context, ?typing: untyped) -> TypeConstruction
|
50
|
+
|
51
|
+
def update_context: () { (TypeInference::Context) -> TypeInference::Context } -> TypeConstruction
|
52
|
+
|
53
|
+
def update_type_env: () { (TypeInference::TypeEnv) -> TypeInference::TypeEnv } -> TypeConstruction
|
54
|
+
|
55
|
+
def check_relation: (sub_type: AST::Types::t, super_type: AST::Types::t, ?constraints: Subtyping::Constraints) -> Subtyping::Result::Base
|
56
|
+
|
57
|
+
# This is a variation of `#check_relation` method.
|
58
|
+
# It checks if given subtyping relation `sub_type <: super_type` holds or not, and returns truthy when *doesn't* hold.
|
59
|
+
#
|
60
|
+
# * Returns `nil` if holds
|
61
|
+
# * Returns subclass of `Result::Base` if the subtyping doesn't hold
|
62
|
+
#
|
63
|
+
# This allow you writing a subtyping check as:
|
64
|
+
#
|
65
|
+
# ```ruby
|
66
|
+
# if relation = no_subtyping?(sub_type: type1, super_type: type2)
|
67
|
+
# # Implement error reporting
|
68
|
+
# end
|
69
|
+
# ```
|
70
|
+
#
|
71
|
+
def no_subtyping?: (sub_type: AST::Types::t, super_type: AST::Types::t, ?constraints: Subtyping::Constraints) -> Subtyping::Result::Base?
|
72
|
+
|
73
|
+
def for_new_method: (Symbol method_name, Parser::AST::Node node, args: Array[Parser::AST::Node], self_type: untyped, definition: RBS::Definition?) -> TypeConstruction
|
74
|
+
|
75
|
+
def with_method_constr: (untyped method_name, untyped node, args: untyped, self_type: untyped, definition: untyped) { (untyped) -> untyped } -> untyped
|
76
|
+
|
77
|
+
def implement_module: (module_name: untyped, annotations: untyped, ?super_name: untyped?) -> untyped
|
78
|
+
|
79
|
+
def default_module_context: (untyped implement_module_name, nesting: untyped) -> untyped
|
80
|
+
|
81
|
+
def for_module: (untyped node, untyped new_module_name) -> untyped
|
82
|
+
|
83
|
+
def with_module_constr: (untyped node, untyped module_name) { (untyped) -> untyped } -> untyped
|
84
|
+
|
85
|
+
def for_class: (untyped node, untyped new_class_name, untyped super_class_name) -> untyped
|
86
|
+
|
87
|
+
def with_class_constr: (untyped node, untyped new_class_name, untyped super_class_name) { (untyped) -> untyped } -> untyped
|
88
|
+
|
89
|
+
def with_sclass_constr: [A] (Parser::AST::Node node, AST::Types::t `type`) { (TypeConstruction?) -> A } -> A
|
90
|
+
|
91
|
+
def for_sclass: (Parser::AST::Node node, AST::Types::t `type`) -> TypeConstruction?
|
92
|
+
|
93
|
+
def for_branch: (Parser::AST::Node node, ?break_context: TypeInference::Context::BreakContext?) -> untyped
|
94
|
+
|
95
|
+
def add_typing: (Parser::AST::Node node, type: AST::Types::t, ?constr: TypeConstruction) -> Pair
|
96
|
+
|
97
|
+
def add_call: (untyped call) -> untyped
|
98
|
+
|
99
|
+
def synthesize: (Parser::AST::Node node, ?hint: AST::Types::t?, ?condition: bool) -> Pair
|
100
|
+
|
101
|
+
def check: (Parser::AST::Node node, AST::Types::t `type`, ?constraints: Subtyping::Constraints) { (AST::Types::t, AST::Types::t, Subtyping::Result::Base) -> void } -> Pair
|
102
|
+
|
103
|
+
def masgn_lhs?: (untyped lhs) -> untyped
|
104
|
+
|
105
|
+
def lvasgn: (Parser::AST::Node node, AST::Types::t) -> Pair
|
106
|
+
|
107
|
+
def ivasgn: (Parser::AST::Node node, AST::Types::t rhs_type) -> Pair
|
108
|
+
|
109
|
+
def type_masgn: (Parser::AST::Node node) -> Pair
|
110
|
+
|
111
|
+
def type_masgn_type: (Parser::AST::Node mlhs_node, AST::Types::t? rhs_type, masgn: TypeInference::MultipleAssignment, optional: bool) -> TypeConstruction?
|
112
|
+
|
113
|
+
def constant_typename: (Parser::AST::Node parent, Symbol name) -> RBS::TypeName?
|
114
|
+
|
115
|
+
def synthesize_constant: (Parser::AST::Node node, Parser::AST::Node? parent_node, Symbol constant_name) { () -> void } -> [AST::Types::t, TypeConstruction, RBS::TypeName?]
|
116
|
+
|
117
|
+
def optional_proc?: (untyped `type`) -> (untyped | nil | nil | nil | nil)
|
118
|
+
|
119
|
+
def type_lambda: (Parser::AST::Node node, params_node: Parser::AST::Node, body_node: Parser::AST::Node, type_hint: AST::Types::t?) -> Pair
|
120
|
+
|
121
|
+
def synthesize_children: (Parser::AST::Node node, ?skips: Array[Parser::AST::Node]) -> TypeConstruction
|
122
|
+
|
123
|
+
def type_send_interface: (Parser::AST::Node node, interface: Interface::Interface, receiver: Parser::AST::Node, receiver_type: AST::Types::t, method_name: Symbol, arguments: Array[Parser::AST::Node], block_params: Parser::AST::Node?, block_body: Parser::AST::Node?) -> Pair
|
124
|
+
|
125
|
+
def type_send: (untyped node, send_node: untyped, block_params: untyped, block_body: untyped, ?unwrap: bool) -> untyped
|
126
|
+
|
127
|
+
def calculate_interface: (untyped `type`, private: untyped, ?self_type: untyped) -> untyped
|
128
|
+
|
129
|
+
def expand_self: (untyped `type`) -> untyped
|
130
|
+
|
131
|
+
SPECIAL_METHOD_NAMES: { array_compact: untyped, hash_compact: untyped }
|
132
|
+
|
133
|
+
KNOWN_PURE_METHODS: Set[method_name]
|
134
|
+
|
135
|
+
def try_special_method: (untyped node, receiver_type: untyped, method_name: untyped, method_type: untyped, arguments: untyped, block_params: untyped, block_body: untyped) -> (::Array[untyped] | nil)
|
136
|
+
|
137
|
+
def type_method_call: (
|
138
|
+
Parser::AST::Node node,
|
139
|
+
method_name: Symbol,
|
140
|
+
receiver_type: AST::Types::t,
|
141
|
+
method: Interface::Interface::Entry,
|
142
|
+
arguments: Array[Parser::AST::Node],
|
143
|
+
block_params: Parser::AST::Node?,
|
144
|
+
block_body: Parser::AST::Node?,
|
145
|
+
topdown_hint: untyped
|
146
|
+
) -> [TypeInference::MethodCall::t, TypeConstruction]?
|
147
|
+
|
148
|
+
def inspect: () -> ::String
|
149
|
+
|
150
|
+
def with_child_typing: (range: untyped) { (untyped) -> untyped } -> untyped
|
151
|
+
|
152
|
+
# Bypass :splat and :kwsplat
|
153
|
+
def bypass_splat: (untyped node) { (untyped) -> untyped } -> untyped
|
154
|
+
|
155
|
+
# Solve a constraint in the block and return a substitution if succeeds.
|
156
|
+
#
|
157
|
+
# * When the constraint has a solution, `#apply_solution` returns a tuple of substituted `MethodType`, `true`, and the substitution.
|
158
|
+
# * When the constraint doesn't have a solution, `#apply_solution` returns a tuple of the original `MethodType`, `false`, and empty substitution.
|
159
|
+
#
|
160
|
+
def apply_solution: (
|
161
|
+
Array[Diagnostic::Ruby::Base] errors,
|
162
|
+
node: Parser::AST::Node,
|
163
|
+
method_type: Interface::MethodType
|
164
|
+
) {
|
165
|
+
() -> Interface::Substitution
|
166
|
+
} -> [Interface::MethodType, bool, Interface::Substitution]
|
167
|
+
|
168
|
+
def eliminate_vars: (untyped `type`, untyped variables, ?to: untyped) -> untyped
|
169
|
+
|
170
|
+
def try_method_type: (Parser::AST::Node node, receiver_type: AST::Types::t, method_name: Symbol, method_type: Interface::MethodType, arguments: Array[Parser::AST::Node], block_params: Parser::AST::Node?, block_body: Parser::AST::Node?, topdown_hint: untyped) -> [TypeInference::MethodCall::t, TypeConstruction]
|
171
|
+
|
172
|
+
def type_check_argument: (Parser::AST::Node node, receiver_type: AST::Types::t, type: AST::Types::t, constraints: Subtyping::Constraints, errors: Array[Diagnostic::Ruby::Base], ?report_node: Parser::AST::Node) -> Pair
|
173
|
+
|
174
|
+
def type_block_without_hint: (node: untyped, block_annotations: untyped, block_params: untyped, block_body: untyped) { () -> untyped } -> untyped
|
175
|
+
|
176
|
+
# Returns a Pair of
|
177
|
+
#
|
178
|
+
# * TypeConstruction to type check the block, and
|
179
|
+
# * Set of local variable names to unpin after type checking the block
|
180
|
+
#
|
181
|
+
def for_block: (
|
182
|
+
Parser::AST::Node? body_node,
|
183
|
+
block_params: TypeInference::BlockParams,
|
184
|
+
block_param_hint: TypeInference::MethodParams?,
|
185
|
+
block_type_hint: AST::Types::t?,
|
186
|
+
block_block_hint: Interface::Block?,
|
187
|
+
block_annotations: AST::Annotation::Collection,
|
188
|
+
node_type_hint: AST::Types::t?
|
189
|
+
) -> TypeConstruction
|
190
|
+
|
191
|
+
# Synthesize the block body and returns the type of the body
|
192
|
+
#
|
193
|
+
# The constructor can be discarded because it cannot change anything outer than block.
|
194
|
+
#
|
195
|
+
def synthesize_block: (node: Parser::AST::Node, block_type_hint: AST::Types::t?, block_body: Parser::AST::Node?) -> AST::Types::t
|
196
|
+
|
197
|
+
def nesting: () -> RBS::Resolver::context
|
198
|
+
|
199
|
+
def absolute_name: (untyped name) -> untyped
|
200
|
+
|
201
|
+
def union_type: (*AST::Types::t types) -> AST::Types::t
|
202
|
+
|
203
|
+
def validate_method_definitions: (untyped node, untyped module_name) -> (nil | untyped)
|
204
|
+
|
205
|
+
def fallback_to_any: (Parser::AST::Node node) ?{ () -> Diagnostic::Ruby::Base } -> Pair
|
206
|
+
|
207
|
+
def self_class?: (untyped node) -> untyped
|
208
|
+
|
209
|
+
def namespace_module?: (untyped node) -> (false | untyped)
|
210
|
+
|
211
|
+
def type_any_rec: (Parser::AST::Node node) -> Pair
|
212
|
+
|
213
|
+
def unwrap: (untyped `type`) -> untyped
|
214
|
+
|
215
|
+
def deep_expand_alias: (AST::Types::t `type`) -> AST::Types::t
|
216
|
+
| [A] (AST::Types::t) { (AST::Types::t) -> A } -> A
|
217
|
+
|
218
|
+
def flatten_union: (untyped `type`) -> untyped
|
219
|
+
|
220
|
+
def select_flatten_types: (untyped `type`) { () -> untyped } -> untyped
|
221
|
+
|
222
|
+
def partition_flatten_types: (AST::Types::t `type`) { (AST::Types::t) -> boolish } -> [Array[AST::Types::t], Array[AST::Types::t]]
|
223
|
+
|
224
|
+
def flatten_array_elements: (untyped `type`) -> untyped
|
225
|
+
|
226
|
+
def expand_alias: (AST::Types::t `type`) -> AST::Types::t
|
227
|
+
| [A] (AST::Types::t) { (AST::Types::t) -> A } -> A
|
228
|
+
|
229
|
+
def test_literal_type: (untyped literal, untyped hint) -> (untyped | nil)
|
230
|
+
|
231
|
+
def to_instance_type: (untyped `type`, ?args: untyped?) -> untyped
|
232
|
+
|
233
|
+
def try_tuple_type!: (Parser::AST::Node node, ?hint: AST::Types::t?) -> Pair
|
234
|
+
|
235
|
+
def try_tuple_type: (Parser::AST::Node node, AST::Types::Tuple? hint) -> (nil | untyped)
|
236
|
+
|
237
|
+
# Try to convert a object of `type` with zero-arity method `method`.
|
238
|
+
#
|
239
|
+
# Returns `nil` when
|
240
|
+
#
|
241
|
+
# 1. The `type` cannot be converted to an interface, or
|
242
|
+
# 2. There is no that `conversion` method defined
|
243
|
+
#
|
244
|
+
# ```ruby
|
245
|
+
# try_convert(`::Object`, :to_s) # Returns `::String`
|
246
|
+
# try_convert(`::String`, :to_ary) # Returns nil
|
247
|
+
# ```
|
248
|
+
#
|
249
|
+
def try_convert: (AST::Types::t `type`, Symbol method) -> AST::Types::t?
|
250
|
+
|
251
|
+
def try_array_type: (untyped node, untyped hint) -> untyped
|
252
|
+
|
253
|
+
# Returns a record type if `hash_node` can have a record type.
|
254
|
+
#
|
255
|
+
# You can give a hint through `record_type` by passing a `AST::Types::Record` object.
|
256
|
+
# If you pass `nil`, then we know the type is expected to be a record, but the detail is not given.
|
257
|
+
#
|
258
|
+
# Returns `nil` when the `hash_node` cannot have a record type.
|
259
|
+
#
|
260
|
+
def type_hash_record: (Parser::AST::Node hash_node, AST::Types::Record? record_type) -> Pair?
|
261
|
+
|
262
|
+
# Give hash_node a type based on hint.
|
263
|
+
#
|
264
|
+
# * When hint is Record type, it may have record type.
|
265
|
+
# * When hint is union type, it tries recursively with the union cases.
|
266
|
+
# * Otherwise, it tries to be a hash instance.
|
267
|
+
#
|
268
|
+
def type_hash: (untyped hash_node, hint: untyped) -> untyped
|
269
|
+
|
270
|
+
# Returns the first one from elements of `types` that returns a type `t` where `t <: hint`.
|
271
|
+
#
|
272
|
+
def pick_one_of: (Array[AST::Types::t] types, range: untyped) { (AST::Types::t hint, TypeConstruction) -> Pair? } -> Pair?
|
273
|
+
|
274
|
+
def save_typing: () -> untyped
|
275
|
+
|
276
|
+
# Returns `true` if a method call can be identified as _pure_.
|
277
|
+
#
|
278
|
+
# * The `node` is not a call with call
|
279
|
+
# * It always calls _pure_ method
|
280
|
+
# * The `receiver` is _pure_
|
281
|
+
# * All of the arguments are _pure_
|
282
|
+
#
|
283
|
+
def pure_send?: (TypeInference::MethodCall::Typed call, Parser::AST::Node receiver, Array[Parser::AST::Node] arguments) -> bool
|
284
|
+
end
|
285
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Steep
|
2
|
+
module TypeInference
|
3
|
+
class BlockParams
|
4
|
+
class Param
|
5
|
+
attr_reader var: Symbol
|
6
|
+
|
7
|
+
attr_reader type: AST::Types::t
|
8
|
+
|
9
|
+
attr_reader value: untyped
|
10
|
+
|
11
|
+
attr_reader node: Parser::AST::Node
|
12
|
+
|
13
|
+
def initialize: (var: Symbol, type: AST::Types::t, value: untyped, node: Parser::AST::Node) -> void
|
14
|
+
|
15
|
+
def ==: (untyped other) -> bool
|
16
|
+
|
17
|
+
alias eql? ==
|
18
|
+
|
19
|
+
def hash: () -> Integer
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader leading_params: untyped
|
23
|
+
|
24
|
+
attr_reader optional_params: untyped
|
25
|
+
|
26
|
+
attr_reader rest_param: untyped
|
27
|
+
|
28
|
+
attr_reader trailing_params: untyped
|
29
|
+
|
30
|
+
attr_reader block_param: untyped
|
31
|
+
|
32
|
+
def initialize: (leading_params: untyped, optional_params: untyped, rest_param: untyped, trailing_params: untyped, block_param: untyped) -> void
|
33
|
+
|
34
|
+
def params: () -> untyped
|
35
|
+
|
36
|
+
def self.from_node: (untyped node, annotations: untyped) -> (nil | untyped)
|
37
|
+
|
38
|
+
def params_type: (?hint: untyped?) -> untyped
|
39
|
+
|
40
|
+
def params_type0: (hint: untyped) -> (nil | untyped)
|
41
|
+
|
42
|
+
def zip: (untyped params_type, untyped block) -> untyped
|
43
|
+
|
44
|
+
def expandable_params?: (untyped params_type) -> (untyped | nil)
|
45
|
+
|
46
|
+
def expandable?: () -> untyped
|
47
|
+
|
48
|
+
def each: () { (Param) -> void } -> void
|
49
|
+
| () -> Enumerator[Param, void]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Steep
|
2
|
+
module TypeInference
|
3
|
+
class ConstantEnv
|
4
|
+
type constant_tuple = [untyped, RBS::TypeName, RBS::Constant::constant_entry]
|
5
|
+
|
6
|
+
attr_reader context: RBS::Resolver::context
|
7
|
+
|
8
|
+
attr_reader factory: AST::Types::Factory
|
9
|
+
|
10
|
+
attr_reader resolver: RBS::Resolver::ConstantResolver
|
11
|
+
|
12
|
+
def initialize: (factory: AST::Types::Factory, context: RBS::Resolver::context, resolver: RBS::Resolver::ConstantResolver) -> void
|
13
|
+
|
14
|
+
def resolve: (Symbol name) -> constant_tuple?
|
15
|
+
|
16
|
+
def toplevel: (Symbol name) -> constant_tuple?
|
17
|
+
|
18
|
+
def constants: () -> Hash[Symbol, constant_tuple]
|
19
|
+
|
20
|
+
def resolve_child: (RBS::TypeName module_name, Symbol constant_name) -> constant_tuple?
|
21
|
+
|
22
|
+
def children: (RBS::TypeName module_name) -> Hash[Symbol, constant_tuple]
|
23
|
+
|
24
|
+
def decompose_constant: (RBS::Constant? constant) -> constant_tuple?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module Steep
|
2
|
+
module TypeInference
|
3
|
+
class Context
|
4
|
+
class MethodContext
|
5
|
+
attr_reader name: untyped
|
6
|
+
|
7
|
+
attr_reader method: untyped
|
8
|
+
|
9
|
+
attr_reader method_type: untyped
|
10
|
+
|
11
|
+
attr_reader return_type: untyped
|
12
|
+
|
13
|
+
attr_reader constructor: untyped
|
14
|
+
|
15
|
+
attr_reader super_method: untyped
|
16
|
+
|
17
|
+
def initialize: (name: untyped, method: untyped, method_type: untyped, return_type: untyped, constructor: untyped, super_method: untyped) -> void
|
18
|
+
|
19
|
+
def block_type: () -> untyped
|
20
|
+
end
|
21
|
+
|
22
|
+
class BlockContext
|
23
|
+
# The type of block itself
|
24
|
+
#
|
25
|
+
# Returns `nil` if no type is specified.
|
26
|
+
#
|
27
|
+
attr_reader body_type: AST::Types::t?
|
28
|
+
|
29
|
+
def initialize: (body_type: AST::Types::t?) -> void
|
30
|
+
|
31
|
+
def subst: (Interface::Substitution) -> BlockContext
|
32
|
+
end
|
33
|
+
|
34
|
+
class BreakContext
|
35
|
+
# Type of arguments to `break` statement
|
36
|
+
#
|
37
|
+
attr_reader break_type: AST::Types::t
|
38
|
+
|
39
|
+
# Type of arguments to `next` statement
|
40
|
+
#
|
41
|
+
# `nil` means the passed value will be ignored.
|
42
|
+
#
|
43
|
+
attr_reader next_type: AST::Types::t?
|
44
|
+
|
45
|
+
def initialize: (break_type: AST::Types::t, next_type: AST::Types::t?) -> void
|
46
|
+
|
47
|
+
def subst: (Interface::Substitution) -> BreakContext
|
48
|
+
end
|
49
|
+
|
50
|
+
class ModuleContext
|
51
|
+
attr_reader instance_type: AST::Types::t
|
52
|
+
|
53
|
+
attr_reader module_type: AST::Types::t
|
54
|
+
|
55
|
+
attr_reader defined_instance_methods: untyped
|
56
|
+
|
57
|
+
attr_reader defined_module_methods: untyped
|
58
|
+
|
59
|
+
attr_reader nesting: RBS::Resolver::context
|
60
|
+
|
61
|
+
attr_reader implement_name: untyped
|
62
|
+
|
63
|
+
attr_reader class_name: RBS::TypeName
|
64
|
+
|
65
|
+
attr_reader instance_definition: RBS::Definition
|
66
|
+
|
67
|
+
attr_reader module_definition: RBS::Definition
|
68
|
+
|
69
|
+
def initialize: (instance_type: untyped, module_type: untyped, implement_name: untyped, class_name: untyped, nesting: untyped, ?instance_definition: untyped?, ?module_definition: untyped?) -> void
|
70
|
+
|
71
|
+
def class_variables: () -> (untyped | nil)
|
72
|
+
|
73
|
+
def update: (?instance_type: untyped, ?module_type: untyped, ?implement_name: untyped, ?class_name: untyped, ?instance_definition: untyped, ?module_definition: untyped, ?nesting: untyped) -> untyped
|
74
|
+
end
|
75
|
+
|
76
|
+
class TypeVariableContext
|
77
|
+
attr_reader table: Hash[Symbol, Interface::TypeParam]
|
78
|
+
|
79
|
+
attr_reader type_params: Array[Interface::TypeParam]
|
80
|
+
|
81
|
+
def initialize: (Array[Interface::TypeParam] type_params, ?parent_context: TypeVariableContext?) -> void
|
82
|
+
|
83
|
+
def []: (Symbol name) -> AST::Types::t?
|
84
|
+
|
85
|
+
def upper_bounds: () -> Hash[Symbol, AST::Types::t]
|
86
|
+
|
87
|
+
def self.empty: () -> TypeVariableContext
|
88
|
+
end
|
89
|
+
|
90
|
+
attr_reader call_context: untyped
|
91
|
+
|
92
|
+
attr_reader method_context: untyped
|
93
|
+
|
94
|
+
# BlockContext for current execution point
|
95
|
+
#
|
96
|
+
# `nil` when not in iterator block.
|
97
|
+
#
|
98
|
+
attr_reader block_context: BlockContext?
|
99
|
+
|
100
|
+
attr_reader break_context: BreakContext?
|
101
|
+
|
102
|
+
attr_reader module_context: untyped
|
103
|
+
|
104
|
+
attr_reader self_type: AST::Types::t
|
105
|
+
|
106
|
+
attr_reader type_env: TypeEnv
|
107
|
+
|
108
|
+
attr_reader variable_context: TypeVariableContext
|
109
|
+
|
110
|
+
def initialize: (
|
111
|
+
method_context: untyped,
|
112
|
+
block_context: BlockContext?,
|
113
|
+
break_context: BreakContext?,
|
114
|
+
module_context: untyped,
|
115
|
+
self_type: untyped,
|
116
|
+
type_env: TypeEnv,
|
117
|
+
call_context: untyped,
|
118
|
+
variable_context: TypeVariableContext
|
119
|
+
) -> void
|
120
|
+
|
121
|
+
def with: (
|
122
|
+
?method_context: untyped,
|
123
|
+
?block_context: BlockContext?,
|
124
|
+
?break_context: BreakContext?,
|
125
|
+
?module_context: untyped,
|
126
|
+
?self_type: untyped,
|
127
|
+
?type_env: TypeEnv,
|
128
|
+
?call_context: untyped,
|
129
|
+
?variable_context: untyped
|
130
|
+
) -> Context
|
131
|
+
|
132
|
+
def factory: () -> AST::Types::Factory
|
133
|
+
|
134
|
+
def env: () -> RBS::Environment
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Steep
|
2
|
+
module TypeInference
|
3
|
+
class LogicTypeInterpreter
|
4
|
+
attr_reader subtyping: Subtyping::Check
|
5
|
+
|
6
|
+
attr_reader typing: Typing
|
7
|
+
|
8
|
+
attr_reader factory (): AST::Types::Factory
|
9
|
+
|
10
|
+
def initialize: (subtyping: Subtyping::Check, typing: Typing) -> void
|
11
|
+
|
12
|
+
def eval: (env: TypeEnv, node: Parser::AST::Node) -> [TypeEnv, TypeEnv, Set[Symbol | Parser::AST::Node], AST::Types::t, AST::Types::t]
|
13
|
+
|
14
|
+
def evaluate_node: (env: TypeEnv, node: Parser::AST::Node, refined_objects: Set[Symbol | Parser::AST::Node]) -> [AST::Types::t, AST::Types::t, TypeEnv, TypeEnv]
|
15
|
+
|
16
|
+
def evaluate_method_call: (env: TypeEnv, type: AST::Types::Logic::Base, receiver: Parser::AST::Node?, arguments: Array[Parser::AST::Node], refined_objects: Set[Symbol | Parser::AST::Node]) -> [TypeEnv, TypeEnv]?
|
17
|
+
|
18
|
+
# Apply type refinement to `node` as `truthy_type` and `falsy_type`.
|
19
|
+
#
|
20
|
+
# This is done by top-down manner.
|
21
|
+
#
|
22
|
+
# Assignes given two types to the node when:
|
23
|
+
#
|
24
|
+
# * `node` is a `lvar`
|
25
|
+
# * `node` is a `lvasgn`
|
26
|
+
# * `node` is a _pure_ method call
|
27
|
+
#
|
28
|
+
def refine_node_type: (env: TypeEnv, node: Parser::AST::Node, truthy_type: AST::Types::t, falsy_type: AST::Types::t, refined_objects: Set[Symbol | Parser::AST::Node]) -> [TypeEnv, TypeEnv]
|
29
|
+
|
30
|
+
# Returns a pair of a node and set of local variable names.
|
31
|
+
#
|
32
|
+
# * The returned node is called _value node_ that is a node the value of given `node` can be taken from
|
33
|
+
# * The local variable names are local variables that have the same value of the _value node_.
|
34
|
+
#
|
35
|
+
# ```ruby
|
36
|
+
# a = 123 # `123` is the _value node_
|
37
|
+
# # :a is included in the set because `a` has the same value of _value node_
|
38
|
+
#
|
39
|
+
# c = b = a # `a` is the _value node_, a set of { :b, :c } will be returned
|
40
|
+
# ```
|
41
|
+
#
|
42
|
+
def decompose_value: (Parser::AST::Node node) -> [Parser::AST::Node, Set[Symbol]]
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def evaluate_assignment: (Parser::AST::Node node, TypeEnv env, AST::Types::t rhs_type, refined_objects: Set[Symbol | Parser::AST::Node]) -> TypeEnv
|
47
|
+
|
48
|
+
def guess_type_from_method: (Parser::AST::Node node) -> (AST::Types::Logic::ReceiverIsArg | AST::Types::Logic::ReceiverIsNil | AST::Types::Logic::Not | AST::Types::Logic::ArgIsReceiver | nil)
|
49
|
+
|
50
|
+
# Decompose to given type to truthy and falsy types.
|
51
|
+
#
|
52
|
+
# This directly corresponds to case-when syntax with literals:
|
53
|
+
#
|
54
|
+
# ```ruby
|
55
|
+
# case x
|
56
|
+
# when nil # value_node == {nil}, arg_type = type_of({x})
|
57
|
+
# ...
|
58
|
+
# when 123 # value_node == {nil}, arg_type = type_of({x})
|
59
|
+
# ...
|
60
|
+
# end
|
61
|
+
# ```
|
62
|
+
#
|
63
|
+
def literal_var_type_case_select: (Parser::AST::Node value_node, AST::Types::t arg_type) -> [Array[AST::Types::t], Array[AST::Types::t]]?
|
64
|
+
|
65
|
+
def type_case_select: (AST::Types::t `type`, RBS::TypeName klass) -> [AST::Types::t, AST::Types::t]
|
66
|
+
|
67
|
+
def type_case_select0: (AST::Types::t `type`, RBS::TypeName klass) -> [Array[AST::Types::t], Array[AST::Types::t]]
|
68
|
+
|
69
|
+
def try_convert: (AST::Types::t, Symbol) -> AST::Types::t?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Steep
|
2
|
+
module TypeInference
|
3
|
+
class MethodCall
|
4
|
+
class MethodDecl
|
5
|
+
attr_reader method_name: method_name
|
6
|
+
|
7
|
+
attr_reader method_def: RBS::Definition::Method::TypeDef
|
8
|
+
|
9
|
+
def initialize: (method_name: method_name, method_def: RBS::Definition::Method::TypeDef) -> void
|
10
|
+
|
11
|
+
def hash: () -> Integer
|
12
|
+
|
13
|
+
def ==: (untyped other) -> bool
|
14
|
+
|
15
|
+
alias eql? ==
|
16
|
+
|
17
|
+
def method_type: () -> RBS::MethodType
|
18
|
+
end
|
19
|
+
|
20
|
+
class MethodContext
|
21
|
+
attr_reader method_name: method_name
|
22
|
+
|
23
|
+
def initialize: (method_name: method_name) -> void
|
24
|
+
|
25
|
+
def to_s: () -> String
|
26
|
+
end
|
27
|
+
|
28
|
+
class ModuleContext
|
29
|
+
attr_reader type_name: RBS::TypeName
|
30
|
+
|
31
|
+
def initialize: (type_name: RBS::TypeName) -> void
|
32
|
+
|
33
|
+
def to_s: () -> String
|
34
|
+
end
|
35
|
+
|
36
|
+
class TopLevelContext
|
37
|
+
def to_s: () -> String
|
38
|
+
end
|
39
|
+
|
40
|
+
class UnknownContext
|
41
|
+
def to_s: () -> String
|
42
|
+
end
|
43
|
+
|
44
|
+
type context = MethodContext | ModuleContext | TopLevelContext | UnknownContext
|
45
|
+
|
46
|
+
class Base
|
47
|
+
attr_reader node: Parser::AST::Node
|
48
|
+
|
49
|
+
attr_reader context: context
|
50
|
+
|
51
|
+
attr_reader method_name: Symbol
|
52
|
+
|
53
|
+
attr_reader return_type: AST::Types::t
|
54
|
+
|
55
|
+
attr_reader receiver_type: AST::Types::t
|
56
|
+
|
57
|
+
def initialize: (node: Parser::AST::Node, context: context, method_name: Symbol, receiver_type: AST::Types::t, return_type: AST::Types::t) -> void
|
58
|
+
|
59
|
+
def with_return_type: (AST::Types::t new_type) -> self
|
60
|
+
|
61
|
+
def ==: (untyped other) -> bool
|
62
|
+
|
63
|
+
alias eql? ==
|
64
|
+
|
65
|
+
def hash: () -> Integer
|
66
|
+
end
|
67
|
+
|
68
|
+
type t = Typed | Special | Untyped | NoMethodError | Error
|
69
|
+
|
70
|
+
class Typed < Base
|
71
|
+
attr_reader actual_method_type: Interface::MethodType
|
72
|
+
|
73
|
+
attr_reader method_decls: Set[MethodDecl]
|
74
|
+
|
75
|
+
def initialize: (node: Parser::AST::Node, context: context, method_name: Symbol, receiver_type: AST::Types::t, actual_method_type: Interface::MethodType, method_decls: Array[MethodDecl], return_type: AST::Types::t) -> void
|
76
|
+
|
77
|
+
def update: (?node: Parser::AST::Node, ?return_type: AST::Types::t) -> self
|
78
|
+
|
79
|
+
def pure?: () -> bool
|
80
|
+
|
81
|
+
def ==: (untyped other) -> bool
|
82
|
+
|
83
|
+
alias eql? ==
|
84
|
+
|
85
|
+
def hash: () -> Integer
|
86
|
+
end
|
87
|
+
|
88
|
+
class Special < Typed
|
89
|
+
end
|
90
|
+
|
91
|
+
class Untyped < Base
|
92
|
+
def initialize: (node: Parser::AST::Node, context: context, method_name: Symbol) -> void
|
93
|
+
end
|
94
|
+
|
95
|
+
class NoMethodError < Base
|
96
|
+
attr_reader error: Diagnostic::Ruby::NoMethod
|
97
|
+
|
98
|
+
def initialize: (
|
99
|
+
node: Parser::AST::Node,
|
100
|
+
context: context,
|
101
|
+
method_name: Symbol,
|
102
|
+
receiver_type: AST::Types::t,
|
103
|
+
error: Diagnostic::Ruby::NoMethod
|
104
|
+
) -> void
|
105
|
+
end
|
106
|
+
|
107
|
+
class Error < Base
|
108
|
+
attr_reader errors: Array[Diagnostic::Ruby::Base]
|
109
|
+
|
110
|
+
attr_reader method_decls: Set[MethodDecl]
|
111
|
+
|
112
|
+
def initialize: (
|
113
|
+
node: Parser::AST::Node,
|
114
|
+
context: context,
|
115
|
+
method_name: Symbol,
|
116
|
+
receiver_type: AST::Types::t,
|
117
|
+
errors: Array[Diagnostic::Ruby::Base],
|
118
|
+
?method_decls: Set[MethodDecl],
|
119
|
+
?return_type: AST::Types::t
|
120
|
+
) -> void
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|