rigortype 0.3.6 → 0.3.7
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 +4 -4
- data/README.md +1 -1
- data/data/builtins/ruby_core/date.yml +6 -3
- data/data/builtins/ruby_core/enumerable.yml +1 -0
- data/data/builtins/ruby_core/exception.yml +2 -1
- data/data/builtins/ruby_core/file.yml +28 -14
- data/data/builtins/ruby_core/hash.yml +5 -2
- data/data/builtins/ruby_core/io.yml +33 -16
- data/data/builtins/ruby_core/random.yml +2 -1
- data/data/builtins/ruby_core/re.yml +6 -3
- data/data/builtins/ruby_core/struct.yml +2 -0
- data/data/builtins/ruby_core/time.yml +2 -1
- data/data/gem_overlay/activesupport/core_ext.rbs +409 -11
- data/docs/manual/02-cli-reference.md +16 -7
- data/docs/manual/05-inspecting-types.md +20 -8
- data/docs/manual/07-plugins.md +4 -0
- data/docs/manual/plugins/rigor-actionpack.md +61 -0
- data/docs/manual/plugins/rigor-activerecord.md +74 -1
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +114 -12
- data/docs/manual/plugins/rigor-sidekiq.md +22 -0
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +12 -0
- data/lib/rigor/analysis/check_rules/dead_version_guard_arms.rb +98 -0
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +3 -3
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +199 -0
- data/lib/rigor/analysis/check_rules/rule_walk.rb +1 -2
- data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +2 -2
- data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +6 -12
- data/lib/rigor/analysis/check_rules.rb +383 -48
- data/lib/rigor/analysis/crash_signature.rb +116 -0
- data/lib/rigor/analysis/dependency_recorder.rb +18 -3
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +2 -1
- data/lib/rigor/analysis/incremental.rb +28 -0
- data/lib/rigor/analysis/incremental_session.rb +44 -9
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +1 -2
- data/lib/rigor/analysis/reachability/graph.rb +14 -5
- data/lib/rigor/analysis/reachability/scan.rb +7 -3
- data/lib/rigor/analysis/result.rb +32 -0
- data/lib/rigor/analysis/run_cache_key.rb +41 -1
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +93 -1
- data/lib/rigor/analysis/runner/pool_coordinator.rb +34 -0
- data/lib/rigor/analysis/runner/project_pre_passes.rb +15 -11
- data/lib/rigor/analysis/runner/run_snapshots.rb +7 -2
- data/lib/rigor/analysis/runner.rb +147 -10
- data/lib/rigor/analysis/worker_session.rb +10 -1
- data/lib/rigor/bleeding_edge.rb +7 -6
- data/lib/rigor/builtins/hkt_builtins.rb +45 -6
- data/lib/rigor/builtins/predefined_constant_refinements.rb +108 -59
- data/lib/rigor/builtins/static_return_refinements.rb +20 -1
- data/lib/rigor/cache/descriptor.rb +42 -2
- data/lib/rigor/cache/incremental_snapshot.rb +40 -3
- data/lib/rigor/cache/rbs_environment_marshal_patch.rb +31 -8
- data/lib/rigor/cache/store.rb +10 -1
- data/lib/rigor/cli/coverage_command.rb +23 -18
- data/lib/rigor/cli/coverage_mutation.rb +13 -17
- data/lib/rigor/cli/coverage_scan.rb +47 -6
- data/lib/rigor/cli/fused_protection_renderer.rb +19 -2
- data/lib/rigor/cli/fused_protection_report.rb +23 -2
- data/lib/rigor/cli/measurement_integrity_warning.rb +57 -0
- data/lib/rigor/cli/mutation_protection_renderer.rb +22 -2
- data/lib/rigor/cli/mutation_protection_report.rb +31 -2
- data/lib/rigor/cli/sig_gen_command.rb +18 -0
- data/lib/rigor/cli/type_of_command.rb +188 -41
- data/lib/rigor/cli/type_of_renderer.rb +72 -3
- data/lib/rigor/cli/type_scan_command.rb +10 -1
- data/lib/rigor/cli.rb +1 -1
- data/lib/rigor/configuration.rb +7 -4
- data/lib/rigor/effects/plugin_facts.rb +1 -1
- data/lib/rigor/effects/scanner.rb +2 -3
- data/lib/rigor/environment/bundle_sig_discovery.rb +64 -13
- data/lib/rigor/environment/lockfile_resolver.rb +15 -5
- data/lib/rigor/environment/missing_gem_constant_index.rb +45 -4
- data/lib/rigor/environment/rbs_hierarchy.rb +16 -22
- data/lib/rigor/environment/rbs_loader.rb +525 -46
- data/lib/rigor/environment.rb +38 -15
- data/lib/rigor/inference/acceptance.rb +172 -20
- data/lib/rigor/inference/captured_locals.rb +62 -0
- data/lib/rigor/inference/content_join.rb +347 -0
- data/lib/rigor/inference/def_handle.rb +15 -3
- data/lib/rigor/inference/def_node_resolver.rb +62 -3
- data/lib/rigor/inference/expression_typer.rb +1020 -141
- data/lib/rigor/inference/fork_map.rb +6 -1
- data/lib/rigor/inference/hkt_reducer.rb +12 -1
- data/lib/rigor/inference/hkt_registry.rb +46 -0
- data/lib/rigor/inference/hkt_sugar_translator.rb +93 -0
- data/lib/rigor/inference/index_write_widening.rb +48 -0
- data/lib/rigor/inference/indexed_narrowing.rb +14 -0
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +7 -5
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +10 -0
- data/lib/rigor/inference/method_dispatcher/json_folding.rb +58 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +81 -38
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +54 -17
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +1 -2
- data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +63 -0
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +63 -10
- data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +104 -0
- data/lib/rigor/inference/method_dispatcher/universal_object_dispatch.rb +81 -0
- data/lib/rigor/inference/method_dispatcher.rb +155 -14
- data/lib/rigor/inference/method_parameter_binder.rb +3 -3
- data/lib/rigor/inference/mutation_widening.rb +244 -174
- data/lib/rigor/inference/narrowing.rb +331 -27
- data/lib/rigor/inference/parameter_inference_collector.rb +1 -0
- data/lib/rigor/inference/pre_eval_constants.rb +15 -0
- data/lib/rigor/inference/precision_scanner.rb +5 -2
- data/lib/rigor/inference/project_patched_scanner.rb +2 -1
- data/lib/rigor/inference/rbs_type_translator.rb +89 -39
- data/lib/rigor/inference/scope_indexer.rb +1493 -140
- data/lib/rigor/inference/statement_evaluator.rb +276 -91
- data/lib/rigor/inference/struct_fold_safety.rb +186 -27
- data/lib/rigor/inference/version_guard.rb +229 -0
- data/lib/rigor/language_server/selection_range_provider.rb +1 -1
- data/lib/rigor/plugin/base.rb +3 -2
- data/lib/rigor/plugin/inflector.rb +14 -5
- data/lib/rigor/plugin/io_boundary.rb +107 -4
- data/lib/rigor/plugin/loader.rb +14 -0
- data/lib/rigor/protection/analysis_guard.rb +60 -0
- data/lib/rigor/protection/closure_kill_oracle.rb +43 -38
- data/lib/rigor/protection/diagnostic_oracle.rb +12 -4
- data/lib/rigor/protection/discovery_seed.rb +1 -1
- data/lib/rigor/protection/measurement_integrity.rb +36 -0
- data/lib/rigor/protection/mutation_scanner.rb +61 -6
- data/lib/rigor/protection/mutator.rb +121 -18
- data/lib/rigor/reflection.rb +182 -30
- data/lib/rigor/scope/discovery_index.rb +39 -1
- data/lib/rigor/scope.rb +385 -4
- data/lib/rigor/sig_gen/classification.rb +12 -1
- data/lib/rigor/sig_gen/generator.rb +254 -5
- data/lib/rigor/sig_gen/renderer.rb +1 -6
- data/lib/rigor/sig_gen/writer.rb +3 -0
- data/lib/rigor/source/constant_path.rb +79 -2
- data/lib/rigor/triage/catalogue.rb +1 -1
- data/lib/rigor/type/combinator.rb +10 -0
- data/lib/rigor/type/maybe.rb +47 -0
- data/lib/rigor/type/refined.rb +1 -2
- data/lib/rigor/type/result.rb +53 -0
- data/lib/rigor/type.rb +2 -0
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +3 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +58 -8
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +15 -2
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +4 -1
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +3 -1
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +39 -14
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +36 -3
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +6 -2
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +21 -5
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +47 -8
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +13 -3
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +242 -4
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +3 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +7 -3
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +62 -11
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +15 -2
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/recurring_scan.rb +3 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +5 -1
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +2 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +798 -22
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +156 -13
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +140 -40
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +2 -2
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +20 -6
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +14 -4
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +6 -3
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +23 -6
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +264 -9
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +876 -23
- data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +99 -0
- data/plugins/rigor-dry-monads/lib/rigor-dry-monads.rb +5 -0
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +34 -0
- data/plugins/rigor-ethon/lib/rigor-ethon.rb +3 -0
- data/plugins/rigor-ethon/sig/ethon.rbs +27 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +3 -2
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/analyzer.rb +198 -0
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/binding_recognizer.rb +75 -0
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/catalog.rb +64 -0
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/discoverer.rb +173 -0
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/target_detector.rb +46 -0
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/types.rb +161 -0
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +121 -0
- data/plugins/rigor-ffi/lib/rigor-ffi.rb +3 -0
- data/plugins/rigor-ffi/sig/ffi.rbs +67 -0
- data/plugins/rigor-ffi-rzmq/lib/rigor/plugin/ffi_rzmq.rb +19 -0
- data/plugins/rigor-ffi-rzmq/lib/rigor-ffi-rzmq.rb +3 -0
- data/plugins/rigor-ffi-rzmq/sig/ffi_rzmq.rbs +29 -0
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +2 -4
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/authorization_scan.rb +2 -1
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +2 -1
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +2 -1
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +2 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +2 -1
- data/plugins/rigor-railties/lib/rigor/plugin/railties.rb +156 -11
- data/plugins/rigor-rbnacl/lib/rigor/plugin/rbnacl.rb +30 -0
- data/plugins/rigor-rbnacl/lib/rigor-rbnacl.rb +3 -0
- data/plugins/rigor-rbnacl/sig/rbnacl.rbs +22 -0
- data/plugins/rigor-sassc/lib/rigor/plugin/sassc.rb +55 -0
- data/plugins/rigor-sassc/lib/rigor-sassc.rb +3 -0
- data/plugins/rigor-sassc/sig/sassc.rbs +24 -0
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +32 -11
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +3 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +4 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +63 -10
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +15 -2
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +61 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +2 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +4 -2
- data/sig/rigor/analysis/baseline.rbs +1 -1
- data/sig/rigor/environment.rbs +3 -0
- data/sig/rigor/inference.rbs +4 -1
- data/sig/rigor/plugin/io_boundary.rbs +2 -0
- data/sig/rigor/reflection.rbs +3 -1
- data/sig/rigor/scope.rbs +25 -1
- data/sig/rigor/type.rbs +95 -1
- data/sig/rigor.rbs +16 -0
- metadata +69 -3
|
@@ -25,8 +25,19 @@ module Rigor
|
|
|
25
25
|
# Element and value types are translated recursively under the caller's `self_type` /
|
|
26
26
|
# `instance_type` / `type_vars` context.
|
|
27
27
|
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
28
|
+
# Alias and intersection types (#529):
|
|
29
|
+
# - `RBS::Types::Alias` resolves through the caller-supplied `alias_expander:` (an object answering
|
|
30
|
+
# `expand_type_alias`, in practice the environment's `RbsLoader`) and the expansion is translated
|
|
31
|
+
# in the same context. Without an expander — or past the expansion budget that bounds recursive
|
|
32
|
+
# aliases like `type json = ... | Array[json]` — the alias degrades to `Dynamic[Top]` as before.
|
|
33
|
+
# - `RBS::Types::Intersection` translates to its first member that carries static evidence. Every
|
|
34
|
+
# value of `A & B` IS an `A`, so any single member is a sound superset read; taking the first
|
|
35
|
+
# informative one turns prism's `type node = Node & _Node` into `Nominal[Prism::Node]` instead of
|
|
36
|
+
# `untyped`. `Type::Intersection` stays out of this path: it is the same-base refinement composite
|
|
37
|
+
# carrier, and the dispatch tiers do not accept it as a receiver.
|
|
38
|
+
#
|
|
39
|
+
# Interface types still degrade to `Dynamic[Top]`; they are bound to acceptance and dispatch rules
|
|
40
|
+
# not yet implemented.
|
|
30
41
|
#
|
|
31
42
|
# The optional `self_type:` and `instance_type:` arguments are the Rigor counterparts of RBS's
|
|
32
43
|
# `self` and `instance` tokens:
|
|
@@ -64,8 +75,8 @@ module Rigor
|
|
|
64
75
|
RBS::Types::Record => :translate_record,
|
|
65
76
|
RBS::Types::Proc => :translate_proc_nominal,
|
|
66
77
|
RBS::Types::ClassSingleton => :translate_class_singleton,
|
|
67
|
-
RBS::Types::Alias => :
|
|
68
|
-
RBS::Types::Intersection => :
|
|
78
|
+
RBS::Types::Alias => :translate_alias,
|
|
79
|
+
RBS::Types::Intersection => :translate_intersection,
|
|
69
80
|
RBS::Types::Variable => :translate_variable,
|
|
70
81
|
RBS::Types::Interface => :translate_untyped
|
|
71
82
|
}.freeze
|
|
@@ -74,6 +85,21 @@ module Rigor
|
|
|
74
85
|
EMPTY_TYPE_VARS = {}.freeze
|
|
75
86
|
private_constant :EMPTY_TYPE_VARS
|
|
76
87
|
|
|
88
|
+
# The immutable translation context threaded through every handler. `alias_depth` counts alias
|
|
89
|
+
# expansions performed on the current walk, so a recursive alias terminates instead of looping.
|
|
90
|
+
Context = Struct.new(:self_type, :instance_type, :type_vars, :alias_expander, :alias_depth) do
|
|
91
|
+
def deeper
|
|
92
|
+
self.class.new(self_type, instance_type, type_vars, alias_expander, alias_depth + 1)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
private_constant :Context
|
|
96
|
+
|
|
97
|
+
# Eight expansions cover any observed nesting (gem sigs rarely go past aliases-of-aliases) while
|
|
98
|
+
# bounding the `type json = ... | Array[json]` family: the ninth nested expansion degrades to
|
|
99
|
+
# `Dynamic[Top]`, which is exactly what every alias read before #529.
|
|
100
|
+
ALIAS_EXPANSION_LIMIT = 8
|
|
101
|
+
private_constant :ALIAS_EXPANSION_LIMIT
|
|
102
|
+
|
|
77
103
|
class << self
|
|
78
104
|
# @param rbs_type [RBS::Types::Bases::Base, RBS::Types::ClassInstance, ...]
|
|
79
105
|
# @param self_type [Rigor::Type, nil] substitute for `Bases::Self`.
|
|
@@ -82,36 +108,43 @@ module Rigor
|
|
|
82
108
|
# @param type_vars [Hash{Symbol => Rigor::Type}] substitution map for `Bases::Variable`. Keys
|
|
83
109
|
# are the RBS variable names (e.g., `:Elem`); values are Rigor types that replace the
|
|
84
110
|
# variable. Variables that are not bound in the map degrade to Dynamic[Top].
|
|
111
|
+
# @param alias_expander [#expand_type_alias, nil] resolves `RBS::Types::Alias` one level out —
|
|
112
|
+
# in practice the environment's `RbsLoader`. When nil, aliases degrade to Dynamic[Top].
|
|
85
113
|
# @return [Rigor::Type]
|
|
86
|
-
def translate(rbs_type, self_type: nil, instance_type: nil, type_vars: EMPTY_TYPE_VARS
|
|
114
|
+
def translate(rbs_type, self_type: nil, instance_type: nil, type_vars: EMPTY_TYPE_VARS,
|
|
115
|
+
alias_expander: nil)
|
|
116
|
+
translate_in(rbs_type, Context.new(self_type, instance_type, type_vars, alias_expander, 0))
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
private
|
|
120
|
+
|
|
121
|
+
def translate_in(rbs_type, context)
|
|
87
122
|
handler = TRANSLATORS[rbs_type.class]
|
|
88
|
-
return send(handler, rbs_type,
|
|
123
|
+
return send(handler, rbs_type, context) if handler
|
|
89
124
|
|
|
90
125
|
Type::Combinator.untyped
|
|
91
126
|
end
|
|
92
127
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def translate_top(_rbs_type, _self_type, _instance_type, _type_vars)
|
|
128
|
+
def translate_top(_rbs_type, _context)
|
|
96
129
|
Type::Combinator.top
|
|
97
130
|
end
|
|
98
131
|
|
|
99
|
-
def translate_bot(_rbs_type,
|
|
132
|
+
def translate_bot(_rbs_type, _context)
|
|
100
133
|
Type::Combinator.bot
|
|
101
134
|
end
|
|
102
135
|
|
|
103
|
-
def translate_untyped(_rbs_type,
|
|
136
|
+
def translate_untyped(_rbs_type, _context)
|
|
104
137
|
Type::Combinator.untyped
|
|
105
138
|
end
|
|
106
139
|
|
|
107
|
-
def translate_nil(_rbs_type,
|
|
140
|
+
def translate_nil(_rbs_type, _context)
|
|
108
141
|
Type::Combinator.constant_of(nil)
|
|
109
142
|
end
|
|
110
143
|
|
|
111
144
|
# `bool` in RBS denotes `true | false`. We fold it to that union eagerly so downstream
|
|
112
145
|
# comparisons (e.g., `result == Constant[true]`) remain structural. Memoized at the module
|
|
113
146
|
# level because the union is value-equal across calls.
|
|
114
|
-
def translate_bool(_rbs_type,
|
|
147
|
+
def translate_bool(_rbs_type, _context)
|
|
115
148
|
BOOL_UNION
|
|
116
149
|
end
|
|
117
150
|
|
|
@@ -121,60 +154,54 @@ module Rigor
|
|
|
121
154
|
).freeze
|
|
122
155
|
private_constant :BOOL_UNION
|
|
123
156
|
|
|
124
|
-
def translate_self(_rbs_type,
|
|
125
|
-
self_type || Type::Combinator.untyped
|
|
157
|
+
def translate_self(_rbs_type, context)
|
|
158
|
+
context.self_type || Type::Combinator.untyped
|
|
126
159
|
end
|
|
127
160
|
|
|
128
|
-
def translate_instance(_rbs_type,
|
|
129
|
-
instance_type || Type::Combinator.untyped
|
|
161
|
+
def translate_instance(_rbs_type, context)
|
|
162
|
+
context.instance_type || Type::Combinator.untyped
|
|
130
163
|
end
|
|
131
164
|
|
|
132
|
-
def translate_optional(rbs_type,
|
|
133
|
-
inner =
|
|
165
|
+
def translate_optional(rbs_type, context)
|
|
166
|
+
inner = translate_in(rbs_type.type, context)
|
|
134
167
|
Type::Combinator.union(inner, Type::Combinator.constant_of(nil))
|
|
135
168
|
end
|
|
136
169
|
|
|
137
|
-
def translate_union(rbs_type,
|
|
138
|
-
members = rbs_type.types.map
|
|
139
|
-
translate(t, self_type: self_type, instance_type: instance_type, type_vars: type_vars)
|
|
140
|
-
end
|
|
170
|
+
def translate_union(rbs_type, context)
|
|
171
|
+
members = rbs_type.types.map { |t| translate_in(t, context) }
|
|
141
172
|
Type::Combinator.union(*members)
|
|
142
173
|
end
|
|
143
174
|
|
|
144
|
-
def translate_literal(rbs_type,
|
|
175
|
+
def translate_literal(rbs_type, _context)
|
|
145
176
|
Type::Combinator.constant_of(rbs_type.literal)
|
|
146
177
|
end
|
|
147
178
|
|
|
148
179
|
# Translates the type arguments recursively so `Array[Integer]` round-trips into
|
|
149
180
|
# `Nominal["Array", [Nominal["Integer"]]]`. Variables inside the args participate in
|
|
150
181
|
# substitution through the same `type_vars:` map.
|
|
151
|
-
def translate_class_instance(rbs_type,
|
|
182
|
+
def translate_class_instance(rbs_type, context)
|
|
152
183
|
name = rbs_type.name.relative!.to_s
|
|
153
|
-
translated_args = rbs_type.args.map
|
|
154
|
-
translate(arg, self_type: self_type, instance_type: instance_type, type_vars: type_vars)
|
|
155
|
-
end
|
|
184
|
+
translated_args = rbs_type.args.map { |arg| translate_in(arg, context) }
|
|
156
185
|
Type::Combinator.nominal_of(name, type_args: translated_args)
|
|
157
186
|
end
|
|
158
187
|
|
|
159
188
|
# Preserves tuple precision through the boundary. Each positional element type is translated
|
|
160
189
|
# recursively under the caller's substitution context, and the resulting list is wrapped in a
|
|
161
190
|
# `Rigor::Type::Tuple`.
|
|
162
|
-
def translate_tuple(rbs_type,
|
|
163
|
-
elements = rbs_type.types.map
|
|
164
|
-
translate(t, self_type: self_type, instance_type: instance_type, type_vars: type_vars)
|
|
165
|
-
end
|
|
191
|
+
def translate_tuple(rbs_type, context)
|
|
192
|
+
elements = rbs_type.types.map { |t| translate_in(t, context) }
|
|
166
193
|
Type::Combinator.tuple_of(*elements)
|
|
167
194
|
end
|
|
168
195
|
|
|
169
196
|
# Preserves hash-record precision through the boundary. RBS records use Symbol keys; the
|
|
170
197
|
# translator keeps them as Symbol keys on the resulting exact closed HashShape so erasure can
|
|
171
198
|
# round-trip back to `{ a: T, ?b: U }` syntax.
|
|
172
|
-
def translate_record(rbs_type,
|
|
199
|
+
def translate_record(rbs_type, context)
|
|
173
200
|
pairs = rbs_type.fields.each_with_object({}) do |(key, value), acc|
|
|
174
|
-
acc[key] =
|
|
201
|
+
acc[key] = translate_in(value, context)
|
|
175
202
|
end
|
|
176
203
|
optional_pairs = rbs_type.optional_fields.each_with_object({}) do |(key, value), acc|
|
|
177
|
-
acc[key] =
|
|
204
|
+
acc[key] = translate_in(value, context)
|
|
178
205
|
end
|
|
179
206
|
Type::Combinator.hash_shape_of(
|
|
180
207
|
pairs.merge(optional_pairs),
|
|
@@ -184,22 +211,45 @@ module Rigor
|
|
|
184
211
|
)
|
|
185
212
|
end
|
|
186
213
|
|
|
187
|
-
def translate_proc_nominal(_rbs_type,
|
|
214
|
+
def translate_proc_nominal(_rbs_type, _context)
|
|
188
215
|
Type::Combinator.nominal_of(Proc)
|
|
189
216
|
end
|
|
190
217
|
|
|
191
218
|
# `singleton(Foo)` is the type of the constant `Foo` itself (the class object). With the
|
|
192
219
|
# dedicated Singleton type, we map directly to `Singleton[Foo]`.
|
|
193
|
-
def translate_class_singleton(rbs_type,
|
|
220
|
+
def translate_class_singleton(rbs_type, _context)
|
|
194
221
|
name = rbs_type.name.relative!.to_s
|
|
195
222
|
Type::Combinator.singleton_of(name)
|
|
196
223
|
end
|
|
197
224
|
|
|
225
|
+
# #529 — sees through a type alias instead of reading `untyped`. `expand_type_alias` resolves
|
|
226
|
+
# one level (with the alias's own type params substituted, so generic aliases work); nested
|
|
227
|
+
# aliases in the expansion recurse back through here with the depth budget decremented. Every
|
|
228
|
+
# decline arm returns exactly what the alias translated to before this handler existed.
|
|
229
|
+
def translate_alias(rbs_type, context)
|
|
230
|
+
expander = context.alias_expander
|
|
231
|
+
return Type::Combinator.untyped if expander.nil? || context.alias_depth >= ALIAS_EXPANSION_LIMIT
|
|
232
|
+
|
|
233
|
+
expanded = expander.expand_type_alias(rbs_type)
|
|
234
|
+
return Type::Combinator.untyped if expanded.nil?
|
|
235
|
+
|
|
236
|
+
translate_in(expanded, context.deeper)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# #529 — `A & B` reads as its first member that carries static evidence. Every value of the
|
|
240
|
+
# intersection IS a value of each member, so any single member is a sound superset read; the
|
|
241
|
+
# skip list drops members that add nothing (an interface's `Dynamic[Top]`, `top` itself) so
|
|
242
|
+
# `Node & _Node` lands on `Nominal[Prism::Node]`. No informative member — the pre-#529 read.
|
|
243
|
+
def translate_intersection(rbs_type, context)
|
|
244
|
+
members = rbs_type.types.map { |t| translate_in(t, context) }
|
|
245
|
+
members.find { |m| !m.is_a?(Type::Dynamic) && !m.is_a?(Type::Top) } || Type::Combinator.untyped
|
|
246
|
+
end
|
|
247
|
+
|
|
198
248
|
# Looks up the variable's RBS name in the substitution map; bound variables are replaced
|
|
199
249
|
# inline, free variables degrade to Dynamic[Top]. We use `fetch` with a default rather than
|
|
200
250
|
# `[]` so a deliberate `nil` binding (a caller mistake) is never silently consumed.
|
|
201
|
-
def translate_variable(rbs_type,
|
|
202
|
-
type_vars.fetch(rbs_type.name) { Type::Combinator.untyped }
|
|
251
|
+
def translate_variable(rbs_type, context)
|
|
252
|
+
context.type_vars.fetch(rbs_type.name) { Type::Combinator.untyped }
|
|
203
253
|
end
|
|
204
254
|
end
|
|
205
255
|
end
|