sorbet-runtime 0.0.1.pre.prealpha → 0.4.4253

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +5 -5
  2. data/lib/sorbet-runtime.rb +100 -0
  3. data/lib/types/_types.rb +245 -0
  4. data/lib/types/abstract_utils.rb +50 -0
  5. data/lib/types/boolean.rb +8 -0
  6. data/lib/types/compatibility_patches.rb +37 -0
  7. data/lib/types/configuration.rb +368 -0
  8. data/lib/types/generic.rb +23 -0
  9. data/lib/types/helpers.rb +31 -0
  10. data/lib/types/interface_wrapper.rb +158 -0
  11. data/lib/types/private/abstract/data.rb +36 -0
  12. data/lib/types/private/abstract/declare.rb +39 -0
  13. data/lib/types/private/abstract/hooks.rb +43 -0
  14. data/lib/types/private/abstract/validate.rb +128 -0
  15. data/lib/types/private/casts.rb +22 -0
  16. data/lib/types/private/class_utils.rb +102 -0
  17. data/lib/types/private/decl_state.rb +18 -0
  18. data/lib/types/private/error_handler.rb +37 -0
  19. data/lib/types/private/methods/_methods.rb +344 -0
  20. data/lib/types/private/methods/call_validation.rb +1177 -0
  21. data/lib/types/private/methods/decl_builder.rb +275 -0
  22. data/lib/types/private/methods/modes.rb +18 -0
  23. data/lib/types/private/methods/signature.rb +196 -0
  24. data/lib/types/private/methods/signature_validation.rb +232 -0
  25. data/lib/types/private/mixins/mixins.rb +27 -0
  26. data/lib/types/private/runtime_levels.rb +41 -0
  27. data/lib/types/private/types/not_typed.rb +23 -0
  28. data/lib/types/private/types/string_holder.rb +26 -0
  29. data/lib/types/private/types/void.rb +33 -0
  30. data/lib/types/profile.rb +27 -0
  31. data/lib/types/props/_props.rb +165 -0
  32. data/lib/types/props/constructor.rb +20 -0
  33. data/lib/types/props/custom_type.rb +84 -0
  34. data/lib/types/props/decorator.rb +826 -0
  35. data/lib/types/props/errors.rb +8 -0
  36. data/lib/types/props/optional.rb +73 -0
  37. data/lib/types/props/plugin.rb +15 -0
  38. data/lib/types/props/pretty_printable.rb +106 -0
  39. data/lib/types/props/serializable.rb +376 -0
  40. data/lib/types/props/type_validation.rb +98 -0
  41. data/lib/types/props/utils.rb +49 -0
  42. data/lib/types/props/weak_constructor.rb +30 -0
  43. data/lib/types/runtime_profiled.rb +36 -0
  44. data/lib/types/sig.rb +28 -0
  45. data/lib/types/struct.rb +8 -0
  46. data/lib/types/types/base.rb +141 -0
  47. data/lib/types/types/class_of.rb +38 -0
  48. data/lib/types/types/enum.rb +42 -0
  49. data/lib/types/types/fixed_array.rb +60 -0
  50. data/lib/types/types/fixed_hash.rb +59 -0
  51. data/lib/types/types/intersection.rb +36 -0
  52. data/lib/types/types/noreturn.rb +25 -0
  53. data/lib/types/types/proc.rb +51 -0
  54. data/lib/types/types/self_type.rb +31 -0
  55. data/lib/types/types/simple.rb +33 -0
  56. data/lib/types/types/type_member.rb +7 -0
  57. data/lib/types/types/type_parameter.rb +23 -0
  58. data/lib/types/types/type_template.rb +7 -0
  59. data/lib/types/types/type_variable.rb +31 -0
  60. data/lib/types/types/typed_array.rb +20 -0
  61. data/lib/types/types/typed_enumerable.rb +141 -0
  62. data/lib/types/types/typed_enumerator.rb +22 -0
  63. data/lib/types/types/typed_hash.rb +29 -0
  64. data/lib/types/types/typed_range.rb +22 -0
  65. data/lib/types/types/typed_set.rb +22 -0
  66. data/lib/types/types/union.rb +59 -0
  67. data/lib/types/types/untyped.rb +25 -0
  68. data/lib/types/utils.rb +223 -0
  69. metadata +122 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: c4f49cb714c88c903514f17f163768e3bd1575acd6b0d03db35f75da70e16c1e
4
- data.tar.gz: 79d77212df76f815de71d6ece2887942d115944b70837bd292726091d43eec83
2
+ SHA1:
3
+ metadata.gz: de11dcda7e38c4977b8e8adb679d16e2e34b94df
4
+ data.tar.gz: 930cdf2804d7b8919dea38ccd474e261a654e03d
5
5
  SHA512:
6
- metadata.gz: 0d4f30e545125cbb41591bb593ceb96460a8fb67deeafa2c9f37d7ec314998c53e26afa21c0af280633840a37ef1a06068c83f12cf330a24ef2bdb0a567dc024
7
- data.tar.gz: be94a5f46d1e95b4ce2f8d767587e84271111bc026706210806349afab18fc327a2acd65295a85098241f13f3c313665b79da3cff0ac4efabeea9178f60f3df4
6
+ metadata.gz: 77caf2c55b6c999939a4860e8be38088854a4530cac75bee1c9cca68ed2d8b8c9ef6182061a15c73d0e5cf343ef6e2caaa7f3e5c45690b79ed41af18ebe1d2b4
7
+ data.tar.gz: 76a0990ca32cd691b58ae71ff7a34e6e63f0c674da3945718d6a5060f91bc08e50ec55972aafb8cf87930fba2220da3a336b557c8ad9121475e0a97445539a78
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ # This file is hand-crafted to encode the dependencies. They load the whole type
5
+ # system since there is such a high chance of it being used, using an autoloader
6
+ # wouldn't buy us any startup time saving.
7
+
8
+ # Namespaces without any implementation
9
+ module T; end
10
+ module T::Helpers; end
11
+ module T::Private; end
12
+ module T::Private::Abstract; end
13
+ module T::Private::Types; end
14
+
15
+ require 'set'
16
+
17
+ # Each section is a group that I believe need a fixed ordering. There is also
18
+ # an ordering between groups.
19
+
20
+ # These are pre-reqs for almost everything in here.
21
+ require_relative 'types/configuration'
22
+ require_relative 'types/profile'
23
+ require_relative 'types/_types'
24
+ require_relative 'types/private/decl_state'
25
+ require_relative 'types/runtime_profiled'
26
+ require_relative 'types/private/class_utils'
27
+ require_relative 'types/private/error_handler'
28
+ require_relative 'types/private/runtime_levels'
29
+ require_relative 'types/private/methods/_methods'
30
+ require_relative 'types/sig'
31
+ require_relative 'types/helpers'
32
+
33
+ # The types themselves. First base classes
34
+ require_relative 'types/types/base'
35
+ require_relative 'types/types/typed_enumerable'
36
+ # Everything else
37
+ require_relative 'types/types/class_of'
38
+ require_relative 'types/types/enum'
39
+ require_relative 'types/types/fixed_array'
40
+ require_relative 'types/types/fixed_hash'
41
+ require_relative 'types/types/intersection'
42
+ require_relative 'types/types/noreturn'
43
+ require_relative 'types/types/proc'
44
+ require_relative 'types/types/self_type'
45
+ require_relative 'types/types/simple'
46
+ require_relative 'types/types/type_parameter'
47
+ require_relative 'types/types/typed_array'
48
+ require_relative 'types/types/typed_enumerator'
49
+ require_relative 'types/types/typed_hash'
50
+ require_relative 'types/types/typed_range'
51
+ require_relative 'types/types/typed_set'
52
+ require_relative 'types/types/union'
53
+ require_relative 'types/types/untyped'
54
+ require_relative 'types/private/types/not_typed'
55
+ require_relative 'types/private/types/void'
56
+ require_relative 'types/private/types/string_holder'
57
+
58
+ require_relative 'types/types/type_variable'
59
+ require_relative 'types/types/type_member'
60
+ require_relative 'types/types/type_template'
61
+
62
+ # Call validation
63
+ require_relative 'types/private/methods/modes'
64
+ require_relative 'types/private/methods/call_validation'
65
+
66
+ # Signature validation
67
+ require_relative 'types/private/methods/signature_validation'
68
+ require_relative 'types/abstract_utils'
69
+ require_relative 'types/private/abstract/validate'
70
+
71
+ # Catch all. Sort of built by `cd extn; find types -type f | grep -v test | sort`
72
+ require_relative 'types/generic'
73
+ require_relative 'types/interface_wrapper'
74
+ require_relative 'types/private/abstract/declare'
75
+ require_relative 'types/private/abstract/hooks'
76
+ require_relative 'types/private/casts'
77
+ require_relative 'types/private/methods/decl_builder'
78
+ require_relative 'types/private/methods/signature'
79
+ require_relative 'types/utils'
80
+ require_relative 'types/boolean'
81
+
82
+ # Props dependencies
83
+ require_relative 'types/private/abstract/data'
84
+ require_relative 'types/private/mixins/mixins'
85
+ require_relative 'types/props/_props'
86
+ require_relative 'types/props/custom_type'
87
+ require_relative 'types/props/decorator'
88
+ require_relative 'types/props/errors'
89
+ require_relative 'types/props/plugin'
90
+ require_relative 'types/props/utils'
91
+ # Props that run sigs statically so have to be after all the others :(
92
+ require_relative 'types/props/optional'
93
+ require_relative 'types/props/weak_constructor'
94
+ require_relative 'types/props/constructor'
95
+ require_relative 'types/props/pretty_printable'
96
+ require_relative 'types/props/serializable'
97
+ require_relative 'types/props/type_validation'
98
+ require_relative 'types/struct'
99
+
100
+ require_relative 'types/compatibility_patches'
@@ -0,0 +1,245 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+ # This is where we define the shortcuts, so we can't use them here
4
+ # rubocop:disable PrisonGuard/UseOpusTypesShortcut
5
+
6
+ # _____
7
+ # |_ _| _ _ __ ___ ___
8
+ # | || | | | '_ \ / _ \/ __|
9
+ # | || |_| | |_) | __/\__ \
10
+ # |_| \__, | .__/ \___||___/
11
+ # |___/|_|
12
+ #
13
+ # Docs at http://go/types.
14
+ #
15
+ # Types that you can pass to `sig`:
16
+ #
17
+ # - a Ruby class
18
+ #
19
+ # - [<Type>, <Type>, ...] -- to specify a "tuple"; a fixed-size array with known types for each member
20
+ #
21
+ # - {key: <Type>, key2: <Type>, ...} -- to speicfy a "shape"; a fixed-size hash
22
+ # with known keys and type values
23
+ #
24
+ # - Any of the `T.foo` methods below
25
+
26
+ module T
27
+ # T.any(<Type>, <Type>, ...) -- matches any of the types listed
28
+ def self.any(type_a, type_b, *types)
29
+ T::Types::Union.new([type_a, type_b] + types)
30
+ end
31
+
32
+ # Shorthand for T.any(type, NilClass)
33
+ def self.nilable(type)
34
+ T::Types::Union.new([type, NilClass])
35
+ end
36
+
37
+ # Matches any object. In the static checker, T.untyped allows any
38
+ # method calls or operations.
39
+ def self.untyped
40
+ T::Types::Untyped.new
41
+ end
42
+
43
+ # Indicates a function never returns (e.g. "Kernel#raise")
44
+ def self.noreturn
45
+ T::Types::NoReturn.new
46
+ end
47
+
48
+ # T.all(<Type>, <Type>, ...) -- matches an object that has all of the types listed
49
+ def self.all(type_a, type_b, *types)
50
+ T::Types::Intersection.new([type_a, type_b] + types)
51
+ end
52
+
53
+ # Matches any of the listed values
54
+ def self.enum(values)
55
+ T::Types::Enum.new(values)
56
+ end
57
+
58
+ # Creates a proc type
59
+ def self.proc
60
+ T::Private::Methods.start_proc
61
+ end
62
+
63
+ # Matches `self`:
64
+ def self.self_type
65
+ T::Types::SelfType.new
66
+ end
67
+
68
+ # Matches any class that subclasses or includes the provided class
69
+ # or module
70
+ def self.class_of(klass)
71
+ T::Types::ClassOf.new(klass)
72
+ end
73
+
74
+
75
+ ## END OF THE METHODS TO PASS TO `sig`.
76
+
77
+
78
+ # Constructs a type alias. Used to create a short name for a larger
79
+ # type. In Ruby this is just equivalent to assignment, but this is
80
+ # needed for support by the static checker. Example usage:
81
+ #
82
+ # NilableString = T.type_alias(T.nilable(String))
83
+ #
84
+ # sig {params(arg: NilableString, default: String).returns(String)}
85
+ # def or_else(arg, default)
86
+ # arg || default
87
+ # end
88
+ #
89
+ # The name of the type alias is not preserved; Error messages will
90
+ # be printed with reference to the underlying type.
91
+ def self.type_alias(type)
92
+ T::Utils.coerce(type)
93
+ end
94
+
95
+ # References a type paramater which was previously defined with
96
+ # `type_parameters`.
97
+ #
98
+ # This is used for generic methods. Example usage:
99
+ #
100
+ # sig
101
+ # .type_parameters(:U)
102
+ # .params(
103
+ # blk: T.proc.params(arg0: Elem).returns(T.type_parameter(:U)),
104
+ # )
105
+ # .returns(T::Array[T.type_parameter(:U)])
106
+ # def map(&blk); end
107
+ def self.type_parameter(name)
108
+ T::Types::TypeParameter.new(name)
109
+ end
110
+
111
+ # Tells the typechecker that `value` is of type `type`. Use this to get additional checking after
112
+ # an expression that the typechecker is unable to analyze. If `checked` is true, raises an
113
+ # exception at runtime if the value doesn't match the type.
114
+ #
115
+ # Compared to `T.let`, `T.cast` is _trusted_ by static system.
116
+ def self.cast(value, type, checked: true)
117
+ return value unless checked
118
+
119
+ Private::Casts.cast(value, type, cast_method: "T.cast")
120
+ end
121
+
122
+ # Tells the typechecker to declare a variable of type `type`. Use
123
+ # like:
124
+ #
125
+ # seconds = T.let(0.0, Float)
126
+ #
127
+ # Compared to `T.cast`, `T.let` is _checked_ by static system.
128
+ #
129
+ # If `checked` is true, raises an exception at runtime if the value
130
+ # doesn't match the type.
131
+ def self.let(value, type, checked: true)
132
+ return value unless checked
133
+
134
+ Private::Casts.cast(value, type, cast_method: "T.let")
135
+ end
136
+
137
+ # Tells the typechecker to ensure that `value` is of type `type` (if not, the typechecker will
138
+ # fail). Use this for debugging typechecking errors, or to ensure that type information is
139
+ # statically known and being checked appropriately. If `checked` is true, raises an exception at
140
+ # runtime if the value doesn't match the type.
141
+ def self.assert_type!(value, type, checked: true)
142
+ return value unless checked
143
+
144
+ Private::Casts.cast(value, type, cast_method: "T.assert_type!")
145
+ end
146
+
147
+ # For the static type checker, strips all type information from a value
148
+ # and returns the same value, but statically-typed as `T.untyped`.
149
+ # Can be used to tell the static checker to "trust you" by discarding type information
150
+ # you know to be incorrect. Use with care!
151
+ # (This has no effect at runtime.)
152
+ #
153
+ # We can't actually write this sig because we ourselves are inside
154
+ # the `T::` module and doing this would create a bootstrapping
155
+ # cycle. However, we also don't actually need to do so; An untyped
156
+ # identity method works just as well here.
157
+ #
158
+ # sig {params(value: T.untyped).returns(T.untyped)}
159
+ def self.unsafe(value)
160
+ value
161
+ end
162
+
163
+ # A convenience method to `raise` when the argument is `nil` and return it
164
+ # otherwise.
165
+ #
166
+ # Intended to be used as:
167
+ #
168
+ # needs_foo(T.must(maybe_gives_foo))
169
+ #
170
+ # Equivalent to:
171
+ #
172
+ # foo = maybe_gives_foo
173
+ # raise "nil" if foo.nil?
174
+ # needs_foo(foo)
175
+ #
176
+ # Intended to be used to promise sorbet that a given nilable value happens
177
+ # to contain a non-nil value at this point.
178
+ #
179
+ # sig {params(arg: T.nilable(A), msg: T.nilable(String)).returns(A)}
180
+ def self.must(arg, msg=nil)
181
+ begin
182
+ if msg
183
+ if !T.unsafe(msg).is_a?(String)
184
+ raise TypeError.new("T.must expects a string as second argument")
185
+ end
186
+ else
187
+ msg = "Passed `nil` into T.must"
188
+ end
189
+ raise TypeError.new(msg) if arg.nil?
190
+ arg
191
+ rescue TypeError => e # raise into rescue to ensure e.backtrace is populated
192
+ T::Private::ErrorHandler.handle_inline_type_error(e)
193
+ arg
194
+ end
195
+ end
196
+
197
+ # A way to ask Sorbet to show what type it thinks an expression has.
198
+ # This can be useful for debugging and checking assumptions.
199
+ # In the runtime, merely returns the value passed in.
200
+ def self.reveal_type(value)
201
+ value
202
+ end
203
+
204
+ ### Generic classes ###
205
+
206
+ module Array
207
+ def self.[](type)
208
+ T::Types::TypedArray.new(type)
209
+ end
210
+ end
211
+
212
+ module Hash
213
+ def self.[](keys, values)
214
+ T::Types::TypedHash.new(keys: keys, values: values)
215
+ end
216
+ end
217
+
218
+ module Enumerable
219
+ def self.[](type)
220
+ T::Types::TypedEnumerable.new(type)
221
+ end
222
+ end
223
+
224
+ module Enumerator
225
+ def self.[](type)
226
+ T::Types::TypedEnumerator.new(type)
227
+ end
228
+ end
229
+
230
+ module Range
231
+ def self.[](type)
232
+ T::Types::TypedRange.new(type)
233
+ end
234
+ end
235
+
236
+ module Set
237
+ def self.[](type)
238
+ T::Types::TypedSet.new(type)
239
+ end
240
+ end
241
+
242
+ # When mixed into a module, indicates that Sorbet may export the CFG for methods in that module
243
+ module CFGExport; end
244
+ end
245
+ # rubocop:enable PrisonGuard/UseOpusTypesShortcut
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ module T::AbstractUtils
5
+ Methods = T::Private::Methods
6
+
7
+ # Returns whether a module is declared as abstract. After the module is finished being declared,
8
+ # this is equivalent to whether it has any abstract methods that haven't been implemented
9
+ # (because we validate that and raise an error otherwise).
10
+ #
11
+ # Note that checking `mod.is_a?(Abstract::Hooks)` is not a safe substitute for this method; when
12
+ # a class extends `Abstract::Hooks`, all of its subclasses, including the eventual concrete
13
+ # ones, will still have `Abstract::Hooks` as an ancestor.
14
+ def self.abstract_module?(mod)
15
+ !T::Private::Abstract::Data.get(mod, :abstract_type).nil?
16
+ end
17
+
18
+ def self.abstract_method?(method)
19
+ signature = Methods.signature_for_method(method)
20
+ signature&.mode == Methods::Modes.abstract
21
+ end
22
+
23
+ # Given a module, returns the set of methods declared as abstract (in itself or ancestors)
24
+ # that have not been implemented.
25
+ def self.abstract_methods_for(mod)
26
+ declared_methods = declared_abstract_methods_for(mod)
27
+ declared_methods.select do |declared_method|
28
+ actual_method = mod.instance_method(declared_method.name)
29
+ # Note that in the case where an abstract method is overridden by another abstract method,
30
+ # this method will return them both. This is intentional to ensure we validate the final
31
+ # implementation against all declarations of an abstract method (they might not all have the
32
+ # same signature).
33
+ abstract_method?(actual_method)
34
+ end
35
+ end
36
+
37
+ # Given a module, returns the set of methods declared as abstract (in itself or ancestors)
38
+ # regardless of whether they have been implemented.
39
+ def self.declared_abstract_methods_for(mod)
40
+ methods = []
41
+ mod.ancestors.each do |ancestor|
42
+ ancestor_methods = ancestor.private_instance_methods(false) + ancestor.instance_methods(false)
43
+ ancestor_methods.each do |method_name|
44
+ method = ancestor.instance_method(method_name)
45
+ methods << method if abstract_method?(method)
46
+ end
47
+ end
48
+ methods
49
+ end
50
+ end
@@ -0,0 +1,8 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module T
5
+ # T::Boolean is a type alias helper for the common `T.any(TrueClass, FalseClass)`.
6
+ # Defined separately from _types.rb because it has a dependency on T::Types::Union.
7
+ Boolean = T.type_alias(T.any(TrueClass, FalseClass))
8
+ end
@@ -0,0 +1,37 @@
1
+ # typed: ignore
2
+
3
+ require_relative 'private/methods/_methods'
4
+
5
+ # Work around an interaction bug with sorbet-runtime and rspec-mocks,
6
+ # which occurs when using *_any_instance_of and and_call_original.
7
+ #
8
+ # When a sig is defined, sorbet-runtime will replace the sigged method
9
+ # with a wrapper that, upon first invocation, re-wraps the method with a faster
10
+ # implementation.
11
+ #
12
+ # When expect_any_instance_of is used, rspec stores a reference to the first wrapper,
13
+ # to be restored later.
14
+ #
15
+ # The first wrapper is invoked as part of the test and sorbet-runtime replaces
16
+ # the method definition with the second wrapper.
17
+ #
18
+ # But when mocks are cleaned up, rspec restores back to the first wrapper.
19
+ # Upon subsequent invocations, the first wrapper is called, and sorbet-runtime
20
+ # throws a runtime error, since this is an unexpected state.
21
+ #
22
+ # We work around this by forcing re-wrapping before rspec stores a reference
23
+ # to the method.
24
+ if defined? ::RSpec::Mocks::AnyInstance
25
+ module T
26
+ module CompatibilityPatches
27
+ module RecorderExtensions
28
+ def observe!(method_name)
29
+ method = @klass.instance_method(method_name.to_sym)
30
+ T::Private::Methods.maybe_run_sig_block_for_method(method)
31
+ super(method_name)
32
+ end
33
+ end
34
+ ::RSpec::Mocks::AnyInstance::Recorder.prepend(RecorderExtensions)
35
+ end
36
+ end
37
+ end