steep 0.25.0 → 0.31.0

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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/bin/smoke_runner.rb +3 -4
  4. data/bin/steep-prof +1 -2
  5. data/lib/steep.rb +6 -4
  6. data/lib/steep/annotation_parser.rb +2 -4
  7. data/lib/steep/ast/builtin.rb +11 -21
  8. data/lib/steep/ast/types.rb +5 -3
  9. data/lib/steep/ast/types/any.rb +1 -3
  10. data/lib/steep/ast/types/boolean.rb +1 -3
  11. data/lib/steep/ast/types/bot.rb +1 -3
  12. data/lib/steep/ast/types/class.rb +2 -2
  13. data/lib/steep/ast/types/factory.rb +265 -90
  14. data/lib/steep/ast/types/helper.rb +6 -0
  15. data/lib/steep/ast/types/instance.rb +2 -2
  16. data/lib/steep/ast/types/intersection.rb +20 -13
  17. data/lib/steep/ast/types/literal.rb +1 -3
  18. data/lib/steep/ast/types/logic.rb +63 -0
  19. data/lib/steep/ast/types/name.rb +15 -67
  20. data/lib/steep/ast/types/nil.rb +1 -3
  21. data/lib/steep/ast/types/proc.rb +5 -2
  22. data/lib/steep/ast/types/record.rb +9 -4
  23. data/lib/steep/ast/types/self.rb +1 -1
  24. data/lib/steep/ast/types/top.rb +1 -3
  25. data/lib/steep/ast/types/tuple.rb +5 -3
  26. data/lib/steep/ast/types/union.rb +13 -9
  27. data/lib/steep/ast/types/var.rb +2 -2
  28. data/lib/steep/ast/types/void.rb +1 -3
  29. data/lib/steep/errors.rb +14 -0
  30. data/lib/steep/interface/interface.rb +5 -62
  31. data/lib/steep/interface/method_type.rb +394 -93
  32. data/lib/steep/interface/substitution.rb +48 -6
  33. data/lib/steep/module_helper.rb +25 -0
  34. data/lib/steep/project.rb +25 -0
  35. data/lib/steep/project/completion_provider.rb +57 -58
  36. data/lib/steep/project/file_loader.rb +7 -2
  37. data/lib/steep/project/hover_content.rb +92 -83
  38. data/lib/steep/project/signature_file.rb +33 -0
  39. data/lib/steep/project/{file.rb → source_file.rb} +24 -54
  40. data/lib/steep/project/target.rb +31 -12
  41. data/lib/steep/server/base_worker.rb +5 -3
  42. data/lib/steep/server/code_worker.rb +31 -45
  43. data/lib/steep/server/interaction_worker.rb +42 -38
  44. data/lib/steep/server/master.rb +23 -31
  45. data/lib/steep/server/utils.rb +46 -13
  46. data/lib/steep/server/worker_process.rb +4 -2
  47. data/lib/steep/signature/validator.rb +3 -3
  48. data/lib/steep/source.rb +59 -2
  49. data/lib/steep/subtyping/check.rb +36 -50
  50. data/lib/steep/subtyping/constraints.rb +8 -0
  51. data/lib/steep/type_construction.rb +388 -366
  52. data/lib/steep/type_inference/block_params.rb +5 -0
  53. data/lib/steep/type_inference/constant_env.rb +2 -5
  54. data/lib/steep/type_inference/logic_type_interpreter.rb +219 -0
  55. data/lib/steep/type_inference/type_env.rb +2 -2
  56. data/lib/steep/version.rb +1 -1
  57. data/smoke/alias/a.rb +1 -1
  58. data/smoke/case/a.rb +1 -1
  59. data/smoke/hash/d.rb +1 -1
  60. data/smoke/if/a.rb +1 -1
  61. data/smoke/module/a.rb +1 -1
  62. data/smoke/rescue/a.rb +4 -13
  63. data/smoke/toplevel/Steepfile +5 -0
  64. data/smoke/toplevel/a.rb +4 -0
  65. data/smoke/toplevel/a.rbs +3 -0
  66. data/smoke/type_case/a.rb +0 -7
  67. data/steep.gemspec +3 -3
  68. metadata +17 -13
  69. data/lib/steep/ast/method_type.rb +0 -126
  70. data/lib/steep/ast/namespace.rb +0 -80
  71. data/lib/steep/names.rb +0 -86
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c290301da65ed473b092cd6c2ea39eebe02f566124a1fa32e0f420d290513cbf
4
- data.tar.gz: ca4fca20e9f3f0b19c57b98d6cdfce0023aeeff8cd0fcd2ee0fc91346e5e0816
3
+ metadata.gz: e315b0a9541b0289ae3c9dd3acb19c2112e990a321176f94ed44f25d4190acb4
4
+ data.tar.gz: 9ce6e2024e81e5a2452fc5d7ca381decd1d91ed917d385dc280133652af51e06
5
5
  SHA512:
6
- metadata.gz: 76c3b0c76e303bcc558bf20efeebe3ddaa3caef432f5d325261261f6d8431f5bbd36bc44af9a4a4dd6a90f2db30ac35ca044181b25063890c0e68c5499d7792c
7
- data.tar.gz: a5fa8fba718f599806d9d0ad62a66c138261469d41694bb39ebafe1b8736ad255e890c55f0e3b4f180f4e0212f0b65b31b5957b5c337cba42d1129b9e935e577
6
+ metadata.gz: bd8db01573d1a2e31b362fb893bfad1325969b8343415d1bfd82428a76f0a6c8f8fe2875f7e474ab94244476e9901b1dda186f57cb90a49602638453826534a8
7
+ data.tar.gz: f1f30e2afc48265917468a4c5dd040fff3e226f92cb17441c3f3fcbba7f95aaa1002172ece399410d567358d9caf7bd80c1f1c27b9083c81a39e1abe61b74a68
@@ -2,6 +2,53 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.31.0 (2020-10-04)
6
+
7
+ * Fix type checking performance ([#230](https://github.com/soutaro/steep/pull/230))
8
+ * Improve LSP completion/hover performance ([#232](https://github.com/soutaro/steep/pull/232))
9
+ * Fix instance variable completion ([#234](https://github.com/soutaro/steep/pull/234))
10
+ * Relax version requirements on Listen to allow installing on Ruby 3 ([#235](https://github.com/soutaro/steep/pull/235))
11
+
12
+ ## 0.30.0 (2020-10-03)
13
+
14
+ * Let top-level defs be methods of Object ([#227](https://github.com/soutaro/steep/pull/227))
15
+ * Fix error caused by attribute definitions ([#228](https://github.com/soutaro/steep/pull/228))
16
+ * LSP worker improvements ([#222](https://github.com/soutaro/steep/pull/222), [#223](https://github.com/soutaro/steep/pull/223), [#226](https://github.com/soutaro/steep/pull/226), [#229](https://github.com/soutaro/steep/pull/229))
17
+
18
+ ## 0.29.0 (2020-09-28)
19
+
20
+ * Implement reasoning on `is_a?`, `nil?`, and `===` methods. ([#218](https://github.com/soutaro/steep/pull/218))
21
+ * Better completion based on interface ([#215](https://github.com/soutaro/steep/pull/215))
22
+ * Fix begin-rescue typing ([#221](https://github.com/soutaro/steep/pull/221))
23
+
24
+ ## 0.28.0 (2020-09-17)
25
+
26
+ * Fix typing case-when with empty body ([#200](https://github.com/soutaro/steep/pull/200))
27
+ * Fix lvasgn typing with `void` type hint ([#200](https://github.com/soutaro/steep/pull/200))
28
+ * Fix subtype checking between type variables and union types ([#200](https://github.com/soutaro/steep/pull/200))
29
+ * Support endless range ([#200](https://github.com/soutaro/steep/pull/200))
30
+ * Fix optarg, kwoptarg typing ([#202](https://github.com/soutaro/steep/pull/202))
31
+ * Better union/intersection types ([#204](https://github.com/soutaro/steep/pull/204))
32
+ * Fix generic method instantiation ([#205](https://github.com/soutaro/steep/pull/205))
33
+ * Fix module typing ([#206](https://github.com/soutaro/steep/pull/206))
34
+ * Fix shutdown problem ([#209](https://github.com/soutaro/steep/pull/209))
35
+ * Update RBS to 0.12.0 ([#210](https://github.com/soutaro/steep/pull/210))
36
+ * Improve processing singleton class decls without RBS ([#211](https://github.com/soutaro/steep/pull/211))
37
+ * Improve processing block parameter with masgn ([#212](https://github.com/soutaro/steep/pull/212))
38
+
39
+ ## 0.27.0 (2020-08-31)
40
+
41
+ * Make tuple types _covariant_ ([#195](https://github.com/soutaro/steep/pull/195))
42
+ * Support `or_asgn`/`and_asgn` with `send` node lhs ([#194](https://github.com/soutaro/steep/pull/194))
43
+ * Performance improvement ([#193](https://github.com/soutaro/steep/pull/193))
44
+ * Add specialized versions of `#first` and `#last` on tuples ([#191](https://github.com/soutaro/steep/pull/191))
45
+ * Typing bug fix on `[]` (empty array) ([#190](https://github.com/soutaro/steep/pull/190))
46
+ * Earlier shutdown with interruption while `steep watch` ([#173](https://github.com/soutaro/steep/pull/173))
47
+
48
+ ## 0.26.0
49
+
50
+ * Skipped
51
+
5
52
  ## 0.25.0 (2020-08-18)
6
53
 
7
54
  * Improve `op_send` typing ([#186](https://github.com/soutaro/steep/pull/186))
@@ -19,8 +19,6 @@ Expectation = Struct.new(:line, :message, :path, :starts) do
19
19
  attr_accessor :prefix_test
20
20
  end
21
21
 
22
- allowed_paths = []
23
-
24
22
  failed = false
25
23
 
26
24
  ARGV.each do |arg|
@@ -29,12 +27,13 @@ ARGV.each do |arg|
29
27
 
30
28
  rb_files = []
31
29
  expectations = []
32
-
30
+ allowed_paths = []
31
+
33
32
  dir.children.each do |file|
34
33
  if file.extname == ".rb"
35
34
  buffer = ::Parser::Source::Buffer.new(file.to_s)
36
35
  buffer.source = file.read
37
- parser = ::Parser::Ruby25.new
36
+ parser = ::Parser::Ruby27.new
38
37
 
39
38
  _, comments, _ = parser.tokenize(buffer)
40
39
  comments.each do |comment|
@@ -9,8 +9,7 @@ def exit(*)
9
9
 
10
10
  end
11
11
 
12
-
13
12
  STDERR.puts "Running profiler: mode=#{mode}, out=#{out}"
14
- StackProf.run(mode: mode, out: out) do
13
+ StackProf.run(mode: mode, out: out, raw: true) do
15
14
  load File.join(__dir__, "../exe/steep")
16
15
  end
@@ -1,7 +1,7 @@
1
1
  require "steep/version"
2
2
 
3
3
  require "pathname"
4
- require "parser/ruby25"
4
+ require "parser/ruby27"
5
5
  require "ast_utils"
6
6
  require "active_support/core_ext/object/try"
7
7
  require "logger"
@@ -16,8 +16,6 @@ require 'uri'
16
16
 
17
17
  require "rbs"
18
18
 
19
- require "steep/ast/namespace"
20
- require "steep/names"
21
19
  require "steep/ast/location"
22
20
  require "steep/ast/types/helper"
23
21
  require "steep/ast/types/any"
@@ -37,6 +35,7 @@ require "steep/ast/types/boolean"
37
35
  require "steep/ast/types/tuple"
38
36
  require "steep/ast/types/proc"
39
37
  require "steep/ast/types/record"
38
+ require "steep/ast/types/logic"
40
39
  require "steep/ast/type_params"
41
40
  require "steep/ast/annotation"
42
41
  require "steep/ast/annotation/collection"
@@ -62,6 +61,7 @@ require "steep/source"
62
61
  require "steep/annotation_parser"
63
62
  require "steep/typing"
64
63
  require "steep/errors"
64
+ require "steep/module_helper"
65
65
  require "steep/type_construction"
66
66
  require "steep/type_inference/context"
67
67
  require "steep/type_inference/context_array"
@@ -71,6 +71,7 @@ require "steep/type_inference/constant_env"
71
71
  require "steep/type_inference/type_env"
72
72
  require "steep/type_inference/local_variable_type_env"
73
73
  require "steep/type_inference/logic"
74
+ require "steep/type_inference/logic_type_interpreter"
74
75
  require "steep/ast/types"
75
76
 
76
77
  require "steep/server/utils"
@@ -82,7 +83,8 @@ require "steep/server/interaction_worker"
82
83
  require "steep/server/master"
83
84
 
84
85
  require "steep/project"
85
- require "steep/project/file"
86
+ require "steep/project/signature_file"
87
+ require "steep/project/source_file"
86
88
  require "steep/project/options"
87
89
  require "steep/project/target"
88
90
  require "steep/project/dsl"
@@ -80,9 +80,7 @@ module Steep
80
80
  name = match[:name]
81
81
  type = parse_type(match[:type])
82
82
 
83
- AST::Annotation::ConstType.new(name: Names::Module.parse(name),
84
- type: type,
85
- location: location)
83
+ AST::Annotation::ConstType.new(name: TypeName(name), type: type, location: location)
86
84
  end
87
85
 
88
86
  when keyword_subject_type("ivar", IVAR_NAME)
@@ -152,7 +150,7 @@ module Steep
152
150
 
153
151
  when /@implements\s+(?<name>#{CONST_NAME})#{TYPE_PARAMS}$/
154
152
  Regexp.last_match.yield_self do |match|
155
- type_name = Names::Module.parse(match[:name])
153
+ type_name = TypeName(match[:name])
156
154
  params = match[:params]&.yield_self {|params| params.split(/,/).map {|param| param.strip.to_sym } } || []
157
155
 
158
156
  name = AST::Annotation::Implements::Module.new(name: type_name, args: params)
@@ -6,7 +6,7 @@ module Steep
6
6
  attr_reader :arity
7
7
 
8
8
  def initialize(module_name, arity: 0)
9
- @module_name = Names::Module.parse(module_name)
9
+ @module_name = TypeName(module_name)
10
10
  @arity = arity
11
11
  end
12
12
 
@@ -15,12 +15,8 @@ module Steep
15
15
  Types::Name::Instance.new(name: module_name, args: args)
16
16
  end
17
17
 
18
- def class_type(constructor: nil)
19
- Types::Name::Class.new(name: module_name, constructor: constructor)
20
- end
21
-
22
18
  def module_type
23
- Types::Name::Module.new(name: module_name)
19
+ Types::Name::Singleton.new(name: module_name)
24
20
  end
25
21
 
26
22
  def instance_type?(type, args: nil)
@@ -36,22 +32,8 @@ module Steep
36
32
  end
37
33
  end
38
34
 
39
- NONE = ::Object.new
40
-
41
- def class_type?(type, constructor: NONE)
42
- if type.is_a?(Types::Name::Class)
43
- unless constructor.equal?(NONE)
44
- type.name == module_name && type.name.constructor == constructor
45
- else
46
- type.name == module_name
47
- end
48
- else
49
- false
50
- end
51
- end
52
-
53
35
  def module_type?(type)
54
- if type.is_a?(Types::Name::Module)
36
+ if type.is_a?(Types::Name::Singleton)
55
37
  type.name == module_name
56
38
  else
57
39
  false
@@ -99,6 +81,14 @@ module Steep
99
81
  def self.optional(type)
100
82
  AST::Types::Union.build(types: [type, nil_type])
101
83
  end
84
+
85
+ def self.true_type
86
+ AST::Types::Literal.new(value: true)
87
+ end
88
+
89
+ def self.false_type
90
+ AST::Types::Literal.new(value: false)
91
+ end
102
92
  end
103
93
  end
104
94
  end
@@ -35,9 +35,11 @@ module Steep
35
35
  "masked(#{type}|#{mask})"
36
36
  end
37
37
 
38
- def free_variables(set = Set.new)
39
- type.free_variables(set)
40
- mask.free_variables(set)
38
+ def free_variables
39
+ @fvs ||= Set.new.tap do |set|
40
+ set.merge(type.free_variables)
41
+ set.merge(mask.free_variables)
42
+ end
41
43
  end
42
44
 
43
45
  def each_type(&block)
@@ -26,9 +26,7 @@ module Steep
26
26
  "untyped"
27
27
  end
28
28
 
29
- def free_variables
30
- Set.new
31
- end
29
+ include Helper::NoFreeVariables
32
30
 
33
31
  def level
34
32
  [1]
@@ -26,9 +26,7 @@ module Steep
26
26
  "bool"
27
27
  end
28
28
 
29
- def free_variables
30
- Set.new
31
- end
29
+ include Helper::NoFreeVariables
32
30
 
33
31
  def level
34
32
  [0]
@@ -26,9 +26,7 @@ module Steep
26
26
  "⟘"
27
27
  end
28
28
 
29
- def free_variables
30
- Set.new
31
- end
29
+ include Helper::NoFreeVariables
32
30
 
33
31
  def level
34
32
  [2]
@@ -22,8 +22,8 @@ module Steep
22
22
  s.module_type or raise "Unexpected substitution: #{inspect}"
23
23
  end
24
24
 
25
- def free_variables
26
- Set.new
25
+ def free_variables()
26
+ @fvs = Set.new([self])
27
27
  end
28
28
 
29
29
  def level
@@ -4,8 +4,17 @@ module Steep
4
4
  class Factory
5
5
  attr_reader :definition_builder
6
6
 
7
+ attr_reader :type_name_cache
8
+ attr_reader :type_cache
9
+
10
+ attr_reader :type_interface_cache
11
+
7
12
  def initialize(builder:)
8
13
  @definition_builder = builder
14
+
15
+ @type_name_cache = {}
16
+ @type_cache = {}
17
+ @type_interface_cache = {}
9
18
  end
10
19
 
11
20
  def type_name_resolver
@@ -13,7 +22,9 @@ module Steep
13
22
  end
14
23
 
15
24
  def type(type)
16
- case type
25
+ ty = type_cache[type] and return ty
26
+
27
+ type_cache[type] = case type
17
28
  when RBS::Types::Bases::Any
18
29
  Any.new(location: nil)
19
30
  when RBS::Types::Bases::Class
@@ -35,18 +46,18 @@ module Steep
35
46
  when RBS::Types::Variable
36
47
  Var.new(name: type.name, location: nil)
37
48
  when RBS::Types::ClassSingleton
38
- type_name = type_name(type.name)
39
- Name::Class.new(name: type_name, location: nil, constructor: nil)
49
+ type_name = type.name
50
+ Name::Singleton.new(name: type_name, location: nil)
40
51
  when RBS::Types::ClassInstance
41
- type_name = type_name(type.name)
52
+ type_name = type.name
42
53
  args = type.args.map {|arg| type(arg) }
43
54
  Name::Instance.new(name: type_name, args: args, location: nil)
44
55
  when RBS::Types::Interface
45
- type_name = type_name(type.name)
56
+ type_name = type.name
46
57
  args = type.args.map {|arg| type(arg) }
47
58
  Name::Interface.new(name: type_name, args: args, location: nil)
48
59
  when RBS::Types::Alias
49
- type_name = type_name(type.name)
60
+ type_name = type.name
50
61
  Name::Alias.new(name: type_name, args: [], location: nil)
51
62
  when RBS::Types::Union
52
63
  Union.build(types: type.types.map {|ty| type(ty) }, location: nil)
@@ -94,23 +105,23 @@ module Steep
94
105
  RBS::Types::Bases::Nil.new(location: nil)
95
106
  when Var
96
107
  RBS::Types::Variable.new(name: type.name, location: nil)
97
- when Name::Class, Name::Module
98
- RBS::Types::ClassSingleton.new(name: type_name_1(type.name), location: nil)
108
+ when Name::Singleton
109
+ RBS::Types::ClassSingleton.new(name: type.name, location: nil)
99
110
  when Name::Instance
100
111
  RBS::Types::ClassInstance.new(
101
- name: type_name_1(type.name),
112
+ name: type.name,
102
113
  args: type.args.map {|arg| type_1(arg) },
103
114
  location: nil
104
115
  )
105
116
  when Name::Interface
106
117
  RBS::Types::Interface.new(
107
- name: type_name_1(type.name),
118
+ name: type.name,
108
119
  args: type.args.map {|arg| type_1(arg) },
109
120
  location: nil
110
121
  )
111
122
  when Name::Alias
112
123
  type.args.empty? or raise "alias type with args is not supported"
113
- RBS::Types::Alias.new(name: type_name_1(type.name), location: nil)
124
+ RBS::Types::Alias.new(name: type.name, location: nil)
114
125
  when Union
115
126
  RBS::Types::Union.new(
116
127
  types: type.types.map {|ty| type_1(ty) },
@@ -143,29 +154,6 @@ module Steep
143
154
  end
144
155
  end
145
156
 
146
- def type_name(name)
147
- case
148
- when name.class?
149
- Names::Module.new(name: name.name, namespace: namespace(name.namespace), location: nil)
150
- when name.interface?
151
- Names::Interface.new(name: name.name, namespace: namespace(name.namespace), location: nil)
152
- when name.alias?
153
- Names::Alias.new(name: name.name, namespace: namespace(name.namespace), location: nil)
154
- end
155
- end
156
-
157
- def type_name_1(name)
158
- RBS::TypeName.new(name: name.name, namespace: namespace_1(name.namespace))
159
- end
160
-
161
- def namespace(namespace)
162
- Namespace.parse(namespace.to_s)
163
- end
164
-
165
- def namespace_1(namespace)
166
- RBS::Namespace.parse(namespace.to_s)
167
- end
168
-
169
157
  def function_1(params, return_type)
170
158
  RBS::Types::Function.new(
171
159
  required_positionals: params.required.map {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
@@ -190,7 +178,7 @@ module Steep
190
178
  )
191
179
  end
192
180
 
193
- def method_type(method_type, self_type:)
181
+ def method_type(method_type, self_type:, subst2: nil, method_def: nil)
194
182
  fvs = self_type.free_variables()
195
183
 
196
184
  type_params = []
@@ -208,19 +196,21 @@ module Steep
208
196
  end
209
197
  end
210
198
  subst = Interface::Substitution.build(alpha_vars, alpha_types)
199
+ subst.merge!(subst2, overwrite: true) if subst2
211
200
 
212
201
  type = Interface::MethodType.new(
213
202
  type_params: type_params,
214
203
  return_type: type(method_type.type.return_type).subst(subst),
215
204
  params: params(method_type.type).subst(subst),
216
- location: nil,
217
205
  block: method_type.block&.yield_self do |block|
218
206
  Interface::Block.new(
219
207
  optional: !block.required,
220
208
  type: Proc.new(params: params(block.type).subst(subst),
221
209
  return_type: type(block.type.return_type).subst(subst), location: nil)
222
210
  )
223
- end
211
+ end,
212
+ method_def: method_def,
213
+ location: method_def&.member&.location
224
214
  )
225
215
 
226
216
  if block_given?
@@ -280,7 +270,7 @@ module Steep
280
270
  end
281
271
 
282
272
  def unfold(type_name)
283
- type_name_1(type_name).yield_self do |type_name|
273
+ type_name.yield_self do |type_name|
284
274
  type(definition_builder.expand_alias(type_name))
285
275
  end
286
276
  end
@@ -300,19 +290,129 @@ module Steep
300
290
  end
301
291
  end
302
292
 
293
+ def deep_expand_alias(type, recursive: Set.new, &block)
294
+ raise "Recursive type definition: #{type}" if recursive.member?(type)
295
+
296
+ ty = case type
297
+ when AST::Types::Name::Alias
298
+ deep_expand_alias(expand_alias(type), recursive: recursive.union([type]))
299
+ when AST::Types::Union
300
+ AST::Types::Union.build(
301
+ types: type.types.map {|ty| deep_expand_alias(ty, recursive: recursive, &block) },
302
+ location: type.location
303
+ )
304
+ else
305
+ type
306
+ end
307
+
308
+ if block_given?
309
+ yield ty
310
+ else
311
+ ty
312
+ end
313
+ end
314
+
315
+ def flatten_union(type, acc = [])
316
+ case type
317
+ when AST::Types::Union
318
+ type.types.each {|ty| flatten_union(ty, acc) }
319
+ else
320
+ acc << type
321
+ end
322
+
323
+ acc
324
+ end
325
+
326
+ def unwrap_optional(type)
327
+ case type
328
+ when AST::Types::Union
329
+ falsy_types, truthy_types = type.types.partition do |type|
330
+ (type.is_a?(AST::Types::Literal) && type.value == false) ||
331
+ type.is_a?(AST::Types::Nil)
332
+ end
333
+
334
+ [
335
+ AST::Types::Union.build(types: truthy_types),
336
+ AST::Types::Union.build(types: falsy_types)
337
+ ]
338
+ when AST::Types::Name::Alias
339
+ unwrap_optional(expand_alias(type))
340
+ else
341
+ [type, nil]
342
+ end
343
+ end
344
+
345
+ def setup_primitives(method_name, method_type)
346
+ if method_def = method_type.method_def
347
+ defined_in = method_def.defined_in
348
+ member = method_def.member
349
+
350
+ if member.is_a?(RBS::AST::Members::MethodDefinition)
351
+ case
352
+ when defined_in == RBS::BuiltinNames::Object.name && member.instance?
353
+ case method_name
354
+ when :is_a?, :kind_of?, :instance_of?
355
+ return method_type.with(
356
+ return_type: AST::Types::Logic::ReceiverIsArg.new(location: method_type.return_type.location)
357
+ )
358
+ when :nil?
359
+ return method_type.with(
360
+ return_type: AST::Types::Logic::ReceiverIsNil.new(location: method_type.return_type.location)
361
+ )
362
+ end
363
+
364
+ when defined_in == AST::Builtin::NilClass.module_name && member.instance?
365
+ case method_name
366
+ when :nil?
367
+ return method_type.with(
368
+ return_type: AST::Types::Logic::ReceiverIsNil.new(location: method_type.return_type.location)
369
+ )
370
+ end
371
+
372
+ when defined_in == RBS::BuiltinNames::BasicObject.name && member.instance?
373
+ case method_name
374
+ when :!
375
+ return method_type.with(
376
+ return_type: AST::Types::Logic::Not.new(location: method_type.return_type.location)
377
+ )
378
+ end
379
+
380
+ when defined_in == RBS::BuiltinNames::Module.name && member.instance?
381
+ case method_name
382
+ when :===
383
+ return method_type.with(
384
+ return_type: AST::Types::Logic::ArgIsReceiver.new(location: method_type.return_type.location)
385
+ )
386
+ end
387
+ end
388
+ end
389
+ end
390
+
391
+ method_type
392
+ end
393
+
303
394
  def interface(type, private:, self_type: type)
304
- type = expand_alias(type)
395
+ Steep.logger.debug { "Factory#interface: #{type}, private=#{private}, self_type=#{self_type}" }
396
+
397
+ cache_key = [type, self_type, private]
398
+ if type_interface_cache.key?(cache_key)
399
+ return type_interface_cache[cache_key]
400
+ end
305
401
 
306
402
  case type
403
+ when Name::Alias
404
+ interface(expand_alias(type), private: private, self_type: self_type)
405
+
307
406
  when Self
308
407
  if self_type != type
309
408
  interface self_type, private: private, self_type: Self.new
310
409
  else
311
410
  raise "Unexpected `self` type interface"
312
411
  end
412
+
313
413
  when Name::Instance
314
414
  Interface::Interface.new(type: self_type, private: private).tap do |interface|
315
- definition = definition_builder.build_instance(type_name_1(type.name))
415
+ definition = definition_builder.build_instance(type.name)
316
416
 
317
417
  instance_type = Name::Instance.new(name: type.name,
318
418
  args: type.args.map { Any.new(location: nil) },
@@ -328,20 +428,27 @@ module Steep
328
428
  )
329
429
 
330
430
  definition.methods.each do |name, method|
331
- next if method.private? && !private
332
-
333
- interface.methods[name] = Interface::Interface::Combination.overload(
334
- method.method_types.map do |type|
335
- method_type(type, self_type: self_type) {|ty| ty.subst(subst) }
336
- end,
337
- incompatible: name == :initialize || name == :new
338
- )
431
+ Steep.logger.tagged "method = #{name}" do
432
+ next if method.private? && !private
433
+
434
+ interface.methods[name] = Interface::Interface::Entry.new(
435
+ method_types: method.defs.map do |type_def|
436
+ setup_primitives(
437
+ name,
438
+ method_type(type_def.type,
439
+ method_def: type_def,
440
+ self_type: self_type,
441
+ subst2: subst)
442
+ )
443
+ end
444
+ )
445
+ end
339
446
  end
340
447
  end
341
448
 
342
449
  when Name::Interface
343
450
  Interface::Interface.new(type: self_type, private: private).tap do |interface|
344
- type_name = type_name_1(type.name)
451
+ type_name = type.name
345
452
  definition = definition_builder.build_interface(type_name)
346
453
 
347
454
  subst = Interface::Substitution.build(
@@ -351,18 +458,17 @@ module Steep
351
458
  )
352
459
 
353
460
  definition.methods.each do |name, method|
354
- interface.methods[name] = Interface::Interface::Combination.overload(
355
- method.method_types.map do |type|
356
- method_type(type, self_type: self_type) {|type| type.subst(subst) }
357
- end,
358
- incompatible: method.attributes.include?(:incompatible)
461
+ interface.methods[name] = Interface::Interface::Entry.new(
462
+ method_types: method.defs.map do |type_def|
463
+ method_type(type_def.type, method_def: type_def, self_type: self_type, subst2: subst)
464
+ end
359
465
  )
360
466
  end
361
467
  end
362
468
 
363
- when Name::Class, Name::Module
469
+ when Name::Singleton
364
470
  Interface::Interface.new(type: self_type, private: private).tap do |interface|
365
- definition = definition_builder.build_singleton(type_name_1(type.name))
471
+ definition = definition_builder.build_singleton(type.name)
366
472
 
367
473
  instance_type = Name::Instance.new(name: type.name,
368
474
  args: definition.type_params.map {Any.new(location: nil)},
@@ -377,11 +483,16 @@ module Steep
377
483
  definition.methods.each do |name, method|
378
484
  next if !private && method.private?
379
485
 
380
- interface.methods[name] = Interface::Interface::Combination.overload(
381
- method.method_types.map do |type|
382
- method_type(type, self_type: self_type) {|type| type.subst(subst) }
383
- end,
384
- incompatible: method.attributes.include?(:incompatible)
486
+ interface.methods[name] = Interface::Interface::Entry.new(
487
+ method_types: method.defs.map do |type_def|
488
+ setup_primitives(
489
+ name,
490
+ method_type(type_def.type,
491
+ method_def: type_def,
492
+ self_type: self_type,
493
+ subst2: subst)
494
+ )
495
+ end
385
496
  )
386
497
  end
387
498
  end
@@ -404,7 +515,25 @@ module Steep
404
515
  Interface::Interface.new(type: self_type, private: private).tap do |interface|
405
516
  common_methods = Set.new(interface1.methods.keys) & Set.new(interface2.methods.keys)
406
517
  common_methods.each do |name|
407
- interface.methods[name] = Interface::Interface::Combination.union([interface1.methods[name], interface2.methods[name]])
518
+ types1 = interface1.methods[name].method_types
519
+ types2 = interface2.methods[name].method_types
520
+
521
+ if types1 == types2
522
+ interface.methods[name] = interface1.methods[name]
523
+ else
524
+ method_types = {}
525
+
526
+ types1.each do |type1|
527
+ types2.each do |type2|
528
+ type = type1 | type2 or next
529
+ method_types[type] = true
530
+ end
531
+ end
532
+
533
+ unless method_types.empty?
534
+ interface.methods[name] = Interface::Interface::Entry.new(method_types: method_types.keys)
535
+ end
536
+ end
408
537
  end
409
538
  end
410
539
  end
@@ -415,11 +544,8 @@ module Steep
415
544
  interfaces = type.types.map {|ty| interface(ty, private: private, self_type: self_type) }
416
545
  interfaces.inject do |interface1, interface2|
417
546
  Interface::Interface.new(type: self_type, private: private).tap do |interface|
418
- all_methods = Set.new(interface1.methods.keys) + Set.new(interface2.methods.keys)
419
- all_methods.each do |name|
420
- methods = [interface1.methods[name], interface2.methods[name]].compact
421
- interface.methods[name] = Interface::Interface::Combination.intersection(methods)
422
- end
547
+ interface.methods.merge!(interface1.methods)
548
+ interface.methods.merge!(interface2.methods)
423
549
  end
424
550
  end
425
551
  end
@@ -430,8 +556,8 @@ module Steep
430
556
  array_type = Builtin::Array.instance_type(element_type)
431
557
  interface(array_type, private: private, self_type: self_type).tap do |array_interface|
432
558
  array_interface.methods[:[]] = array_interface.methods[:[]].yield_self do |aref|
433
- Interface::Interface::Combination.overload(
434
- type.types.map.with_index {|elem_type, index|
559
+ Interface::Interface::Entry.new(
560
+ method_types: type.types.map.with_index {|elem_type, index|
435
561
  Interface::MethodType.new(
436
562
  type_params: [],
437
563
  params: Interface::Params.new(required: [AST::Types::Literal.new(value: index)],
@@ -442,16 +568,16 @@ module Steep
442
568
  rest_keywords: nil),
443
569
  block: nil,
444
570
  return_type: elem_type,
571
+ method_def: nil,
445
572
  location: nil
446
573
  )
447
- } + aref.types,
448
- incompatible: false
574
+ } + aref.method_types
449
575
  )
450
576
  end
451
577
 
452
578
  array_interface.methods[:[]=] = array_interface.methods[:[]=].yield_self do |update|
453
- Interface::Interface::Combination.overload(
454
- type.types.map.with_index {|elem_type, index|
579
+ Interface::Interface::Entry.new(
580
+ method_types: type.types.map.with_index {|elem_type, index|
455
581
  Interface::MethodType.new(
456
582
  type_params: [],
457
583
  params: Interface::Params.new(required: [AST::Types::Literal.new(value: index), elem_type],
@@ -462,10 +588,40 @@ module Steep
462
588
  rest_keywords: nil),
463
589
  block: nil,
464
590
  return_type: elem_type,
591
+ method_def: nil,
592
+ location: nil
593
+ )
594
+ } + update.method_types
595
+ )
596
+ end
597
+
598
+ array_interface.methods[:first] = array_interface.methods[:first].yield_self do |first|
599
+ Interface::Interface::Entry.new(
600
+ method_types: [
601
+ Interface::MethodType.new(
602
+ type_params: [],
603
+ params: Interface::Params.empty,
604
+ block: nil,
605
+ return_type: type.types[0] || AST::Builtin.nil_type,
606
+ method_def: nil,
607
+ location: nil
608
+ )
609
+ ]
610
+ )
611
+ end
612
+
613
+ array_interface.methods[:last] = array_interface.methods[:last].yield_self do |last|
614
+ Interface::Interface::Entry.new(
615
+ method_types: [
616
+ Interface::MethodType.new(
617
+ type_params: [],
618
+ params: Interface::Params.empty,
619
+ block: nil,
620
+ return_type: type.types.last || AST::Builtin.nil_type,
621
+ method_def: nil,
465
622
  location: nil
466
623
  )
467
- } + update.types,
468
- incompatible: false
624
+ ]
469
625
  )
470
626
  end
471
627
  end
@@ -481,8 +637,8 @@ module Steep
481
637
 
482
638
  interface(hash_type, private: private, self_type: self_type).tap do |hash_interface|
483
639
  hash_interface.methods[:[]] = hash_interface.methods[:[]].yield_self do |ref|
484
- Interface::Interface::Combination.overload(
485
- type.elements.map {|key_value, value_type|
640
+ Interface::Interface::Entry.new(
641
+ method_types: type.elements.map {|key_value, value_type|
486
642
  key_type = Literal.new(value: key_value, location: nil)
487
643
  Interface::MethodType.new(
488
644
  type_params: [],
@@ -494,16 +650,16 @@ module Steep
494
650
  rest_keywords: nil),
495
651
  block: nil,
496
652
  return_type: value_type,
653
+ method_def: nil,
497
654
  location: nil
498
655
  )
499
- } + ref.types,
500
- incompatible: false
656
+ } + ref.method_types
501
657
  )
502
658
  end
503
659
 
504
660
  hash_interface.methods[:[]=] = hash_interface.methods[:[]=].yield_self do |update|
505
- Interface::Interface::Combination.overload(
506
- type.elements.map {|key_value, value_type|
661
+ Interface::Interface::Entry.new(
662
+ method_types: type.elements.map {|key_value, value_type|
507
663
  key_type = Literal.new(value: key_value, location: nil)
508
664
  Interface::MethodType.new(
509
665
  type_params: [],
@@ -515,10 +671,10 @@ module Steep
515
671
  rest_keywords: nil),
516
672
  block: nil,
517
673
  return_type: value_type,
674
+ method_def: nil,
518
675
  location: nil
519
676
  )
520
- } + update.types,
521
- incompatible: false
677
+ } + update.method_types
522
678
  )
523
679
  end
524
680
  end
@@ -531,26 +687,30 @@ module Steep
531
687
  params: type.params,
532
688
  return_type: type.return_type,
533
689
  block: nil,
690
+ method_def: nil,
534
691
  location: nil
535
692
  )
536
693
 
537
- interface.methods[:[]] = Interface::Interface::Combination.overload([method_type], incompatible: false)
538
- interface.methods[:call] = Interface::Interface::Combination.overload([method_type], incompatible: false)
694
+ interface.methods[:[]] = Interface::Interface::Entry.new(method_types: [method_type])
695
+ interface.methods[:call] = Interface::Interface::Entry.new(method_types: [method_type])
539
696
  end
540
697
 
698
+ when Logic::Base
699
+ interface(AST::Builtin.bool_type, private: private, self_type: self_type)
700
+
541
701
  else
542
702
  raise "Unexpected type for interface: #{type}"
703
+ end.tap do |interface|
704
+ type_interface_cache[cache_key] = interface
543
705
  end
544
706
  end
545
707
 
546
708
  def module_name?(type_name)
547
- name = type_name_1(type_name)
548
- entry = env.class_decls[name] and entry.is_a?(RBS::Environment::ModuleEntry)
709
+ entry = env.class_decls[type_name] and entry.is_a?(RBS::Environment::ModuleEntry)
549
710
  end
550
711
 
551
712
  def class_name?(type_name)
552
- name = type_name_1(type_name)
553
- entry = env.class_decls[name] and entry.is_a?(RBS::Environment::ClassEntry)
713
+ entry = env.class_decls[type_name] and entry.is_a?(RBS::Environment::ClassEntry)
554
714
  end
555
715
 
556
716
  def env
@@ -565,7 +725,22 @@ module Steep
565
725
  end
566
726
 
567
727
  def absolute_type_name(type_name, namespace:)
568
- type_name_resolver.resolve(type_name, context: namespace_1(namespace).ascend)
728
+ type_name_resolver.resolve(type_name, context: namespace.ascend)
729
+ end
730
+
731
+ def instance_type(type_name, args: nil, location: nil)
732
+ raise unless type_name.class?
733
+
734
+ definition = definition_builder.build_singleton(type_name)
735
+ def_args = definition.type_params.map { Any.new(location: nil) }
736
+
737
+ if args
738
+ raise if def_args.size != args.size
739
+ else
740
+ args = def_args
741
+ end
742
+
743
+ AST::Types::Name::Instance.new(location: location, name: type_name, args: args)
569
744
  end
570
745
  end
571
746
  end