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
|
@@ -5,92 +5,69 @@ require_relative "method_catalog"
|
|
|
5
5
|
module Rigor
|
|
6
6
|
module Inference
|
|
7
7
|
module Builtins
|
|
8
|
-
# `Proc` / `Method` / `UnboundMethod` catalog. Singleton —
|
|
9
|
-
# load once, consult during dispatch.
|
|
8
|
+
# `Proc` / `Method` / `UnboundMethod` catalog. Singleton — load once, consult during dispatch.
|
|
10
9
|
#
|
|
11
|
-
# The three callable carriers are imported together because
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
# themselves do not call `rb_funcall*` / `rb_yield` directly
|
|
20
|
-
# (they delegate through the VM's optimised call paths and
|
|
21
|
-
# method-entry table), but folding any of them at compile
|
|
22
|
-
# time would freeze a value the runtime never actually
|
|
23
|
-
# produces twice.
|
|
10
|
+
# The three callable carriers are imported together because `Init_Proc` registers them in a single
|
|
11
|
+
# C init block. They share the same fundamental hazard at the catalog tier: most of their public
|
|
12
|
+
# methods invoke the wrapped Ruby code (the proc body, the bound method's receiver, …) and that code
|
|
13
|
+
# can do anything — read mutable state, call I/O, return different values on successive calls. The
|
|
14
|
+
# static C-body classifier marks these `:leaf` because the C functions themselves do not call
|
|
15
|
+
# `rb_funcall*` / `rb_yield` directly (they delegate through the VM's optimised call paths and
|
|
16
|
+
# method-entry table), but folding any of them at compile time would freeze a value the runtime
|
|
17
|
+
# never actually produces twice.
|
|
24
18
|
#
|
|
25
|
-
# The blocklist below errs aggressively on the side of
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
# `#source_location`, `#name`, `#owner`, `#receiver`) remain
|
|
32
|
-
# foldable; the RBS tier still resolves return types for
|
|
33
|
-
# the blocklisted methods so callers do not lose precision.
|
|
19
|
+
# The blocklist below errs aggressively on the side of caution: a hypothetical future
|
|
20
|
+
# `Constant<Proc>` / `Constant<Method>` / `Constant<UnboundMethod>` carrier would have very little
|
|
21
|
+
# to gain from these folds and a great deal to lose if user code ran behind the analyzer's back.
|
|
22
|
+
# Reflective readers (`#arity`, `#parameters`, `#source_location`, `#name`, `#owner`, `#receiver`)
|
|
23
|
+
# remain foldable; the RBS tier still resolves return types for the blocklisted methods so callers
|
|
24
|
+
# do not lose precision.
|
|
34
25
|
PROC_CATALOG = MethodCatalog.for_topic(
|
|
35
26
|
"proc",
|
|
36
27
|
mutating_selectors: {
|
|
37
28
|
"Proc" => Set[
|
|
38
|
-
# `#call` / `#[]` / `#===` / `#yield` invoke the proc
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
# classifier cannot see into); the proc body can do
|
|
42
|
-
# anything — read globals, mutate captured locals,
|
|
43
|
-
# raise. MUST decline to fold.
|
|
29
|
+
# `#call` / `#[]` / `#===` / `#yield` invoke the proc body. The C body routes through
|
|
30
|
+
# `OPTIMIZED_METHOD_TYPE_CALL` (a VM fast path the classifier cannot see into); the proc body
|
|
31
|
+
# can do anything — read globals, mutate captured locals, raise. MUST decline to fold.
|
|
44
32
|
:call,
|
|
45
33
|
:[],
|
|
46
34
|
:===,
|
|
47
35
|
:yield,
|
|
48
|
-
# `#curry` / `#<<` / `#>>` allocate a fresh `Proc`
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
# never actually produces (object_id differs every
|
|
53
|
-
# call), so the catalog tier declines.
|
|
36
|
+
# `#curry` / `#<<` / `#>>` allocate a fresh `Proc` that closes over the receiver (and, for
|
|
37
|
+
# `<<` / `>>`, over the argument). Folding would freeze a specific `Proc` instance whose
|
|
38
|
+
# identity the runtime never actually produces (object_id differs every call), so the catalog
|
|
39
|
+
# tier declines.
|
|
54
40
|
:curry,
|
|
55
41
|
:<<,
|
|
56
42
|
:>>,
|
|
57
|
-
# `#to_proc` returns `self` for `Proc` (cheap), but
|
|
58
|
-
#
|
|
59
|
-
# three callable carriers (Method#to_proc allocates a
|
|
60
|
-
# fresh `Proc`).
|
|
43
|
+
# `#to_proc` returns `self` for `Proc` (cheap), but blocking it keeps the rule shape uniform
|
|
44
|
+
# across the three callable carriers (Method#to_proc allocates a fresh `Proc`).
|
|
61
45
|
:to_proc,
|
|
62
|
-
# Identity-based equality and hashing: `#hash` is
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
# `Constant<Integer>` / `Constant<bool>` would freeze
|
|
66
|
-
# an answer that depends on memory layout. Defensive.
|
|
46
|
+
# Identity-based equality and hashing: `#hash` is derived from the underlying ISeq pointer;
|
|
47
|
+
# `#==` / `#eql?` compare ISeq + binding. Folding to a `Constant<Integer>` / `Constant<bool>`
|
|
48
|
+
# would freeze an answer that depends on memory layout. Defensive.
|
|
67
49
|
:hash,
|
|
68
50
|
:==,
|
|
69
51
|
:eql?,
|
|
70
|
-
# `initialize_copy` is blocklisted by convention so a
|
|
71
|
-
#
|
|
72
|
-
# fold an aliasing copy through the catalog.
|
|
52
|
+
# `initialize_copy` is blocklisted by convention so a hypothetical future `Constant<Proc>`
|
|
53
|
+
# carrier cannot fold an aliasing copy through the catalog.
|
|
73
54
|
:initialize_copy
|
|
74
55
|
],
|
|
75
56
|
"Method" => Set[
|
|
76
|
-
# `#call` / `#[]` / `#===` invoke the bound method.
|
|
77
|
-
#
|
|
78
|
-
# arbitrary side effects.
|
|
57
|
+
# `#call` / `#[]` / `#===` invoke the bound method. Same hazard as `Proc#call`: arbitrary user
|
|
58
|
+
# code, arbitrary side effects.
|
|
79
59
|
:call,
|
|
80
60
|
:[],
|
|
81
61
|
:===,
|
|
82
|
-
# `#curry` / `#<<` / `#>>` allocate a fresh `Proc`
|
|
83
|
-
# that closes over the bound method.
|
|
62
|
+
# `#curry` / `#<<` / `#>>` allocate a fresh `Proc` that closes over the bound method.
|
|
84
63
|
:curry,
|
|
85
64
|
:<<,
|
|
86
65
|
:>>,
|
|
87
|
-
# `#to_proc` allocates a fresh `Proc` wrapping the
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
# but the explicit entry keeps the intent obvious.
|
|
66
|
+
# `#to_proc` allocates a fresh `Proc` wrapping the bound method — folding would freeze its
|
|
67
|
+
# object_id. The classifier already marks it `:block_dependent`, but the explicit entry keeps
|
|
68
|
+
# the intent obvious.
|
|
91
69
|
:to_proc,
|
|
92
|
-
# `#unbind` allocates a fresh `UnboundMethod` whose
|
|
93
|
-
# identity differs every call.
|
|
70
|
+
# `#unbind` allocates a fresh `UnboundMethod` whose identity differs every call.
|
|
94
71
|
:unbind,
|
|
95
72
|
# Identity-based equality and hashing.
|
|
96
73
|
:hash,
|
|
@@ -100,9 +77,8 @@ module Rigor
|
|
|
100
77
|
:initialize_copy
|
|
101
78
|
],
|
|
102
79
|
"UnboundMethod" => Set[
|
|
103
|
-
# `#bind` allocates a fresh `Method` whose object_id
|
|
104
|
-
#
|
|
105
|
-
# method (already classified `:block_dependent`).
|
|
80
|
+
# `#bind` allocates a fresh `Method` whose object_id differs every call; `#bind_call` invokes
|
|
81
|
+
# the bound method (already classified `:block_dependent`).
|
|
106
82
|
:bind,
|
|
107
83
|
:bind_call,
|
|
108
84
|
# Identity-based equality and hashing.
|
|
@@ -5,47 +5,36 @@ require_relative "method_catalog"
|
|
|
5
5
|
module Rigor
|
|
6
6
|
module Inference
|
|
7
7
|
module Builtins
|
|
8
|
-
# `Random` catalog. Singleton — load once, consult during
|
|
9
|
-
# dispatch.
|
|
8
|
+
# `Random` catalog. Singleton — load once, consult during dispatch.
|
|
10
9
|
#
|
|
11
|
-
# The static classifier marks most Random methods `:leaf`
|
|
12
|
-
#
|
|
13
|
-
# `
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
# `Random.new_seed` and `Random.urandom` are non-deterministic
|
|
20
|
-
# (different output every call); even though they are
|
|
21
|
-
# functionally pure they would produce a misleading constant
|
|
22
|
-
# at fold time. The whole class is conservative-by-default
|
|
23
|
-
# at the catalog tier; precision flows through the RBS layer.
|
|
10
|
+
# The static classifier marks most Random methods `:leaf` because their C bodies do not call
|
|
11
|
+
# `rb_funcall*` / `rb_yield` / `rb_check_frozen` directly. Random is the canonical case where that
|
|
12
|
+
# heuristic under-counts: every call to `#rand` / `#bytes` / `Random.rand` / `Random.bytes` advances
|
|
13
|
+
# the receiver's Mersenne-Twister state through a helper (`rand_random` -> `random_real` /
|
|
14
|
+
# `random_ulong_limited`), so folding any of them statically is unsound. `Random.new_seed` and
|
|
15
|
+
# `Random.urandom` are non-deterministic (different output every call); even though they are
|
|
16
|
+
# functionally pure they would produce a misleading constant at fold time. The whole class is
|
|
17
|
+
# conservative-by-default at the catalog tier; precision flows through the RBS layer.
|
|
24
18
|
RANDOM_CATALOG = MethodCatalog.for_topic(
|
|
25
19
|
"random",
|
|
26
20
|
mutating_selectors: {
|
|
27
21
|
"Random" => Set[
|
|
28
|
-
# `rand_random` -> `random_real` / `random_ulong_limited`
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
# classifier misses the indirect mutator.
|
|
22
|
+
# `rand_random` -> `random_real` / `random_ulong_limited` advance the MT state on the receiver
|
|
23
|
+
# (instance #rand) and on `Random::DEFAULT` (singleton .rand). The classifier misses the
|
|
24
|
+
# indirect mutator.
|
|
32
25
|
:rand,
|
|
33
|
-
# `random_bytes` / `random_s_bytes` consume MT output
|
|
34
|
-
# the
|
|
35
|
-
# underlying generator.
|
|
26
|
+
# `random_bytes` / `random_s_bytes` consume MT output the same way #rand does — every call
|
|
27
|
+
# mutates the underlying generator.
|
|
36
28
|
:bytes,
|
|
37
|
-
# Non-deterministic: each call produces a fresh seed
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
# never actually returns twice.
|
|
29
|
+
# Non-deterministic: each call produces a fresh seed via `with_random_seed` reading platform
|
|
30
|
+
# entropy. Folding to a constant would freeze a value that the runtime never actually returns
|
|
31
|
+
# twice.
|
|
41
32
|
:new_seed,
|
|
42
|
-
# Non-deterministic: reads from platform CSPRNG (e.g.
|
|
43
|
-
#
|
|
44
|
-
# as `new_seed`.
|
|
33
|
+
# Non-deterministic: reads from platform CSPRNG (e.g. /dev/urandom). Folding is unsound for
|
|
34
|
+
# the same reason as `new_seed`.
|
|
45
35
|
:urandom,
|
|
46
|
-
# `initialize_copy` is blocklisted by convention so a
|
|
47
|
-
#
|
|
48
|
-
# cannot fold an aliasing copy through the catalog.
|
|
36
|
+
# `initialize_copy` is blocklisted by convention so a hypothetical future `Constant<Random>`
|
|
37
|
+
# carrier cannot fold an aliasing copy through the catalog.
|
|
49
38
|
:initialize_copy
|
|
50
39
|
]
|
|
51
40
|
}
|
|
@@ -5,35 +5,26 @@ require_relative "method_catalog"
|
|
|
5
5
|
module Rigor
|
|
6
6
|
module Inference
|
|
7
7
|
module Builtins
|
|
8
|
-
# `Range` catalog. Singleton — load once, consult during
|
|
9
|
-
# dispatch.
|
|
8
|
+
# `Range` catalog. Singleton — load once, consult during dispatch.
|
|
10
9
|
#
|
|
11
|
-
# Range is largely immutable: `begin`, `end`, and `excl` are
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# routes through a helper the block/yield regex does not
|
|
16
|
-
# recognise, so the classifier mis-flags them as `:leaf`
|
|
17
|
-
# despite yielding to a block.
|
|
10
|
+
# Range is largely immutable: `begin`, `end`, and `excl` are set at construction by
|
|
11
|
+
# `range_initialize` and never mutated afterwards. The blocklist below therefore stays small. The
|
|
12
|
+
# entries we DO need are the iteration methods whose C body routes through a helper the block/yield
|
|
13
|
+
# regex does not recognise, so the classifier mis-flags them as `:leaf` despite yielding to a block.
|
|
18
14
|
RANGE_CATALOG = MethodCatalog.for_topic(
|
|
19
15
|
"range",
|
|
20
16
|
mutating_selectors: {
|
|
21
17
|
"Range" => Set[
|
|
22
|
-
# `range_initialize` / `range_initialize_copy` write
|
|
23
|
-
# `
|
|
24
|
-
#
|
|
25
|
-
# accessor not `rb_check_frozen`. Blocked for symmetry
|
|
26
|
-
# with String / Array.
|
|
18
|
+
# `range_initialize` / `range_initialize_copy` write `begin`/`end`/`excl` slots on the
|
|
19
|
+
# receiver; classed `:leaf` because the writes go through the struct accessor not
|
|
20
|
+
# `rb_check_frozen`. Blocked for symmetry with String / Array.
|
|
27
21
|
:initialize, :initialize_copy,
|
|
28
|
-
# `range_reverse_each` yields to its block via
|
|
29
|
-
# `range_each_func` -> caller's block; the regex
|
|
22
|
+
# `range_reverse_each` yields to its block via `range_each_func` -> caller's block; the regex
|
|
30
23
|
# classifier follows direct `rb_yield*` calls only.
|
|
31
24
|
:reverse_each,
|
|
32
|
-
# `range_percent_step` returns an Enumerator unless a
|
|
33
|
-
# block
|
|
34
|
-
#
|
|
35
|
-
# against a literal Range and tries to materialise an
|
|
36
|
-
# Enumerator into a Constant.
|
|
25
|
+
# `range_percent_step` returns an Enumerator unless a block is supplied, in which case it
|
|
26
|
+
# yields. Treated as block-dependent so the fold tier never invokes it against a literal Range
|
|
27
|
+
# and tries to materialise an Enumerator into a Constant.
|
|
37
28
|
:%
|
|
38
29
|
]
|
|
39
30
|
}
|
|
@@ -5,23 +5,17 @@ require_relative "method_catalog"
|
|
|
5
5
|
module Rigor
|
|
6
6
|
module Inference
|
|
7
7
|
module Builtins
|
|
8
|
-
# `Rational` catalog. Singleton — load once, consult during
|
|
9
|
-
# dispatch.
|
|
8
|
+
# `Rational` catalog. Singleton — load once, consult during dispatch.
|
|
10
9
|
#
|
|
11
|
-
# Rational is fully immutable: numerator / denominator slots
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# user-redefinable `==` / `Float()` — `nurat_eqeq_p` and
|
|
17
|
-
# `nurat_fdiv`). Bang-suffixed mutators do not exist on
|
|
18
|
-
# Rational.
|
|
10
|
+
# Rational is fully immutable: numerator / denominator slots are written once during
|
|
11
|
+
# `nurat_s_new_internal` and the C body never reaches for `rb_check_frozen`. Every catalog entry
|
|
12
|
+
# classifies cleanly (`:leaf`, `:leaf_when_numeric`, or `:dispatch` for the two methods that
|
|
13
|
+
# delegate into user-redefinable `==` / `Float()` — `nurat_eqeq_p` and `nurat_fdiv`). Bang-suffixed
|
|
14
|
+
# mutators do not exist on Rational.
|
|
19
15
|
#
|
|
20
|
-
# The blocklist therefore stays minimal. `initialize_copy`
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
# fold an aliasing copy through the catalog and surface a
|
|
24
|
-
# shared mutable handle.
|
|
16
|
+
# The blocklist therefore stays minimal. `initialize_copy` is added defensively (mirrors Range /
|
|
17
|
+
# Set) so a hypothetical future `Constant<Rational>` carrier cannot fold an aliasing copy through
|
|
18
|
+
# the catalog and surface a shared mutable handle.
|
|
25
19
|
RATIONAL_CATALOG = MethodCatalog.for_topic(
|
|
26
20
|
"rational",
|
|
27
21
|
mutating_selectors: {
|
|
@@ -5,70 +5,51 @@ require_relative "method_catalog"
|
|
|
5
5
|
module Rigor
|
|
6
6
|
module Inference
|
|
7
7
|
module Builtins
|
|
8
|
-
# `Regexp` / `MatchData` catalog. Singleton — load once,
|
|
9
|
-
# consult during dispatch.
|
|
8
|
+
# `Regexp` / `MatchData` catalog. Singleton — load once, consult during dispatch.
|
|
10
9
|
#
|
|
11
|
-
# `Init_Regexp` in `references/ruby/re.c` registers BOTH
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
# (the result-of-match carrier produced by `Regexp#match` /
|
|
15
|
-
# `String#match` and consulted via `$~`). The catalog wiring
|
|
10
|
+
# `Init_Regexp` in `references/ruby/re.c` registers BOTH classes in a single C init block, so the
|
|
11
|
+
# catalog carries both — `Regexp` (the pattern carrier) plus `MatchData` (the result-of-match
|
|
12
|
+
# carrier produced by `Regexp#match` / `String#match` and consulted via `$~`). The catalog wiring
|
|
16
13
|
# therefore mostly governs:
|
|
17
14
|
#
|
|
18
|
-
# 1. The reader surface on each class (`Regexp#source`,
|
|
19
|
-
# `
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
# `Regexp#=~`, `#===` and `#~` all call `rb_backref_set`
|
|
26
|
-
# (writing `$~` and the `$1..$N` / `$&` / `` $` `` / `$'`
|
|
27
|
-
# aliases). A constant-fold that dropped those calls
|
|
28
|
-
# would silently change the visible state of the program,
|
|
15
|
+
# 1. The reader surface on each class (`Regexp#source`, `Regexp#options`, `Regexp#casefold?`,
|
|
16
|
+
# `MatchData#size`, `MatchData#captures`, etc.) — RBS-declared returns are preserved through
|
|
17
|
+
# dispatch.
|
|
18
|
+
# 2. The blocklist below, which keeps methods that touch process-global state (the `$~` backref)
|
|
19
|
+
# from being folded. Regexp matching is observably stateful: `Regexp#=~`, `#===` and `#~` all
|
|
20
|
+
# call `rb_backref_set` (writing `$~` and the `$1..$N` / `$&` / `` $` `` / `$'` aliases). A
|
|
21
|
+
# constant-fold that dropped those calls would silently change the visible state of the program,
|
|
29
22
|
# so they MUST decline through to the RBS tier.
|
|
30
23
|
#
|
|
31
|
-
# `Regexp.last_match` and `Regexp.timeout` / `Regexp.timeout=`
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
# so listing them here would be dead code. Their RBS-tier
|
|
38
|
-
# signatures already widen the answer enough to keep the
|
|
39
|
-
# behaviour sound; revisit if the dispatcher ever grows a
|
|
40
|
-
# singleton-aware catalog path.
|
|
24
|
+
# `Regexp.last_match` and `Regexp.timeout` / `Regexp.timeout=` are class-level (singleton) methods
|
|
25
|
+
# that also touch process-global state, but the dispatcher's catalog lookup only consults
|
|
26
|
+
# `:instance` entries today — class-method calls on a `Singleton` receiver type take the `meta_*`
|
|
27
|
+
# path in `MethodDispatcher` rather than walking `CATALOG_BY_CLASS` — so listing them here would be
|
|
28
|
+
# dead code. Their RBS-tier signatures already widen the answer enough to keep the behaviour sound;
|
|
29
|
+
# revisit if the dispatcher ever grows a singleton-aware catalog path.
|
|
41
30
|
REGEXP_CATALOG = MethodCatalog.for_topic(
|
|
42
31
|
"re",
|
|
43
32
|
mutating_selectors: {
|
|
44
33
|
"Regexp" => Set[
|
|
45
|
-
# Defensive: aliasing-copy semantics already covered
|
|
46
|
-
#
|
|
47
|
-
# symmetry with String / Array / Hash / Range / Set.
|
|
34
|
+
# Defensive: aliasing-copy semantics already covered by the `:mutates_self` classifier,
|
|
35
|
+
# listed here for symmetry with String / Array / Hash / Range / Set.
|
|
48
36
|
:initialize_copy,
|
|
49
|
-
# `=~`, `===`, `~` all run `rb_reg_search` (or call
|
|
50
|
-
# `
|
|
51
|
-
#
|
|
52
|
-
# `$1..$N` / `$&` / `` $` `` / `$'` aliases. Folding
|
|
53
|
-
# would discard the visible side effect.
|
|
37
|
+
# `=~`, `===`, `~` all run `rb_reg_search` (or call `rb_backref_set(Qnil)` directly) — every
|
|
38
|
+
# successful OR failing match writes `$~` and the `$1..$N` / `$&` / `` $` `` / `$'` aliases.
|
|
39
|
+
# Folding would discard the visible side effect.
|
|
54
40
|
:=~,
|
|
55
41
|
:"===",
|
|
56
42
|
:~,
|
|
57
|
-
# `match` is already `:block_dependent` (the C body
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
# reclassifies it as `:leaf` (because the yield is
|
|
61
|
-
# behind a helper) does not silently fold it.
|
|
43
|
+
# `match` is already `:block_dependent` (the C body yields), but it ALSO writes `$~`
|
|
44
|
+
# regardless of the block. Listed here so a future extractor that reclassifies it as `:leaf`
|
|
45
|
+
# (because the yield is behind a helper) does not silently fold it.
|
|
62
46
|
:match
|
|
63
47
|
],
|
|
64
48
|
"MatchData" => Set[
|
|
65
|
-
# Defensive entry mirroring the other catalogs.
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
# mutator); blocked so a future
|
|
70
|
-
# `Constant<MatchData>` carrier never folds an
|
|
71
|
-
# aliasing copy through the catalog.
|
|
49
|
+
# Defensive entry mirroring the other catalogs. `match_init_copy` is already `:leaf` per the
|
|
50
|
+
# extractor (it copies the regs slot in place but uses no helper the C-body regex flags as a
|
|
51
|
+
# mutator); blocked so a future `Constant<MatchData>` carrier never folds an aliasing copy
|
|
52
|
+
# through the catalog.
|
|
72
53
|
:initialize_copy
|
|
73
54
|
]
|
|
74
55
|
}
|
|
@@ -7,41 +7,32 @@ module Rigor
|
|
|
7
7
|
module Builtins
|
|
8
8
|
# `Set` catalog. Singleton — load once, consult during dispatch.
|
|
9
9
|
#
|
|
10
|
-
# Set was rewritten in C and folded into CRuby for Ruby 3.2+;
|
|
11
|
-
# the
|
|
12
|
-
# `
|
|
13
|
-
#
|
|
14
|
-
# `rb_provide("set.rb")` makes `require "set"` a no-op against
|
|
15
|
-
# the built-in.
|
|
10
|
+
# Set was rewritten in C and folded into CRuby for Ruby 3.2+; the reference branch (`ruby_4_0`)
|
|
11
|
+
# ships the implementation in `references/ruby/set.c` with `Init_Set` registering every method
|
|
12
|
+
# directly. There is no `set.rb` prelude — the trailing `rb_provide("set.rb")` makes `require "set"`
|
|
13
|
+
# a no-op against the built-in.
|
|
16
14
|
#
|
|
17
|
-
# The blocklist below catches the catalog `:leaf` entries the
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# does not yet recognise as block-yielding or mutating.
|
|
15
|
+
# The blocklist below catches the catalog `:leaf` entries the C-body classifier mis-attributes.
|
|
16
|
+
# Set's iteration helpers (`set_iter`, `RETURN_SIZED_ENUMERATOR`) and its identity-mode and reset
|
|
17
|
+
# paths drive into helpers the regex classifier does not yet recognise as block-yielding or
|
|
18
|
+
# mutating.
|
|
22
19
|
SET_CATALOG = MethodCatalog.for_topic(
|
|
23
20
|
"set",
|
|
24
21
|
mutating_selectors: {
|
|
25
22
|
"Set" => Set[
|
|
26
|
-
# Indirect mutators classified `:leaf` because the C
|
|
27
|
-
#
|
|
23
|
+
# Indirect mutators classified `:leaf` because the C classifier did not follow the helper
|
|
24
|
+
# functions:
|
|
28
25
|
#
|
|
29
|
-
# - `initialize_copy` calls `set_copy` to overwrite the
|
|
30
|
-
#
|
|
31
|
-
# - `
|
|
32
|
-
# via `set_reset_table_with_type`.
|
|
33
|
-
# - `reset` rebuilds the internal table to dedup after
|
|
34
|
-
# element mutation.
|
|
26
|
+
# - `initialize_copy` calls `set_copy` to overwrite the receiver's table.
|
|
27
|
+
# - `compare_by_identity` swaps the internal hash type via `set_reset_table_with_type`.
|
|
28
|
+
# - `reset` rebuilds the internal table to dedup after element mutation.
|
|
35
29
|
:initialize_copy, :compare_by_identity, :reset,
|
|
36
|
-
# Block-dependent methods classified `:leaf` because the
|
|
37
|
-
#
|
|
38
|
-
# rather than calling `rb_yield` directly:
|
|
30
|
+
# Block-dependent methods classified `:leaf` because the C body uses `set_iter` /
|
|
31
|
+
# `RETURN_SIZED_ENUMERATOR` rather than calling `rb_yield` directly:
|
|
39
32
|
:each, :classify, :divide,
|
|
40
|
-
# `disjoint?` delegates into `set_i_intersect`, which
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
# classifier missed because the call site is in a
|
|
44
|
-
# sibling function.
|
|
33
|
+
# `disjoint?` delegates into `set_i_intersect`, which for non-Set enumerables uses
|
|
34
|
+
# `rb_funcall(other, :any?, ...)` — that is user-redefinable dispatch the classifier missed
|
|
35
|
+
# because the call site is in a sibling function.
|
|
45
36
|
:disjoint?
|
|
46
37
|
]
|
|
47
38
|
}
|
|
@@ -5,16 +5,12 @@ require_relative "method_catalog"
|
|
|
5
5
|
module Rigor
|
|
6
6
|
module Inference
|
|
7
7
|
module Builtins
|
|
8
|
-
# `String` and `Symbol` catalog. Singleton — load once,
|
|
9
|
-
# consult during dispatch.
|
|
8
|
+
# `String` and `Symbol` catalog. Singleton — load once, consult during dispatch.
|
|
10
9
|
#
|
|
11
|
-
# The blocklist below is the curated set of catalog `:leaf`
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# mutation primitives). Adding to the blocklist is the
|
|
16
|
-
# corrective surface for false positives until the
|
|
17
|
-
# classifier learns the helper functions.
|
|
10
|
+
# The blocklist below is the curated set of catalog `:leaf` entries the C-body classifier
|
|
11
|
+
# mis-attributes (the body of `rb_str_replace` calls `str_modifiable` / `str_discard` which the
|
|
12
|
+
# regex-based classifier does not recognise as mutation primitives). Adding to the blocklist is the
|
|
13
|
+
# corrective surface for false positives until the classifier learns the helper functions.
|
|
18
14
|
STRING_CATALOG = MethodCatalog.for_topic(
|
|
19
15
|
"string",
|
|
20
16
|
mutating_selectors: {
|
|
@@ -23,19 +19,16 @@ module Rigor
|
|
|
23
19
|
:prepend, :force_encoding, :encode, :scrub, :unicode_normalize, :"[]=",
|
|
24
20
|
:upto, :each_byte, :each_char, :each_codepoint,
|
|
25
21
|
:each_grapheme_cluster, :each_line, :bytesplice,
|
|
26
|
-
# `crypt` is not a mutator but is blocked from folding for the
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
# an analyzed project may target. The catalog classifies it
|
|
32
|
-
# `:leaf` from its C body; this entry overrides that.
|
|
22
|
+
# `crypt` is not a mutator but is blocked from folding for the same "do not bake a non-pure
|
|
23
|
+
# result into a Constant" reason: `rb_str_crypt` delegates to the platform `crypt(3)`, whose
|
|
24
|
+
# output (algorithm and digest) varies by libc / OS, so `"x".crypt("ab")` is not deterministic
|
|
25
|
+
# across the platforms an analyzed project may target. The catalog classifies it `:leaf` from
|
|
26
|
+
# its C body; this entry overrides that.
|
|
33
27
|
:crypt
|
|
34
28
|
],
|
|
35
29
|
"Symbol" => Set[
|
|
36
|
-
# Symbol is immutable in Ruby; the classifier mis-flags
|
|
37
|
-
#
|
|
38
|
-
# mutable buffer. Allow it.
|
|
30
|
+
# Symbol is immutable in Ruby; the classifier mis-flags `inspect` because `rb_sym_inspect`
|
|
31
|
+
# builds a temporary mutable buffer. Allow it.
|
|
39
32
|
]
|
|
40
33
|
}
|
|
41
34
|
)
|
|
@@ -5,44 +5,32 @@ require_relative "method_catalog"
|
|
|
5
5
|
module Rigor
|
|
6
6
|
module Inference
|
|
7
7
|
module Builtins
|
|
8
|
-
# `Struct` catalog. Singleton — load once, consult during
|
|
9
|
-
# dispatch.
|
|
8
|
+
# `Struct` catalog. Singleton — load once, consult during dispatch.
|
|
10
9
|
#
|
|
11
|
-
# `Struct` is a meta-class: `Struct.new(*members)` returns a
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# the shape and forbids unsafe folds in case a future tier
|
|
16
|
-
# learns to lift literal struct instances into the value
|
|
17
|
-
# lattice.
|
|
10
|
+
# `Struct` is a meta-class: `Struct.new(*members)` returns a fresh anonymous subclass — never a
|
|
11
|
+
# `Struct` value. Today Rigor never produces a `Constant<Struct>` carrier (a literal struct
|
|
12
|
+
# instance), so the catalog is defensive: it documents the shape and forbids unsafe folds in case a
|
|
13
|
+
# future tier learns to lift literal struct instances into the value lattice.
|
|
18
14
|
#
|
|
19
|
-
# Subclasses define their own writers (`name=`) at class-build
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
# member but the answer depends on the subclass's member
|
|
24
|
-
# definition, which the catalog does not see, so we blocklist
|
|
25
|
-
# it defensively.
|
|
15
|
+
# Subclasses define their own writers (`name=`) at class-build time, so per-instance member
|
|
16
|
+
# accessors do not appear in this YAML — only the generic `[]` / `[]=` pair on the base class. `[]=`
|
|
17
|
+
# is already classified `:mutates_self`; `[]` reads a member but the answer depends on the
|
|
18
|
+
# subclass's member definition, which the catalog does not see, so we blocklist it defensively.
|
|
26
19
|
STRUCT_CATALOG = MethodCatalog.for_topic(
|
|
27
20
|
"struct",
|
|
28
21
|
mutating_selectors: {
|
|
29
22
|
"Struct" => Set[
|
|
30
|
-
# Defensive: aliasing-copy semantics on a hypothetical
|
|
31
|
-
#
|
|
32
|
-
# other catalogs (Range, Random, Pathname).
|
|
23
|
+
# Defensive: aliasing-copy semantics on a hypothetical `Constant<Struct>` carrier. Convention
|
|
24
|
+
# across the other catalogs (Range, Random, Pathname).
|
|
33
25
|
:initialize_copy,
|
|
34
|
-
# `rb_struct_hash` mixes member values via
|
|
35
|
-
# `rb_hash`
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
# on the member values' `#hash` — user-redefinable.
|
|
39
|
-
# Block to avoid folding a hash that would diverge
|
|
40
|
-
# from the runtime once a member overrides `#hash`.
|
|
26
|
+
# `rb_struct_hash` mixes member values via `rb_hash` -> `rb_funcall(:hash, ...)`. The
|
|
27
|
+
# classifier sees no direct dispatch because the recursion goes through `rb_hash` (a helper),
|
|
28
|
+
# but the answer depends on the member values' `#hash` — user-redefinable. Block to avoid
|
|
29
|
+
# folding a hash that would diverge from the runtime once a member overrides `#hash`.
|
|
41
30
|
:hash,
|
|
42
|
-
# `rb_struct_aref` reads a member by name or index; the
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
# the layout would be unsound.
|
|
31
|
+
# `rb_struct_aref` reads a member by name or index; the answer depends on the subclass's
|
|
32
|
+
# member layout, which the catalog does not carry. Folding without knowing the layout would
|
|
33
|
+
# be unsound.
|
|
46
34
|
:[]
|
|
47
35
|
]
|
|
48
36
|
}
|