steep 0.23.0 → 0.29.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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -0
  3. data/bin/smoke_runner.rb +3 -4
  4. data/lib/steep.rb +4 -3
  5. data/lib/steep/annotation_parser.rb +2 -4
  6. data/lib/steep/ast/builtin.rb +11 -21
  7. data/lib/steep/ast/types.rb +5 -3
  8. data/lib/steep/ast/types/any.rb +1 -3
  9. data/lib/steep/ast/types/boolean.rb +1 -3
  10. data/lib/steep/ast/types/bot.rb +1 -3
  11. data/lib/steep/ast/types/class.rb +2 -2
  12. data/lib/steep/ast/types/factory.rb +249 -89
  13. data/lib/steep/ast/types/helper.rb +6 -0
  14. data/lib/steep/ast/types/instance.rb +2 -2
  15. data/lib/steep/ast/types/intersection.rb +20 -13
  16. data/lib/steep/ast/types/literal.rb +1 -3
  17. data/lib/steep/ast/types/logic.rb +63 -0
  18. data/lib/steep/ast/types/name.rb +15 -67
  19. data/lib/steep/ast/types/nil.rb +1 -3
  20. data/lib/steep/ast/types/proc.rb +5 -2
  21. data/lib/steep/ast/types/record.rb +9 -4
  22. data/lib/steep/ast/types/self.rb +1 -1
  23. data/lib/steep/ast/types/top.rb +1 -3
  24. data/lib/steep/ast/types/tuple.rb +5 -3
  25. data/lib/steep/ast/types/union.rb +16 -9
  26. data/lib/steep/ast/types/var.rb +2 -2
  27. data/lib/steep/ast/types/void.rb +1 -3
  28. data/lib/steep/drivers/check.rb +4 -0
  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/completion_provider.rb +48 -51
  35. data/lib/steep/project/file.rb +3 -3
  36. data/lib/steep/project/hover_content.rb +4 -6
  37. data/lib/steep/project/target.rb +5 -2
  38. data/lib/steep/server/base_worker.rb +5 -3
  39. data/lib/steep/server/code_worker.rb +2 -0
  40. data/lib/steep/server/master.rb +10 -1
  41. data/lib/steep/signature/validator.rb +3 -3
  42. data/lib/steep/source.rb +4 -3
  43. data/lib/steep/subtyping/check.rb +46 -59
  44. data/lib/steep/subtyping/constraints.rb +8 -0
  45. data/lib/steep/type_construction.rb +771 -513
  46. data/lib/steep/type_inference/block_params.rb +5 -0
  47. data/lib/steep/type_inference/constant_env.rb +3 -6
  48. data/lib/steep/type_inference/context.rb +8 -0
  49. data/lib/steep/type_inference/context_array.rb +4 -3
  50. data/lib/steep/type_inference/logic.rb +31 -0
  51. data/lib/steep/type_inference/logic_type_interpreter.rb +219 -0
  52. data/lib/steep/type_inference/type_env.rb +2 -2
  53. data/lib/steep/typing.rb +7 -0
  54. data/lib/steep/version.rb +1 -1
  55. data/smoke/alias/a.rb +1 -1
  56. data/smoke/case/a.rb +1 -1
  57. data/smoke/hash/d.rb +1 -1
  58. data/smoke/if/a.rb +1 -1
  59. data/smoke/module/a.rb +1 -1
  60. data/smoke/rescue/a.rb +4 -13
  61. data/smoke/type_case/a.rb +0 -7
  62. data/steep.gemspec +2 -2
  63. metadata +10 -10
  64. data/lib/steep/ast/method_type.rb +0 -126
  65. data/lib/steep/ast/namespace.rb +0 -80
  66. data/lib/steep/names.rb +0 -86
@@ -15,6 +15,12 @@ module Steep
15
15
  end || []
16
16
  end
17
17
  end
18
+
19
+ module NoFreeVariables
20
+ def free_variables()
21
+ @fvs ||= Set.new
22
+ end
23
+ end
18
24
  end
19
25
  end
20
26
  end
@@ -22,8 +22,8 @@ module Steep
22
22
  s.instance_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 to_s
@@ -28,39 +28,46 @@ module Steep
28
28
  else
29
29
  type
30
30
  end
31
- end.compact.uniq.yield_self do |tys|
32
- if tys.size == 1
31
+ end.compact.yield_self do |tys|
32
+ dups = Set.new(tys)
33
+
34
+ case dups.size
35
+ when 0
36
+ AST::Types::Top.new(location: location)
37
+ when 1
33
38
  tys.first
34
39
  else
35
- new(types: tys.sort_by(&:hash), location: location)
40
+ new(types: dups.to_a, location: location)
36
41
  end
37
42
  end
38
43
  end
39
44
 
40
45
  def ==(other)
41
- other.is_a?(Intersection) &&
42
- other.types == types
46
+ other.is_a?(Intersection) && other.types == types
43
47
  end
44
48
 
45
49
  def hash
46
- self.class.hash ^ types.hash
50
+ @hash ||= self.class.hash ^ types.hash
47
51
  end
48
52
 
49
53
  alias eql? ==
50
54
 
51
55
  def subst(s)
52
- self.class.build(location: location,
53
- types: types.map {|ty| ty.subst(s) })
56
+ self.class.build(location: location, types: types.map {|ty| ty.subst(s) })
54
57
  end
55
58
 
56
59
  def to_s
57
- "(#{types.map(&:to_s).sort.join(" & ")})"
60
+ "(#{types.map(&:to_s).join(" & ")})"
58
61
  end
59
62
 
60
- def free_variables
61
- types.each.with_object(Set.new) do |type, set|
62
- set.merge(type.free_variables)
63
- end
63
+ def free_variables()
64
+ @fvs ||= begin
65
+ set = Set.new
66
+ types.each do |type|
67
+ set.merge(type.free_variables)
68
+ end
69
+ set
70
+ end
64
71
  end
65
72
 
66
73
  include Helper::ChildrenLevel
@@ -29,9 +29,7 @@ module Steep
29
29
  value.inspect
30
30
  end
31
31
 
32
- def free_variables
33
- Set.new
34
- end
32
+ include Helper::NoFreeVariables
35
33
 
36
34
  def level
37
35
  [0]
@@ -0,0 +1,63 @@
1
+ module Steep
2
+ module AST
3
+ module Types
4
+ module Logic
5
+ class Base
6
+ attr_reader :location
7
+
8
+ def subst(s)
9
+ self
10
+ end
11
+
12
+ def free_variables
13
+ @fvs ||= Set[]
14
+ end
15
+
16
+ def hash
17
+ self.class.hash
18
+ end
19
+
20
+ def ==(other)
21
+ other.class ==self.class
22
+ end
23
+
24
+ alias eql? ==
25
+
26
+ def to_s
27
+ "<% #{self.class} %>"
28
+ end
29
+ end
30
+
31
+ class Not < Base
32
+ def initialize(location: nil)
33
+ @location = location
34
+ end
35
+ end
36
+
37
+ class ReceiverIsNil < Base
38
+ def initialize(location: nil)
39
+ @location = location
40
+ end
41
+ end
42
+
43
+ class ReceiverIsNotNil < Base
44
+ def initialize(location: nil)
45
+ @location = location
46
+ end
47
+ end
48
+
49
+ class ReceiverIsArg < Base
50
+ def initialize(location: nil)
51
+ @location = location
52
+ end
53
+ end
54
+
55
+ class ArgIsReceiver < Base
56
+ def initialize(location: nil)
57
+ @location = location
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -11,9 +11,7 @@ module Steep
11
11
  @name = name
12
12
  end
13
13
 
14
- def free_variables
15
- Set.new
16
- end
14
+ include Helper::NoFreeVariables
17
15
 
18
16
  def subst(s)
19
17
  self
@@ -41,7 +39,7 @@ module Steep
41
39
  alias eql? ==
42
40
 
43
41
  def hash
44
- self.class.hash ^ name.hash ^ args.hash
42
+ @hash ||= self.class.hash ^ name.hash ^ args.hash
45
43
  end
46
44
 
47
45
  def to_s
@@ -57,14 +55,20 @@ module Steep
57
55
  end
58
56
 
59
57
  def subst(s)
60
- self.class.new(location: location,
61
- name: name,
62
- args: args.map {|a| a.subst(s) })
58
+ if free_variables.intersect?(s.domain)
59
+ self.class.new(location: location,
60
+ name: name,
61
+ args: args.map {|a| a.subst(s) })
62
+ else
63
+ self
64
+ end
63
65
  end
64
66
 
65
67
  def free_variables
66
- args.each.with_object(Set.new) do |type, vars|
67
- vars.merge(type.free_variables)
68
+ @fvs ||= Set.new().tap do |set|
69
+ args.each do |type|
70
+ set.merge(type.free_variables)
71
+ end
68
72
  end
69
73
  end
70
74
 
@@ -75,59 +79,7 @@ module Steep
75
79
  end
76
80
  end
77
81
 
78
- class Class < Base
79
- attr_reader :constructor
80
-
81
- def initialize(name:, constructor:, location: nil)
82
- raise "Name should be a module name: #{name.inspect}" unless name.is_a?(Names::Module)
83
- super(name: name, location: location)
84
- @constructor = constructor
85
- end
86
-
87
- def ==(other)
88
- other.class == self.class &&
89
- other.name == name &&
90
- other.constructor == constructor
91
- end
92
-
93
- alias eql? ==
94
-
95
- def hash
96
- self.class.hash ^ name.hash ^ constructor.hash
97
- end
98
-
99
- def to_s
100
- k = case constructor
101
- when true
102
- " constructor"
103
- when false
104
- " noconstructor"
105
- when nil
106
- ""
107
- end
108
- "singleton(#{name.to_s})"
109
- end
110
-
111
- def with_location(new_location)
112
- self.class.new(name: name, constructor: constructor, location: new_location)
113
- end
114
-
115
- def to_instance(*args)
116
- Instance.new(name: name, args: args)
117
- end
118
-
119
- NOTHING = ::Object.new
120
-
121
- def updated(constructor: NOTHING)
122
- if NOTHING == constructor
123
- constructor = self.constructor
124
- end
125
-
126
- self.class.new(name: name, constructor: constructor, location: location)
127
- end
128
- end
129
-
130
- class Module < Base
82
+ class Singleton < Base
131
83
  def ==(other)
132
84
  other.class == self.class &&
133
85
  other.name == name
@@ -149,12 +101,8 @@ module Steep
149
101
  end
150
102
 
151
103
  class Instance < Applying
152
- def to_class(constructor:)
153
- Class.new(name: name, location: location, constructor: constructor)
154
- end
155
-
156
104
  def to_module
157
- Module.new(name: name, location: location)
105
+ Singleton.new(name: name, location: location)
158
106
  end
159
107
  end
160
108
 
@@ -26,9 +26,7 @@ module Steep
26
26
  "nil"
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]
@@ -36,8 +36,11 @@ module Steep
36
36
  "^#{params} -> #{return_type}"
37
37
  end
38
38
 
39
- def free_variables
40
- params.free_variables + return_type.free_variables
39
+ def free_variables()
40
+ @fvs ||= Set.new.tap do |set|
41
+ set.merge(params.free_variables)
42
+ set.merge(return_type.free_variables)
43
+ end
41
44
  end
42
45
 
43
46
  def level
@@ -26,12 +26,17 @@ module Steep
26
26
  end
27
27
 
28
28
  def to_s
29
- "{ #{elements.map {|key, value| "#{key.inspect} => #{value}" }.join(", ")} }"
29
+ strings = elements.keys.sort.map do |key|
30
+ "#{key.inspect} => #{elements[key]}"
31
+ end
32
+ "{ #{strings.join(", ")} }"
30
33
  end
31
34
 
32
- def free_variables
33
- elements.each_value.with_object(Set.new) do |type, set|
34
- set.merge(type.free_variables)
35
+ def free_variables()
36
+ @fvs ||= Set.new.tap do |set|
37
+ elements.each_value do |type|
38
+ set.merge(type.free_variables)
39
+ end
35
40
  end
36
41
  end
37
42
 
@@ -27,7 +27,7 @@ module Steep
27
27
  end
28
28
 
29
29
  def free_variables
30
- Set.new
30
+ @fvs ||= Set.new([self])
31
31
  end
32
32
 
33
33
  def level
@@ -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]
@@ -30,9 +30,11 @@ module Steep
30
30
  "[#{types.join(", ")}]"
31
31
  end
32
32
 
33
- def free_variables
34
- types.each.with_object(Set.new) do |type, set|
35
- set.merge(type.free_variables)
33
+ def free_variables()
34
+ @fvs ||= Set.new.tap do |set|
35
+ types.each do |type|
36
+ set.merge(type.free_variables)
37
+ end
36
38
  end
37
39
  end
38
40
 
@@ -11,6 +11,9 @@ module Steep
11
11
  end
12
12
 
13
13
  def self.build(types:, location: nil)
14
+ return AST::Types::Bot.new if types.empty?
15
+ return types.first if types.size == 1
16
+
14
17
  types.flat_map do |type|
15
18
  if type.is_a?(Union)
16
19
  type.types
@@ -29,37 +32,41 @@ module Steep
29
32
  type
30
33
  end
31
34
  end.compact.uniq.yield_self do |tys|
32
- if tys.length == 1
35
+ case tys.size
36
+ when 0
37
+ AST::Types::Bot.new
38
+ when 1
33
39
  tys.first
34
40
  else
35
- new(types: tys.sort_by(&:hash), location: location)
41
+ new(types: tys, location: location)
36
42
  end
37
43
  end
38
44
  end
39
45
 
40
46
  def ==(other)
41
47
  other.is_a?(Union) &&
42
- other.types == types
48
+ Set.new(other.types) == Set.new(types)
43
49
  end
44
50
 
45
51
  def hash
46
- self.class.hash ^ types.hash
52
+ @hash ||= self.class.hash ^ types.sort_by(&:to_s).hash
47
53
  end
48
54
 
49
55
  alias eql? ==
50
56
 
51
57
  def subst(s)
52
- self.class.build(location: location,
53
- types: types.map {|ty| ty.subst(s) })
58
+ self.class.build(location: location, types: types.map {|ty| ty.subst(s) })
54
59
  end
55
60
 
56
61
  def to_s
57
- "(#{types.map(&:to_s).sort.join(" | ")})"
62
+ "(#{types.map(&:to_s).join(" | ")})"
58
63
  end
59
64
 
60
65
  def free_variables
61
- types.each.with_object(Set.new) do |type, set|
62
- set.merge(type.free_variables)
66
+ @fvs ||= Set.new.tap do |set|
67
+ types.each do |type|
68
+ set.merge(type.free_variables)
69
+ end
63
70
  end
64
71
  end
65
72
 
@@ -44,8 +44,8 @@ module Steep
44
44
  end
45
45
  end
46
46
 
47
- def free_variables
48
- Set.new([name])
47
+ def free_variables()
48
+ @fvs ||= Set.new([name])
49
49
  end
50
50
 
51
51
  def level
@@ -26,9 +26,7 @@ module Steep
26
26
  "void"
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]