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.
Files changed (414) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/docs/manual/04-diagnostics.md +7 -4
  4. data/docs/manual/06-baseline.md +5 -2
  5. data/docs/manual/15-type-protection-coverage.md +6 -4
  6. data/lib/rigor/analysis/baseline.rb +56 -96
  7. data/lib/rigor/analysis/buffer_binding.rb +13 -20
  8. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +29 -48
  9. data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +35 -54
  10. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +23 -37
  11. data/lib/rigor/analysis/check_rules/main_pass_collector.rb +16 -23
  12. data/lib/rigor/analysis/check_rules/rule_walk.rb +48 -71
  13. data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +19 -28
  14. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +48 -67
  15. data/lib/rigor/analysis/check_rules.rb +174 -274
  16. data/lib/rigor/analysis/dependency_recorder.rb +26 -38
  17. data/lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb +13 -25
  18. data/lib/rigor/analysis/dependency_source_inference/builder.rb +17 -30
  19. data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +15 -26
  20. data/lib/rigor/analysis/dependency_source_inference/index.rb +45 -76
  21. data/lib/rigor/analysis/dependency_source_inference/return_type_heuristic.rb +23 -40
  22. data/lib/rigor/analysis/dependency_source_inference/walker.rb +50 -83
  23. data/lib/rigor/analysis/dependency_source_inference.rb +6 -10
  24. data/lib/rigor/analysis/diagnostic.rb +48 -75
  25. data/lib/rigor/analysis/erb_template_detector.rb +13 -18
  26. data/lib/rigor/analysis/fact_store.rb +12 -22
  27. data/lib/rigor/analysis/incremental.rb +47 -63
  28. data/lib/rigor/analysis/incremental_session.rb +74 -100
  29. data/lib/rigor/analysis/project_scan.rb +12 -23
  30. data/lib/rigor/analysis/result.rb +3 -5
  31. data/lib/rigor/analysis/rule_catalog.rb +67 -95
  32. data/lib/rigor/analysis/run_stats.rb +38 -61
  33. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +101 -160
  34. data/lib/rigor/analysis/runner/pool_coordinator.rb +121 -188
  35. data/lib/rigor/analysis/runner/project_pre_passes.rb +62 -96
  36. data/lib/rigor/analysis/runner/run_snapshots.rb +12 -18
  37. data/lib/rigor/analysis/runner.rb +220 -333
  38. data/lib/rigor/analysis/self_call_resolution_recorder.rb +30 -43
  39. data/lib/rigor/analysis/worker_session.rb +64 -102
  40. data/lib/rigor/ast/type_node.rb +6 -8
  41. data/lib/rigor/ast.rb +6 -10
  42. data/lib/rigor/bleeding_edge.rb +27 -35
  43. data/lib/rigor/builtins/hkt_builtins.rb +7 -14
  44. data/lib/rigor/builtins/imported_refinements.rb +106 -149
  45. data/lib/rigor/builtins/predefined_constant_refinements.rb +51 -65
  46. data/lib/rigor/builtins/regex_refinement.rb +32 -43
  47. data/lib/rigor/builtins/static_return_refinements.rb +57 -81
  48. data/lib/rigor/cache/descriptor.rb +58 -94
  49. data/lib/rigor/cache/incremental_snapshot.rb +32 -48
  50. data/lib/rigor/cache/rbs_cache_producer.rb +10 -15
  51. data/lib/rigor/cache/rbs_class_ancestor_table.rb +10 -16
  52. data/lib/rigor/cache/rbs_class_type_param_names.rb +10 -16
  53. data/lib/rigor/cache/rbs_constant_table.rb +8 -13
  54. data/lib/rigor/cache/rbs_descriptor.rb +8 -13
  55. data/lib/rigor/cache/rbs_environment.rb +11 -19
  56. data/lib/rigor/cache/rbs_environment_marshal_patch.rb +11 -19
  57. data/lib/rigor/cache/rbs_known_class_names.rb +8 -12
  58. data/lib/rigor/cache/store.rb +96 -151
  59. data/lib/rigor/cli/annotate_command.rb +51 -88
  60. data/lib/rigor/cli/baseline_command.rb +10 -17
  61. data/lib/rigor/cli/check_command.rb +121 -199
  62. data/lib/rigor/cli/check_runner_factory.rb +8 -14
  63. data/lib/rigor/cli/ci_detector.rb +9 -14
  64. data/lib/rigor/cli/command.rb +8 -14
  65. data/lib/rigor/cli/coverage_command.rb +19 -26
  66. data/lib/rigor/cli/coverage_mutation.rb +14 -19
  67. data/lib/rigor/cli/coverage_report.rb +0 -2
  68. data/lib/rigor/cli/coverage_scan.rb +7 -11
  69. data/lib/rigor/cli/diagnostic_formats.rb +43 -62
  70. data/lib/rigor/cli/diff_command.rb +10 -20
  71. data/lib/rigor/cli/docs_command.rb +26 -40
  72. data/lib/rigor/cli/doctor_command.rb +8 -9
  73. data/lib/rigor/cli/explain_command.rb +4 -7
  74. data/lib/rigor/cli/fused_protection_renderer.rb +4 -5
  75. data/lib/rigor/cli/fused_protection_report.rb +6 -8
  76. data/lib/rigor/cli/lsp_command.rb +11 -19
  77. data/lib/rigor/cli/mcp_command.rb +4 -6
  78. data/lib/rigor/cli/mutation_protection_renderer.rb +3 -4
  79. data/lib/rigor/cli/mutation_protection_report.rb +6 -9
  80. data/lib/rigor/cli/options.rb +11 -19
  81. data/lib/rigor/cli/plugin_command.rb +18 -30
  82. data/lib/rigor/cli/plugins_command.rb +29 -51
  83. data/lib/rigor/cli/plugins_renderer.rb +12 -20
  84. data/lib/rigor/cli/prism_colorizer.rb +13 -19
  85. data/lib/rigor/cli/protection_renderer.rb +5 -7
  86. data/lib/rigor/cli/protection_report.rb +27 -17
  87. data/lib/rigor/cli/renderable.rb +4 -6
  88. data/lib/rigor/cli/show_bleedingedge_command.rb +5 -8
  89. data/lib/rigor/cli/sig_gen_command.rb +14 -26
  90. data/lib/rigor/cli/skill_command.rb +30 -47
  91. data/lib/rigor/cli/skill_describe.rb +40 -64
  92. data/lib/rigor/cli/trace_command.rb +9 -16
  93. data/lib/rigor/cli/trace_renderer.rb +35 -51
  94. data/lib/rigor/cli/triage_command.rb +6 -10
  95. data/lib/rigor/cli/triage_renderer.rb +1 -2
  96. data/lib/rigor/cli/type_of_command.rb +14 -23
  97. data/lib/rigor/cli/type_of_renderer.rb +3 -5
  98. data/lib/rigor/cli/type_scan_command.rb +6 -10
  99. data/lib/rigor/cli/type_scan_renderer.rb +3 -5
  100. data/lib/rigor/cli/type_scan_report.rb +2 -3
  101. data/lib/rigor/cli/upgrade_command.rb +2 -3
  102. data/lib/rigor/cli.rb +16 -28
  103. data/lib/rigor/config_audit.rb +35 -44
  104. data/lib/rigor/configuration/dependencies.rb +41 -70
  105. data/lib/rigor/configuration/severity_profile.rb +28 -42
  106. data/lib/rigor/configuration.rb +150 -241
  107. data/lib/rigor/environment/bundle_sig_discovery.rb +74 -118
  108. data/lib/rigor/environment/class_registry.rb +19 -26
  109. data/lib/rigor/environment/constant_type_cache_holder.rb +14 -21
  110. data/lib/rigor/environment/hkt_registry_holder.rb +6 -12
  111. data/lib/rigor/environment/lockfile_resolver.rb +31 -47
  112. data/lib/rigor/environment/rbs_collection_discovery.rb +39 -63
  113. data/lib/rigor/environment/rbs_coverage_report.rb +24 -42
  114. data/lib/rigor/environment/rbs_loader.rb +420 -518
  115. data/lib/rigor/environment/reflection.rb +28 -53
  116. data/lib/rigor/environment/reporters.rb +13 -24
  117. data/lib/rigor/environment.rb +176 -291
  118. data/lib/rigor/flow_contribution/conflict.rb +16 -27
  119. data/lib/rigor/flow_contribution/element.rb +7 -12
  120. data/lib/rigor/flow_contribution/fact.rb +33 -57
  121. data/lib/rigor/flow_contribution/merge_result.rb +6 -9
  122. data/lib/rigor/flow_contribution/merger.rb +32 -47
  123. data/lib/rigor/flow_contribution.rb +37 -55
  124. data/lib/rigor/inference/acceptance.rb +133 -219
  125. data/lib/rigor/inference/block_parameter_binder.rb +52 -82
  126. data/lib/rigor/inference/body_fixpoint.rb +22 -30
  127. data/lib/rigor/inference/budget_trace.rb +43 -63
  128. data/lib/rigor/inference/builtins/array_catalog.rb +4 -6
  129. data/lib/rigor/inference/builtins/comparable_catalog.rb +4 -6
  130. data/lib/rigor/inference/builtins/complex_catalog.rb +13 -19
  131. data/lib/rigor/inference/builtins/date_catalog.rb +38 -67
  132. data/lib/rigor/inference/builtins/encoding_catalog.rb +22 -36
  133. data/lib/rigor/inference/builtins/enumerable_catalog.rb +4 -6
  134. data/lib/rigor/inference/builtins/exception_catalog.rb +38 -57
  135. data/lib/rigor/inference/builtins/hash_catalog.rb +9 -14
  136. data/lib/rigor/inference/builtins/method_catalog.rb +29 -48
  137. data/lib/rigor/inference/builtins/numeric_catalog.rb +13 -18
  138. data/lib/rigor/inference/builtins/pathname_catalog.rb +8 -13
  139. data/lib/rigor/inference/builtins/proc_catalog.rb +38 -62
  140. data/lib/rigor/inference/builtins/random_catalog.rb +21 -32
  141. data/lib/rigor/inference/builtins/range_catalog.rb +12 -21
  142. data/lib/rigor/inference/builtins/rational_catalog.rb +9 -15
  143. data/lib/rigor/inference/builtins/re_catalog.rb +29 -48
  144. data/lib/rigor/inference/builtins/set_catalog.rb +18 -27
  145. data/lib/rigor/inference/builtins/string_catalog.rb +12 -19
  146. data/lib/rigor/inference/builtins/struct_catalog.rb +18 -30
  147. data/lib/rigor/inference/builtins/time_catalog.rb +28 -44
  148. data/lib/rigor/inference/closure_escape_analyzer.rb +44 -67
  149. data/lib/rigor/inference/coverage_scanner.rb +13 -18
  150. data/lib/rigor/inference/def_return_typer.rb +8 -14
  151. data/lib/rigor/inference/dynamic_origin.rb +23 -20
  152. data/lib/rigor/inference/expression_typer.rb +774 -1152
  153. data/lib/rigor/inference/fallback.rb +8 -12
  154. data/lib/rigor/inference/fallback_tracer.rb +4 -10
  155. data/lib/rigor/inference/flow_tracer.rb +25 -36
  156. data/lib/rigor/inference/hkt_body.rb +45 -68
  157. data/lib/rigor/inference/hkt_body_parser.rb +33 -52
  158. data/lib/rigor/inference/hkt_reducer.rb +38 -59
  159. data/lib/rigor/inference/hkt_registry.rb +50 -76
  160. data/lib/rigor/inference/indexed_narrowing.rb +55 -81
  161. data/lib/rigor/inference/macro_block_self_type.rb +21 -34
  162. data/lib/rigor/inference/method_dispatcher/array_to_h_folding.rb +11 -18
  163. data/lib/rigor/inference/method_dispatcher/block_folding.rb +49 -83
  164. data/lib/rigor/inference/method_dispatcher/call_context.rb +16 -23
  165. data/lib/rigor/inference/method_dispatcher/cgi_folding.rb +13 -22
  166. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +307 -454
  167. data/lib/rigor/inference/method_dispatcher/data_folding.rb +24 -34
  168. data/lib/rigor/inference/method_dispatcher/file_folding.rb +22 -37
  169. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +52 -81
  170. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +51 -78
  171. data/lib/rigor/inference/method_dispatcher/literal_string_folding.rb +60 -97
  172. data/lib/rigor/inference/method_dispatcher/math_folding.rb +23 -34
  173. data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +18 -26
  174. data/lib/rigor/inference/method_dispatcher/method_folding.rb +37 -71
  175. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +114 -182
  176. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +122 -193
  177. data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +15 -24
  178. data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +64 -93
  179. data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +31 -45
  180. data/lib/rigor/inference/method_dispatcher/set_folding.rb +6 -9
  181. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +356 -511
  182. data/lib/rigor/inference/method_dispatcher/shellwords_folding.rb +22 -32
  183. data/lib/rigor/inference/method_dispatcher/singleton_folding.rb +15 -21
  184. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +66 -82
  185. data/lib/rigor/inference/method_dispatcher/time_folding.rb +10 -15
  186. data/lib/rigor/inference/method_dispatcher/uri_folding.rb +9 -13
  187. data/lib/rigor/inference/method_dispatcher.rb +378 -524
  188. data/lib/rigor/inference/method_parameter_binder.rb +81 -114
  189. data/lib/rigor/inference/multi_target_binder.rb +51 -68
  190. data/lib/rigor/inference/mutation_widening.rb +115 -158
  191. data/lib/rigor/inference/narrowing.rb +509 -727
  192. data/lib/rigor/inference/origin_lookup.rb +38 -0
  193. data/lib/rigor/inference/parameter_inference_collector.rb +100 -100
  194. data/lib/rigor/inference/precision_scanner.rb +26 -35
  195. data/lib/rigor/inference/project_patched_methods.rb +20 -32
  196. data/lib/rigor/inference/project_patched_scanner.rb +23 -37
  197. data/lib/rigor/inference/protection_scanner.rb +16 -18
  198. data/lib/rigor/inference/rbs_type_translator.rb +49 -66
  199. data/lib/rigor/inference/scope_indexer.rb +473 -817
  200. data/lib/rigor/inference/statement_evaluator.rb +706 -1111
  201. data/lib/rigor/inference/struct_fold_safety.rb +34 -48
  202. data/lib/rigor/inference/synthetic_method.rb +9 -16
  203. data/lib/rigor/inference/synthetic_method_index.rb +20 -35
  204. data/lib/rigor/inference/synthetic_method_scanner.rb +63 -103
  205. data/lib/rigor/language_server/buffer_resolution.rb +6 -9
  206. data/lib/rigor/language_server/buffer_table.rb +11 -18
  207. data/lib/rigor/language_server/completion_provider.rb +69 -116
  208. data/lib/rigor/language_server/debouncer.rb +16 -25
  209. data/lib/rigor/language_server/diagnostic_publisher.rb +26 -40
  210. data/lib/rigor/language_server/document_symbol_provider.rb +14 -19
  211. data/lib/rigor/language_server/folding_range_provider.rb +11 -19
  212. data/lib/rigor/language_server/hover_provider.rb +8 -11
  213. data/lib/rigor/language_server/hover_renderer.rb +56 -93
  214. data/lib/rigor/language_server/loop.rb +14 -19
  215. data/lib/rigor/language_server/project_context.rb +46 -74
  216. data/lib/rigor/language_server/selection_range_provider.rb +9 -12
  217. data/lib/rigor/language_server/server.rb +55 -83
  218. data/lib/rigor/language_server/signature_help_provider.rb +29 -46
  219. data/lib/rigor/language_server/synchronized_writer.rb +4 -7
  220. data/lib/rigor/language_server/uri.rb +8 -13
  221. data/lib/rigor/language_server.rb +4 -6
  222. data/lib/rigor/mcp/loop.rb +2 -3
  223. data/lib/rigor/mcp/server.rb +4 -7
  224. data/lib/rigor/mcp.rb +3 -6
  225. data/lib/rigor/plugin/access_denied_error.rb +5 -8
  226. data/lib/rigor/plugin/additional_initializer.rb +21 -31
  227. data/lib/rigor/plugin/base.rb +335 -518
  228. data/lib/rigor/plugin/blueprint.rb +14 -23
  229. data/lib/rigor/plugin/box.rb +18 -29
  230. data/lib/rigor/plugin/fact_store.rb +16 -26
  231. data/lib/rigor/plugin/inflector.rb +37 -53
  232. data/lib/rigor/plugin/io_boundary.rb +33 -56
  233. data/lib/rigor/plugin/isolation.rb +42 -55
  234. data/lib/rigor/plugin/load_error.rb +10 -15
  235. data/lib/rigor/plugin/loader.rb +30 -49
  236. data/lib/rigor/plugin/macro/block_as_method.rb +20 -32
  237. data/lib/rigor/plugin/macro/heredoc_template.rb +35 -58
  238. data/lib/rigor/plugin/macro/nested_class_template.rb +22 -36
  239. data/lib/rigor/plugin/macro/trait_registry.rb +34 -51
  240. data/lib/rigor/plugin/macro.rb +10 -15
  241. data/lib/rigor/plugin/manifest.rb +85 -144
  242. data/lib/rigor/plugin/node_context.rb +14 -22
  243. data/lib/rigor/plugin/node_rule_walk.rb +49 -74
  244. data/lib/rigor/plugin/protocol_contract.rb +25 -39
  245. data/lib/rigor/plugin/registry.rb +132 -205
  246. data/lib/rigor/plugin/services.rb +21 -33
  247. data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +11 -19
  248. data/lib/rigor/plugin/trust_policy.rb +24 -38
  249. data/lib/rigor/plugin/type_node_resolver.rb +15 -24
  250. data/lib/rigor/protection/diagnostic_oracle.rb +11 -13
  251. data/lib/rigor/protection/mutation_scanner.rb +27 -35
  252. data/lib/rigor/protection/mutator.rb +50 -70
  253. data/lib/rigor/protection/test_suite_oracle.rb +20 -27
  254. data/lib/rigor/rbs_extended/conformance_checker.rb +48 -68
  255. data/lib/rigor/rbs_extended/hkt_directives.rb +28 -54
  256. data/lib/rigor/rbs_extended/reporter.rb +24 -40
  257. data/lib/rigor/rbs_extended.rb +107 -197
  258. data/lib/rigor/reflection.rb +68 -86
  259. data/lib/rigor/scope/discovery_index.rb +14 -19
  260. data/lib/rigor/scope.rb +255 -310
  261. data/lib/rigor/sig_gen/classification.rb +6 -10
  262. data/lib/rigor/sig_gen/generator.rb +197 -323
  263. data/lib/rigor/sig_gen/layout_index.rb +12 -20
  264. data/lib/rigor/sig_gen/method_candidate.rb +12 -17
  265. data/lib/rigor/sig_gen/observation_collector.rb +38 -70
  266. data/lib/rigor/sig_gen/observed_call.rb +13 -23
  267. data/lib/rigor/sig_gen/path_mapper.rb +17 -29
  268. data/lib/rigor/sig_gen/renderer.rb +7 -13
  269. data/lib/rigor/sig_gen/type_elaborator.rb +15 -28
  270. data/lib/rigor/sig_gen/write_result.rb +8 -16
  271. data/lib/rigor/sig_gen/writer.rb +95 -174
  272. data/lib/rigor/sig_gen.rb +3 -6
  273. data/lib/rigor/signature_path_audit.rb +24 -30
  274. data/lib/rigor/source/constant_path.rb +10 -14
  275. data/lib/rigor/source/literals.rb +31 -45
  276. data/lib/rigor/source/node_locator.rb +9 -11
  277. data/lib/rigor/source/node_walker.rb +9 -13
  278. data/lib/rigor/source.rb +3 -4
  279. data/lib/rigor/testing.rb +16 -20
  280. data/lib/rigor/triage/catalogue.rb +38 -62
  281. data/lib/rigor/triage.rb +31 -52
  282. data/lib/rigor/trinary.rb +9 -13
  283. data/lib/rigor/type/acceptance_router.rb +4 -6
  284. data/lib/rigor/type/accepts_result.rb +10 -14
  285. data/lib/rigor/type/app.rb +19 -27
  286. data/lib/rigor/type/bot.rb +4 -6
  287. data/lib/rigor/type/bound_method.rb +10 -15
  288. data/lib/rigor/type/combinator.rb +165 -257
  289. data/lib/rigor/type/constant.rb +23 -34
  290. data/lib/rigor/type/data_class.rb +10 -15
  291. data/lib/rigor/type/data_instance.rb +14 -20
  292. data/lib/rigor/type/difference.rb +21 -32
  293. data/lib/rigor/type/dynamic.rb +3 -5
  294. data/lib/rigor/type/hash_shape.rb +32 -18
  295. data/lib/rigor/type/integer_range.rb +11 -16
  296. data/lib/rigor/type/intersection.rb +27 -42
  297. data/lib/rigor/type/nominal.rb +10 -15
  298. data/lib/rigor/type/plain_lattice.rb +9 -13
  299. data/lib/rigor/type/refined.rb +67 -114
  300. data/lib/rigor/type/singleton.rb +4 -6
  301. data/lib/rigor/type/struct_class.rb +11 -16
  302. data/lib/rigor/type/struct_instance.rb +15 -21
  303. data/lib/rigor/type/tuple.rb +14 -19
  304. data/lib/rigor/type/union.rb +30 -42
  305. data/lib/rigor/type_node/generic.rb +14 -26
  306. data/lib/rigor/type_node/identifier.rb +12 -19
  307. data/lib/rigor/type_node.rb +3 -12
  308. data/lib/rigor/value_semantics.rb +16 -21
  309. data/lib/rigor/version.rb +1 -1
  310. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +18 -30
  311. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +16 -29
  312. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +12 -23
  313. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +22 -39
  314. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +26 -46
  315. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +51 -87
  316. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +10 -17
  317. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +26 -39
  318. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +118 -176
  319. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +30 -51
  320. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +57 -92
  321. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +71 -108
  322. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +13 -22
  323. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +15 -25
  324. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +8 -13
  325. data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +16 -24
  326. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +30 -47
  327. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +79 -129
  328. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +36 -57
  329. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +27 -41
  330. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +16 -24
  331. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +148 -235
  332. data/plugins/rigor-activerecord/lib/rigor-activerecord.rb +3 -5
  333. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +8 -14
  334. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +9 -15
  335. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +4 -7
  336. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +23 -41
  337. data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +3 -5
  338. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +6 -10
  339. data/plugins/rigor-activesupport-core-ext/lib/rigor-activesupport-core-ext.rb +8 -11
  340. data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +30 -45
  341. data/plugins/rigor-devise/lib/rigor-devise.rb +3 -5
  342. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +43 -69
  343. data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +26 -35
  344. data/plugins/rigor-dry-schema/lib/rigor-dry-schema.rb +3 -5
  345. data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +30 -47
  346. data/plugins/rigor-dry-struct/lib/rigor-dry-struct.rb +3 -5
  347. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +67 -113
  348. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +29 -46
  349. data/plugins/rigor-dry-types/lib/rigor-dry-types.rb +3 -5
  350. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +13 -20
  351. data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +14 -23
  352. data/plugins/rigor-dry-validation/lib/rigor-dry-validation.rb +2 -3
  353. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +22 -37
  354. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +28 -46
  355. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +13 -17
  356. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +30 -47
  357. data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +52 -80
  358. data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +21 -31
  359. data/plugins/rigor-graphql/lib/rigor-graphql.rb +3 -5
  360. data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +11 -17
  361. data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +20 -34
  362. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +45 -75
  363. data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +22 -36
  364. data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +22 -41
  365. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +17 -32
  366. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +6 -12
  367. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +4 -8
  368. data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +17 -32
  369. data/plugins/rigor-rails/lib/rigor-rails.rb +11 -18
  370. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +58 -92
  371. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +20 -34
  372. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +20 -31
  373. data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +49 -82
  374. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +55 -92
  375. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +51 -90
  376. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +17 -30
  377. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +38 -70
  378. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +42 -74
  379. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +280 -497
  380. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +54 -89
  381. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +32 -54
  382. data/plugins/rigor-rbs-inline/lib/rigor-rbs-inline.rb +8 -13
  383. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +9 -16
  384. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +24 -39
  385. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +13 -22
  386. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +34 -56
  387. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/scope_walker.rb +22 -42
  388. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +43 -75
  389. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +27 -39
  390. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/http_status_codes.rb +14 -19
  391. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +20 -34
  392. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +28 -47
  393. data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +21 -37
  394. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +13 -22
  395. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +18 -31
  396. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +6 -10
  397. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +14 -29
  398. data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +23 -41
  399. data/plugins/rigor-sinatra/lib/rigor-sinatra.rb +3 -5
  400. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +23 -38
  401. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +57 -96
  402. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +22 -35
  403. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +41 -69
  404. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/method_signature.rb +6 -10
  405. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +24 -41
  406. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +29 -50
  407. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +55 -88
  408. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +159 -262
  409. data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +21 -29
  410. data/plugins/rigor-statesman/lib/rigor-statesman.rb +3 -5
  411. data/plugins/rigor-typescript-utility-types/lib/rigor/plugin/typescript_utility_types.rb +23 -37
  412. data/plugins/rigor-typescript-utility-types/lib/rigor-typescript-utility-types.rb +4 -6
  413. data/sig/rigor/scope.rbs +6 -0
  414. metadata +2 -1
@@ -8,66 +8,46 @@ require_relative "receiver_affinity"
8
8
  module Rigor
9
9
  module Inference
10
10
  module MethodDispatcher
11
- # Picks the RBS overload that should answer a call given the
12
- # caller's actual argument types. Slice 4 phase 2c shape (with
13
- # the v0.1.2 interface-strictness preference layered on top):
11
+ # Picks the RBS overload that should answer a call given the caller's actual argument types. Slice 4
12
+ # phase 2c shape (with the v0.1.2 interface-strictness preference layered on top):
14
13
  #
15
- # 1. Filter overloads by positional arity (required, optional and
16
- # rest_positionals are honored; required_keywords disqualify the
17
- # overload because we do not yet thread keyword args through
14
+ # 1. Filter overloads by positional arity (required, optional and rest_positionals are honored;
15
+ # required_keywords disqualify the overload because we do not yet thread keyword args through
18
16
  # `call_arg_types`).
19
- # 2. **Pass 1 — strict matches first.** Among the arity-matching
20
- # overloads, prefer the first one whose every (param, arg)
21
- # pair returns a `yes` or `maybe` answer AND whose param
22
- # types do NOT translate through `RBS::Types::Alias` /
23
- # `Interface` / `Intersection`. The translator demotes those
24
- # to `Dynamic[Top]`, which gradually accepts any argument
25
- # so without this preference, an alias-typed overload like
26
- # `Array#[](::int) -> Elem` would beat the strict
27
- # `Array#[](Range) -> Array[Elem]?` overload for a Range
28
- # argument.
29
- # 3. **Pass 2gradual fall-back.** If no fully strict overload
30
- # matches, accept the first arity-and-gradual-accept match
31
- # (the v0.1.1 behaviour). Alias / Interface / Intersection
32
- # params still reach this pass, so call sites whose only
33
- # candidate IS an alias-typed overload keep working. One
34
- # exclusion: an `untyped` argument does NOT gradually match
35
- # a value-pinning param (`nil` / literal types carriers
36
- # that admit only specific values). Those overloads carry
37
- # value-precise returns (`Kernel#Array: (nil) -> []`,
38
- # `Regexp#=~: (nil) -> nil`) that would otherwise win purely
39
- # by list position and inject false constants into the flow;
40
- # they remain selectable when the argument PROVES the value
41
- # (strict pass) or when no other overload matches (step 4's
42
- # fallback picks the first overload regardless).
43
- # 4. If no overload matches at all, fall back to
44
- # `method_types.first` so existing call sites keep their
45
- # phase 1 / 2b behavior. This preserves the fail-soft
46
- # invariant of the dispatcher.
17
+ # 2. **Pass 1 — strict matches first.** Among the arity-matching overloads, prefer the first one
18
+ # whose every (param, arg) pair returns a `yes` or `maybe` answer AND whose param types do NOT
19
+ # translate through `RBS::Types::Alias` / `Interface` / `Intersection`. The translator demotes
20
+ # those to `Dynamic[Top]`, which gradually accepts any argument — so without this preference, an
21
+ # alias-typed overload like `Array#[](::int) -> Elem` would beat the strict
22
+ # `Array#[](Range) -> Array[Elem]?` overload for a Range argument.
23
+ # 3. **Pass 2 gradual fall-back.** If no fully strict overload matches, accept the first
24
+ # arity-and-gradual-accept match (the v0.1.1 behaviour). Alias / Interface / Intersection params
25
+ # still reach this pass, so call sites whose only candidate IS an alias-typed overload keep
26
+ # working. One exclusion: an `untyped` argument does NOT gradually match a value-pinning param
27
+ # (`nil` / literal typescarriers that admit only specific values). Those overloads carry
28
+ # value-precise returns (`Kernel#Array: (nil) -> []`, `Regexp#=~: (nil) -> nil`) that would
29
+ # otherwise win purely by list position and inject false constants into the flow; they remain
30
+ # selectable when the argument PROVES the value (strict pass) or when no other overload matches
31
+ # (step 4's fallback picks the first overload regardless).
32
+ # 4. If no overload matches at all, fall back to `method_types.first` so existing call sites keep
33
+ # their phase 1 / 2b behavior. This preserves the fail-soft invariant of the dispatcher.
47
34
  #
48
- # The selector is intentionally agnostic about the dispatch kind
49
- # (instance vs singleton). Both kinds share the same arity and
50
- # acceptance shape; the difference is only in which `Definition`
51
- # the caller fetched.
35
+ # The selector is intentionally agnostic about the dispatch kind (instance vs singleton). Both kinds
36
+ # share the same arity and acceptance shape; the difference is only in which `Definition` the caller
37
+ # fetched.
52
38
  module OverloadSelector
53
39
  module_function
54
40
 
55
- # Canonical RBS-core aliases shipped by `core/builtin.rbs`
56
- # whose body is `<Nominal> | _DuckType`. Matching an
57
- # overload against an Integer literal should pick the
58
- # `(int) -> Array[Elem]` body over the `(string) -> String`
59
- # body because Integer satisfies `int`'s strict arm and
60
- # not `string`'s. The translator collapses both aliases
61
- # to `Dynamic[Top]` (interfaces are not structurally
62
- # matched yet), so a dedicated pass 1.5 between strict
63
- # and gradual consults this map to pick the alias whose
64
- # strict arm matches.
41
+ # Canonical RBS-core aliases shipped by `core/builtin.rbs` whose body is `<Nominal> | _DuckType`.
42
+ # Matching an overload against an Integer literal should pick the `(int) -> Array[Elem]` body over
43
+ # the `(string) -> String` body because Integer satisfies `int`'s strict arm and not `string`'s.
44
+ # The translator collapses both aliases to `Dynamic[Top]` (interfaces are not structurally matched
45
+ # yet), so a dedicated pass 1.5 between strict and gradual consults this map to pick the alias
46
+ # whose strict arm matches.
65
47
  #
66
- # Symbol keys are the alias names as they appear under
67
- # `RBS::Types::Alias#name.to_s` (the `name` is a
68
- # `TypeName` whose `to_s` includes the `::` prefix).
69
- # Values are an Array of class names whose Nominal[..]
70
- # form is the alias's strict-arm matcher.
48
+ # Symbol keys are the alias names as they appear under `RBS::Types::Alias#name.to_s` (the `name` is
49
+ # a `TypeName` whose `to_s` includes the `::` prefix). Values are an Array of class names whose
50
+ # Nominal[..] form is the alias's strict-arm matcher.
71
51
  ALIAS_STRICT_NOMINALS = {
72
52
  "::int" => ["Integer"],
73
53
  "::string" => ["String"],
@@ -80,46 +60,35 @@ module Rigor
80
60
  private_constant :ALIAS_STRICT_NOMINALS
81
61
 
82
62
  # @param method_definition [RBS::Definition::Method]
83
- # @param arg_types [Array<Rigor::Type>] caller-provided types in
84
- # positional order. Empty when there are no arguments.
63
+ # @param arg_types [Array<Rigor::Type>] caller-provided types in positional order. Empty when
64
+ # there are no arguments.
85
65
  # @param self_type [Rigor::Type] substitute for `Bases::Self`.
86
66
  # @param instance_type [Rigor::Type] substitute for `Bases::Instance`.
87
- # @param type_vars [Hash{Symbol => Rigor::Type}] substitution map
88
- # for class-level type variables (Slice 4 phase 2d). The
89
- # selector threads it through to {RbsTypeTranslator} so
90
- # parameter types like `::Array[Elem]` substitute Elem before
91
- # the accepts check, instead of degrading the param to
92
- # `Array[Dynamic[Top]]`.
93
- # @param block_required [Boolean] when `true`, only overloads
94
- # that declare a block clause are considered (Slice 6 phase C
95
- # sub-phase 1). The fallback also prefers a block-bearing
96
- # overload over `method_types.first`. When `false` (the
97
- # Slice 4 phase 2c default) the selector behaves exactly as
98
- # before: `find` over arity-compatible overloads, falling
99
- # back to the first declaration.
100
- # @return [RBS::MethodType, nil] the chosen overload, or nil
101
- # when the definition has no method types at all.
67
+ # @param type_vars [Hash{Symbol => Rigor::Type}] substitution map for class-level type variables
68
+ # (Slice 4 phase 2d). The selector threads it through to {RbsTypeTranslator} so parameter types
69
+ # like `::Array[Elem]` substitute Elem before the accepts check, instead of degrading the param
70
+ # to `Array[Dynamic[Top]]`.
71
+ # @param block_required [Boolean] when `true`, only overloads that declare a block clause are
72
+ # considered (Slice 6 phase C sub-phase 1). The fallback also prefers a block-bearing overload
73
+ # over `method_types.first`. When `false` (the Slice 4 phase 2c default) the selector behaves
74
+ # exactly as before: `find` over arity-compatible overloads, falling back to the first
75
+ # declaration.
76
+ # @return [RBS::MethodType, nil] the chosen overload, or nil when the definition has no method
77
+ # types at all.
102
78
  def select(method_definition, arg_types:, self_type:, instance_type:, type_vars: {}, block_required: false,
103
79
  environment: nil)
104
80
  overloads = method_definition.method_types
105
81
  return nil if overloads.empty?
106
82
 
107
- # `rigor:v1:param: <name> <refinement>` annotations on
108
- # this method override the RBS-declared parameter type
109
- # at the matching name. The map is consumed inside
110
- # `accepts_param?` so overload selection sees the
111
- # tighter type when filtering candidates by argument
112
- # compatibility.
83
+ # `rigor:v1:param: <name> <refinement>` annotations on this method override the RBS-declared
84
+ # parameter type at the matching name. The map is consumed inside `accepts_param?` so overload
85
+ # selection sees the tighter type when filtering candidates by argument compatibility.
113
86
  param_overrides = RbsExtended.param_type_override_map(method_definition, environment: environment)
114
87
 
115
- # Pre-sort: demote overloads whose param class is a
116
- # disjoint sibling of the receiver class (e.g.
117
- # `Integer#+(BigDecimal) -> BigDecimal` from the
118
- # `bigdecimal` RBS reopen). Honors the coerce
119
- # convention so `5 + ?` for unknown `?` resolves to
120
- # the receiver-class-preserving arm rather than an
121
- # arbitrary sibling-class arm that only wins by
122
- # overload-list position.
88
+ # Pre-sort: demote overloads whose param class is a disjoint sibling of the receiver class (e.g.
89
+ # `Integer#+(BigDecimal) -> BigDecimal` from the `bigdecimal` RBS reopen). Honors the coerce
90
+ # convention so `5 + ?` for unknown `?` resolves to the receiver-class-preserving arm rather than
91
+ # an arbitrary sibling-class arm that only wins by overload-list position.
123
92
  overloads = ReceiverAffinity.reorder(overloads, self_type: self_type, environment: environment)
124
93
 
125
94
  passes = lambda do |require_block|
@@ -132,28 +101,21 @@ module Rigor
132
101
  match = passes.call(block_required)
133
102
  return match if match
134
103
 
135
- # A block at the call site that no block-declaring overload
136
- # matched: Ruby ignores a block handed to a method that never
137
- # yields it, so retry treating the block as ignorable rather
138
- # than failing the dispatch. Without this, a block-bearing
139
- # call to a method whose RBS declares no block (e.g.
140
- # `define_command(:x) do … end` against
141
- # `def define_command: (Symbol) -> Symbol`) degraded to
142
- # `Dynamic[Top]` — and on a self-send suppressed the whole
143
- # method's return type.
104
+ # A block at the call site that no block-declaring overload matched: Ruby ignores a block handed
105
+ # to a method that never yields it, so retry treating the block as ignorable rather than failing
106
+ # the dispatch. Without this, a block-bearing call to a method whose RBS declares no block (e.g.
107
+ # `define_command(:x) do end` against `def define_command: (Symbol) -> Symbol`) degraded to
108
+ # `Dynamic[Top]` and on a self-send suppressed the whole method's return type.
144
109
  if block_required
145
110
  match = passes.call(false)
146
111
  return match if match
147
112
  end
148
113
 
149
- # No (usable) block at the call site: prefer an overload that does
150
- # not REQUIRE a block over `overloads.first`. Methods like
151
- # `Array#filter` / `Enumerable#map` declare the block-
152
- # bearing overload first (`() { ... } -> Array[Elem]`) and
153
- # the bare-call overload second (`() -> Enumerator[...]`).
154
- # Without this, a no-block `[1, 2].filter` would adopt the
155
- # block overload's `Array[Elem]` return when the call
156
- # actually yields an `Enumerator`.
114
+ # No (usable) block at the call site: prefer an overload that does not REQUIRE a block over
115
+ # `overloads.first`. Methods like `Array#filter` / `Enumerable#map` declare the block-bearing
116
+ # overload first (`() { ... } -> Array[Elem]`) and the bare-call overload second
117
+ # (`() -> Enumerator[...]`). Without this, a no-block `[1, 2].filter` would adopt the block
118
+ # overload's `Array[Elem]` return when the call actually yields an `Enumerator`.
157
119
  overloads.find { |mt| !overload_requires_block?(mt) } || overloads.first
158
120
  end
159
121
 
@@ -161,10 +123,9 @@ module Rigor
161
123
  method_type.respond_to?(:block) && method_type.block
162
124
  end
163
125
 
164
- # True when the overload declares a block that the caller
165
- # MUST supply (`{ ... }` in RBS). An optional block
166
- # (`?{ ... }`) does NOT count — that overload is a valid
167
- # match for a block-less call.
126
+ # True when the overload declares a block that the caller MUST supply (`{ ... }` in RBS). An
127
+ # optional block (`?{ ... }`) does NOT count that overload is a valid match for a block-less
128
+ # call.
168
129
  def overload_requires_block?(method_type)
169
130
  block = overload_has_block?(method_type)
170
131
  !!block && block.required
@@ -174,18 +135,13 @@ module Rigor
174
135
  private
175
136
 
176
137
  # Three-pass overload search:
177
- # - Pass 1 (strict): skipped when any arg is
178
- # `Dynamic[Top]`, because gradual acceptance against
179
- # an untyped arg accepts every param indiscriminately
180
- # and would let pass 1 lock in an arbitrary strict
181
- # overload (e.g. `Regexp#=~(nil) -> nil` over the
182
- # `(::interned?) -> Integer?` overload).
183
- # - Pass 1.5 (alias-resolved): consults each `RBS::Types::Alias`'s
184
- # strict arm so e.g. `Array#*(int)` wins over the
185
- # `Array#*(string) -> String` overload for Integer args.
186
- # - Pass 2 (gradual): the original gradual matcher so
187
- # overloads that legitimately rely on duck-typed
188
- # params still resolve when nothing stricter applies.
138
+ # - Pass 1 (strict): skipped when any arg is `Dynamic[Top]`, because gradual acceptance against
139
+ # an untyped arg accepts every param indiscriminately and would let pass 1 lock in an arbitrary
140
+ # strict overload (e.g. `Regexp#=~(nil) -> nil` over the `(::interned?) -> Integer?` overload).
141
+ # - Pass 1.5 (alias-resolved): consults each `RBS::Types::Alias`'s strict arm so e.g.
142
+ # `Array#*(int)` wins over the `Array#*(string) -> String` overload for Integer args.
143
+ # - Pass 2 (gradual): the original gradual matcher so overloads that legitimately rely on
144
+ # duck-typed params still resolve when nothing stricter applies.
189
145
  def run_selection_passes(overloads, arg_types:, self_type:, instance_type:, type_vars:, block_required:,
190
146
  param_overrides:)
191
147
  shared = {
@@ -219,25 +175,19 @@ module Rigor
219
175
  end
220
176
  # rubocop:enable Metrics/ParameterLists
221
177
 
222
- # Treats the literal `untyped` carrier (`Dynamic[Top]`)
223
- # as too imprecise to drive a strict-pass match. Other
224
- # `Dynamic`-wrapped types with a concrete static facet
225
- # carry enough information to pick a sensible overload.
178
+ # Treats the literal `untyped` carrier (`Dynamic[Top]`) as too imprecise to drive a strict-pass
179
+ # match. Other `Dynamic`-wrapped types with a concrete static facet carry enough information to
180
+ # pick a sensible overload.
226
181
  def untyped_arg?(type)
227
182
  type.is_a?(Type::Dynamic) && type.static_facet.is_a?(Type::Top)
228
183
  end
229
184
 
230
- # Pass 1.5: for arity-compatible overloads whose every
231
- # positional param is either a strict nominal OR a
232
- # well-known core alias (`int` / `string` / `interned`
233
- # / etc.), check the arg against the alias's STRICT
234
- # arm. An Integer literal arg matches `int` here but
235
- # not `string`, so `Array#*(int)` wins over the
236
- # `Array#*(string) -> String` overload — even though
237
- # both translate to `Dynamic[Top]` at the param level.
238
- # Only fires when EVERY positional param has a known
239
- # alias-or-strict shape; otherwise gradual matching
240
- # takes over.
185
+ # Pass 1.5: for arity-compatible overloads whose every positional param is either a strict
186
+ # nominal OR a well-known core alias (`int` / `string` / `interned` / etc.), check the arg
187
+ # against the alias's STRICT arm. An Integer literal arg matches `int` here but not `string`, so
188
+ # `Array#*(int)` wins over the `Array#*(string) -> String` overload — even though both translate
189
+ # to `Dynamic[Top]` at the param level. Only fires when EVERY positional param has a known
190
+ # alias-or-strict shape; otherwise gradual matching takes over.
241
191
  def find_matching_overload_via_aliases(overloads, arg_types:, block_required:)
242
192
  overloads.find do |method_type|
243
193
  next false if block_required && !OverloadSelector.overload_has_block?(method_type)
@@ -253,11 +203,9 @@ module Rigor
253
203
  end
254
204
  end
255
205
 
256
- # Checks the param's RBS type against an arg using
257
- # alias-strict-arm matching. Optional / Union wrappers
258
- # are flattened; alias resolution is one level deep
259
- # (the canonical core aliases all have non-alias
260
- # strict arms).
206
+ # Checks the param's RBS type against an arg using alias-strict-arm matching. Optional / Union
207
+ # wrappers are flattened; alias resolution is one level deep (the canonical core aliases all have
208
+ # non-alias strict arms).
261
209
  def alias_param_accepts?(rbs_type, arg)
262
210
  nominal_names = strict_nominal_names_for(rbs_type)
263
211
  return false if nominal_names.nil? || nominal_names.empty?
@@ -268,10 +216,9 @@ module Rigor
268
216
  end
269
217
  end
270
218
 
271
- # Returns the candidate class names a param's RBS type
272
- # accepts under alias-resolved strict matching, or nil
273
- # when the shape cannot be reduced to a closed set of
274
- # nominals (e.g. an Interface or an unrecognised alias).
219
+ # Returns the candidate class names a param's RBS type accepts under alias-resolved strict
220
+ # matching, or nil when the shape cannot be reduced to a closed set of nominals (e.g. an
221
+ # Interface or an unrecognised alias).
275
222
  def strict_nominal_names_for(rbs_type)
276
223
  case rbs_type
277
224
  when RBS::Types::ClassInstance
@@ -288,13 +235,10 @@ module Rigor
288
235
  end
289
236
  end
290
237
 
291
- # Returns true when every positional param the call
292
- # site engages translates to a non-`Dynamic[Top]`
293
- # carrier. Alias / Interface / Intersection RBS types
294
- # all degrade to `Dynamic[Top]` per the translator's
295
- # current shape — those gradually accept any arg, so
296
- # an overload that includes one would beat strictly-
297
- # typed alternatives in pass 2 of the selector.
238
+ # Returns true when every positional param the call site engages translates to a non-`Dynamic[Top]`
239
+ # carrier. Alias / Interface / Intersection RBS types all degrade to `Dynamic[Top]` per the
240
+ # translator's current shape those gradually accept any arg, so an overload that includes one
241
+ # would beat strictly-typed alternatives in pass 2 of the selector.
298
242
  def strictly_typed_params?(method_type, actual_count)
299
243
  fun = method_type.type
300
244
  return false unless arity_compatible?(fun, actual_count)
@@ -303,20 +247,15 @@ module Rigor
303
247
  params.all? { |param| !alias_or_interface_param?(param.type) }
304
248
  end
305
249
 
306
- # Recursive: an Optional / Union wrapper is strict iff
307
- # every member is strict. Type args of a ClassInstance
308
- # are NOT walked `Range[::int]` is a Range carrier
309
- # at the param level; the alias only colours the
310
- # element type, which is checked separately when the
311
- # element is actually accessed.
250
+ # Recursive: an Optional / Union wrapper is strict iff every member is strict. Type args of a
251
+ # ClassInstance are NOT walked `Range[::int]` is a Range carrier at the param level; the alias
252
+ # only colours the element type, which is checked separately when the element is actually
253
+ # accessed.
312
254
  #
313
- # `RBS::Types::Bases::Any` (the explicit `untyped`
314
- # keyword) is treated like Alias / Interface /
315
- # Intersection both translate to `Dynamic[Top]`,
316
- # both gradually accept anything. A `(untyped) -> T`
317
- # catch-all overload that comes after the strictly-
318
- # typed ones must lose pass 1 so the typed overloads
319
- # win when their param actually fits the arg.
255
+ # `RBS::Types::Bases::Any` (the explicit `untyped` keyword) is treated like Alias / Interface /
256
+ # Intersection both translate to `Dynamic[Top]`, both gradually accept anything. A
257
+ # `(untyped) -> T` catch-all overload that comes after the strictly-typed ones must lose pass 1
258
+ # so the typed overloads win when their param actually fits the arg.
320
259
  def alias_or_interface_param?(rbs_type)
321
260
  case rbs_type
322
261
  when RBS::Types::Alias, RBS::Types::Interface,
@@ -350,9 +289,8 @@ module Rigor
350
289
  end
351
290
  end
352
291
 
353
- # Slice 4 phase 2c does not pass keyword arguments through the
354
- # call site (caller passes only positional `arg_types`). An
355
- # overload that requires keywords is therefore not a viable
292
+ # Slice 4 phase 2c does not pass keyword arguments through the call site (caller passes only
293
+ # positional `arg_types`). An overload that requires keywords is therefore not a viable
356
294
  # candidate; we skip it instead of forcing a fallback.
357
295
  def rejects_keyword_required?(method_type)
358
296
  fun = method_type.type
@@ -371,11 +309,10 @@ module Rigor
371
309
  actual_count <= max_arity
372
310
  end
373
311
 
374
- # Builds the list of formal parameter declarations to compare
375
- # against the actual arguments, in positional order: required
376
- # first, then as many optionals as needed, then trailing
377
- # required. Rest_positionals consumes the remainder; we
378
- # repeat its single declaration for each absorbed argument.
312
+ # Builds the list of formal parameter declarations to compare against the actual arguments, in
313
+ # positional order: required first, then as many optionals as needed, then trailing required.
314
+ # Rest_positionals consumes the remainder; we repeat its single declaration for each absorbed
315
+ # argument.
379
316
  def positional_params_for(fun, actual_count)
380
317
  required = fun.required_positionals
381
318
  optional = fun.optional_positionals
@@ -400,25 +337,20 @@ module Rigor
400
337
  instance_type: instance_type,
401
338
  type_vars: type_vars
402
339
  )
403
- # An `untyped` arg gradually accepts against every param,
404
- # so a value-pinning param would be "matched" with zero
405
- # evidence and its value-precise return (`(nil) -> []`)
406
- # would beat broader overloads purely by list position.
407
- # Decline the pair; only the strict pass (where the arg
408
- # proves the value) or the final first-overload fallback
409
- # may select such an overload. (Pass 1 already skips
410
- # untyped args entirely, so this only engages pass 2.)
340
+ # An `untyped` arg gradually accepts against every param, so a value-pinning param would be
341
+ # "matched" with zero evidence and its value-precise return (`(nil) -> []`) would beat broader
342
+ # overloads purely by list position. Decline the pair; only the strict pass (where the arg
343
+ # proves the value) or the final first-overload fallback may select such an overload. (Pass 1
344
+ # already skips untyped args entirely, so this only engages pass 2.)
411
345
  return false if untyped_arg?(arg) && value_pinning?(param_type)
412
346
 
413
347
  result = param_type.accepts(arg, mode: :gradual)
414
348
  result.yes? || result.maybe?
415
349
  end
416
350
 
417
- # A type that admits only specific VALUES rather than a
418
- # class of values: a `Constant` carrier (RBS `nil` and
419
- # literal types both translate to one) or a union made up
420
- # entirely of them (`true | false`, `1 | 2`, `nil?`-style
421
- # optionals of literals).
351
+ # A type that admits only specific VALUES rather than a class of values: a `Constant` carrier
352
+ # (RBS `nil` and literal types both translate to one) or a union made up entirely of them
353
+ # (`true | false`, `1 | 2`, `nil?`-style optionals of literals).
422
354
  def value_pinning?(type)
423
355
  case type
424
356
  when Type::Constant then true