rigortype 0.3.8 → 0.4.0
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 +2 -2
- data/data/capability_roles/capability_roles.rbs +36 -0
- data/data/core_overlay/enumerable.rbs +51 -0
- data/data/core_overlay/enumerator.rbs +84 -0
- data/data/core_overlay/hash_rbs3.rbs +41 -0
- data/data/core_overlay/process.rbs +40 -0
- data/data/core_overlay/string_io.rbs +33 -0
- data/data/effects/core.yml +3 -3
- data/data/gem_overlay/activesupport/core_ext.rbs +236 -17
- data/docs/handbook/02-everyday-types.md +17 -14
- data/docs/handbook/03-narrowing.md +132 -14
- data/docs/handbook/04-tuples-and-shapes.md +8 -6
- data/docs/handbook/05-methods-and-blocks.md +1 -1
- data/docs/handbook/06-classes.md +2 -2
- data/docs/handbook/07-rbs-and-extended.md +19 -1
- data/docs/handbook/10-sorbet.md +9 -10
- data/docs/handbook/11-sig-gen.md +525 -13
- data/docs/handbook/README.md +1 -1
- data/docs/handbook/appendix-elixir.md +2 -2
- data/docs/handbook/appendix-go.md +2 -2
- data/docs/handbook/appendix-java-csharp.md +2 -2
- data/docs/handbook/appendix-mypy.md +2 -2
- data/docs/handbook/appendix-phpstan.md +1 -1
- data/docs/handbook/appendix-rust.md +1 -1
- data/docs/handbook/appendix-type-theory.md +4 -4
- data/docs/handbook/appendix-typescript.md +1 -1
- data/docs/llms.txt +2 -0
- data/docs/manual/02-cli-reference.md +95 -6
- data/docs/manual/03-configuration.md +18 -0
- data/docs/manual/04-diagnostics.md +15 -0
- data/docs/manual/07-plugins.md +15 -5
- data/docs/manual/08-skills.md +23 -2
- data/docs/manual/10-mcp-server.md +3 -2
- data/docs/manual/11-ci.md +9 -0
- data/docs/manual/15-type-protection-coverage.md +8 -0
- data/docs/manual/16-rbs-extended-annotations.md +46 -8
- data/docs/manual/18-removing-dead-code.md +10 -8
- data/docs/manual/19-effect-labels.md +10 -0
- data/docs/manual/plugins/README.md +7 -0
- data/docs/manual/plugins/rigor-actioncable.md +8 -1
- data/docs/manual/plugins/rigor-actionmailer.md +7 -0
- data/docs/manual/plugins/rigor-actionpack.md +261 -0
- data/docs/manual/plugins/rigor-active-model-serializers.md +153 -0
- data/docs/manual/plugins/rigor-activejob.md +7 -0
- data/docs/manual/plugins/rigor-activerecord.md +138 -4
- data/docs/manual/plugins/rigor-activestorage.md +8 -1
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +43 -7
- data/docs/manual/plugins/rigor-grape.md +106 -0
- data/docs/manual/plugins/rigor-graphql.md +23 -2
- data/docs/manual/plugins/rigor-pundit.md +8 -1
- data/docs/manual/plugins/rigor-rails-i18n.md +10 -5
- data/docs/manual/plugins/rigor-rails-routes.md +7 -0
- data/docs/manual/plugins/rigor-rbs-inline.md +229 -1
- data/docs/manual/plugins/rigor-sidekiq.md +8 -1
- data/docs/manual/plugins/rigor-sorbet.md +21 -5
- data/exe/rigor +19 -4
- data/lib/rigor/analysis/baseline.rb +3 -3
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules/dead_version_guard_arms.rb +1 -5
- data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +167 -2
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +10 -2
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +189 -0
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +6 -4
- data/lib/rigor/analysis/check_rules/published_constant_guard.rb +15 -6
- data/lib/rigor/analysis/check_rules/rule_ids.rb +21 -6
- data/lib/rigor/analysis/check_rules/rule_walk.rb +41 -5
- data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +1 -1
- data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +1 -1
- data/lib/rigor/analysis/check_rules/source_arity.rb +323 -0
- data/lib/rigor/analysis/check_rules/special_global_setters.rb +146 -0
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +38 -4
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +0 -1
- data/lib/rigor/analysis/check_rules.rb +718 -79
- data/lib/rigor/analysis/crash_signature.rb +8 -24
- data/lib/rigor/analysis/dependency_recorder.rb +23 -0
- data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +1 -1
- data/lib/rigor/analysis/dependency_source_inference/builder.rb +0 -2
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +0 -2
- data/lib/rigor/analysis/dependency_source_inference/index.rb +5 -5
- data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +1 -2
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +4 -4
- data/lib/rigor/analysis/effects_cache_probe.rb +3 -4
- data/lib/rigor/analysis/erb_template_detector.rb +1 -2
- data/lib/rigor/analysis/fact_store.rb +15 -1
- data/lib/rigor/analysis/incremental.rb +42 -0
- data/lib/rigor/analysis/incremental_session.rb +117 -26
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +0 -1
- data/lib/rigor/analysis/project_scan.rb +11 -1
- data/lib/rigor/analysis/reachability/graph.rb +3 -5
- data/lib/rigor/analysis/reachability/plugin_roots.rb +5 -5
- data/lib/rigor/analysis/reachability/project_files.rb +2 -2
- data/lib/rigor/analysis/reachability/scan.rb +5 -5
- data/lib/rigor/analysis/reachability/scan_cache.rb +3 -2
- data/lib/rigor/analysis/reachability/signature_scan.rb +2 -2
- data/lib/rigor/analysis/result.rb +1 -3
- data/lib/rigor/analysis/rule_catalog.rb +131 -1
- data/lib/rigor/analysis/run_cache_key.rb +21 -12
- data/lib/rigor/analysis/run_cache_probe.rb +3 -5
- data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +6 -8
- data/lib/rigor/analysis/runner/declaration_position.rb +1 -2
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +340 -33
- data/lib/rigor/analysis/runner/effect_annotation_residual_pass.rb +2 -3
- data/lib/rigor/analysis/runner/effect_envelope_pass.rb +18 -14
- data/lib/rigor/analysis/runner/pool_coordinator.rb +357 -97
- data/lib/rigor/analysis/runner/project_pre_passes.rb +38 -13
- data/lib/rigor/analysis/runner/run_snapshots.rb +6 -1
- data/lib/rigor/analysis/runner.rb +407 -51
- data/lib/rigor/analysis/template_unit_collector.rb +303 -0
- data/lib/rigor/analysis/template_unit_paths.rb +91 -0
- data/lib/rigor/analysis/template_unit_positions.rb +293 -0
- data/lib/rigor/analysis/template_units.rb +399 -0
- data/lib/rigor/analysis/worker_session.rb +62 -20
- data/lib/rigor/bleeding_edge.rb +10 -24
- data/lib/rigor/builtins/hkt_builtins.rb +3 -2
- data/lib/rigor/builtins/imported_refinements.rb +159 -21
- data/lib/rigor/builtins/predefined_constant_refinements.rb +5 -7
- data/lib/rigor/builtins/regex_refinement.rb +21 -13
- data/lib/rigor/builtins/static_return_refinements.rb +7 -6
- data/lib/rigor/cache/annotation_location.rb +2 -4
- data/lib/rigor/cache/descriptor.rb +63 -20
- data/lib/rigor/cache/engine_source.rb +33 -5
- data/lib/rigor/cache/file_digest.rb +9 -1
- data/lib/rigor/cache/incremental_snapshot.rb +72 -6
- data/lib/rigor/cache/rbs_cache_producer.rb +4 -0
- data/lib/rigor/cache/rbs_class_ancestor_table.rb +0 -3
- data/lib/rigor/cache/rbs_class_type_param_names.rb +0 -3
- data/lib/rigor/cache/rbs_constant_table.rb +0 -3
- data/lib/rigor/cache/rbs_descriptor.rb +112 -14
- data/lib/rigor/cache/rbs_environment.rb +8 -4
- data/lib/rigor/cache/rbs_known_class_names.rb +0 -3
- data/lib/rigor/cache/store.rb +76 -32
- data/lib/rigor/ci_detector.rb +1 -0
- data/lib/rigor/cli/annotate_command.rb +5 -6
- data/lib/rigor/cli/check_command.rb +57 -10
- data/lib/rigor/cli/check_invocation.rb +6 -11
- data/lib/rigor/cli/check_runner_factory.rb +1 -5
- data/lib/rigor/cli/coverage_command.rb +1 -1
- data/lib/rigor/cli/coverage_mutation.rb +12 -3
- data/lib/rigor/cli/coverage_scan.rb +1 -5
- data/lib/rigor/cli/diff_command.rb +1 -1
- data/lib/rigor/cli/doc_links.rb +4 -4
- data/lib/rigor/cli/docs_command.rb +6 -6
- data/lib/rigor/cli/doctor_command.rb +85 -38
- data/lib/rigor/cli/effects_command.rb +2 -2
- data/lib/rigor/cli/effects_diff_renderer.rb +3 -3
- data/lib/rigor/cli/effects_snapshot_command.rb +1 -1
- data/lib/rigor/cli/explain_command.rb +34 -1
- data/lib/rigor/cli/fused_protection_report.rb +7 -1
- data/lib/rigor/cli/lsp_command.rb +1 -1
- data/lib/rigor/cli/mcp_command.rb +1 -1
- data/lib/rigor/cli/measurement_integrity_warning.rb +4 -5
- data/lib/rigor/cli/mutation_fork_scan.rb +6 -6
- data/lib/rigor/cli/mutation_protection_report.rb +7 -1
- data/lib/rigor/cli/plugin_command.rb +4 -4
- data/lib/rigor/cli/plugins_command.rb +2 -1
- data/lib/rigor/cli/prism_colorizer.rb +1 -2
- data/lib/rigor/cli/protection_fork_scan.rb +6 -6
- data/lib/rigor/cli/show_bleedingedge_command.rb +1 -1
- data/lib/rigor/cli/sig_gen_command.rb +212 -31
- data/lib/rigor/cli/skill_command.rb +2 -2
- data/lib/rigor/cli/skill_deep_probe.rb +4 -4
- data/lib/rigor/cli/skill_describe.rb +35 -35
- data/lib/rigor/cli/trace_command.rb +4 -4
- data/lib/rigor/cli/trace_renderer.rb +5 -6
- data/lib/rigor/cli/triage_command.rb +1 -1
- data/lib/rigor/cli/type_of_command.rb +29 -11
- data/lib/rigor/cli/type_of_renderer.rb +20 -9
- data/lib/rigor/cli/type_of_template_probe.rb +189 -0
- data/lib/rigor/cli/type_scan_command.rb +4 -4
- data/lib/rigor/cli/unused_command.rb +11 -3
- data/lib/rigor/cli/upgrade_command.rb +1 -1
- data/lib/rigor/cli.rb +89 -9
- data/lib/rigor/config_audit.rb +30 -5
- data/lib/rigor/configuration/severity_profile.rb +25 -9
- data/lib/rigor/configuration.rb +109 -7
- data/lib/rigor/effects/ancestry_recorder.rb +191 -0
- data/lib/rigor/effects/attribution.rb +12 -5
- data/lib/rigor/effects/callee_rule.rb +368 -0
- data/lib/rigor/effects/catalog.rb +7 -4
- data/lib/rigor/effects/collector.rb +11 -5
- data/lib/rigor/effects/config_envelopes.rb +15 -10
- data/lib/rigor/effects/definition_context.rb +179 -0
- data/lib/rigor/effects/definition_lines.rb +25 -6
- data/lib/rigor/effects/effect_table.rb +11 -4
- data/lib/rigor/effects/entry_points.rb +0 -2
- data/lib/rigor/effects/envelope_check.rb +9 -9
- data/lib/rigor/effects/envelope_index.rb +20 -8
- data/lib/rigor/effects/file_collection.rb +59 -5
- data/lib/rigor/effects/framework_units.rb +5 -7
- data/lib/rigor/effects/identity.rb +20 -6
- data/lib/rigor/effects/inline_anchor.rb +7 -7
- data/lib/rigor/effects/label_intent.rb +3 -4
- data/lib/rigor/effects/liskov_check.rb +8 -8
- data/lib/rigor/effects/local_ownership.rb +38 -12
- data/lib/rigor/effects/method_key.rb +22 -1
- data/lib/rigor/effects/mutation_classifier.rb +23 -12
- data/lib/rigor/effects/plugin_facts.rb +47 -37
- data/lib/rigor/effects/propagator.rb +297 -19
- data/lib/rigor/effects/registry.rb +1 -1
- data/lib/rigor/effects/scanner.rb +122 -73
- data/lib/rigor/effects/signature_sources.rb +4 -6
- data/lib/rigor/effects/snapshot.rb +12 -11
- data/lib/rigor/effects/snapshot_diff.rb +1 -1
- data/lib/rigor/effects/summary.rb +27 -4
- data/lib/rigor/effects/unit_scan.rb +393 -38
- data/lib/rigor/effects/unknown_label_check.rb +3 -8
- data/lib/rigor/effects/unknown_label_report.rb +3 -4
- data/lib/rigor/effects/visibility.rb +101 -0
- data/lib/rigor/environment/bundle_sig_discovery.rb +6 -6
- data/lib/rigor/environment/class_registry.rb +3 -1
- data/lib/rigor/environment/failure_slot.rb +2 -2
- data/lib/rigor/environment/installed_gem_set.rb +85 -0
- data/lib/rigor/environment/lockfile_resolver.rb +68 -4
- data/lib/rigor/environment/member_consistency/comparator.rb +708 -0
- data/lib/rigor/environment/member_consistency.rb +298 -0
- data/lib/rigor/environment/missing_gem_constant_index.rb +4 -4
- data/lib/rigor/environment/rbs_collection_discovery.rb +5 -5
- data/lib/rigor/environment/rbs_coverage_report.rb +5 -5
- data/lib/rigor/environment/rbs_hierarchy.rb +3 -1
- data/lib/rigor/environment/rbs_loader.rb +674 -79
- data/lib/rigor/environment.rb +174 -24
- data/lib/rigor/flow_contribution/merger.rb +0 -2
- data/lib/rigor/flow_contribution.rb +11 -13
- data/lib/rigor/hashing/xxh3.rb +264 -0
- data/lib/rigor/inference/acceptance.rb +292 -17
- data/lib/rigor/inference/block_auto_splat.rb +216 -0
- data/lib/rigor/inference/block_call_timing.rb +338 -0
- data/lib/rigor/inference/block_parameter_binder.rb +75 -30
- data/lib/rigor/inference/block_repetition.rb +71 -0
- data/lib/rigor/inference/body_fixpoint.rb +7 -6
- data/lib/rigor/inference/budget_trace.rb +3 -6
- data/lib/rigor/inference/builtins/method_catalog.rb +2 -1
- data/lib/rigor/inference/builtins/string_catalog.rb +1 -1
- data/lib/rigor/inference/captured_locals.rb +389 -18
- data/lib/rigor/inference/closure_escape_analyzer.rb +159 -17
- data/lib/rigor/inference/content_join.rb +200 -27
- data/lib/rigor/inference/coverage_scanner.rb +4 -6
- data/lib/rigor/inference/def_return_typer.rb +11 -7
- data/lib/rigor/inference/define_method_block_self.rb +64 -0
- data/lib/rigor/inference/dynamic_origin.rb +1 -1
- data/lib/rigor/inference/element_read_widening.rb +180 -0
- data/lib/rigor/inference/error_info.rb +196 -0
- data/lib/rigor/inference/expression_typer.rb +2124 -468
- data/lib/rigor/inference/external_ancestor_resolution.rb +267 -0
- data/lib/rigor/inference/fork_map.rb +5 -7
- data/lib/rigor/inference/fresh_frame_blocks.rb +127 -0
- data/lib/rigor/inference/global_write_census.rb +239 -0
- data/lib/rigor/inference/guard_rebinding.rb +447 -0
- data/lib/rigor/inference/hash_lookup_mutation.rb +88 -0
- data/lib/rigor/inference/hkt_reducer.rb +2 -3
- data/lib/rigor/inference/hkt_registry.rb +4 -7
- data/lib/rigor/inference/index_write_widening.rb +16 -7
- data/lib/rigor/inference/indexed_narrowing.rb +61 -9
- data/lib/rigor/inference/jump_targets.rb +82 -0
- data/lib/rigor/inference/last_line/implicit_self.rb +210 -0
- data/lib/rigor/inference/last_line/self_evidence.rb +329 -0
- data/lib/rigor/inference/last_line.rb +340 -0
- data/lib/rigor/inference/last_status.rb +144 -0
- data/lib/rigor/inference/macro_block_self_type.rb +168 -21
- data/lib/rigor/inference/match_rebinding/calls.rb +281 -0
- data/lib/rigor/inference/match_rebinding/frame.rb +148 -0
- data/lib/rigor/inference/match_rebinding/operands.rb +236 -0
- data/lib/rigor/inference/match_rebinding/self_calls.rb +83 -0
- data/lib/rigor/inference/match_rebinding.rb +392 -0
- data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +36 -0
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +87 -33
- data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +305 -19
- data/lib/rigor/inference/method_dispatcher/data_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +147 -0
- data/lib/rigor/inference/method_dispatcher/file_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/hash_transform_keys_folding.rb +191 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +6 -2
- data/lib/rigor/inference/method_dispatcher/json_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +7 -1
- data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +159 -0
- data/lib/rigor/inference/method_dispatcher/math_folding.rb +41 -3
- data/lib/rigor/inference/method_dispatcher/method_folding.rb +2 -5
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +165 -111
- data/lib/rigor/inference/method_dispatcher/process_folding.rb +56 -0
- data/lib/rigor/inference/method_dispatcher/proven_overload.rb +72 -0
- data/lib/rigor/inference/method_dispatcher/random_folding.rb +82 -0
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +1046 -69
- data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +25 -4
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +2 -8
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/self_substitute.rb +142 -0
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +129 -54
- data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/singleton_mixin_dispatch.rb +1 -2
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +5 -6
- data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +85 -4
- data/lib/rigor/inference/method_dispatcher/time_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/universal_object_dispatch.rb +1 -2
- data/lib/rigor/inference/method_dispatcher/uri_folding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher.rb +225 -25
- data/lib/rigor/inference/method_parameter_binder.rb +12 -9
- data/lib/rigor/inference/multi_target_binder.rb +341 -55
- data/lib/rigor/inference/mutation_rejoin.rb +171 -0
- data/lib/rigor/inference/mutation_widening.rb +156 -85
- data/lib/rigor/inference/narrowing.rb +835 -162
- data/lib/rigor/inference/operand_effects.rb +167 -0
- data/lib/rigor/inference/operand_walk.rb +88 -0
- data/lib/rigor/inference/optimistic_origin.rb +153 -16
- data/lib/rigor/inference/origin_lookup.rb +2 -3
- data/lib/rigor/inference/parameter_inference_collector.rb +7 -7
- data/lib/rigor/inference/pre_eval_constants.rb +6 -5
- data/lib/rigor/inference/precision_scanner.rb +3 -4
- data/lib/rigor/inference/project_method_ownership.rb +136 -0
- data/lib/rigor/inference/project_patched_methods.rb +9 -4
- data/lib/rigor/inference/project_patched_scanner.rb +10 -6
- data/lib/rigor/inference/protection_scanner.rb +1 -2
- data/lib/rigor/inference/range_constant.rb +57 -0
- data/lib/rigor/inference/rbs_type_translator.rb +49 -11
- data/lib/rigor/inference/receiver_alias.rb +93 -4
- data/lib/rigor/inference/receiver_blind_block.rb +219 -0
- data/lib/rigor/inference/refinement_mutation.rb +76 -0
- data/lib/rigor/inference/repeated_or_writes.rb +463 -0
- data/lib/rigor/inference/return_barrier.rb +54 -0
- data/lib/rigor/inference/rewrite_mutation.rb +120 -0
- data/lib/rigor/inference/scope_indexer.rb +5228 -627
- data/lib/rigor/inference/statement_evaluator.rb +3452 -595
- data/lib/rigor/inference/stored_block_call.rb +54 -0
- data/lib/rigor/inference/string_mutation.rb +97 -0
- data/lib/rigor/inference/struct_fold_safety.rb +6 -7
- data/lib/rigor/inference/synthetic_method_index.rb +1 -2
- data/lib/rigor/inference/synthetic_method_scanner.rb +4 -6
- data/lib/rigor/inference/unknown_store_widening.rb +200 -0
- data/lib/rigor/inference/unthreaded_rebinds.rb +282 -0
- data/lib/rigor/inference/version_guard.rb +28 -21
- data/lib/rigor/inference/void_origin.rb +3 -3
- data/lib/rigor/inference/void_tail_summary.rb +2 -4
- data/lib/rigor/language_server/buffer_table.rb +4 -4
- data/lib/rigor/language_server/completion_provider.rb +1 -1
- data/lib/rigor/language_server/debouncer.rb +0 -1
- data/lib/rigor/language_server/diagnostic_publisher.rb +7 -6
- data/lib/rigor/language_server/document_symbol_provider.rb +1 -1
- data/lib/rigor/language_server/folding_range_provider.rb +1 -1
- data/lib/rigor/language_server/hover_provider.rb +1 -1
- data/lib/rigor/language_server/hover_renderer.rb +4 -4
- data/lib/rigor/language_server/incremental_sync.rb +6 -6
- data/lib/rigor/language_server/project_context.rb +7 -8
- data/lib/rigor/language_server/publish_batcher.rb +2 -2
- data/lib/rigor/language_server/selection_range_provider.rb +2 -2
- data/lib/rigor/language_server/server.rb +9 -9
- data/lib/rigor/language_server/signature_help_provider.rb +1 -1
- data/lib/rigor/language_server/uri.rb +1 -1
- data/lib/rigor/mcp/server.rb +2 -1
- data/lib/rigor/plugin/base.rb +258 -26
- data/lib/rigor/plugin/box_probe.rb +91 -0
- data/lib/rigor/plugin/bundled_catalog.rb +167 -0
- data/lib/rigor/plugin/effect_attribution.rb +65 -11
- data/lib/rigor/plugin/effect_entry_points.rb +3 -3
- data/lib/rigor/plugin/fact_store.rb +6 -6
- data/lib/rigor/plugin/io_boundary.rb +93 -8
- data/lib/rigor/plugin/isolation.rb +29 -6
- data/lib/rigor/plugin/loader.rb +33 -13
- data/lib/rigor/plugin/macro/block_as_method.rb +45 -6
- data/lib/rigor/plugin/macro/heredoc_template.rb +1 -1
- data/lib/rigor/plugin/macro/trait_registry.rb +1 -1
- data/lib/rigor/plugin/manifest.rb +94 -11
- data/lib/rigor/plugin/registry.rb +76 -12
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +21 -4
- data/lib/rigor/plugin/template_unit.rb +196 -0
- data/lib/rigor/plugin/trust_policy.rb +2 -4
- data/lib/rigor/plugin/type_node_resolver.rb +3 -3
- data/lib/rigor/plugin.rb +1 -0
- data/lib/rigor/plugin_gap_advisory.rb +96 -0
- data/lib/rigor/project_environment.rb +138 -0
- data/lib/rigor/protection/analysis_guard.rb +93 -14
- data/lib/rigor/protection/closure_kill_oracle.rb +67 -23
- data/lib/rigor/protection/dependency_closure.rb +5 -8
- data/lib/rigor/protection/diagnostic_oracle.rb +2 -2
- data/lib/rigor/protection/discovery_seed.rb +14 -12
- data/lib/rigor/protection/kill_signature.rb +1 -4
- data/lib/rigor/protection/measurement_integrity.rb +1 -3
- data/lib/rigor/protection/mutation_cache.rb +7 -11
- data/lib/rigor/protection/mutation_scanner.rb +12 -15
- data/lib/rigor/protection/mutator.rb +2 -1
- data/lib/rigor/protection/test_suite_oracle.rb +5 -5
- data/lib/rigor/rbs_extended/conformance_checker.rb +4 -3
- data/lib/rigor/rbs_extended/envelope_scanner.rb +4 -6
- data/lib/rigor/rbs_extended/reporter.rb +36 -10
- data/lib/rigor/rbs_extended.rb +88 -21
- data/lib/rigor/reflection/constant_ancestors.rb +97 -0
- data/lib/rigor/reflection/constant_path.rb +139 -0
- data/lib/rigor/reflection.rb +93 -110
- data/lib/rigor/runtime/jit.rb +6 -8
- data/lib/rigor/scope/discovery_index.rb +165 -2
- data/lib/rigor/scope.rb +1041 -32
- data/lib/rigor/sig_gen/alias_index.rb +289 -0
- data/lib/rigor/sig_gen/classification.rb +22 -5
- data/lib/rigor/sig_gen/declaration_equivalence.rb +127 -0
- data/lib/rigor/sig_gen/effect_annotation.rb +202 -0
- data/lib/rigor/sig_gen/generator.rb +673 -53
- data/lib/rigor/sig_gen/inline_declarations.rb +184 -0
- data/lib/rigor/sig_gen/layout_index.rb +3 -4
- data/lib/rigor/sig_gen/meta_class_shape.rb +3 -5
- data/lib/rigor/sig_gen/method_candidate.rb +47 -3
- data/lib/rigor/sig_gen/observation_collector.rb +18 -16
- data/lib/rigor/sig_gen/path_mapper.rb +4 -6
- data/lib/rigor/sig_gen/rbs_validity.rb +4 -4
- data/lib/rigor/sig_gen/renderer.rb +128 -14
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +154 -0
- data/lib/rigor/sig_gen/superclass_spelling.rb +27 -0
- data/lib/rigor/sig_gen/type_elaborator.rb +1 -3
- data/lib/rigor/sig_gen/write_result.rb +19 -3
- data/lib/rigor/sig_gen/writer.rb +189 -41
- data/lib/rigor/sig_gen.rb +3 -0
- data/lib/rigor/signature_path_audit.rb +153 -6
- data/lib/rigor/source/literals.rb +0 -23
- data/lib/rigor/source/node_children.rb +0 -2
- data/lib/rigor/source/node_locator.rb +5 -11
- data/lib/rigor/source/node_walker.rb +0 -6
- data/lib/rigor/source/parameter_envelope.rb +72 -0
- data/lib/rigor/source.rb +1 -0
- data/lib/rigor/triage/catalogue.rb +1 -3
- data/lib/rigor/triage.rb +3 -5
- data/lib/rigor/type/accepts_result.rb +24 -6
- data/lib/rigor/type/combinator.rb +144 -5
- data/lib/rigor/type/data_class.rb +2 -2
- data/lib/rigor/type/data_instance.rb +4 -4
- data/lib/rigor/type/difference.rb +1 -0
- data/lib/rigor/type/float_range.rb +128 -0
- data/lib/rigor/type/hash_shape.rb +6 -6
- data/lib/rigor/type/integer_range.rb +13 -8
- data/lib/rigor/type/nominal.rb +8 -2
- data/lib/rigor/type/refined.rb +4 -3
- data/lib/rigor/type/struct_class.rb +3 -3
- data/lib/rigor/type/struct_instance.rb +4 -4
- data/lib/rigor/type.rb +1 -0
- data/lib/rigor/type_node/generic.rb +1 -1
- data/lib/rigor/type_node/range_literal.rb +25 -0
- data/lib/rigor/type_node/resolver_chain.rb +1 -1
- data/lib/rigor/type_node.rb +1 -0
- data/lib/rigor/version.rb +1 -1
- data/lib/rigor.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +0 -4
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +0 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +0 -2
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/effects.rb +1 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +10 -5
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +0 -4
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +3 -5
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +1 -4
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +14 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +32 -30
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +0 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +1 -3
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_scan.rb +96 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/effects.rb +65 -8
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/erb_compiler.rb +270 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/render_locals.rb +402 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +370 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_units.rb +132 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +264 -3
- data/plugins/rigor-actionpack/sig/action_controller.rbs +71 -0
- data/plugins/rigor-actionpack/sig/action_view.rbs +43 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_discoverer.rb +220 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_index.rb +56 -0
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +263 -0
- data/plugins/rigor-active-model-serializers/lib/rigor-active-model-serializers.rb +7 -0
- data/plugins/rigor-active-model-serializers/sig/active_model_serializers.rbs +45 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +0 -4
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/effects.rb +2 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +0 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +0 -2
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/recurring_scan.rb +1 -1
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +10 -5
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +35 -3
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/effects.rb +72 -12
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +383 -7
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +14 -6
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +1 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +1 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +322 -41
- data/plugins/rigor-activerecord/sig/active_record/framework.rbs +123 -0
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +206 -31
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +26 -14
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext/effects.rb +9 -2
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +9 -2
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +290 -19
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +1 -0
- data/plugins/rigor-dry-monads/lib/rigor/plugin/dry_monads.rb +3 -0
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +9 -7
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +7 -3
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +1 -0
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +8 -6
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +11 -7
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -11
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +9 -4
- data/plugins/rigor-ethon/lib/rigor/plugin/ethon.rb +2 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +0 -5
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +0 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +8 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/types.rb +1 -1
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +36 -4
- data/plugins/rigor-ffi-rzmq/lib/rigor/plugin/ffi_rzmq.rb +1 -0
- data/plugins/rigor-grape/lib/rigor/plugin/grape.rb +141 -0
- data/plugins/rigor-grape/lib/rigor-grape.rb +6 -0
- data/plugins/rigor-grape/sig/grape.rbs +263 -0
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +8 -6
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +78 -5
- data/plugins/rigor-graphql/sig/graphql.rbs +485 -0
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +1 -0
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +2 -1
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +2 -3
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +1 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +0 -5
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/authorization_scan.rb +2 -2
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +0 -1
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +0 -1
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +12 -7
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +0 -12
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +1 -3
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +0 -1
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +36 -37
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/acronyms.rb +5 -5
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +0 -10
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +5 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +3 -2
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +2 -2
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +2 -2
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +9 -10
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +2 -3
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +10 -17
- data/plugins/rigor-railties/lib/rigor/plugin/railties.rb +1 -0
- data/plugins/rigor-rbnacl/lib/rigor/plugin/rbnacl.rb +13 -1
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline/same_line_annotations.rb +149 -0
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +324 -18
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +0 -3
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +0 -3
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +1 -5
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +2 -3
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +1 -0
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +0 -3
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +1 -0
- data/plugins/rigor-sassc/lib/rigor/plugin/sassc.rb +1 -0
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +1 -9
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +1 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +0 -4
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/effects.rb +1 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/schedule_scan.rb +2 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +0 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +0 -2
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +10 -5
- data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +1 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +2 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +1 -4
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +3 -9
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +4 -4
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +1 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +3 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +7 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +51 -6
- data/plugins/rigor-sorbet/sig/sorbet.rbs +277 -0
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +1 -0
- data/sig/rigor/analysis/baseline.rbs +69 -7
- data/sig/rigor/analysis/fact_store.rbs +1 -1
- data/sig/rigor/analysis/project_scan.rbs +74 -0
- data/sig/rigor/analysis/reachability/scan_cache.rbs +12 -0
- data/sig/rigor/cache.rbs +2 -3
- data/sig/rigor/effects/config_envelopes.rbs +100 -0
- data/sig/rigor/effects/effect_table.rbs +60 -0
- data/sig/rigor/effects/envelope.rbs +97 -0
- data/sig/rigor/effects/envelope_index.rbs +33 -0
- data/sig/rigor/effects/file_collection.rbs +81 -0
- data/sig/rigor/effects/label.rbs +26 -0
- data/sig/rigor/effects/label_set.rbs +46 -0
- data/sig/rigor/effects/method_key.rbs +24 -0
- data/sig/rigor/effects/origin.rbs +50 -0
- data/sig/rigor/effects/plugin_facts.rbs +141 -0
- data/sig/rigor/effects/registry.rbs +68 -0
- data/sig/rigor/effects/summary.rbs +50 -0
- data/sig/rigor/effects/taint_cause.rbs +12 -0
- data/sig/rigor/environment.rbs +17 -10
- data/sig/rigor/inference/optimistic_origin.rbs +10 -0
- data/sig/rigor/inference.rbs +9 -14
- data/sig/rigor/plugin/additional_initializer.rbs +36 -0
- data/sig/rigor/plugin/base.rbs +30 -7
- data/sig/rigor/plugin/effect_ancestry.rbs +27 -0
- data/sig/rigor/plugin/effect_attribution.rbs +66 -0
- data/sig/rigor/plugin/effect_edge.rbs +33 -0
- data/sig/rigor/plugin/effect_entry_points.rbs +25 -0
- data/sig/rigor/plugin/io_boundary.rbs +4 -0
- data/sig/rigor/plugin/loader.rbs +3 -3
- data/sig/rigor/plugin/manifest.rbs +51 -11
- data/sig/rigor/plugin/protocol_contract.rbs +68 -0
- data/sig/rigor/plugin/registry.rbs +62 -1
- data/sig/rigor/plugin.rbs +1 -1
- data/sig/rigor/rbs_extended.rbs +1 -1
- data/sig/rigor/reflection.rbs +9 -6
- data/sig/rigor/scope.rbs +148 -12
- data/sig/rigor/sig_gen/skip_reason_catalog.rbs +21 -0
- data/sig/rigor/source.rbs +4 -4
- data/sig/rigor/testing.rbs +10 -4
- data/sig/rigor/type.rbs +33 -1
- data/sig/rigor.rbs +39 -20
- data/skills/rigor-ask/SKILL.md +16 -11
- data/skills/rigor-baseline-reduce/SKILL.md +4 -6
- data/skills/rigor-ci-setup/SKILL.md +17 -21
- data/skills/rigor-doctor/SKILL.md +24 -22
- data/skills/rigor-doctor/references/01-checks.md +97 -33
- data/skills/rigor-editor-setup/SKILL.md +6 -4
- data/skills/rigor-mcp-setup/SKILL.md +5 -4
- data/skills/rigor-monkeypatch-resolve/SKILL.md +5 -3
- data/skills/rigor-next-steps/SKILL.md +4 -2
- data/skills/rigor-plugin-author/SKILL.md +19 -23
- data/skills/rigor-plugin-author/references/01-plan-and-scaffold.md +9 -8
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +25 -27
- data/skills/rigor-plugin-author/references/03-test-and-ship.md +6 -8
- data/skills/rigor-plugin-review/SKILL.md +6 -4
- data/skills/rigor-plugin-review/references/01-best-practices-checklist.md +2 -1
- data/skills/rigor-plugin-tune/SKILL.md +4 -2
- data/skills/rigor-project-init/SKILL.md +15 -10
- data/skills/rigor-project-init/references/01-detect.md +13 -9
- data/skills/rigor-project-init/references/02-configure.md +43 -14
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +14 -14
- data/skills/rigor-project-init/references/04-sig-uplift.md +27 -14
- data/skills/rigor-project-init/references/06-agent-contract.md +67 -0
- data/skills/rigor-protection-uplift/SKILL.md +4 -6
- data/skills/rigor-rbs-setup/SKILL.md +4 -2
- data/skills/rigor-type-oracle/SKILL.md +226 -0
- data/skills/rigor-type-oracle/references/01-oracle-commands.md +265 -0
- data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +52 -0
- data/skills/rigor-type-oracle/references/03-gap-protocol.md +125 -0
- data/skills/rigor-unused-adjudicate/SKILL.md +12 -7
- data/skills/rigor-upgrade/SKILL.md +13 -8
- metadata +133 -3
- data/lib/rigor/cli/probe_environment.rb +0 -85
- data/sig/rigor/inference/builtins/numeric_catalog.rbs +0 -3
|
@@ -5,7 +5,12 @@ require "prism"
|
|
|
5
5
|
require_relative "../type"
|
|
6
6
|
require_relative "../source/node_children"
|
|
7
7
|
require_relative "content_join"
|
|
8
|
+
require_relative "hash_lookup_mutation"
|
|
9
|
+
require_relative "mutation_rejoin"
|
|
8
10
|
require_relative "receiver_alias"
|
|
11
|
+
require_relative "refinement_mutation"
|
|
12
|
+
require_relative "rewrite_mutation"
|
|
13
|
+
require_relative "string_mutation"
|
|
9
14
|
|
|
10
15
|
module Rigor
|
|
11
16
|
module Inference
|
|
@@ -49,6 +54,8 @@ module Rigor
|
|
|
49
54
|
#
|
|
50
55
|
# - `arr.<mutator>(...)` where `arr` is a local variable.
|
|
51
56
|
# - `@arr.<mutator>(...)` where `@arr` is an instance variable.
|
|
57
|
+
# - `@@arr.<mutator>(...)` / `$arr.<mutator>(...)` where the receiver is a class variable or global, and
|
|
58
|
+
# `it.<mutator>(...)` on the Ruby 3.4 `it` parameter ({ReceiverAlias.mutated_reads}).
|
|
52
59
|
# - a receiver that *selects* among such variables rather than naming one —
|
|
53
60
|
# `(kind == :required ? required : optional)[key] = info`, an `if`/`else`, `||` / `&&`. Every
|
|
54
61
|
# variable the expression can evaluate to is a possible mutation target, so every one widens
|
|
@@ -86,19 +93,21 @@ module Rigor
|
|
|
86
93
|
].to_set.freeze
|
|
87
94
|
|
|
88
95
|
# Hash mutators that invalidate a `HashShape` carrier. Same principle as `ARRAY_MUTATORS`:
|
|
89
|
-
# only the receiver-mutating methods are listed.
|
|
96
|
+
# only the receiver-mutating methods are listed. A name both classes define is listed in
|
|
97
|
+
# both tables — being in `ARRAY_MUTATORS` does not put it here, and `shift`'s absence let
|
|
98
|
+
# `k = { a: 1 }; k.shift` keep the literal shape of a hash that is empty at runtime.
|
|
90
99
|
HASH_MUTATORS = %i[
|
|
91
100
|
[]= store
|
|
92
|
-
delete delete_if reject! select! filter! keep_if
|
|
101
|
+
shift delete delete_if reject! select! filter! keep_if
|
|
93
102
|
clear compact! merge! update transform_keys! transform_values!
|
|
94
103
|
replace
|
|
95
104
|
].to_set.freeze
|
|
96
105
|
|
|
97
106
|
# Every method name {#widen_for_mutator} responds to — the one set a body scan asks "could an
|
|
98
107
|
# in-place call on this name change its binding?" against (issue #587: the block-return
|
|
99
|
-
# threading gate). Derived from the
|
|
100
|
-
#
|
|
101
|
-
SHAPE_MUTATORS = (ARRAY_MUTATORS | HASH_MUTATORS).freeze
|
|
108
|
+
# threading gate). Derived from the tables rather than spelled out, so the scan and the
|
|
109
|
+
# widening it predicts cannot drift apart.
|
|
110
|
+
SHAPE_MUTATORS = (ARRAY_MUTATORS | HASH_MUTATORS | HashLookupMutation::MUTATORS | StringMutation::MUTATORS).freeze
|
|
102
111
|
|
|
103
112
|
# Methods that return the receiver (or a shallow copy) and cannot mutate it. They must not
|
|
104
113
|
# trigger widening or any other receiver-fact invalidation. The list is intentionally
|
|
@@ -110,9 +119,7 @@ module Rigor
|
|
|
110
119
|
|
|
111
120
|
# True when `method_name` is a pure self-returner that must
|
|
112
121
|
# not invalidate the receiver's facts.
|
|
113
|
-
def pure_self_returner?(method_name)
|
|
114
|
-
PURE_SELF_RETURNERS.include?(method_name)
|
|
115
|
-
end
|
|
122
|
+
def pure_self_returner?(method_name) = PURE_SELF_RETURNERS.include?(method_name)
|
|
116
123
|
|
|
117
124
|
# Returns a scope with the call's receiver widened, for every variable the receiver expression
|
|
118
125
|
# can evaluate to ({ReceiverAlias.candidates}) whose current binding is a literal-shape carrier
|
|
@@ -126,10 +133,6 @@ module Rigor
|
|
|
126
133
|
# pre-join behaviour exactly.
|
|
127
134
|
NO_ARG_TYPES = [].freeze
|
|
128
135
|
|
|
129
|
-
# @param call_node [Prism::CallNode]
|
|
130
|
-
# @param current_scope [Rigor::Scope]
|
|
131
|
-
# @param arg_types [Array<Rigor::Type::Base>]
|
|
132
|
-
# @return [Rigor::Scope]
|
|
133
136
|
def widen_after_call(call_node:, current_scope:, arg_types: NO_ARG_TYPES)
|
|
134
137
|
return current_scope if pure_self_returner?(call_node.name)
|
|
135
138
|
|
|
@@ -138,26 +141,43 @@ module Rigor
|
|
|
138
141
|
|
|
139
142
|
# True when `receiver` names at least one variable whose CURRENT binding is a literal-shape
|
|
140
143
|
# carrier — the only pre-state {#widen_for_mutator} joins into. Callers use it to skip typing a
|
|
141
|
-
# mutator's arguments when nothing will consume them
|
|
142
|
-
# already-nominal Array are the common cases, and `Scope#type_of` memoizes nothing.
|
|
144
|
+
# mutator's arguments when nothing will consume them, and `Scope#type_of` memoizes nothing.
|
|
143
145
|
def joinable_receiver?(receiver, scope)
|
|
144
146
|
return false if receiver.nil?
|
|
145
147
|
|
|
146
|
-
ReceiverAlias.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
when Prism::LocalVariableReadNode then scope.local(read.name)
|
|
150
|
-
when Prism::InstanceVariableReadNode then scope.ivar(read.name)
|
|
151
|
-
end
|
|
152
|
-
current.is_a?(Type::Tuple) || current.is_a?(Type::HashShape)
|
|
148
|
+
ReceiverAlias.mutated_reads(receiver).any? do |read|
|
|
149
|
+
getter, = ALIAS_ACCESSORS[read.class]
|
|
150
|
+
getter && shape_carrier?(scope.public_send(getter, ReceiverAlias.read_name(read)))
|
|
153
151
|
end
|
|
154
152
|
end
|
|
155
153
|
|
|
156
|
-
#
|
|
154
|
+
# A union carrying a shape member is joinable too (issue #645): {#widen_union} widens that
|
|
155
|
+
# member through the same join, so the arguments the caller would skip are the evidence it
|
|
156
|
+
# needs.
|
|
157
|
+
# A `Constant[String]` counts too since issue #617 residue (4): the gate exists to skip typing arguments
|
|
158
|
+
# nothing will consume, and this carrier IS consumed now — `buf << x` on a `+"ab"` rewrites the binding.
|
|
159
|
+
# An empty-witness `Difference` counts too (issue #936): the `non-empty-array[T]` arm joins the
|
|
160
|
+
# mutator's added element now, so its arguments are evidence this seam consumes rather than
|
|
161
|
+
# arguments nothing will read.
|
|
162
|
+
def shape_carrier?(type)
|
|
163
|
+
case type
|
|
164
|
+
when Type::Tuple, Type::HashShape then true
|
|
165
|
+
when Type::Constant then StringMutation.constant?(type)
|
|
166
|
+
# A re-openable nominal counts since issue #580: skipping it made the one-way door
|
|
167
|
+
# self-fulfilling, since the arm never saw the arg types it grows from.
|
|
168
|
+
when Type::Nominal then MutationRejoin.regrowable_carrier?(type)
|
|
169
|
+
when Type::Difference then type.removes_empty_witness?
|
|
170
|
+
when Type::Union then type.members.any? { |m| shape_carrier?(m) }
|
|
171
|
+
else false
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Widens every variable `receiver` can evaluate to ({ReceiverAlias.mutated_reads}), against `method_name`'s
|
|
176
|
+
# mutator table.
|
|
157
177
|
def widen_receiver_aliases(receiver, method_name, current_scope, arg_types: NO_ARG_TYPES)
|
|
158
178
|
return current_scope if receiver.nil?
|
|
159
179
|
|
|
160
|
-
ReceiverAlias.
|
|
180
|
+
ReceiverAlias.mutated_reads(receiver).reduce(current_scope) do |acc, read|
|
|
161
181
|
widen_alias_read(method_name, read, acc, arg_types: arg_types)
|
|
162
182
|
end
|
|
163
183
|
end
|
|
@@ -212,9 +232,10 @@ module Rigor
|
|
|
212
232
|
return scope if receiver.nil?
|
|
213
233
|
|
|
214
234
|
ReceiverAlias.candidates(receiver).reduce(scope) do |acc, read|
|
|
215
|
-
# A block-local read (`depth == 0`) is not a
|
|
216
|
-
# name against the OUTER scope would hit an
|
|
217
|
-
|
|
235
|
+
# A block-local read ({ReceiverAlias.block_local?}: a `depth == 0` local, or `it`) is not a
|
|
236
|
+
# capture of the outer scope, so widening its name against the OUTER scope would hit an
|
|
237
|
+
# unrelated same-named binding.
|
|
238
|
+
next acc if ReceiverAlias.block_local?(read)
|
|
218
239
|
|
|
219
240
|
# `values: :keep` — this is the block-capture path, and the slice-C content join that runs
|
|
220
241
|
# after it re-adds the appended values' types onto the widened seed, so the seed's own value
|
|
@@ -224,30 +245,30 @@ module Rigor
|
|
|
224
245
|
end
|
|
225
246
|
end
|
|
226
247
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
return current_scope if widened.nil?
|
|
248
|
+
# The arms per kind of binding differ only in which pair of `Scope` accessors they use, so they are read out
|
|
249
|
+
# of one table rather than written once per kind: a carrier the widening responds to must not be widened on
|
|
250
|
+
# one kind of binding and left on another. `$g << x; $g == "k"` folded always-truthy on a `$g` Ruby holds
|
|
251
|
+
# as `"kx"` while the table had only the local and ivar rows. A local rebinds through `with_mutated_local`: the
|
|
252
|
+
# mutated binding names the same object, so it keeps the marks a write drops (issue #1287).
|
|
253
|
+
ALIAS_ACCESSORS = Ractor.make_shareable({
|
|
254
|
+
Prism::LocalVariableReadNode => %i[local with_mutated_local],
|
|
255
|
+
Prism::ItLocalVariableReadNode => %i[local with_mutated_local],
|
|
256
|
+
Prism::InstanceVariableReadNode => %i[ivar with_ivar],
|
|
257
|
+
Prism::ClassVariableReadNode => %i[cvar with_cvar],
|
|
258
|
+
Prism::GlobalVariableReadNode => %i[global with_global]
|
|
259
|
+
})
|
|
260
|
+
private_constant :ALIAS_ACCESSORS
|
|
241
261
|
|
|
242
|
-
|
|
243
|
-
|
|
262
|
+
def widen_alias_read(method_name, read, scope, values: :widen, arg_types: NO_ARG_TYPES)
|
|
263
|
+
getter, builder = ALIAS_ACCESSORS[read.class]
|
|
264
|
+
return scope if getter.nil?
|
|
244
265
|
|
|
245
|
-
|
|
246
|
-
current =
|
|
266
|
+
name = ReceiverAlias.read_name(read)
|
|
267
|
+
current = scope.public_send(getter, name)
|
|
247
268
|
widened = widen_for_mutator(current, method_name, values: values, arg_types: arg_types)
|
|
248
|
-
return
|
|
269
|
+
return scope if widened.nil?
|
|
249
270
|
|
|
250
|
-
|
|
271
|
+
MutationRejoin.rebind(scope, builder, name, widened, pre_state: current, kind: getter)
|
|
251
272
|
end
|
|
252
273
|
|
|
253
274
|
# Mutators that can land a NEW value in an EXISTING slot, falsifying that slot's value pinning
|
|
@@ -259,29 +280,74 @@ module Rigor
|
|
|
259
280
|
private_constant :VALUE_REWRITING_MUTATORS
|
|
260
281
|
|
|
261
282
|
# Returns the widened type for a binding whose receiver is about to be mutated by
|
|
262
|
-
# `method_name`, or `nil` when no widening applies (binding is not a
|
|
263
|
-
#
|
|
264
|
-
# nominal
|
|
283
|
+
# `method_name`, or `nil` when no widening applies (binding is not a carrier the mutation
|
|
284
|
+
# stands for, OR the method is not a mutator for that shape, OR the carrier is a PRECISE
|
|
285
|
+
# nominal, whose element set is a claim this seam may not grow — see {MutationRejoin.regrowable_carrier?}).
|
|
265
286
|
def widen_for_mutator(type, method_name, values: :widen, arg_types: NO_ARG_TYPES)
|
|
266
287
|
values = :keep unless VALUE_REWRITING_MUTATORS.include?(method_name)
|
|
288
|
+
values = RewriteMutation.values_mode(type, method_name, values)
|
|
267
289
|
|
|
268
290
|
return nil if type.nil?
|
|
269
291
|
|
|
270
292
|
case type
|
|
293
|
+
when Type::Nominal then MutationRejoin.widen_nominal(type, method_name, values:, arg_types:)
|
|
271
294
|
when Type::Tuple
|
|
272
295
|
return nil unless ARRAY_MUTATORS.include?(method_name)
|
|
273
296
|
|
|
274
297
|
join_added_elements(widen_tuple(type, values: values), method_name, arg_types, type.elements)
|
|
275
298
|
when Type::HashShape
|
|
276
|
-
return
|
|
299
|
+
return HashLookupMutation.widen_shape(type, method_name) unless HASH_MUTATORS.include?(method_name)
|
|
277
300
|
|
|
278
301
|
join_added_pairs(widen_hash_shape(type, values: values), method_name, arg_types,
|
|
279
302
|
ContentJoin.hash_shape_key_values(type))
|
|
303
|
+
when Type::Constant then StringMutation.widen_constant(type, method_name)
|
|
280
304
|
when Type::Difference
|
|
281
|
-
widen_difference(type, method_name)
|
|
305
|
+
widen_difference(type, method_name, arg_types: arg_types)
|
|
306
|
+
when Type::Union
|
|
307
|
+
widen_union(type, method_name, values: values, arg_types: arg_types)
|
|
282
308
|
end
|
|
283
309
|
end
|
|
284
310
|
|
|
311
|
+
# A `Union` seed is widened MEMBERWISE (issue #645). Declining it outright left a straight-line
|
|
312
|
+
# mutation on a union binding recording nothing at all — `out = flag ? 5 : [2]; out << 2` kept
|
|
313
|
+
# the `[2]` Tuple's arity after the mutation falsified it, so a later `out.size == 1` folds on a
|
|
314
|
+
# value the program never holds.
|
|
315
|
+
#
|
|
316
|
+
# Which members the mutation stands for is {ContentJoin}'s residue partition read from this
|
|
317
|
+
# side, so the straight-line seam and the block seam (#631) agree about a union: a member the
|
|
318
|
+
# mutator's class carries widens through the ordinary non-union path above, every other member
|
|
319
|
+
# survives whole. The two tables are consulted per member rather than once for the union, which
|
|
320
|
+
# is what a name in BOTH of them (`clear`, `delete`, `replace`) needs on a mixed
|
|
321
|
+
# `Array | Hash` seed.
|
|
322
|
+
#
|
|
323
|
+
# `nil` when no member widened — a union with no carrier member, or one whose carriers are
|
|
324
|
+
# already nominal, is untouched exactly as the scalar path leaves them.
|
|
325
|
+
def widen_union(union, method_name, values: :widen, arg_types: NO_ARG_TYPES)
|
|
326
|
+
widened_any = false
|
|
327
|
+
members = union.members.map do |member|
|
|
328
|
+
next member unless mutation_carrier?(member, method_name)
|
|
329
|
+
|
|
330
|
+
widened = widen_for_mutator(member, method_name, values: values, arg_types: arg_types)
|
|
331
|
+
next member if widened.nil?
|
|
332
|
+
|
|
333
|
+
widened_any = true
|
|
334
|
+
widened
|
|
335
|
+
end
|
|
336
|
+
return nil unless widened_any
|
|
337
|
+
|
|
338
|
+
Type::Combinator.union(*members)
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# True when the mutator's own class stands for `member` — the absorbed side of
|
|
342
|
+
# {ContentJoin.array_residue} / {ContentJoin.hash_residue}, whichever table names the call. A
|
|
343
|
+
# {HashLookupMutation} name stands for a Hash member as a Hash mutator does.
|
|
344
|
+
def mutation_carrier?(member, method_name)
|
|
345
|
+
(ARRAY_MUTATORS.include?(method_name) && ContentJoin.array_residue(member).empty?) ||
|
|
346
|
+
((HASH_MUTATORS.include?(method_name) || HashLookupMutation::MUTATORS.include?(method_name)) &&
|
|
347
|
+
ContentJoin.hash_residue(member).empty?) ||
|
|
348
|
+
(StringMutation::MUTATORS.include?(method_name) && StringMutation.constant?(member))
|
|
349
|
+
end
|
|
350
|
+
|
|
285
351
|
# Joins the element evidence the mutator's own ARGUMENTS introduce into the already-widened
|
|
286
352
|
# Array carrier (issue #560). Without it the widening keeps only the SEED's elements, which
|
|
287
353
|
# under-covers precisely the value the mutation added: `u = [1, 2]; u.push(6)` left
|
|
@@ -305,7 +371,11 @@ module Rigor
|
|
|
305
371
|
# **The join records what it saw; it never CLOSES the parameter.** That is
|
|
306
372
|
# {#gradual_floor}'s job, and the reason is the seam this method sits on rather than anything
|
|
307
373
|
# about Array or Hash.
|
|
374
|
+
#
|
|
375
|
+
# A mutator whose arguments do not describe what it stores ({RewriteMutation}) takes that module's gradual
|
|
376
|
+
# arm first, on every path that reaches this join: the literal arms, the refinement arm, and the re-join.
|
|
308
377
|
def join_added_elements(widened, method_name, arg_types, seed_elements)
|
|
378
|
+
widened = RewriteMutation.arm(widened, method_name)
|
|
309
379
|
return widened unless ContentJoin::ARRAY_CONTENT_ADDERS.include?(method_name)
|
|
310
380
|
|
|
311
381
|
added = value_pin_widened(ContentJoin.array_added_elements(method_name, arg_types))
|
|
@@ -340,7 +410,10 @@ module Rigor
|
|
|
340
410
|
# BLOCK path (ADR-56 slice C) on the other side: `content_writeback_block_captures` scans the
|
|
341
411
|
# whole body and joins every mutator call in it before writing back, so its evidence IS
|
|
342
412
|
# complete for that body and its precise join stays justified — `acc = []; xs.each { |x|
|
|
343
|
-
# acc.push(x) }` keeps reading `Array[Integer]`.
|
|
413
|
+
# acc.push(x) }` keeps reading `Array[Integer]`. Seeing every store is only half of that
|
|
414
|
+
# claim: a store computed from the collection's own contents (`h[k] = h[k] + 1`) is
|
|
415
|
+
# complete evidence only once it holds past the first iteration, which is why that seam
|
|
416
|
+
# iterates such a store to a fixpoint instead of typing it once (ADR-56 WD2.13).
|
|
344
417
|
#
|
|
345
418
|
# `Array[Integer | Dynamic[top]]` still does everything issue #560 needs: a union carrying
|
|
346
419
|
# `Dynamic` cannot constant-fold, so every stale always-falsey the join was written to remove
|
|
@@ -351,12 +424,17 @@ module Rigor
|
|
|
351
424
|
|
|
352
425
|
# The Hash-side twin of {#join_added_elements}: `h[k] = v` / `h.store(k, v)` join the stored
|
|
353
426
|
# key and value into the widened `Hash[K, V]` carrier, each admitted against its OWN side's
|
|
354
|
-
# seed evidence (a foreign key does not make the value gradual, or the reverse).
|
|
427
|
+
# seed evidence (a foreign key does not make the value gradual, or the reverse). {RewriteMutation}'s arm lands
|
|
428
|
+
# first, as it does in {#join_added_elements}.
|
|
355
429
|
def join_added_pairs(widened, method_name, arg_types, seed_pairs)
|
|
430
|
+
widened = RewriteMutation.arm(widened, method_name)
|
|
356
431
|
return widened unless ContentJoin::HASH_CONTENT_ADDERS.include?(method_name)
|
|
357
432
|
return widened if arg_types.size < 2
|
|
358
433
|
|
|
359
|
-
|
|
434
|
+
# A `nil` index marks a splat for the Array splice classifier; the pair seam reads
|
|
435
|
+
# `arg_types.first` as the KEY, where the splat's expansion is an unknown key rather
|
|
436
|
+
# than absent arity — it degrades to untyped, not `nil` (issue #1140).
|
|
437
|
+
added = value_pin_widened([arg_types.first || Type::Combinator.untyped, arg_types.last])
|
|
360
438
|
return widened unless added.size == 2
|
|
361
439
|
|
|
362
440
|
seed_keys, seed_values = seed_pairs
|
|
@@ -433,25 +511,19 @@ module Rigor
|
|
|
433
511
|
end
|
|
434
512
|
end
|
|
435
513
|
|
|
436
|
-
#
|
|
437
|
-
#
|
|
438
|
-
#
|
|
439
|
-
#
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
return nil unless difference.removes_empty_witness?
|
|
450
|
-
|
|
451
|
-
base = difference.base
|
|
452
|
-
case base.class_name
|
|
453
|
-
when "Array" then ARRAY_MUTATORS.include?(method_name) ? base : nil
|
|
454
|
-
when "Hash" then HASH_MUTATORS.include?(method_name) ? base : nil
|
|
514
|
+
# The empty-witness refinement arm. {RefinementMutation} owns the witness half — whether
|
|
515
|
+
# `xs` is still provably non-empty after `method_name` — and takes the content half from
|
|
516
|
+
# here, so a refinement joins the mutator's added content on exactly the terms the `Tuple` /
|
|
517
|
+
# `HashShape` arms above do (issue #936, ADR-56 WD2.9's deferred branch).
|
|
518
|
+
def widen_difference(difference, method_name, arg_types: NO_ARG_TYPES)
|
|
519
|
+
RefinementMutation.widen(difference, method_name, arg_types) do |base|
|
|
520
|
+
if base.class_name == "Array"
|
|
521
|
+
ARRAY_MUTATORS.include?(method_name) &&
|
|
522
|
+
join_added_elements(base, method_name, arg_types, ContentJoin.collection_element_types(base))
|
|
523
|
+
else
|
|
524
|
+
HASH_MUTATORS.include?(method_name) &&
|
|
525
|
+
join_added_pairs(base, method_name, arg_types, ContentJoin.hash_shape_key_values(base))
|
|
526
|
+
end
|
|
455
527
|
end
|
|
456
528
|
end
|
|
457
529
|
|
|
@@ -473,16 +545,17 @@ module Rigor
|
|
|
473
545
|
Type::Combinator.nominal_of("Array", type_args: [element_type])
|
|
474
546
|
end
|
|
475
547
|
|
|
476
|
-
# `HashShape`
|
|
477
|
-
#
|
|
478
|
-
#
|
|
479
|
-
# `
|
|
480
|
-
# `
|
|
548
|
+
# Closed `HashShape` → `Nominal[Hash, [Kunion, Vunion]]`. An empty or an open shape degrades to
|
|
549
|
+
# a fully-untyped Hash: an open shape's unseen keys may hold any value, and one {HashLookupMutation}
|
|
550
|
+
# opened reads its DEFAULT for a missing key, so a bound built from the known values alone would
|
|
551
|
+
# pin that read to one of them (`{ a: 1 }` under `default = 0` then `delete(:a)` read `h[:b]` as
|
|
552
|
+
# `1`). Values widen their pinning the same way {#widen_tuple}'s elements do (issue #560):
|
|
553
|
+
# `opts = {headers: false}` then `opts[:encoding] = v` must not keep `false` as the whole value
|
|
554
|
+
# bound — redmine's `import.rb:274` read the stored key back through it and drew a false
|
|
555
|
+
# always-falsey.
|
|
481
556
|
def widen_hash_shape(shape, values: :widen)
|
|
482
|
-
if shape.pairs.empty?
|
|
483
|
-
return Type::Combinator.nominal_of("Hash",
|
|
484
|
-
type_args: [Type::Combinator.untyped,
|
|
485
|
-
Type::Combinator.untyped])
|
|
557
|
+
if shape.pairs.empty? || shape.open?
|
|
558
|
+
return Type::Combinator.nominal_of("Hash", type_args: [Type::Combinator.untyped, Type::Combinator.untyped])
|
|
486
559
|
end
|
|
487
560
|
|
|
488
561
|
key_type = key_union_for(shape.pairs.keys)
|
|
@@ -497,9 +570,7 @@ module Rigor
|
|
|
497
570
|
# `key_union_for` is delegated rather than duplicated: {#widen_hash_shape} and
|
|
498
571
|
# `ContentJoin.hash_shape_key_values` must map a literal key set the SAME way, or a widened
|
|
499
572
|
# carrier and the join that reads it back disagree about the key parameter.
|
|
500
|
-
def key_union_for(keys)
|
|
501
|
-
ContentJoin.key_union_for(keys)
|
|
502
|
-
end
|
|
573
|
+
def key_union_for(keys) = ContentJoin.key_union_for(keys)
|
|
503
574
|
end
|
|
504
575
|
end
|
|
505
576
|
end
|