rigortype 0.4.7 → 0.4.8
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 +3 -1
- data/data/core_overlay/bigdecimal.rbs +33 -0
- data/data/core_overlay/resolv.rbs +30 -0
- data/data/gem_overlay/activesupport/core_ext.rbs +29 -0
- data/data/gem_overlay/addressable/addressable.rbs +40 -0
- data/docs/handbook/01-getting-started.md +1 -1
- data/docs/handbook/11-sig-gen.md +35 -0
- data/docs/install.md +20 -0
- data/docs/manual/01-installation.md +67 -26
- data/docs/manual/02-cli-reference.md +307 -91
- data/docs/manual/03-configuration.md +41 -3
- data/docs/manual/04-diagnostics.md +5 -4
- data/docs/manual/08-skills.md +11 -0
- data/docs/manual/09-editor-integration.md +8 -0
- data/docs/manual/14-rails-quickstart.md +1 -1
- data/docs/manual/19-effect-labels.md +3 -4
- data/docs/manual/plugins/rigor-actionpack.md +15 -6
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +3 -0
- data/docs/manual/plugins/rigor-sorbet.md +17 -3
- data/lib/rigor/analysis/check_rules/always_raises_shield.rb +147 -0
- data/lib/rigor/analysis/check_rules/call_facts.rb +58 -0
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +8 -0
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +13 -2
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +6 -0
- data/lib/rigor/analysis/check_rules/plugin_api_surface.rb +195 -0
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +40 -11
- data/lib/rigor/analysis/check_rules/rbs_receiver_surface.rb +27 -1
- data/lib/rigor/analysis/check_rules/replaced_singleton_defs.rb +96 -0
- data/lib/rigor/analysis/check_rules/rule_ids.rb +8 -1
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules.rb +598 -99
- data/lib/rigor/analysis/crash_signature.rb +43 -1
- data/lib/rigor/analysis/dependency_recorder.rb +233 -76
- data/lib/rigor/analysis/incremental.rb +11 -1
- data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +2 -1
- data/lib/rigor/analysis/incremental_session.rb +279 -37
- data/lib/rigor/analysis/reachability/plugin_roots.rb +6 -3
- data/lib/rigor/analysis/rule_catalog.rb +37 -1
- data/lib/rigor/analysis/run_cache_key.rb +27 -3
- data/lib/rigor/analysis/run_disclosure_credit.rb +26 -6
- data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +4 -0
- data/lib/rigor/analysis/runner/declaration_position.rb +7 -7
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +72 -20
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +3 -8
- data/lib/rigor/analysis/runner/pool_coordinator.rb +26 -5
- data/lib/rigor/analysis/runner/project_pre_passes.rb +4 -37
- data/lib/rigor/analysis/runner.rb +222 -39
- data/lib/rigor/analysis/self_call_resolution_recorder.rb +61 -22
- data/lib/rigor/analysis/worker_session.rb +42 -41
- data/lib/rigor/bleeding_edge.rb +19 -4
- data/lib/rigor/cache/file_digest.rb +39 -31
- data/lib/rigor/cache/incremental_snapshot.rb +66 -7
- data/lib/rigor/cache/rbs_descriptor.rb +37 -2
- data/lib/rigor/cache/rbs_environment.rb +5 -1
- data/lib/rigor/cli/baseline_command.rb +15 -2
- data/lib/rigor/cli/check_command.rb +4 -2
- data/lib/rigor/cli/effects_snapshot_command.rb +8 -1
- data/lib/rigor/cli/lens_command.rb +17 -2
- data/lib/rigor/cli/sig_gen_command.rb +8 -0
- data/lib/rigor/cli/skill_describe.rb +1 -0
- data/lib/rigor/cli.rb +5 -2
- data/lib/rigor/config_audit.rb +32 -18
- data/lib/rigor/configuration/severity_profile.rb +9 -0
- data/lib/rigor/configuration.rb +32 -5
- data/lib/rigor/effects/collector.rb +53 -21
- data/lib/rigor/environment/bundle_sig_discovery.rb +63 -28
- data/lib/rigor/environment/constant_type_cache_holder.rb +5 -0
- data/lib/rigor/environment/default_libraries.rb +17 -0
- data/lib/rigor/environment/deferred_signature_plan.rb +104 -6
- data/lib/rigor/environment/hkt_registry_holder.rb +6 -0
- data/lib/rigor/environment/rbs_collection_discovery.rb +123 -8
- data/lib/rigor/environment/rbs_coverage_report.rb +12 -11
- data/lib/rigor/environment/rbs_hierarchy.rb +6 -0
- data/lib/rigor/environment/rbs_loader.rb +312 -63
- data/lib/rigor/environment.rb +131 -35
- data/lib/rigor/inference/acceptance.rb +50 -15
- data/lib/rigor/inference/alias_mutation_floor/foreign_locals.rb +117 -0
- data/lib/rigor/inference/alias_mutation_floor/memos.rb +85 -0
- data/lib/rigor/inference/alias_mutation_floor/reach.rb +119 -0
- data/lib/rigor/inference/alias_mutation_floor/site_collector.rb +252 -0
- data/lib/rigor/inference/alias_mutation_floor.rb +339 -0
- data/lib/rigor/inference/anonymous_meta_class.rb +18 -0
- data/lib/rigor/inference/block_auto_splat.rb +1 -1
- data/lib/rigor/inference/block_run_count.rb +9 -2
- data/lib/rigor/inference/builtins/array_catalog.rb +2 -2
- data/lib/rigor/inference/callee_mutation_chain.rb +1 -1
- data/lib/rigor/inference/captured_locals.rb +2 -0
- data/lib/rigor/inference/census_foreign_block.rb +354 -0
- data/lib/rigor/inference/clause_widening.rb +1 -1
- data/lib/rigor/inference/closure_escape_analyzer.rb +11 -4
- data/lib/rigor/inference/construction_escape.rb +56 -15
- data/lib/rigor/inference/declaration_walk.rb +4 -0
- data/lib/rigor/inference/def_node_resolver.rb +32 -14
- data/lib/rigor/inference/def_return_typer.rb +1 -1
- data/lib/rigor/inference/definer_resolution.rb +15 -7
- data/lib/rigor/inference/definers_index.rb +72 -16
- data/lib/rigor/inference/error_info.rb +16 -0
- data/lib/rigor/inference/expression_typer.rb +1459 -287
- data/lib/rigor/inference/flow_tracer.rb +31 -14
- data/lib/rigor/inference/fork_map.rb +3 -0
- data/lib/rigor/inference/fresh_frame_blocks.rb +52 -1
- data/lib/rigor/inference/global_write_census.rb +8 -6
- data/lib/rigor/inference/in_effect_refinements.rb +7 -0
- data/lib/rigor/inference/indexed_narrowing.rb +57 -8
- data/lib/rigor/inference/ivar_writer_census.rb +106 -11
- data/lib/rigor/inference/key_presence_guard.rb +51 -25
- data/lib/rigor/inference/last_line/self_evidence.rb +30 -0
- data/lib/rigor/inference/last_line.rb +5 -2
- data/lib/rigor/inference/loop_value_record.rb +63 -15
- data/lib/rigor/inference/match_rebinding/frame.rb +11 -0
- data/lib/rigor/inference/match_rebinding/yielding_match.rb +74 -18
- data/lib/rigor/inference/match_rebinding.rb +21 -8
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +43 -29
- data/lib/rigor/inference/method_dispatcher/class_keyed_block_params.rb +65 -0
- data/lib/rigor/inference/method_dispatcher/core_enumerable_receiver.rb +44 -0
- data/lib/rigor/inference/method_dispatcher/declared_constructor.rb +151 -0
- data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/imprecise_argument.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/interface_shape.rb +181 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +12 -0
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +409 -67
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +384 -64
- data/lib/rigor/inference/method_dispatcher/singleton_type_params.rb +104 -0
- data/lib/rigor/inference/method_dispatcher.rb +66 -18
- data/lib/rigor/inference/method_parameter_binder.rb +136 -56
- data/lib/rigor/inference/module_function_state/spellings.rb +2 -2
- data/lib/rigor/inference/module_function_state.rb +13 -2
- data/lib/rigor/inference/multi_target_binder.rb +1 -1
- data/lib/rigor/inference/mutation_widening.rb +44 -4
- data/lib/rigor/inference/narrowing.rb +201 -27
- data/lib/rigor/inference/operand_effects.rb +43 -2
- data/lib/rigor/inference/optimistic_origin.rb +133 -8
- data/lib/rigor/inference/origin_lookup.rb +1 -1
- data/lib/rigor/inference/precision_scanner.rb +1 -1
- data/lib/rigor/inference/project_method_ownership.rb +28 -10
- data/lib/rigor/inference/project_patched_methods.rb +65 -13
- data/lib/rigor/inference/project_patched_scanner.rb +120 -25
- data/lib/rigor/inference/project_patched_visibility.rb +39 -3
- data/lib/rigor/inference/rbs_type_translator.rb +68 -15
- data/lib/rigor/inference/receiver_writer_call.rb +67 -0
- data/lib/rigor/inference/recursion_rebinding.rb +157 -0
- data/lib/rigor/inference/refined_dispatch/constructed_class.rb +56 -18
- data/lib/rigor/inference/refined_dispatch/own_method.rb +51 -17
- data/lib/rigor/inference/refined_dispatch.rb +13 -0
- data/lib/rigor/inference/reflective_ivar_write.rb +19 -11
- data/lib/rigor/inference/remover_holder_scan.rb +76 -22
- data/lib/rigor/inference/scope_indexer/class_cvars_collector.rb +13 -6
- data/lib/rigor/inference/scope_indexer/declared_param_writes.rb +12 -11
- data/lib/rigor/inference/scope_indexer/ivar_contributions.rb +188 -28
- data/lib/rigor/inference/scope_indexer/mixin_accumulator.rb +136 -9
- data/lib/rigor/inference/scope_indexer.rb +2079 -183
- data/lib/rigor/inference/self_call_ivar_writes.rb +26 -7
- data/lib/rigor/inference/self_preserving_block.rb +87 -0
- data/lib/rigor/inference/singleton_hook_decline.rb +41 -6
- data/lib/rigor/inference/singleton_object_constant.rb +32 -2
- data/lib/rigor/inference/statement_evaluator.rb +970 -250
- data/lib/rigor/inference/string_mutation.rb +14 -0
- data/lib/rigor/inference/synthetic_method_scanner.rb +35 -11
- data/lib/rigor/inference/toplevel_def_census.rb +14 -6
- data/lib/rigor/inference/unknown_store_widening.rb +1 -1
- data/lib/rigor/inference/untyped_rejoin.rb +1 -1
- data/lib/rigor/inference/void_tail_summary.rb +29 -10
- data/lib/rigor/lens/claims/comparison.rb +78 -0
- data/lib/rigor/lens/claims/request.rb +131 -0
- data/lib/rigor/lens/claims/type_reader.rb +216 -0
- data/lib/rigor/lens/claims.rb +208 -0
- data/lib/rigor/lens/contract_reader.rb +5 -0
- data/lib/rigor/lens/document.rb +1 -1
- data/lib/rigor/lens/file_reader.rb +21 -8
- data/lib/rigor/lens/run.rb +8 -0
- data/lib/rigor/lens.rb +1 -1
- data/lib/rigor/library_probe.rb +68 -0
- data/lib/rigor/memo_audit.rb +282 -0
- data/lib/rigor/plugin/base.rb +15 -2
- data/lib/rigor/plugin/io_boundary.rb +25 -3
- data/lib/rigor/plugin/manifest.rb +7 -3
- data/lib/rigor/plugin/registry.rb +13 -2
- data/lib/rigor/plugin/trust_policy.rb +46 -0
- data/lib/rigor/protection/mutation_cache.rb +4 -1
- data/lib/rigor/reflection/constant_ancestors.rb +79 -22
- data/lib/rigor/reflection/declaration_collectors.rb +55 -0
- data/lib/rigor/reflection/declarations.rb +58 -0
- data/lib/rigor/reflection/project_method.rb +177 -0
- data/lib/rigor/reflection.rb +2 -0
- data/lib/rigor/rooted_glob.rb +18 -1
- data/lib/rigor/run_scoped_slots.rb +20 -20
- data/lib/rigor/scope/discovery_index.rb +149 -2
- data/lib/rigor/scope/resolution_chain/relevance.rb +14 -1
- data/lib/rigor/scope/resolution_chain.rb +900 -55
- data/lib/rigor/scope.rb +307 -34
- data/lib/rigor/sig_gen/bot_proposal_guard.rb +306 -0
- data/lib/rigor/sig_gen/classification.rb +14 -1
- data/lib/rigor/sig_gen/generator.rb +222 -13
- data/lib/rigor/sig_gen/method_candidate.rb +14 -0
- data/lib/rigor/sig_gen/observation_collector.rb +11 -2
- data/lib/rigor/sig_gen/platform_guarded_files.rb +184 -0
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +47 -0
- data/lib/rigor/sig_gen/writer.rb +21 -0
- data/lib/rigor/sig_gen.rb +1 -0
- data/lib/rigor/source/forwardable_delegators.rb +122 -0
- data/lib/rigor/source/node_children.rb +13 -0
- data/lib/rigor/type/combinator.rb +164 -8
- data/lib/rigor/type/interface.rb +60 -0
- data/lib/rigor/type.rb +1 -0
- data/lib/rigor/type_of_memo/serving.rb +99 -0
- data/lib/rigor/type_of_memo/stats.rb +43 -0
- data/lib/rigor/type_of_memo.rb +337 -0
- data/lib/rigor/typing_state.rb +1094 -0
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +2 -2
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +57 -25
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +3 -6
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +25 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +16 -6
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +4 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +2 -1
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +130 -30
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +20 -5
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +7 -4
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +49 -13
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +19 -5
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +4 -2
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +13 -5
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +29 -0
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_collector.rb +15 -21
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_discoverer.rb +1 -6
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +4 -2
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +12 -2
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +6 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +199 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +3 -2
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +4 -4
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +209 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +146 -7
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +52 -34
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +80 -3
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_collector.rb +16 -16
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_discoverer.rb +1 -6
- data/sig/rigor/analysis/check_rules/rule_walk.rbs +6 -0
- data/sig/rigor/analysis/fact_store.rbs +2 -3
- data/sig/rigor/cache/descriptor.rbs +14 -0
- data/sig/rigor/environment.rbs +4 -1
- data/sig/rigor/plugin/base.rbs +53 -19
- data/sig/rigor/plugin/interfaces.rbs +51 -0
- data/sig/rigor/plugin/io_boundary.rbs +2 -3
- data/sig/rigor/plugin/node_context.rbs +21 -0
- data/sig/rigor/reflection.rbs +37 -0
- data/sig/rigor/scope.rbs +22 -3
- data/sig/rigor/trinary.rbs +1 -0
- data/sig/rigor/type.rbs +9 -3
- data/sig/rigor.rbs +3 -2
- data/skills/rigor-ask/SKILL.md +1 -0
- data/skills/rigor-project-init/references/01-detect.md +1 -0
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +5 -1
- data/skills/rigor-project-init/references/06-agent-contract.md +4 -4
- data/skills/rigor-rbs-contract/SKILL.md +147 -0
- data/skills/rigor-rbs-contract/references/01-finding-candidates.md +212 -0
- data/skills/rigor-rbs-contract/references/02-contract-rules.md +157 -0
- data/skills/rigor-rbs-contract/references/03-target-own-code.md +90 -0
- data/skills/rigor-rbs-contract/references/04-target-gem-rbs-collection.md +210 -0
- data/skills/rigor-rbs-contract/references/05-declaration-mutants.md +182 -0
- data/skills/rigor-rbs-setup/SKILL.md +3 -1
- data/skills/rigor-type-oracle/SKILL.md +26 -1
- data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +4 -3
- metadata +48 -2
- data/lib/rigor/inference/memo_audit.rb +0 -55
|
@@ -82,11 +82,16 @@ module Rigor
|
|
|
82
82
|
# the entry's answer, as `[owner_name, value]` (the owner is part of the answer so that two worlds naming
|
|
83
83
|
# different parents disagree). It is the override lints' parent read: the nearest project ancestor after the
|
|
84
84
|
# class whose block answers.
|
|
85
|
+
#
|
|
86
|
+
# Issue #3156 — a class or module the project declares but whose Ruby body records no method, superclass or
|
|
87
|
+
# include (`module PMod; end`, `class AMid` / `end`) is an external entry on the chain, which only its RBS
|
|
88
|
+
# declaration speaks for. The override block answers from RBS, so such an entry is asked too, under the
|
|
89
|
+
# project name it resolves to (`ResolutionChain::Entry#declared_name`); an undeclared external is not.
|
|
85
90
|
def override_answer(scope)
|
|
86
91
|
lambda do |chain, from|
|
|
87
|
-
first_hit(chain, scope, from) do |
|
|
88
|
-
value = yield(
|
|
89
|
-
[
|
|
92
|
+
first_hit(chain, scope, from, askable_external: true) do |name|
|
|
93
|
+
value = yield(name)
|
|
94
|
+
[name, value] unless value.nil?
|
|
90
95
|
end
|
|
91
96
|
end
|
|
92
97
|
end
|
|
@@ -331,17 +336,20 @@ module Rigor
|
|
|
331
336
|
kind == :singleton ? [:singleton, method_name.to_sym] : method_name.to_sym
|
|
332
337
|
end
|
|
333
338
|
|
|
334
|
-
|
|
339
|
+
# The first entry at or after `from` whose block answers. The default answer functions are handed the project
|
|
340
|
+
# entry; the override one (`askable_external:`) is handed a name, and also asks an external entry the project
|
|
341
|
+
# declares.
|
|
342
|
+
def first_hit(chain, scope, from, askable_external: false)
|
|
335
343
|
index = from - 1
|
|
336
344
|
found = nil
|
|
337
345
|
chain.search(scope, from) do |entry|
|
|
338
346
|
index += 1
|
|
339
|
-
next
|
|
347
|
+
next unless (name = entry.external? ? askable_external && entry.declared_name(scope) : entry.name)
|
|
340
348
|
|
|
341
|
-
answer = yield(entry)
|
|
349
|
+
answer = yield(askable_external ? name : entry)
|
|
342
350
|
next if answer.nil?
|
|
343
351
|
|
|
344
|
-
found = Hit.new(answer,
|
|
352
|
+
found = Hit.new(answer, name, index, entry.side)
|
|
345
353
|
end
|
|
346
354
|
found
|
|
347
355
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "../
|
|
3
|
+
require_relative "../typing_state"
|
|
4
|
+
require_relative "../memo_audit"
|
|
4
5
|
|
|
5
6
|
module Rigor
|
|
6
7
|
module Inference
|
|
@@ -21,12 +22,32 @@ module Rigor
|
|
|
21
22
|
module DefinersIndex
|
|
22
23
|
# These thread slots are bounded, like `ExpressionTyper#method_definers_index`'s two ways. Each is a fixed
|
|
23
24
|
# number of entries, replaced rather than accumulated: two `[merged, seed]` pairs (the last file's two def
|
|
24
|
-
# tables) and two seed indexes. The run that filled them releases them when it ends (
|
|
25
|
+
# tables) and two seed indexes. The run that filled them releases them when it ends (run-scoped, #2399),
|
|
25
26
|
# so a finished run keeps none of its seed tables or their indexes alive.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
#
|
|
28
|
+
# ADR-129 WD1 — all three are run-scoped Memos keyed on table identity. The layers say only which seed a merged
|
|
29
|
+
# table was built over, a shortcut: {.for} answers the same index owners, `Layered` or whole, so the answer is
|
|
30
|
+
# a function of the table alone. Each seed index is a pure function of its seed table.
|
|
31
|
+
#
|
|
32
|
+
# Each hit goes through `MemoAudit.check`: a `Layered` answer is compared, in {.canonical} form, with the table
|
|
33
|
+
# inverted whole, and a seed index with the seed inverted again. While an audit recomputation runs
|
|
34
|
+
# ({MemoAudit.suspended?}) the three are neither read nor written, so it inverts every table whole.
|
|
35
|
+
LAYERS = TypingState.memo(
|
|
36
|
+
:definers_index_layers,
|
|
37
|
+
run_scoped: true, audit: "definers index layers",
|
|
38
|
+
reason: "the seed each of the last two merged tables was built over; keyed on table identity"
|
|
39
|
+
)
|
|
40
|
+
SEED_INDEX = TypingState.memo(
|
|
41
|
+
:definers_index_seed,
|
|
42
|
+
run_scoped: true, audit: "definers index seed",
|
|
43
|
+
reason: "pure function of the seed table it keys on"
|
|
44
|
+
)
|
|
45
|
+
SEED_INDEX_ALT = TypingState.memo(
|
|
46
|
+
:definers_index_seed_alt,
|
|
47
|
+
run_scoped: true, audit: "definers index seed alt",
|
|
48
|
+
reason: "pure function of the seed table it keys on"
|
|
49
|
+
)
|
|
50
|
+
private_constant :LAYERS, :SEED_INDEX, :SEED_INDEX_ALT
|
|
30
51
|
|
|
31
52
|
# A name's owners: the seed's, less the owners the file replaced, plus the replaced owners' own.
|
|
32
53
|
class Layered
|
|
@@ -46,6 +67,9 @@ module Rigor
|
|
|
46
67
|
owners = from_file.nil? ? from_seed : (from_seed || []) + from_file
|
|
47
68
|
@answers[method_name] = owners.nil? || owners.empty? ? nil : owners
|
|
48
69
|
end
|
|
70
|
+
|
|
71
|
+
# Every name some owner may define, for {DefinersIndex.canonical}.
|
|
72
|
+
def names = @seed_index.keys | @replaced_index.keys
|
|
49
73
|
end
|
|
50
74
|
|
|
51
75
|
module_function
|
|
@@ -53,13 +77,18 @@ module Rigor
|
|
|
53
77
|
# Records that the final `merged` table was built over `seed`. The last two are kept (a file merges an
|
|
54
78
|
# instance and a singleton table), replaced rather than accumulated.
|
|
55
79
|
def record_layers(merged, seed)
|
|
56
|
-
|
|
57
|
-
|
|
80
|
+
return if MemoAudit.enabled? && MemoAudit.suspended?
|
|
81
|
+
|
|
82
|
+
state = TypingState.current
|
|
83
|
+
previous = state[LAYERS]
|
|
84
|
+
state[LAYERS] = [[merged, seed], previous&.first].compact
|
|
58
85
|
end
|
|
59
86
|
|
|
60
87
|
# The definers index over `table`.
|
|
61
88
|
def for(table)
|
|
62
|
-
|
|
89
|
+
return build(table) if MemoAudit.suspended?
|
|
90
|
+
|
|
91
|
+
seed = TypingState.current[LAYERS]&.find { |entry| entry[0].equal?(table) }&.last
|
|
63
92
|
return build(table) if seed.nil? || !deeply_frozen?(seed)
|
|
64
93
|
|
|
65
94
|
replaced = {}
|
|
@@ -73,7 +102,25 @@ module Rigor
|
|
|
73
102
|
end
|
|
74
103
|
return build(table) unless kept + replaced.count { |owner, _| seed.key?(owner) } == seed.size
|
|
75
104
|
|
|
76
|
-
Layered.new(seed_index(seed), replaced, build(replaced))
|
|
105
|
+
audit_layered(Layered.new(seed_index(seed), replaced, build(replaced)), table)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# `index`, after checking it against `table` inverted whole when the audit is on.
|
|
109
|
+
def audit_layered(index, table)
|
|
110
|
+
return index unless MemoAudit.enabled?
|
|
111
|
+
|
|
112
|
+
MemoAudit.check("definers index layers", canonical(index), table.size) { canonical(build(table)) }
|
|
113
|
+
index
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# `index` as a plain `name → sorted owners` Hash, so a `Layered` index and a whole one compare equal when they
|
|
117
|
+
# hold the same owners. Audit-only: it reads every name.
|
|
118
|
+
def canonical(index)
|
|
119
|
+
names = index.is_a?(Layered) ? index.names : index.keys
|
|
120
|
+
names.each_with_object({}) do |name, out|
|
|
121
|
+
owners = index[name]
|
|
122
|
+
out[name] = owners.sort if owners
|
|
123
|
+
end
|
|
77
124
|
end
|
|
78
125
|
|
|
79
126
|
def deeply_frozen?(seed)
|
|
@@ -82,13 +129,22 @@ module Rigor
|
|
|
82
129
|
|
|
83
130
|
# The seed's index, built once per seed table. Two ways, an instance and a singleton seed table.
|
|
84
131
|
def seed_index(seed)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
132
|
+
state = TypingState.current
|
|
133
|
+
slot = state[SEED_INDEX]
|
|
134
|
+
if slot && slot[0].equal?(seed)
|
|
135
|
+
return MemoAudit.check("definers index seed", slot[1], seed.size) do
|
|
136
|
+
build(seed)
|
|
137
|
+
end
|
|
88
138
|
end
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
139
|
+
|
|
140
|
+
slot = state[SEED_INDEX_ALT]
|
|
141
|
+
if slot && slot[0].equal?(seed)
|
|
142
|
+
return MemoAudit.check("definers index seed alt", slot[1], seed.size) { build(seed) }
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
index = MemoAudit.key_audit("definers index seed") { build(seed) }
|
|
146
|
+
state[SEED_INDEX_ALT] = state[SEED_INDEX]
|
|
147
|
+
state[SEED_INDEX] = [seed, index]
|
|
92
148
|
index
|
|
93
149
|
end
|
|
94
150
|
|
|
@@ -37,6 +37,22 @@ module Rigor
|
|
|
37
37
|
|
|
38
38
|
module_function
|
|
39
39
|
|
|
40
|
+
# The exception instance type a `RescueNode` binds its reference to: `StandardError` for a bare `rescue`, else
|
|
41
|
+
# the union over the named exceptions, each the instance of the class the block types it as (`yield`ed the
|
|
42
|
+
# exception node) or `Dynamic[top]` when that is not a `Singleton` (a splat list, an unresolved constant).
|
|
43
|
+
# Shared by `StatementEvaluator#rescue_exception_type` and the class-ivar census (issue #1217), so the two
|
|
44
|
+
# agree.
|
|
45
|
+
def rescue_exception_type(rescue_node)
|
|
46
|
+
exceptions = rescue_node.exceptions
|
|
47
|
+
return Type::Combinator.nominal_of("StandardError") if exceptions.empty?
|
|
48
|
+
|
|
49
|
+
types = exceptions.map do |exception_node|
|
|
50
|
+
type = yield(exception_node)
|
|
51
|
+
type.is_a?(Type::Singleton) ? Type::Combinator.nominal_of(type.class_name) : Type::Combinator.untyped
|
|
52
|
+
end
|
|
53
|
+
Type::Combinator.union(*types)
|
|
54
|
+
end
|
|
55
|
+
|
|
40
56
|
# The scope a `rescue` clause, or a rescue modifier's fallback, runs from: `$!` bound to the exception it rescued
|
|
41
57
|
# and `$@` to that exception's backtrace, with `$?` unbound. `exception_type` is what `rescue … => e` binds `e` to
|
|
42
58
|
# (`StatementEvaluator#rescue_exception_type`): the union of the named classes' instances, `StandardError` for a
|