sorbet-runtime 0.6.13275 → 0.6.13277

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 717e7a8e84d644a5afb7d14417ccaed42da2a6ef811c9dd3035feeee101c11fd
4
- data.tar.gz: 16f5fb77e086aa31acbf1d1b77f968ddd05511fdec586df1d24e26dfc61c1c2c
3
+ metadata.gz: 2205d03d1b0986fb0660902a75836d623c48307ad1b7c3b32b4a44ad79fe3c8c
4
+ data.tar.gz: 4a38dae4916789de65364bfe2bcb44f68fc1abf80c410b285013ffa1b540b902
5
5
  SHA512:
6
- metadata.gz: d16177658b783935acd782292692cc60f574fa472646eb0d88d78d90e4367352a48232969f7ce907d2e5b08fbbbe1077196c36dba6aa46da0854fd914f556fdd
7
- data.tar.gz: f3fb7b569a24bc63aaebb77b0ec9c9b920a6b246fd3bdaf8c1b98a24895529e51305cc6a383acce813696d4b0032a0bec9e4e7762af9aa9d91ad755d8d369a42
6
+ metadata.gz: c9835bded347ddabb8ea4ca593150f6d37aa676c01eff1ccc652fb176c8ca11886f6bbb303f454d40c6b0c366bd375c4d7781e277d654e7c55dc5dd11b034481
7
+ data.tar.gz: 625b9908b3f1732a2440252835719c8d6dd46160df04fb45622bd720f142274d4c06ffb0ffe5b01ae4fef73ef6baba5677abb91f72242ff8809a7066cd76eafd
@@ -25,7 +25,9 @@ require_relative 'types/private/class_utils'
25
25
  require_relative 'types/private/runtime_levels'
26
26
  require_relative 'types/private/methods/_methods'
27
27
  require_relative 'types/sig'
28
+ require_relative 'types/def_mods'
28
29
  require_relative 'types/helpers'
30
+ require_relative 'types/syntax'
29
31
  require_relative 'types/private/final'
30
32
  require_relative 'types/private/sealed'
31
33
 
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ # Optional mixin providing `abstract`, `override`, `overridable`, and `final`
5
+ # as method-level DSL keywords. Use with `extend T::DefMods`.
6
+ #
7
+ # These are alternatives to writing modifiers inside a `sig { ... }` block:
8
+ #
9
+ # sig { void }
10
+ # abstract def foo; end
11
+ #
12
+ # is equivalent to:
13
+ #
14
+ # sig { abstract.void }
15
+ # def foo; end
16
+ #
17
+ # They all return the method name, so that they can be chained with methods
18
+ # like `private`. However, unlike those methods, these methods use the `sig`
19
+ # declaration to discover the most-recently-defined method, instead of needing
20
+ # `*_class_method` variants, like `private_class_method`.
21
+ module T::DefMods
22
+ def abstract(method_name)
23
+ Kernel.raise TypeError.new("abstract accepts a Symbol, got #{method_name.class}") unless method_name.is_a?(Symbol)
24
+
25
+ begin
26
+ T::Private::Methods.declare_abstract(T.unsafe(self), method_name)
27
+ rescue T::Private::Methods::DeclBuilder::BuilderError => e
28
+ T::Configuration.sig_builder_error_handler(e, Kernel.caller_locations(1, 1)&.first)
29
+ end
30
+
31
+ method_name
32
+ end
33
+
34
+ def override(method_name, allow_incompatible: false)
35
+ Kernel.raise TypeError.new("override accepts a Symbol, got #{method_name.class}") unless method_name.is_a?(Symbol)
36
+
37
+ begin
38
+ T::Private::Methods.declare_override(T.unsafe(self), method_name, allow_incompatible: allow_incompatible)
39
+ rescue T::Private::Methods::DeclBuilder::BuilderError => e
40
+ T::Configuration.sig_builder_error_handler(e, Kernel.caller_locations(1, 1)&.first)
41
+ end
42
+
43
+ method_name
44
+ end
45
+
46
+ def final(method_name)
47
+ Kernel.raise TypeError.new("final accepts a Symbol, got #{method_name.class}") unless method_name.is_a?(Symbol)
48
+
49
+ begin
50
+ T::Private::Methods.declare_final(T.unsafe(self), method_name)
51
+ rescue T::Private::Methods::DeclBuilder::BuilderError => e
52
+ T::Configuration.sig_builder_error_handler(e, Kernel.caller_locations(1, 1)&.first)
53
+ end
54
+
55
+ method_name
56
+ end
57
+
58
+ def overridable(method_name)
59
+ Kernel.raise TypeError.new("overridable accepts a Symbol, got #{method_name.class}") unless method_name.is_a?(Symbol)
60
+
61
+ begin
62
+ T::Private::Methods.declare_overridable(T.unsafe(self), method_name)
63
+ rescue T::Private::Methods::DeclBuilder::BuilderError => e
64
+ T::Configuration.sig_builder_error_handler(e, Kernel.caller_locations(1, 1)&.first)
65
+ end
66
+
67
+ method_name
68
+ end
69
+ end
@@ -12,9 +12,17 @@ class T::Private::DeclState
12
12
 
13
13
  attr_accessor :active_declaration
14
14
  attr_accessor :skip_on_method_added
15
+ attr_accessor :previous_declaration
15
16
 
16
17
  def reset!
17
18
  self.active_declaration = nil
19
+ @previous_declaration = nil
20
+ end
21
+
22
+ def consume!
23
+ @previous_declaration = self.active_declaration
24
+ self.active_declaration = nil
25
+ @previous_declaration
18
26
  end
19
27
 
20
28
  def without_on_method_added
@@ -48,7 +48,7 @@ module T::Private::Methods
48
48
  # (This can matter for circular load-time behavior, where a method is
49
49
  # called while its Signature is being built)
50
50
  # - It's `nil` if we've finished building the sig
51
- DeclarationBlock = Struct.new(:mod, :loc, :blk_or_decl, :final)
51
+ DeclarationBlock = Struct.new(:mod, :method_name, :loc, :blk_or_decl, :final, :abstract, :override, :overridable)
52
52
 
53
53
  def self.declare_sig(mod, loc, arg, &blk)
54
54
  if T::Private::DeclState.current.active_declaration
@@ -60,13 +60,122 @@ module T::Private::Methods
60
60
  raise "Invalid argument to `sig`: #{arg}"
61
61
  end
62
62
 
63
- T::Private::DeclState.current.active_declaration = DeclarationBlock.new(mod, loc, blk, arg == :final)
63
+ method_name = nil # will be filled in once the next method is defined
64
+ abstract = nil
65
+ override = nil
66
+ overridable = nil
67
+ T::Private::DeclState.current.active_declaration = DeclarationBlock.new(mod, method_name, loc, blk, arg == :final, abstract, override, overridable)
68
+
69
+ nil
70
+ end
71
+
72
+ private_class_method def self.ensure_valid_declare_dsl!(mod, method_name, dsl_name)
73
+ previous_declaration = T::Private::DeclState.current.previous_declaration
74
+ if previous_declaration.nil?
75
+ # TODO(jez) Eventually, relax this and allow these DSLs without a preceding `sig`
76
+ raise DeclBuilder::BuilderError.new("You must declare a `sig` before using `#{dsl_name}` on the method `#{method_name}`")
77
+ end
78
+
79
+ if !previous_declaration.blk_or_decl.is_a?(Proc)
80
+ raise DeclBuilder::BuilderError.new("Cannot call `#{dsl_name} #{method_name.inspect}`, because the sig block has already run")
81
+ end
82
+
83
+ # previous_declaration.mod is the method owner (which for `def self.foo`
84
+ # is the singleton class). The DSL caller's `self` is the class itself,
85
+ # so we also accept mod.singleton_class == previous_declaration.mod.
86
+ mod_matches = previous_declaration.mod == mod || previous_declaration.mod == mod.singleton_class
87
+ if !mod_matches || previous_declaration.method_name != method_name
88
+ raise DeclBuilder::BuilderError.new(
89
+ "Can only call `#{dsl_name} #{method_name.inspect}` for the previously sig'd method. " \
90
+ "Expected: #{previous_declaration.mod}##{previous_declaration.method_name}"
91
+ )
92
+ end
93
+
94
+ previous_declaration
95
+ end
96
+
97
+ def self.declare_abstract(mod, method_name)
98
+ previous_declaration = ensure_valid_declare_dsl!(mod, method_name, :abstract)
99
+ return unless previous_declaration
100
+
101
+ if previous_declaration.abstract
102
+ raise DeclBuilder::BuilderError.new("Cannot call `abstract` twice for the method `#{method_name}`")
103
+ end
104
+
105
+ previous_declaration.abstract = true
106
+
107
+ # # TODO(jez) In the future, we will want some logic like this, but ONLY if
108
+ # # the method did not have a sig. The first-call sig wrapper is normally in
109
+ # # charge of running the sig block (even for abstract methods) If we know
110
+ # # for sure that we're not going to have a sig, but we want the runtime
111
+ # # `super` logic (possibly because there is an RBS method annotation), we
112
+ # # are safe to eagerly call `create_abstract_wrapper` to overwrite the
113
+ # # user's method.
114
+ # #
115
+ # # (Omitting this until we support DSL methods without runtime `sig`'s)
116
+ # original_visibility = T::Private::ClassUtils.visibility_method_name(mod, method_name)
117
+ # T::Private::Methods::CallValidation.create_abstract_wrapper(mod, method_name, original_visibility)
118
+
119
+ nil
120
+ end
121
+
122
+ def self.declare_override(mod, method_name, allow_incompatible:)
123
+ previous_declaration = ensure_valid_declare_dsl!(mod, method_name, :override)
124
+ return unless previous_declaration
125
+
126
+ if previous_declaration.override
127
+ raise DeclBuilder::BuilderError.new("Cannot call `override` twice for the method `#{method_name}`")
128
+ end
129
+
130
+ method = mod.instance_method(method_name)
131
+ super_method = method.super_method
132
+ if super_method.nil?
133
+ source_loc = Kernel.caller_locations(2, 1)&.map { |loc| [loc.path || "<unknown>", loc.lineno] }&.first
134
+ T::Private::Methods::SignatureValidation.validate_non_override_mode(Modes.override, method_name, method, source_loc)
135
+ end
136
+
137
+ previous_declaration.override = {allow_incompatible: allow_incompatible}
138
+
139
+ nil
140
+ end
141
+
142
+ def self.declare_final(mod, method_name)
143
+ previous_declaration = ensure_valid_declare_dsl!(mod, method_name, :final)
144
+ return unless previous_declaration
145
+
146
+ if previous_declaration.final
147
+ raise DeclBuilder::BuilderError.new("Cannot declare `#{method_name}` final twice (from `sig(:final)` nor `final def`)")
148
+ end
149
+
150
+ previous_declaration.final = true
151
+
152
+ # Register final bookkeeping that _on_method_added would have done if it
153
+ # had seen final=true at that time. Use previous_declaration.mod (the actual
154
+ # method owner, which is the singleton_class for `def self.foo`).
155
+ add_module_with_final_method(previous_declaration.mod, method_name)
156
+
157
+ nil
158
+ end
159
+
160
+ def self.declare_overridable(mod, method_name)
161
+ previous_declaration = ensure_valid_declare_dsl!(mod, method_name, :overridable)
162
+ return unless previous_declaration
163
+
164
+ if previous_declaration.overridable
165
+ raise DeclBuilder::BuilderError.new("Cannot call `overridable` twice for the method `#{method_name}`")
166
+ end
167
+
168
+ previous_declaration.overridable = true
64
169
 
65
170
  nil
66
171
  end
67
172
 
68
173
  def self.start_proc
69
- DeclBuilder.new(PROC_TYPE)
174
+ # abstract/override/overridable don't make sense on procs
175
+ abstract = false
176
+ override = nil
177
+ overridable = false
178
+ DeclBuilder.new(PROC_TYPE, abstract, override, overridable)
70
179
  end
71
180
 
72
181
  def self.finalize_proc(decl)
@@ -192,7 +301,7 @@ module T::Private::Methods
192
301
  return
193
302
  end
194
303
 
195
- current_declaration = T::Private::DeclState.current.active_declaration
304
+ current_declaration = T::Private::DeclState.current.consume!
196
305
 
197
306
  if T::Private::Final.final_module?(mod) && (current_declaration.nil? || !current_declaration.final)
198
307
  raise "#{mod} was declared as final but its method `#{method_name}` was not declared as final"
@@ -208,7 +317,8 @@ module T::Private::Methods
208
317
  if current_declaration.nil?
209
318
  return
210
319
  end
211
- T::Private::DeclState.current.reset!
320
+
321
+ current_declaration.method_name = method_name
212
322
 
213
323
  if method_name == :method_added || method_name == :singleton_method_added
214
324
  raise(
@@ -217,9 +327,23 @@ module T::Private::Methods
217
327
  )
218
328
  end
219
329
 
330
+ # We allow `sig` in the current module's context (normal case) and
331
+ if hook_mod != current_declaration.mod &&
332
+ # inside `class << self`, and
333
+ hook_mod.singleton_class != current_declaration.mod &&
334
+ # on `self` at the top level of a file
335
+ current_declaration.mod != TOP_SELF
336
+ raise "A method (#{method_name}) is being added on a different class/module (#{hook_mod}) than the " \
337
+ "last call to `sig` (#{current_declaration.mod}). Make sure each call " \
338
+ "to `sig` is immediately followed by a method definition on the same " \
339
+ "class/module."
340
+ end
341
+ # Overwrite the DeclarationBlock mod with `mod`, which is the Module that owns the method.
342
+ current_declaration.mod = mod
343
+
220
344
  original_method = mod.instance_method(method_name)
221
345
  sig_block = lambda do
222
- T::Private::Methods.run_sig(hook_mod, method_name, original_method, current_declaration)
346
+ T::Private::Methods.run_sig(method_name, original_method, current_declaration)
223
347
  end
224
348
 
225
349
  # Always replace the original method with this wrapper,
@@ -298,7 +422,7 @@ module T::Private::Methods
298
422
 
299
423
  # Executes the `sig` block, and converts the resulting Declaration
300
424
  # to a Signature.
301
- def self.run_sig(hook_mod, method_name, original_method, declaration_block)
425
+ def self.run_sig(method_name, original_method, declaration_block)
302
426
  current_declaration =
303
427
  begin
304
428
  run_builder(declaration_block)
@@ -312,7 +436,7 @@ module T::Private::Methods
312
436
 
313
437
  signature =
314
438
  if current_declaration
315
- build_sig(hook_mod, method_name, original_method, current_declaration)
439
+ build_sig(method_name, original_method, current_declaration)
316
440
  else
317
441
  Signature.new_untyped(method: original_method)
318
442
  end
@@ -335,27 +459,20 @@ module T::Private::Methods
335
459
  raise "DeclarationBlock for #{declaration_block.mod} at #{declaration_block.loc} should have already been unwrapped"
336
460
  end
337
461
 
338
- builder = DeclBuilder.new(declaration_block.mod)
462
+ builder = DeclBuilder.new(
463
+ declaration_block.mod,
464
+ declaration_block.abstract,
465
+ declaration_block.override,
466
+ declaration_block.overridable
467
+ )
339
468
  decl = builder.instance_exec(&blk_or_decl).finalize!.decl
340
469
  # Record that we've already run `blk` once and constructed a `Declaration`
341
470
  declaration_block.blk_or_decl = decl
342
471
  decl
343
472
  end
344
473
 
345
- def self.build_sig(hook_mod, method_name, original_method, current_declaration)
474
+ def self.build_sig(method_name, original_method, current_declaration)
346
475
  begin
347
- # We allow `sig` in the current module's context (normal case) and
348
- if hook_mod != current_declaration.mod &&
349
- # inside `class << self`, and
350
- hook_mod.singleton_class != current_declaration.mod &&
351
- # on `self` at the top level of a file
352
- current_declaration.mod != TOP_SELF
353
- raise "A method (#{method_name}) is being added on a different class/module (#{hook_mod}) than the " \
354
- "last call to `sig` (#{current_declaration.mod}). Make sure each call " \
355
- "to `sig` is immediately followed by a method definition on the same " \
356
- "class/module."
357
- end
358
-
359
476
  signature = Signature.new(
360
477
  method: original_method,
361
478
  method_name: method_name,
@@ -475,6 +592,10 @@ module T::Private::Methods
475
592
  key, = first_wrapper
476
593
  run_sig_block_for_key(key, force_type_init: force_type_init)
477
594
  end
595
+
596
+ # Make sure that there are no lingering declaration blocks being kept alive
597
+ # (so we're not retaining any extra references for a possible GC)
598
+ T::Private::DeclState.current.reset!
478
599
  end
479
600
 
480
601
  def self.all_checked_tests_sigs
@@ -15,7 +15,7 @@ module T::Private::Methods
15
15
  end
16
16
  end
17
17
 
18
- def initialize(mod)
18
+ def initialize(mod, abstract, override, overridable)
19
19
  @decl = Declaration.new(
20
20
  mod,
21
21
  ARG_NOT_PROVIDED, # params
@@ -28,6 +28,21 @@ module T::Private::Methods
28
28
  false, # override_allow_incompatible
29
29
  ARG_NOT_PROVIDED, # type_parameters
30
30
  )
31
+
32
+ # Call the methods after the fact (instead of setting them in the constructor)
33
+ # so we get the BuilderError's, if applicable
34
+
35
+ if abstract
36
+ self.abstract
37
+ end
38
+
39
+ if override
40
+ self.override(**override)
41
+ end
42
+
43
+ if overridable
44
+ self.overridable
45
+ end
31
46
  end
32
47
 
33
48
  def params(*unused_positional_params, **params)
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ # Used as a shortcut for mixing in the three most common "syntax" extensions
5
+ # that Sorbet provides: `sig`, the various sig DSL methods like `abstract` and
6
+ # `override`, and the `final!`/`interface!` etc. syntax for class-level
7
+ # annotations
8
+ module T::Syntax
9
+ include T::Sig
10
+ include T::DefMods
11
+ include T::Helpers
12
+
13
+ # ===== NOTE: Must keep in sync with `T::Sig`! ==============================
14
+ #
15
+ # However, there are some slight differences:
16
+ #
17
+ # - We don't need the extra `include ... MethodHooks` lines, because those
18
+ # come from the `include T::Sig` (c.f. `T::DefMods` though, where those
19
+ # extra `include` *are* required because there is otherwise no inheritance
20
+ # relationship between `T::Sig` and `T::DefMods`)
21
+ #
22
+ # - We don't do the TOP_SELF things, because it's not clear that you ever
23
+ # really want this for TOP_SELF. e.g. what would it mean to write
24
+ # `interface!` there?
25
+ #
26
+ # Rather than encourage people to write `extend T::Syntax` in their script
27
+ # top-levels, let's encourage people to just write `extend T::Sig` to keep
28
+ # things simpler.
29
+ #
30
+ # (We could revisit this in the future if people do really want this.)
31
+
32
+ private_class_method def self.included(other)
33
+ return unless Module == other
34
+ other.prepend(T::Private::Methods::MethodHooks)
35
+ end
36
+
37
+ private_class_method def self.extended(other)
38
+ return unless Module.===(other) && other.singleton_class?
39
+ other.include(T::Private::Methods::SingletonMethodHooks)
40
+ end
41
+ # ===========================================================================
42
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorbet-runtime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.13275
4
+ version: 0.6.13277
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
@@ -162,6 +162,7 @@ files:
162
162
  - lib/types/boolean.rb
163
163
  - lib/types/compatibility_patches.rb
164
164
  - lib/types/configuration.rb
165
+ - lib/types/def_mods.rb
165
166
  - lib/types/enum.rb
166
167
  - lib/types/generic.rb
167
168
  - lib/types/helpers.rb
@@ -212,6 +213,7 @@ files:
212
213
  - lib/types/props/weak_constructor.rb
213
214
  - lib/types/sig.rb
214
215
  - lib/types/struct.rb
216
+ - lib/types/syntax.rb
215
217
  - lib/types/types/anything.rb
216
218
  - lib/types/types/attached_class.rb
217
219
  - lib/types/types/base.rb