steep 0.25.0 → 0.31.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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,40 +32,41 @@ module Steep
29
32
  type
30
33
  end
31
34
  end.compact.uniq.yield_self do |tys|
32
- case tys.length
35
+ case tys.size
33
36
  when 0
34
37
  AST::Types::Bot.new
35
38
  when 1
36
39
  tys.first
37
40
  else
38
- new(types: tys.sort_by(&:hash), location: location)
41
+ new(types: tys, location: location)
39
42
  end
40
43
  end
41
44
  end
42
45
 
43
46
  def ==(other)
44
47
  other.is_a?(Union) &&
45
- other.types == types
48
+ Set.new(other.types) == Set.new(types)
46
49
  end
47
50
 
48
51
  def hash
49
- self.class.hash ^ types.hash
52
+ @hash ||= self.class.hash ^ types.sort_by(&:to_s).hash
50
53
  end
51
54
 
52
55
  alias eql? ==
53
56
 
54
57
  def subst(s)
55
- self.class.build(location: location,
56
- types: types.map {|ty| ty.subst(s) })
58
+ self.class.build(location: location, types: types.map {|ty| ty.subst(s) })
57
59
  end
58
60
 
59
61
  def to_s
60
- "(#{types.map(&:to_s).sort.join(" | ")})"
62
+ "(#{types.map(&:to_s).join(" | ")})"
61
63
  end
62
64
 
63
65
  def free_variables
64
- types.each.with_object(Set.new) do |type, set|
65
- 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
66
70
  end
67
71
  end
68
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]