rigortype 0.2.7 → 0.2.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 +1 -1
- data/docs/manual/04-diagnostics.md +7 -4
- data/docs/manual/06-baseline.md +5 -2
- data/docs/manual/15-type-protection-coverage.md +6 -4
- data/lib/rigor/analysis/baseline.rb +56 -96
- data/lib/rigor/analysis/buffer_binding.rb +13 -20
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +29 -48
- data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +35 -54
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +23 -37
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +16 -23
- data/lib/rigor/analysis/check_rules/rule_walk.rb +48 -71
- data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +19 -28
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +48 -67
- data/lib/rigor/analysis/check_rules.rb +174 -274
- data/lib/rigor/analysis/dependency_recorder.rb +26 -38
- data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +13 -25
- data/lib/rigor/analysis/dependency_source_inference/builder.rb +17 -30
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +15 -26
- data/lib/rigor/analysis/dependency_source_inference/index.rb +45 -76
- data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +23 -40
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +50 -83
- data/lib/rigor/analysis/dependency_source_inference.rb +6 -10
- data/lib/rigor/analysis/diagnostic.rb +48 -75
- data/lib/rigor/analysis/erb_template_detector.rb +13 -18
- data/lib/rigor/analysis/fact_store.rb +12 -22
- data/lib/rigor/analysis/incremental.rb +47 -63
- data/lib/rigor/analysis/incremental_session.rb +74 -100
- data/lib/rigor/analysis/project_scan.rb +12 -23
- data/lib/rigor/analysis/result.rb +3 -5
- data/lib/rigor/analysis/rule_catalog.rb +67 -95
- data/lib/rigor/analysis/run_stats.rb +38 -61
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +101 -160
- data/lib/rigor/analysis/runner/pool_coordinator.rb +121 -188
- data/lib/rigor/analysis/runner/project_pre_passes.rb +62 -96
- data/lib/rigor/analysis/runner/run_snapshots.rb +12 -18
- data/lib/rigor/analysis/runner.rb +220 -333
- data/lib/rigor/analysis/self_call_resolution_recorder.rb +30 -43
- data/lib/rigor/analysis/worker_session.rb +64 -102
- data/lib/rigor/ast/type_node.rb +6 -8
- data/lib/rigor/ast.rb +6 -10
- data/lib/rigor/bleeding_edge.rb +27 -35
- data/lib/rigor/builtins/hkt_builtins.rb +7 -14
- data/lib/rigor/builtins/imported_refinements.rb +106 -149
- data/lib/rigor/builtins/predefined_constant_refinements.rb +51 -65
- data/lib/rigor/builtins/regex_refinement.rb +32 -43
- data/lib/rigor/builtins/static_return_refinements.rb +57 -81
- data/lib/rigor/cache/descriptor.rb +58 -94
- data/lib/rigor/cache/incremental_snapshot.rb +32 -48
- data/lib/rigor/cache/rbs_cache_producer.rb +10 -15
- data/lib/rigor/cache/rbs_class_ancestor_table.rb +10 -16
- data/lib/rigor/cache/rbs_class_type_param_names.rb +10 -16
- data/lib/rigor/cache/rbs_constant_table.rb +8 -13
- data/lib/rigor/cache/rbs_descriptor.rb +8 -13
- data/lib/rigor/cache/rbs_environment.rb +11 -19
- data/lib/rigor/cache/rbs_environment_marshal_patch.rb +11 -19
- data/lib/rigor/cache/rbs_known_class_names.rb +8 -12
- data/lib/rigor/cache/store.rb +96 -151
- data/lib/rigor/cli/annotate_command.rb +51 -88
- data/lib/rigor/cli/baseline_command.rb +10 -17
- data/lib/rigor/cli/check_command.rb +121 -199
- data/lib/rigor/cli/check_runner_factory.rb +8 -14
- data/lib/rigor/cli/ci_detector.rb +9 -14
- data/lib/rigor/cli/command.rb +8 -14
- data/lib/rigor/cli/coverage_command.rb +19 -26
- data/lib/rigor/cli/coverage_mutation.rb +14 -19
- data/lib/rigor/cli/coverage_report.rb +0 -2
- data/lib/rigor/cli/coverage_scan.rb +7 -11
- data/lib/rigor/cli/diagnostic_formats.rb +43 -62
- data/lib/rigor/cli/diff_command.rb +10 -20
- data/lib/rigor/cli/docs_command.rb +26 -40
- data/lib/rigor/cli/doctor_command.rb +8 -9
- data/lib/rigor/cli/explain_command.rb +4 -7
- data/lib/rigor/cli/fused_protection_renderer.rb +4 -5
- data/lib/rigor/cli/fused_protection_report.rb +6 -8
- data/lib/rigor/cli/lsp_command.rb +11 -19
- data/lib/rigor/cli/mcp_command.rb +4 -6
- data/lib/rigor/cli/mutation_protection_renderer.rb +3 -4
- data/lib/rigor/cli/mutation_protection_report.rb +6 -9
- data/lib/rigor/cli/options.rb +11 -19
- data/lib/rigor/cli/plugin_command.rb +18 -30
- data/lib/rigor/cli/plugins_command.rb +29 -51
- data/lib/rigor/cli/plugins_renderer.rb +12 -20
- data/lib/rigor/cli/prism_colorizer.rb +13 -19
- data/lib/rigor/cli/protection_renderer.rb +5 -7
- data/lib/rigor/cli/protection_report.rb +27 -17
- data/lib/rigor/cli/renderable.rb +4 -6
- data/lib/rigor/cli/show_bleedingedge_command.rb +5 -8
- data/lib/rigor/cli/sig_gen_command.rb +14 -26
- data/lib/rigor/cli/skill_command.rb +30 -47
- data/lib/rigor/cli/skill_describe.rb +40 -64
- data/lib/rigor/cli/trace_command.rb +9 -16
- data/lib/rigor/cli/trace_renderer.rb +35 -51
- data/lib/rigor/cli/triage_command.rb +6 -10
- data/lib/rigor/cli/triage_renderer.rb +1 -2
- data/lib/rigor/cli/type_of_command.rb +14 -23
- data/lib/rigor/cli/type_of_renderer.rb +3 -5
- data/lib/rigor/cli/type_scan_command.rb +6 -10
- data/lib/rigor/cli/type_scan_renderer.rb +3 -5
- data/lib/rigor/cli/type_scan_report.rb +2 -3
- data/lib/rigor/cli/upgrade_command.rb +2 -3
- data/lib/rigor/cli.rb +16 -28
- data/lib/rigor/config_audit.rb +35 -44
- data/lib/rigor/configuration/dependencies.rb +41 -70
- data/lib/rigor/configuration/severity_profile.rb +28 -42
- data/lib/rigor/configuration.rb +150 -241
- data/lib/rigor/environment/bundle_sig_discovery.rb +74 -118
- data/lib/rigor/environment/class_registry.rb +19 -26
- data/lib/rigor/environment/constant_type_cache_holder.rb +14 -21
- data/lib/rigor/environment/hkt_registry_holder.rb +6 -12
- data/lib/rigor/environment/lockfile_resolver.rb +31 -47
- data/lib/rigor/environment/rbs_collection_discovery.rb +39 -63
- data/lib/rigor/environment/rbs_coverage_report.rb +24 -42
- data/lib/rigor/environment/rbs_loader.rb +420 -518
- data/lib/rigor/environment/reflection.rb +28 -53
- data/lib/rigor/environment/reporters.rb +13 -24
- data/lib/rigor/environment.rb +176 -291
- data/lib/rigor/flow_contribution/conflict.rb +16 -27
- data/lib/rigor/flow_contribution/element.rb +7 -12
- data/lib/rigor/flow_contribution/fact.rb +33 -57
- data/lib/rigor/flow_contribution/merge_result.rb +6 -9
- data/lib/rigor/flow_contribution/merger.rb +32 -47
- data/lib/rigor/flow_contribution.rb +37 -55
- data/lib/rigor/inference/acceptance.rb +133 -219
- data/lib/rigor/inference/block_parameter_binder.rb +52 -82
- data/lib/rigor/inference/body_fixpoint.rb +22 -30
- data/lib/rigor/inference/budget_trace.rb +43 -63
- data/lib/rigor/inference/builtins/array_catalog.rb +4 -6
- data/lib/rigor/inference/builtins/comparable_catalog.rb +4 -6
- data/lib/rigor/inference/builtins/complex_catalog.rb +13 -19
- data/lib/rigor/inference/builtins/date_catalog.rb +38 -67
- data/lib/rigor/inference/builtins/encoding_catalog.rb +22 -36
- data/lib/rigor/inference/builtins/enumerable_catalog.rb +4 -6
- data/lib/rigor/inference/builtins/exception_catalog.rb +38 -57
- data/lib/rigor/inference/builtins/hash_catalog.rb +9 -14
- data/lib/rigor/inference/builtins/method_catalog.rb +29 -48
- data/lib/rigor/inference/builtins/numeric_catalog.rb +13 -18
- data/lib/rigor/inference/builtins/pathname_catalog.rb +8 -13
- data/lib/rigor/inference/builtins/proc_catalog.rb +38 -62
- data/lib/rigor/inference/builtins/random_catalog.rb +21 -32
- data/lib/rigor/inference/builtins/range_catalog.rb +12 -21
- data/lib/rigor/inference/builtins/rational_catalog.rb +9 -15
- data/lib/rigor/inference/builtins/re_catalog.rb +29 -48
- data/lib/rigor/inference/builtins/set_catalog.rb +18 -27
- data/lib/rigor/inference/builtins/string_catalog.rb +12 -19
- data/lib/rigor/inference/builtins/struct_catalog.rb +18 -30
- data/lib/rigor/inference/builtins/time_catalog.rb +28 -44
- data/lib/rigor/inference/closure_escape_analyzer.rb +44 -67
- data/lib/rigor/inference/coverage_scanner.rb +13 -18
- data/lib/rigor/inference/def_return_typer.rb +8 -14
- data/lib/rigor/inference/dynamic_origin.rb +23 -20
- data/lib/rigor/inference/expression_typer.rb +774 -1152
- data/lib/rigor/inference/fallback.rb +8 -12
- data/lib/rigor/inference/fallback_tracer.rb +4 -10
- data/lib/rigor/inference/flow_tracer.rb +25 -36
- data/lib/rigor/inference/hkt_body.rb +45 -68
- data/lib/rigor/inference/hkt_body_parser.rb +33 -52
- data/lib/rigor/inference/hkt_reducer.rb +38 -59
- data/lib/rigor/inference/hkt_registry.rb +50 -76
- data/lib/rigor/inference/indexed_narrowing.rb +55 -81
- data/lib/rigor/inference/macro_block_self_type.rb +21 -34
- data/lib/rigor/inference/method_dispatcher/array_to_h_folding.rb +11 -18
- data/lib/rigor/inference/method_dispatcher/block_folding.rb +49 -83
- data/lib/rigor/inference/method_dispatcher/call_context.rb +16 -23
- data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +13 -22
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +307 -454
- data/lib/rigor/inference/method_dispatcher/data_folding.rb +24 -34
- data/lib/rigor/inference/method_dispatcher/file_folding.rb +22 -37
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +52 -81
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +51 -78
- data/lib/rigor/inference/method_dispatcher/literal_string_folding.rb +60 -97
- data/lib/rigor/inference/method_dispatcher/math_folding.rb +23 -34
- data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +18 -26
- data/lib/rigor/inference/method_dispatcher/method_folding.rb +37 -71
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +114 -182
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +122 -193
- data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +15 -24
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +64 -93
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +31 -45
- data/lib/rigor/inference/method_dispatcher/set_folding.rb +6 -9
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +356 -511
- data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +22 -32
- data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +15 -21
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +66 -82
- data/lib/rigor/inference/method_dispatcher/time_folding.rb +10 -15
- data/lib/rigor/inference/method_dispatcher/uri_folding.rb +9 -13
- data/lib/rigor/inference/method_dispatcher.rb +378 -524
- data/lib/rigor/inference/method_parameter_binder.rb +81 -114
- data/lib/rigor/inference/multi_target_binder.rb +51 -68
- data/lib/rigor/inference/mutation_widening.rb +115 -158
- data/lib/rigor/inference/narrowing.rb +509 -727
- data/lib/rigor/inference/origin_lookup.rb +38 -0
- data/lib/rigor/inference/parameter_inference_collector.rb +100 -100
- data/lib/rigor/inference/precision_scanner.rb +26 -35
- data/lib/rigor/inference/project_patched_methods.rb +20 -32
- data/lib/rigor/inference/project_patched_scanner.rb +23 -37
- data/lib/rigor/inference/protection_scanner.rb +16 -18
- data/lib/rigor/inference/rbs_type_translator.rb +49 -66
- data/lib/rigor/inference/scope_indexer.rb +473 -817
- data/lib/rigor/inference/statement_evaluator.rb +706 -1111
- data/lib/rigor/inference/struct_fold_safety.rb +34 -48
- data/lib/rigor/inference/synthetic_method.rb +9 -16
- data/lib/rigor/inference/synthetic_method_index.rb +20 -35
- data/lib/rigor/inference/synthetic_method_scanner.rb +63 -103
- data/lib/rigor/language_server/buffer_resolution.rb +6 -9
- data/lib/rigor/language_server/buffer_table.rb +11 -18
- data/lib/rigor/language_server/completion_provider.rb +69 -116
- data/lib/rigor/language_server/debouncer.rb +16 -25
- data/lib/rigor/language_server/diagnostic_publisher.rb +26 -40
- data/lib/rigor/language_server/document_symbol_provider.rb +14 -19
- data/lib/rigor/language_server/folding_range_provider.rb +11 -19
- data/lib/rigor/language_server/hover_provider.rb +8 -11
- data/lib/rigor/language_server/hover_renderer.rb +56 -93
- data/lib/rigor/language_server/loop.rb +14 -19
- data/lib/rigor/language_server/project_context.rb +46 -74
- data/lib/rigor/language_server/selection_range_provider.rb +9 -12
- data/lib/rigor/language_server/server.rb +55 -83
- data/lib/rigor/language_server/signature_help_provider.rb +29 -46
- data/lib/rigor/language_server/synchronized_writer.rb +4 -7
- data/lib/rigor/language_server/uri.rb +8 -13
- data/lib/rigor/language_server.rb +4 -6
- data/lib/rigor/mcp/loop.rb +2 -3
- data/lib/rigor/mcp/server.rb +4 -7
- data/lib/rigor/mcp.rb +3 -6
- data/lib/rigor/plugin/access_denied_error.rb +5 -8
- data/lib/rigor/plugin/additional_initializer.rb +21 -31
- data/lib/rigor/plugin/base.rb +335 -518
- data/lib/rigor/plugin/blueprint.rb +14 -23
- data/lib/rigor/plugin/box.rb +18 -29
- data/lib/rigor/plugin/fact_store.rb +16 -26
- data/lib/rigor/plugin/inflector.rb +37 -53
- data/lib/rigor/plugin/io_boundary.rb +33 -56
- data/lib/rigor/plugin/isolation.rb +42 -55
- data/lib/rigor/plugin/load_error.rb +10 -15
- data/lib/rigor/plugin/loader.rb +30 -49
- data/lib/rigor/plugin/macro/block_as_method.rb +20 -32
- data/lib/rigor/plugin/macro/heredoc_template.rb +35 -58
- data/lib/rigor/plugin/macro/nested_class_template.rb +22 -36
- data/lib/rigor/plugin/macro/trait_registry.rb +34 -51
- data/lib/rigor/plugin/macro.rb +10 -15
- data/lib/rigor/plugin/manifest.rb +85 -144
- data/lib/rigor/plugin/node_context.rb +14 -22
- data/lib/rigor/plugin/node_rule_walk.rb +49 -74
- data/lib/rigor/plugin/protocol_contract.rb +25 -39
- data/lib/rigor/plugin/registry.rb +132 -205
- data/lib/rigor/plugin/services.rb +21 -33
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -19
- data/lib/rigor/plugin/trust_policy.rb +24 -38
- data/lib/rigor/plugin/type_node_resolver.rb +15 -24
- data/lib/rigor/protection/diagnostic_oracle.rb +11 -13
- data/lib/rigor/protection/mutation_scanner.rb +27 -35
- data/lib/rigor/protection/mutator.rb +50 -70
- data/lib/rigor/protection/test_suite_oracle.rb +20 -27
- data/lib/rigor/rbs_extended/conformance_checker.rb +48 -68
- data/lib/rigor/rbs_extended/hkt_directives.rb +28 -54
- data/lib/rigor/rbs_extended/reporter.rb +24 -40
- data/lib/rigor/rbs_extended.rb +107 -197
- data/lib/rigor/reflection.rb +68 -86
- data/lib/rigor/scope/discovery_index.rb +14 -19
- data/lib/rigor/scope.rb +255 -310
- data/lib/rigor/sig_gen/classification.rb +6 -10
- data/lib/rigor/sig_gen/generator.rb +197 -323
- data/lib/rigor/sig_gen/layout_index.rb +12 -20
- data/lib/rigor/sig_gen/method_candidate.rb +12 -17
- data/lib/rigor/sig_gen/observation_collector.rb +38 -70
- data/lib/rigor/sig_gen/observed_call.rb +13 -23
- data/lib/rigor/sig_gen/path_mapper.rb +17 -29
- data/lib/rigor/sig_gen/renderer.rb +7 -13
- data/lib/rigor/sig_gen/type_elaborator.rb +15 -28
- data/lib/rigor/sig_gen/write_result.rb +8 -16
- data/lib/rigor/sig_gen/writer.rb +95 -174
- data/lib/rigor/sig_gen.rb +3 -6
- data/lib/rigor/signature_path_audit.rb +24 -30
- data/lib/rigor/source/constant_path.rb +10 -14
- data/lib/rigor/source/literals.rb +31 -45
- data/lib/rigor/source/node_locator.rb +9 -11
- data/lib/rigor/source/node_walker.rb +9 -13
- data/lib/rigor/source.rb +3 -4
- data/lib/rigor/testing.rb +16 -20
- data/lib/rigor/triage/catalogue.rb +38 -62
- data/lib/rigor/triage.rb +31 -52
- data/lib/rigor/trinary.rb +9 -13
- data/lib/rigor/type/acceptance_router.rb +4 -6
- data/lib/rigor/type/accepts_result.rb +10 -14
- data/lib/rigor/type/app.rb +19 -27
- data/lib/rigor/type/bot.rb +4 -6
- data/lib/rigor/type/bound_method.rb +10 -15
- data/lib/rigor/type/combinator.rb +165 -257
- data/lib/rigor/type/constant.rb +23 -34
- data/lib/rigor/type/data_class.rb +10 -15
- data/lib/rigor/type/data_instance.rb +14 -20
- data/lib/rigor/type/difference.rb +21 -32
- data/lib/rigor/type/dynamic.rb +3 -5
- data/lib/rigor/type/hash_shape.rb +32 -18
- data/lib/rigor/type/integer_range.rb +11 -16
- data/lib/rigor/type/intersection.rb +27 -42
- data/lib/rigor/type/nominal.rb +10 -15
- data/lib/rigor/type/plain_lattice.rb +9 -13
- data/lib/rigor/type/refined.rb +67 -114
- data/lib/rigor/type/singleton.rb +4 -6
- data/lib/rigor/type/struct_class.rb +11 -16
- data/lib/rigor/type/struct_instance.rb +15 -21
- data/lib/rigor/type/tuple.rb +14 -19
- data/lib/rigor/type/union.rb +30 -42
- data/lib/rigor/type_node/generic.rb +14 -26
- data/lib/rigor/type_node/identifier.rb +12 -19
- data/lib/rigor/type_node.rb +3 -12
- data/lib/rigor/value_semantics.rb +16 -21
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +18 -30
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +16 -29
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +12 -23
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +22 -39
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +26 -46
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +51 -87
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +10 -17
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +26 -39
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +118 -176
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +30 -51
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +57 -92
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +71 -108
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +13 -22
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +15 -25
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +8 -13
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +16 -24
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +30 -47
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +79 -129
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +36 -57
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +27 -41
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +16 -24
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +148 -235
- data/plugins/rigor-activerecord/lib/rigor-activerecord.rb +3 -5
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +8 -14
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +9 -15
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +4 -7
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +23 -41
- data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +3 -5
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +6 -10
- data/plugins/rigor-activesupport-core-ext/lib/rigor-activesupport-core-ext.rb +8 -11
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +30 -45
- data/plugins/rigor-devise/lib/rigor-devise.rb +3 -5
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +43 -69
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +26 -35
- data/plugins/rigor-dry-schema/lib/rigor-dry-schema.rb +3 -5
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +30 -47
- data/plugins/rigor-dry-struct/lib/rigor-dry-struct.rb +3 -5
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +67 -113
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +29 -46
- data/plugins/rigor-dry-types/lib/rigor-dry-types.rb +3 -5
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -20
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +14 -23
- data/plugins/rigor-dry-validation/lib/rigor-dry-validation.rb +2 -3
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +22 -37
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +28 -46
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +13 -17
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +30 -47
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +52 -80
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +21 -31
- data/plugins/rigor-graphql/lib/rigor-graphql.rb +3 -5
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +11 -17
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +20 -34
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +45 -75
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +22 -36
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +22 -41
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +17 -32
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +6 -12
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +4 -8
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +17 -32
- data/plugins/rigor-rails/lib/rigor-rails.rb +11 -18
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +58 -92
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +20 -34
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +20 -31
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +49 -82
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +55 -92
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +51 -90
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +17 -30
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +38 -70
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +42 -74
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +280 -497
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +54 -89
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +32 -54
- data/plugins/rigor-rbs-inline/lib/rigor-rbs-inline.rb +8 -13
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +9 -16
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +24 -39
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +13 -22
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +34 -56
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/scope_walker.rb +22 -42
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +43 -75
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +27 -39
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/http_status_codes.rb +14 -19
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +20 -34
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +28 -47
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +21 -37
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +13 -22
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +18 -31
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +6 -10
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +14 -29
- data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +23 -41
- data/plugins/rigor-sinatra/lib/rigor-sinatra.rb +3 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +23 -38
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +57 -96
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +22 -35
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +41 -69
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/method_signature.rb +6 -10
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +24 -41
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +29 -50
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +55 -88
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +159 -262
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +21 -29
- data/plugins/rigor-statesman/lib/rigor-statesman.rb +3 -5
- data/plugins/rigor-typescript-utility-types/lib/rigor/plugin/typescript_utility_types.rb +23 -37
- data/plugins/rigor-typescript-utility-types/lib/rigor-typescript-utility-types.rb +4 -6
- data/sig/rigor/scope.rbs +6 -0
- metadata +2 -1
|
@@ -9,110 +9,80 @@ require_relative "overload_selector"
|
|
|
9
9
|
module Rigor
|
|
10
10
|
module Inference
|
|
11
11
|
module MethodDispatcher
|
|
12
|
-
# Slice 4 dispatch tier that consults RBS method signatures.
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# precision; only the calls the folder cannot prove fall through
|
|
16
|
-
# to RBS.
|
|
12
|
+
# Slice 4 dispatch tier that consults RBS method signatures. Sits behind {ConstantFolding}, so
|
|
13
|
+
# anything the constant folder already proves (e.g., `1 + 2 == 3`) keeps its full Constant precision;
|
|
14
|
+
# only the calls the folder cannot prove fall through to RBS.
|
|
17
15
|
#
|
|
18
|
-
# Phase 2b extends the dispatcher to recognise `Singleton[Foo]`
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# resolves to `Singleton[Foo]`, and `Foo.new` / `Foo.bar` look up
|
|
22
|
-
# the corresponding *class* methods.
|
|
16
|
+
# Phase 2b extends the dispatcher to recognise `Singleton[Foo]` receivers, routing those calls
|
|
17
|
+
# through `singleton_method` instead of `instance_method`. The constant `Foo` therefore now resolves
|
|
18
|
+
# to `Singleton[Foo]`, and `Foo.new` / `Foo.bar` look up the corresponding *class* methods.
|
|
23
19
|
#
|
|
24
|
-
# Phase 2c adds argument-typed overload selection: instead of
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
# selector falls back to the first overload so the existing
|
|
30
|
-
# phase-1/2b behavior is preserved.
|
|
20
|
+
# Phase 2c adds argument-typed overload selection: instead of always returning `method_types.first`,
|
|
21
|
+
# the dispatcher delegates to {OverloadSelector} which filters overloads by positional arity and
|
|
22
|
+
# consults `Rigor::Type#accepts` for each parameter. When no overload accepts the actual argument
|
|
23
|
+
# types, the selector falls back to the first overload so the existing phase-1/2b behavior is
|
|
24
|
+
# preserved.
|
|
31
25
|
#
|
|
32
|
-
# Phase 2d adds generics instantiation. Receivers carry an
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
# `[
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
# rather than degrading the variable to `Dynamic[Top]`. When
|
|
40
|
-
# arities mismatch (raw receiver, partial generics) the map is
|
|
41
|
-
# left empty and free variables degrade as before.
|
|
26
|
+
# Phase 2d adds generics instantiation. Receivers carry an ordered `type_args` array on
|
|
27
|
+
# `Rigor::Type::Nominal`. The dispatcher zips the receiver's `type_args` against the class's declared
|
|
28
|
+
# type-parameter names (`Array` -> `[:Elem]`, `Hash` -> `[:K, :V]`, ...) to build a substitution map;
|
|
29
|
+
# that map is then threaded through {RbsTypeTranslator} so a return type like `::Array[Elem]`
|
|
30
|
+
# resolves to `Nominal["Array", [Integer]]` rather than degrading the variable to `Dynamic[Top]`.
|
|
31
|
+
# When arities mismatch (raw receiver, partial generics) the map is left empty and free variables
|
|
32
|
+
# degrade as before.
|
|
42
33
|
#
|
|
43
|
-
# Slice 5 phase 1 projects shape-carrying receivers onto their
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
# Tuple/HashShape element precision (e.g., `tuple[0]` returning
|
|
49
|
-
# the precise member) is handled by the preceding `ShapeDispatch`
|
|
50
|
-
# tier.
|
|
34
|
+
# Slice 5 phase 1 projects shape-carrying receivers onto their underlying nominal so the existing
|
|
35
|
+
# dispatch + substitution machinery works without duplication: `Tuple[Integer, String]` dispatches as
|
|
36
|
+
# `Array[Integer | String]`, and `HashShape{a: Integer}` dispatches as `Hash[Symbol, Integer]`.
|
|
37
|
+
# Tuple/HashShape element precision (e.g., `tuple[0]` returning the precise member) is handled by the
|
|
38
|
+
# preceding `ShapeDispatch` tier.
|
|
51
39
|
#
|
|
52
40
|
# Remaining limitations:
|
|
53
41
|
#
|
|
54
|
-
# * `block_type:` is ignored; method types that constrain the
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
# * Method-level type parameters (e.g., `def foo[T]: (T) -> T`)
|
|
60
|
-
# are not bound; their variables remain `Dynamic[Top]` after
|
|
61
|
-
# substitution.
|
|
42
|
+
# * `block_type:` is ignored; method types that constrain the block return type are not yet honored.
|
|
43
|
+
# * Keyword arguments are not threaded through call_arg_types, so overloads with required keywords
|
|
44
|
+
# are skipped (they cannot match the empty kwargs we send).
|
|
45
|
+
# * Method-level type parameters (e.g., `def foo[T]: (T) -> T`) are not bound; their variables remain
|
|
46
|
+
# `Dynamic[Top]` after substitution.
|
|
62
47
|
#
|
|
63
48
|
# See docs/adr/4-type-inference-engine.md for the broader plan.
|
|
64
49
|
# rubocop:disable Metrics/ModuleLength
|
|
65
50
|
module RbsDispatch
|
|
66
51
|
module_function
|
|
67
52
|
|
|
68
|
-
# ADR-43 — ancestor classes whose RBS is authoritative and
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
# owns both the class and `sig/rigor/plugin/base.rbs`, and the
|
|
76
|
-
# `lib` self-check keeps them in lock-step. NOT a place for
|
|
77
|
-
# third-party/core classes whose objects answer to methods
|
|
78
|
-
# their RBS omits (`ActionController::Base`, `Hash`, …).
|
|
53
|
+
# ADR-43 — ancestor classes whose RBS is authoritative and COMPLETE, so a call a subclass makes
|
|
54
|
+
# that the ancestor's RBS does not declare is a genuine mistake rather than a gap. Membership
|
|
55
|
+
# unlocks inherited-method resolution (and thus `call.undefined-method`) for Ruby-source
|
|
56
|
+
# subclasses of these classes; every other RBS ancestor stays on the Dynamic fallback. Seeded with
|
|
57
|
+
# the plugin contract base — this repo owns both the class and `sig/rigor/plugin/base.rbs`, and
|
|
58
|
+
# the `lib` self-check keeps them in lock-step. NOT a place for third-party/core classes whose
|
|
59
|
+
# objects answer to methods their RBS omits (`ActionController::Base`, `Hash`, …).
|
|
79
60
|
ALLOWED_RBS_COMPLETE_ANCESTORS = ["Rigor::Plugin::Base"].freeze
|
|
80
61
|
|
|
81
62
|
# @param receiver [Rigor::Type]
|
|
82
63
|
# @param method_name [Symbol]
|
|
83
64
|
# @param args [Array<Rigor::Type>]
|
|
84
65
|
# @param environment [Rigor::Environment]
|
|
85
|
-
# @param block_type [Rigor::Type, nil] inferred block return
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
# to
|
|
95
|
-
#
|
|
96
|
-
#
|
|
97
|
-
# (
|
|
98
|
-
# `
|
|
99
|
-
# `Bundler::URI::Generic` per `Kernel#dup: () -> self`
|
|
100
|
-
# rather than `Object`. Defaults to nil (compute self
|
|
101
|
-
# from the resolved class_name as before).
|
|
102
|
-
# @param public_only [Boolean] when true, a method whose RBS
|
|
103
|
-
# accessibility is `:private` does not resolve (the call
|
|
104
|
-
# yields `nil`, i.e. "no rule"). Set by the explicit-
|
|
105
|
-
# non-`self`-receiver user-class fallback so a call like
|
|
106
|
-
# `Favourite.select(...)` does not adopt the private
|
|
66
|
+
# @param block_type [Rigor::Type, nil] inferred block return type, propagated from
|
|
67
|
+
# `MethodDispatcher.dispatch`. When non-nil, the selector prefers a block-bearing overload and
|
|
68
|
+
# binds the method-level type parameter that the block's return type references to `block_type`
|
|
69
|
+
# (Slice 6 phase C sub-phase 2).
|
|
70
|
+
# @param self_type_override [Rigor::Type, nil] when set, the substitution for `Bases::Self` in the
|
|
71
|
+
# method's return type. Used by `MethodDispatcher#try_user_class_fallback` to preserve the
|
|
72
|
+
# ORIGINAL receiver as the substitute for `self` even though the dispatch is routed through
|
|
73
|
+
# `Nominal[Object]` — so that `Bundler::URI::Generic.dup` (which resolves through the `Object`
|
|
74
|
+
# fallback because `Bundler::URI::Generic` lacks RBS) returns `Bundler::URI::Generic` per
|
|
75
|
+
# `Kernel#dup: () -> self` rather than `Object`. Defaults to nil (compute self from the resolved
|
|
76
|
+
# class_name as before).
|
|
77
|
+
# @param public_only [Boolean] when true, a method whose RBS accessibility is `:private` does not
|
|
78
|
+
# resolve (the call yields `nil`, i.e. "no rule"). Set by the explicit-non-`self`-receiver
|
|
79
|
+
# user-class fallback so a call like `Favourite.select(...)` does not adopt the private
|
|
107
80
|
# `Kernel#select` signature.
|
|
108
|
-
# @return [Rigor::Type, nil] inferred return type, or `nil`
|
|
109
|
-
#
|
|
110
|
-
#
|
|
111
|
-
#
|
|
112
|
-
#
|
|
113
|
-
# `ALLOWED_RBS_COMPLETE_ANCESTORS`. `nil` keeps inherited calls
|
|
114
|
-
# unresolved (`Dynamic[Top]`) — the FP-safe default for open
|
|
115
|
-
# hierarchies (`< ActionController::Base`, …).
|
|
81
|
+
# @return [Rigor::Type, nil] inferred return type, or `nil` when no rule resolves (no class name,
|
|
82
|
+
# no method, dispatch on a Top/Dynamic[Top] receiver, etc.).
|
|
83
|
+
# @param scope [Rigor::Scope, nil] when supplied, enables ADR-43 RBS-complete-ancestor resolution
|
|
84
|
+
# against `ALLOWED_RBS_COMPLETE_ANCESTORS`. `nil` keeps inherited calls unresolved
|
|
85
|
+
# (`Dynamic[Top]`) — the FP-safe default for open hierarchies (`< ActionController::Base`, …).
|
|
116
86
|
def try_dispatch(context)
|
|
117
87
|
environment = context.environment
|
|
118
88
|
return nil if environment.nil?
|
|
@@ -130,27 +100,22 @@ module Rigor
|
|
|
130
100
|
)
|
|
131
101
|
end
|
|
132
102
|
|
|
133
|
-
# Slice 6 (Phase C sub-phase 1) probe: returns the positional
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
-
# by the StatementEvaluator to bind block parameter names
|
|
137
|
-
# before evaluating the block body.
|
|
103
|
+
# Slice 6 (Phase C sub-phase 1) probe: returns the positional block-parameter types declared by
|
|
104
|
+
# the receiving method's selected RBS overload, translated into `Rigor::Type`. Used by the
|
|
105
|
+
# StatementEvaluator to bind block parameter names before evaluating the block body.
|
|
138
106
|
#
|
|
139
|
-
# The probe shares the receiver descriptor / overload selector
|
|
140
|
-
#
|
|
141
|
-
#
|
|
142
|
-
# type). Returns an empty array when:
|
|
107
|
+
# The probe shares the receiver descriptor / overload selector plumbing with `try_dispatch`; only
|
|
108
|
+
# the projection at the end differs (the block's positional params instead of the return type).
|
|
109
|
+
# Returns an empty array when:
|
|
143
110
|
#
|
|
144
111
|
# - the environment / RBS loader is missing,
|
|
145
112
|
# - the receiver does not project to a known class,
|
|
146
113
|
# - the method has no signature in RBS,
|
|
147
114
|
# - the selected overload has no `block:` clause, or
|
|
148
|
-
# - the block is `untyped` / `UntypedFunction` (no statically
|
|
149
|
-
# declared parameter types).
|
|
115
|
+
# - the block is `untyped` / `UntypedFunction` (no statically declared parameter types).
|
|
150
116
|
#
|
|
151
|
-
# This deliberately does NOT differentiate "no overload had a
|
|
152
|
-
#
|
|
153
|
-
# the same way (every parameter defaults to `Dynamic[Top]`).
|
|
117
|
+
# This deliberately does NOT differentiate "no overload had a block" from "the block is untyped";
|
|
118
|
+
# the binder treats both the same way (every parameter defaults to `Dynamic[Top]`).
|
|
154
119
|
# @return [Array<Rigor::Type>] positional block parameter types.
|
|
155
120
|
def block_param_types(context)
|
|
156
121
|
environment = context.environment
|
|
@@ -215,23 +180,18 @@ module Rigor
|
|
|
215
180
|
self_type_override: self_type_override
|
|
216
181
|
)
|
|
217
182
|
rescue StandardError
|
|
218
|
-
# Defensive: if RBS' definition builder raises on a broken
|
|
219
|
-
#
|
|
220
|
-
# dispatcher MUST stay fail-soft.
|
|
183
|
+
# Defensive: if RBS' definition builder raises on a broken hierarchy (e.g., partially loaded
|
|
184
|
+
# user signatures), the dispatcher MUST stay fail-soft.
|
|
221
185
|
nil
|
|
222
186
|
end
|
|
223
187
|
|
|
224
|
-
# Maps a Rigor::Type receiver to a
|
|
225
|
-
# `
|
|
226
|
-
#
|
|
227
|
-
# the receiver
|
|
228
|
-
# singleton receivers, since `Singleton[Foo]` carries no
|
|
229
|
-
# generic args today). Returns nil when the receiver does
|
|
230
|
-
# not correspond to a single concrete class.
|
|
188
|
+
# Maps a Rigor::Type receiver to a `[class_name, kind, type_args]` triple where `kind` is either
|
|
189
|
+
# `:instance` or `:singleton` and `type_args` carries the receiver's generic instantiation (empty
|
|
190
|
+
# for raw or singleton receivers, since `Singleton[Foo]` carries no generic args today). Returns
|
|
191
|
+
# nil when the receiver does not correspond to a single concrete class.
|
|
231
192
|
#
|
|
232
|
-
# Slice 5 phase 1 projects Tuple/HashShape receivers to
|
|
233
|
-
#
|
|
234
|
-
# generic-typed pipeline.
|
|
193
|
+
# Slice 5 phase 1 projects Tuple/HashShape receivers to their underlying Array/Hash nominal so
|
|
194
|
+
# dispatch reuses the generic-typed pipeline.
|
|
235
195
|
def receiver_descriptor(receiver)
|
|
236
196
|
case receiver
|
|
237
197
|
when Type::Constant
|
|
@@ -247,27 +207,21 @@ module Rigor
|
|
|
247
207
|
when Type::DataInstance, Type::DataClass, Type::StructInstance, Type::StructClass
|
|
248
208
|
member_carrier_descriptor(receiver)
|
|
249
209
|
when Type::BoundMethod
|
|
250
|
-
# `BoundMethod` is a precision-bearing alias for
|
|
251
|
-
# `
|
|
252
|
-
# `(
|
|
253
|
-
#
|
|
254
|
-
#
|
|
255
|
-
# site (`.owner` / `.name` / `.arity` / …) must
|
|
256
|
-
# still resolve through Method's RBS contract.
|
|
257
|
-
# Routing here keeps reflective Method methods
|
|
258
|
-
# working without forcing the carrier to
|
|
259
|
-
# collapse to a plain Nominal at construction.
|
|
210
|
+
# `BoundMethod` is a precision-bearing alias for `Nominal[Method]`: it carries the
|
|
211
|
+
# `(receiver, method_name)` binding that `MethodFolding.try_backward` consumes at
|
|
212
|
+
# `.call` / `.()` / `[]`, but every other call site (`.owner` / `.name` / `.arity` / …) must
|
|
213
|
+
# still resolve through Method's RBS contract. Routing here keeps reflective Method methods
|
|
214
|
+
# working without forcing the carrier to collapse to a plain Nominal at construction.
|
|
260
215
|
["Method", :instance, []]
|
|
261
216
|
when Type::Dynamic
|
|
262
217
|
receiver_descriptor(receiver.static_facet)
|
|
263
218
|
end
|
|
264
219
|
end
|
|
265
220
|
|
|
266
|
-
# ADR-48 — project a `Data`/`Struct` member carrier to its tagging
|
|
267
|
-
#
|
|
268
|
-
#
|
|
269
|
-
#
|
|
270
|
-
# folded by DataFolding / StructFolding above this tier.
|
|
221
|
+
# ADR-48 — project a `Data`/`Struct` member carrier to its tagging class (or the `Data`/`Struct`
|
|
222
|
+
# supertype) so non-member calls (`inspect`, `==`, `frozen?`, ...) resolve through RBS rather
|
|
223
|
+
# than mis-firing undefined-method. Precise member reads were already folded by DataFolding /
|
|
224
|
+
# StructFolding above this tier.
|
|
271
225
|
def member_carrier_descriptor(receiver)
|
|
272
226
|
case receiver
|
|
273
227
|
when Type::DataInstance then [receiver.class_name || "Data", :instance, []]
|
|
@@ -294,11 +248,9 @@ module Rigor
|
|
|
294
248
|
]
|
|
295
249
|
end
|
|
296
250
|
|
|
297
|
-
# True when the RBS method definition is `private`. A call
|
|
298
|
-
#
|
|
299
|
-
# private
|
|
300
|
-
# explicit-receiver user-class fallback uses this to reject
|
|
301
|
-
# private signatures rather than return a wrong type.
|
|
251
|
+
# True when the RBS method definition is `private`. A call with an explicit, non-`self` receiver
|
|
252
|
+
# cannot reach a private method (Ruby raises `NoMethodError`), so the explicit-receiver
|
|
253
|
+
# user-class fallback uses this to reject private signatures rather than return a wrong type.
|
|
302
254
|
def method_private?(method_definition)
|
|
303
255
|
method_definition.respond_to?(:accessibility) &&
|
|
304
256
|
method_definition.accessibility == :private
|
|
@@ -308,15 +260,12 @@ module Rigor
|
|
|
308
260
|
direct = lookup_method_on(environment, class_name, kind, method_name)
|
|
309
261
|
return direct if direct
|
|
310
262
|
|
|
311
|
-
# ADR-43 — scoped inherited-method resolution. The direct
|
|
312
|
-
#
|
|
313
|
-
#
|
|
314
|
-
#
|
|
315
|
-
#
|
|
316
|
-
#
|
|
317
|
-
# resolve and the normal call rules apply. Bounded to the
|
|
318
|
-
# allow-list, so open hierarchies stay on the Dynamic
|
|
319
|
-
# fallback (no false positive on `< ActionController::Base`).
|
|
263
|
+
# ADR-43 — scoped inherited-method resolution. The direct lookup misses when `class_name` is a
|
|
264
|
+
# Ruby-source subclass absent from RBS (so no ancestor walk runs). If its discovered
|
|
265
|
+
# superclass chain reaches an allow-listed RBS-complete ancestor, resolve the method there so
|
|
266
|
+
# inherited contract calls (`self.manifest` on a plugin) resolve and the normal call rules
|
|
267
|
+
# apply. Bounded to the allow-list, so open hierarchies stay on the Dynamic fallback (no false
|
|
268
|
+
# positive on `< ActionController::Base`).
|
|
320
269
|
ancestor = allowed_rbs_complete_ancestor(environment, class_name, scope)
|
|
321
270
|
return nil unless ancestor
|
|
322
271
|
|
|
@@ -332,13 +281,11 @@ module Rigor
|
|
|
332
281
|
end
|
|
333
282
|
end
|
|
334
283
|
|
|
335
|
-
# The first allow-listed, RBS-complete ancestor reachable from
|
|
336
|
-
# `
|
|
337
|
-
#
|
|
338
|
-
#
|
|
339
|
-
#
|
|
340
|
-
# The walk carries a visited set so a malformed cyclic
|
|
341
|
-
# `A < B < A` source cannot loop.
|
|
284
|
+
# The first allow-listed, RBS-complete ancestor reachable from `class_name` through
|
|
285
|
+
# `scope.discovered_superclasses`, or nil. Returns nil when no scope is threaded, when
|
|
286
|
+
# `class_name` is itself RBS-known (the direct lookup already had authority), or when the
|
|
287
|
+
# discovered chain reaches no allow-listed class. The walk carries a visited set so a malformed
|
|
288
|
+
# cyclic `A < B < A` source cannot loop.
|
|
342
289
|
def allowed_rbs_complete_ancestor(environment, class_name, scope)
|
|
343
290
|
return nil if scope.nil?
|
|
344
291
|
return nil if Rigor::Reflection.rbs_class_known?(class_name, environment: environment)
|
|
@@ -355,12 +302,10 @@ module Rigor
|
|
|
355
302
|
nil
|
|
356
303
|
end
|
|
357
304
|
|
|
358
|
-
# Slice 4 phase 2d substitution map. Zips the class's
|
|
359
|
-
#
|
|
360
|
-
#
|
|
361
|
-
#
|
|
362
|
-
# variables in the method's return type degrade to
|
|
363
|
-
# `Dynamic[Top]` per the translator's contract.
|
|
305
|
+
# Slice 4 phase 2d substitution map. Zips the class's declared type-parameter names against the
|
|
306
|
+
# receiver's `type_args`. Returns an empty hash when either side is empty or when arities
|
|
307
|
+
# disagree -- in both cases free variables in the method's return type degrade to `Dynamic[Top]`
|
|
308
|
+
# per the translator's contract.
|
|
364
309
|
def build_type_vars(environment, class_name, receiver_args)
|
|
365
310
|
return {} if receiver_args.empty?
|
|
366
311
|
|
|
@@ -375,12 +320,9 @@ module Rigor
|
|
|
375
320
|
def translate_return_type(method_definition, class_name:, kind:, args:, type_vars:, block_type:,
|
|
376
321
|
environment: nil, self_type_override: nil)
|
|
377
322
|
# rubocop:enable Metrics/ParameterLists
|
|
378
|
-
# Slice 4b-3 (ADR-7 § "Slice 4-A/4-B") — read the
|
|
379
|
-
#
|
|
380
|
-
#
|
|
381
|
-
# `return_type` slot at this call site compose with
|
|
382
|
-
# the RBS::Extended directive instead of silently
|
|
383
|
-
# racing it.
|
|
323
|
+
# Slice 4b-3 (ADR-7 § "Slice 4-A/4-B") — read the return-type override through the merger so
|
|
324
|
+
# future plugin / `:rbs_extended` bundles that also assert a `return_type` slot at this call
|
|
325
|
+
# site compose with the RBS::Extended directive instead of silently racing it.
|
|
384
326
|
override = merged_return_type(method_definition, environment: environment)
|
|
385
327
|
return override if override
|
|
386
328
|
|
|
@@ -390,11 +332,9 @@ module Rigor
|
|
|
390
332
|
when :singleton then Type::Combinator.singleton_of(class_name)
|
|
391
333
|
else instance_type
|
|
392
334
|
end
|
|
393
|
-
# `self_type_override` lets the user-class fallback
|
|
394
|
-
#
|
|
395
|
-
#
|
|
396
|
-
# resolved through the Object fallback returns the
|
|
397
|
-
# caller's type, not Object.
|
|
335
|
+
# `self_type_override` lets the user-class fallback path preserve the ORIGINAL receiver as the
|
|
336
|
+
# substitute for `Bases::Self` — so `Kernel#dup: () -> self` resolved through the Object
|
|
337
|
+
# fallback returns the caller's type, not Object.
|
|
398
338
|
self_type = self_type_override || resolved_self_type
|
|
399
339
|
|
|
400
340
|
method_type = OverloadSelector.select(
|
|
@@ -418,12 +358,9 @@ module Rigor
|
|
|
418
358
|
)
|
|
419
359
|
end
|
|
420
360
|
|
|
421
|
-
# ADR-7 § "Slice 4-A/4-B" — folds the
|
|
422
|
-
# `
|
|
423
|
-
#
|
|
424
|
-
# slices add at this call site) through the merger
|
|
425
|
-
# before consuming. Returns the merged return type
|
|
426
|
-
# or nil when no contribution overrides the
|
|
361
|
+
# ADR-7 § "Slice 4-A/4-B" — folds the `RBS::Extended` `return:` directive (and any other
|
|
362
|
+
# `return_type`-bearing contribution future slices add at this call site) through the merger
|
|
363
|
+
# before consuming. Returns the merged return type or nil when no contribution overrides the
|
|
427
364
|
# RBS-declared return.
|
|
428
365
|
def merged_return_type(method_definition, environment: nil)
|
|
429
366
|
contribution = RbsExtended.read_flow_contribution(method_definition, environment: environment)
|
|
@@ -432,18 +369,13 @@ module Rigor
|
|
|
432
369
|
Rigor::FlowContribution::Merger.merge([contribution]).return_type
|
|
433
370
|
end
|
|
434
371
|
|
|
435
|
-
# When a block type is supplied, locate the method-level
|
|
436
|
-
# type
|
|
437
|
-
#
|
|
438
|
-
#
|
|
439
|
-
#
|
|
440
|
-
# `
|
|
441
|
-
# `
|
|
442
|
-
# type at the same call site. Anything outside this exact
|
|
443
|
-
# shape (no block clause, an `untyped` block, a non-
|
|
444
|
-
# variable block return type, a variable not declared in
|
|
445
|
-
# `type_params`) returns the original `type_vars` so
|
|
446
|
-
# fallbacks stay consistent.
|
|
372
|
+
# When a block type is supplied, locate the method-level type parameter that the selected
|
|
373
|
+
# overload's block return type references and bind it to `block_type`. The contribution layers
|
|
374
|
+
# on top of the receiver-derived `type_vars` so a method like
|
|
375
|
+
# `def map[U] { (Elem) -> U } -> Array[U]` resolves `Elem` from the receiver and `U` from the
|
|
376
|
+
# block return type at the same call site. Anything outside this exact shape (no block clause,
|
|
377
|
+
# an `untyped` block, a non-variable block return type, a variable not declared in
|
|
378
|
+
# `type_params`) returns the original `type_vars` so fallbacks stay consistent.
|
|
447
379
|
def compose_block_type_vars(method_type, type_vars, block_type)
|
|
448
380
|
return type_vars if block_type.nil?
|
|
449
381
|
|
|
@@ -485,12 +417,10 @@ module Rigor
|
|
|
485
417
|
end
|
|
486
418
|
end
|
|
487
419
|
|
|
488
|
-
# For a union receiver we keep the conservative answer: only
|
|
489
|
-
#
|
|
490
|
-
#
|
|
491
|
-
#
|
|
492
|
-
# support yet). Mismatches degrade to the empty array so the
|
|
493
|
-
# binder defaults all params to Dynamic[Top].
|
|
420
|
+
# For a union receiver we keep the conservative answer: only return block param types when every
|
|
421
|
+
# member resolves the same arity and types (otherwise the call sites would have to thread
|
|
422
|
+
# per-member binders, which the slice does not support yet). Mismatches degrade to the empty
|
|
423
|
+
# array so the binder defaults all params to Dynamic[Top].
|
|
494
424
|
def probe_block_param_types_union(receiver, method_name, args, environment)
|
|
495
425
|
results = receiver.members.map do |member|
|
|
496
426
|
probe_block_param_types_one(member, method_name, args, environment)
|
|
@@ -553,11 +483,10 @@ module Rigor
|
|
|
553
483
|
)
|
|
554
484
|
end
|
|
555
485
|
|
|
556
|
-
# `RBS::Types::Block#type` is normally an `RBS::Types::Function`
|
|
557
|
-
#
|
|
558
|
-
#
|
|
559
|
-
#
|
|
560
|
-
# return an empty array so the binder defaults every slot.
|
|
486
|
+
# `RBS::Types::Block#type` is normally an `RBS::Types::Function` carrying the block's parameter
|
|
487
|
+
# list; some signatures use `RBS::Types::UntypedFunction` (a `(?)` block) which exposes no
|
|
488
|
+
# parameter types -- we treat it as "no information" and return an empty array so the binder
|
|
489
|
+
# defaults every slot.
|
|
561
490
|
def translate_block_positional_params(block, self_type:, instance_type:, type_vars:)
|
|
562
491
|
fun = block.type
|
|
563
492
|
return [] unless fun.respond_to?(:required_positionals)
|
|
@@ -5,25 +5,18 @@ require_relative "../../type"
|
|
|
5
5
|
module Rigor
|
|
6
6
|
module Inference
|
|
7
7
|
module MethodDispatcher
|
|
8
|
-
# Stable-sort an overload list so that "receiver-affinity"
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# `Integer#+(?)` by overload-list position alone, returning
|
|
17
|
-
# a spurious `BigDecimal` for plain integer arithmetic.
|
|
18
|
-
# Demoting the arm honours the coerce convention: when the
|
|
19
|
-
# arg type is unknown or itself an Integer, the
|
|
20
|
-
# receiver-preserving `(Integer) -> Integer` arm should win.
|
|
8
|
+
# Stable-sort an overload list so that "receiver-affinity" arms come first. An overload is
|
|
9
|
+
# receiver-affinity-matching when every positional param's class equals `self_type`'s class name OR
|
|
10
|
+
# is one of its proper RBS ancestors. The canonical case the helper exists for: when `bigdecimal`'s
|
|
11
|
+
# stdlib RBS reopens `Integer#+` at the FRONT of the overload list with `(BigDecimal) -> BigDecimal`,
|
|
12
|
+
# that disjoint-sibling arm would win every dispatch for `Integer#+(?)` by overload-list position
|
|
13
|
+
# alone, returning a spurious `BigDecimal` for plain integer arithmetic. Demoting the arm honours the
|
|
14
|
+
# coerce convention: when the arg type is unknown or itself an Integer, the receiver-preserving
|
|
15
|
+
# `(Integer) -> Integer` arm should win.
|
|
21
16
|
#
|
|
22
|
-
# No-op when (a) the environment can't answer
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
# is stable, so within each bucket the RBS-declared order
|
|
26
|
-
# is preserved.
|
|
17
|
+
# No-op when (a) the environment can't answer `class_ordering` (nil env), or (b) the receiver isn't a
|
|
18
|
+
# nominal / singleton carrying a class name. The partition is stable, so within each bucket the
|
|
19
|
+
# RBS-declared order is preserved.
|
|
27
20
|
module ReceiverAffinity
|
|
28
21
|
module_function
|
|
29
22
|
|
|
@@ -56,12 +49,10 @@ module Rigor
|
|
|
56
49
|
params.all? { |param| param_class_in_ancestry?(param.type, self_class_name, environment) }
|
|
57
50
|
end
|
|
58
51
|
|
|
59
|
-
# Walks Optional and Union one level so `(Numeric?)` and
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
# don't carry a clean class identity and therefore
|
|
64
|
-
# disqualify the overload from the affinity bucket.
|
|
52
|
+
# Walks Optional and Union one level so `(Numeric?)` and `(Integer | Float)` still classify when
|
|
53
|
+
# every branch sits in the ancestry. Non-`ClassInstance` shapes (Alias / Interface / Intersection
|
|
54
|
+
# / type variables) don't carry a clean class identity and therefore disqualify the overload from
|
|
55
|
+
# the affinity bucket.
|
|
65
56
|
def param_class_in_ancestry?(rbs_type, self_class_name, environment)
|
|
66
57
|
case rbs_type
|
|
67
58
|
when RBS::Types::ClassInstance
|