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
@@ -7,60 +7,44 @@ module Rigor
7
7
  module Builtins
8
8
  # `Time` catalog. Singleton — load once, consult during dispatch.
9
9
  #
10
- # Time is a pure-C built-in: the Init block in
11
- # `references/ruby/time.c` registers the bulk of the surface,
12
- # and the Ruby-side prelude `references/ruby/timev.rb`
13
- # contributes the class-side constructors (`Time.now`,
14
- # `Time.at`, `Time.new`) through Primitive cexpr stubs.
10
+ # Time is a pure-C built-in: the Init block in `references/ruby/time.c` registers the bulk of the
11
+ # surface, and the Ruby-side prelude `references/ruby/timev.rb` contributes the class-side
12
+ # constructors (`Time.now`, `Time.at`, `Time.new`) through Primitive cexpr stubs.
15
13
  #
16
- # Time receivers are not lifted to a `Constant` carrier today
17
- # (there is no `Time` literal node the closest is
18
- # `Time.now` / `Time.new(...)`, which produce `Nominal[Time]`).
19
- # The catalog wiring therefore mostly governs:
14
+ # Time receivers are not lifted to a `Constant` carrier today (there is no `Time` literal node — the
15
+ # closest is `Time.now` / `Time.new(...)`, which produce `Nominal[Time]`). The catalog wiring
16
+ # therefore mostly governs:
20
17
  #
21
- # 1. The size-projection-equivalent reader surface (`#year`,
22
- # `#month`, `#hour`, `#sec`, `#wday`, …) RBS-declared
23
- # `Integer` is preserved through dispatch.
24
- # 2. The blocklist below, which keeps the indirect-mutator
25
- # methods that the C-body classifier mis-flagged as
26
- # `:leaf` from ever folding through a hypothetical future
27
- # `Constant<Time>` carrier.
18
+ # 1. The size-projection-equivalent reader surface (`#year`, `#month`, `#hour`, `#sec`, `#wday`, …)
19
+ # RBS-declared `Integer` is preserved through dispatch.
20
+ # 2. The blocklist below, which keeps the indirect-mutator methods that the C-body classifier
21
+ # mis-flagged as `:leaf` from ever folding through a hypothetical future `Constant<Time>`
22
+ # carrier.
28
23
  #
29
- # The blocklist captures the false-positive `:leaf` entries
30
- # whose helper functions the regex classifier did not
31
- # recognise as mutators.
24
+ # The blocklist captures the false-positive `:leaf` entries whose helper functions the regex
25
+ # classifier did not recognise as mutators.
32
26
  TIME_CATALOG = MethodCatalog.for_topic(
33
27
  "time",
34
28
  mutating_selectors: {
35
29
  "Time" => Set[
36
- # `time_init_copy` writes the `timew` and `vtm` slots on
37
- # the receiver via `time_set_timew` / `time_set_vtm`.
38
- # Classed `:leaf` because those setters are not in the
39
- # mutator regex's helper list. Blocked for symmetry with
40
- # String / Array / Range / Set initialize_copy entries.
30
+ # `time_init_copy` writes the `timew` and `vtm` slots on the receiver via `time_set_timew` /
31
+ # `time_set_vtm`. Classed `:leaf` because those setters are not in the mutator regex's helper
32
+ # list. Blocked for symmetry with String / Array / Range / Set initialize_copy entries.
41
33
  :initialize_copy,
42
- # `time_localtime_m` -> `time_localtime` calls
43
- # `time_modify(time)` to mark the receiver mutable
44
- # before rewriting its `vtm` cache and `tzmode`. The
45
- # docstring is explicit ("converts time to local time
46
- # in place"). The C-body classifier mis-flagged it as
47
- # `:leaf` because `time_modify` is not in its mutator
48
- # regex.
34
+ # `time_localtime_m` -> `time_localtime` calls `time_modify(time)` to mark the receiver
35
+ # mutable before rewriting its `vtm` cache and `tzmode`. The docstring is explicit ("converts
36
+ # time to local time in place"). The C-body classifier mis-flagged it as `:leaf` because
37
+ # `time_modify` is not in its mutator regex.
49
38
  :localtime,
50
- # `time_gmtime` (registered as both `gmtime` and `utc`
51
- # against `rb_cTime`) follows the same in-place pattern
52
- # as `time_localtime`: `time_modify(time)` then a
53
- # `time_set_vtm` write and `TZMODE_SET_UTC`. Both
54
- # selectors share the cfunc, so both must be blocked.
39
+ # `time_gmtime` (registered as both `gmtime` and `utc` against `rb_cTime`) follows the same
40
+ # in-place pattern as `time_localtime`: `time_modify(time)` then a `time_set_vtm` write and
41
+ # `TZMODE_SET_UTC`. Both selectors share the cfunc, so both must be blocked.
55
42
  :gmtime, :utc,
56
- # `getlocal` is not a mutator — it returns a fresh Time —
57
- # but the fresh Time is pinned to the *analysis machine's*
58
- # timezone. Folding it through a `Constant[Time]` carrier
59
- # (which only ever holds a UTC literal from `Time.utc`)
60
- # would bake a host-dependent wall clock / `utc_offset`
61
- # into the inferred type. Blocked so the fold stays
62
- # machine-independent; the RBS tier answers `Nominal[Time]`.
63
- # `getutc` / `getgm` stay foldable — their result is UTC.
43
+ # `getlocal` is not a mutator — it returns a fresh Time — but the fresh Time is pinned to the
44
+ # *analysis machine's* timezone. Folding it through a `Constant[Time]` carrier (which only
45
+ # ever holds a UTC literal from `Time.utc`) would bake a host-dependent wall clock /
46
+ # `utc_offset` into the inferred type. Blocked so the fold stays machine-independent; the RBS
47
+ # tier answers `Nominal[Time]`. `getutc` / `getgm` stay foldable — their result is UTC.
64
48
  :getlocal
65
49
  ]
66
50
  }
@@ -6,73 +6,55 @@ module Rigor
6
6
  module Inference
7
7
  # Slice 6 phase C sub-phase 3a — closure-escape classification.
8
8
  #
9
- # Given a `(receiver_type, method_name)` pair representing a
10
- # block-accepting call, this analyzer answers one question:
11
- # does the receiver's method invoke its block **immediately and
12
- # synchronously**, without retaining the block past the call?
9
+ # Given a `(receiver_type, method_name)` pair representing a block-accepting call, this analyzer answers
10
+ # one question: does the receiver's method invoke its block **immediately and synchronously**, without
11
+ # retaining the block past the call?
13
12
  #
14
13
  # The answer is one of three outcomes:
15
14
  #
16
- # - `:non_escaping` — the block is proven to be invoked
17
- # immediately, zero or more times, and is NOT retained past
18
- # the call. The receiver does not store the block in an
19
- # instance variable, return it as a value, or schedule it for
20
- # later invocation. Outer-local narrowing facts that survive
21
- # the block body MAY safely survive the call.
22
- # - `:escaping` — the block is proven to be retained past the
23
- # call (stored, returned, or invoked asynchronously). Outer
24
- # narrowing facts on locals the block can rebind MUST be
25
- # dropped at the call boundary.
26
- # - `:unknown` — the analyzer cannot prove either edge. Callers
27
- # MUST treat `:unknown` as conservatively as `:escaping` for
28
- # the purposes of fact retention; the distinction exists so
29
- # diagnostics and later RBS-Extended effect plumbing can
30
- # tell "deliberately conservative" apart from "declared
31
- # escape".
15
+ # - `:non_escaping` — the block is proven to be invoked immediately, zero or more times, and is NOT
16
+ # retained past the call. The receiver does not store the block in an instance variable, return it as a
17
+ # value, or schedule it for later invocation. Outer-local narrowing facts that survive the block body
18
+ # MAY safely survive the call.
19
+ # - `:escaping` the block is proven to be retained past the call (stored, returned, or invoked
20
+ # asynchronously). Outer narrowing facts on locals the block can rebind MUST be dropped at the call
21
+ # boundary.
22
+ # - `:unknown` the analyzer cannot prove either edge. Callers MUST treat `:unknown` as conservatively as
23
+ # `:escaping` for the purposes of fact retention; the distinction exists so diagnostics and later
24
+ # RBS-Extended effect plumbing can tell "deliberately conservative" apart from "declared escape".
32
25
  #
33
26
  # ## Catalogue
34
27
  #
35
- # Sub-phase 3a is RBS-blind: it ships a hardcoded catalogue
36
- # keyed by Ruby class name. A future sub-phase will replace
37
- # this with an `RBS::Extended` call-timing effect read from
38
- # method signatures. The catalogue therefore covers ONLY the
39
- # core-and-stdlib surface where immediate invocation is part of
40
- # the documented contract:
28
+ # Sub-phase 3a is RBS-blind: it ships a hardcoded catalogue keyed by Ruby class name. A future sub-phase
29
+ # will replace this with an `RBS::Extended` call-timing effect read from method signatures. The catalogue
30
+ # therefore covers ONLY the core-and-stdlib surface where immediate invocation is part of the documented
31
+ # contract:
41
32
  #
42
- # - `Array`, `Hash`, `Range`, `Integer`, `Enumerator::Lazy`
43
- # iteration methods (`each`, `map`, `select`, `reject`,
44
- # `flat_map`, `find`/`detect`, `any?`, `all?`, `none?`,
45
- # `one?`, `count`, `inject`/`reduce`, `each_with_index`,
46
- # `each_with_object`, `min_by`, `max_by`, `sort_by`,
47
- # `partition`, `group_by`, `tally`, `sum`, `take_while`,
48
- # `drop_while`, `chunk_while`, `slice_when`, `zip`,
49
- # `collect`, `collect_concat`, `filter`, `filter_map`).
50
- # - `Hash`-only iteration: `each_pair`, `each_key`, `each_value`,
51
- # `transform_keys`, `transform_values`.
52
- # - `Integer#times`, `Integer#upto`, `Integer#downto`,
53
- # `Range#each`, `Range#step`.
33
+ # - `Array`, `Hash`, `Range`, `Integer`, `Enumerator::Lazy` iteration methods (`each`, `map`, `select`,
34
+ # `reject`, `flat_map`, `find`/`detect`, `any?`, `all?`, `none?`, `one?`, `count`, `inject`/`reduce`,
35
+ # `each_with_index`, `each_with_object`, `min_by`, `max_by`, `sort_by`, `partition`, `group_by`,
36
+ # `tally`, `sum`, `take_while`, `drop_while`, `chunk_while`, `slice_when`, `zip`, `collect`,
37
+ # `collect_concat`, `filter`, `filter_map`).
38
+ # - `Hash`-only iteration: `each_pair`, `each_key`, `each_value`, `transform_keys`, `transform_values`.
39
+ # - `Integer#times`, `Integer#upto`, `Integer#downto`, `Range#each`, `Range#step`.
54
40
  # - `Object#tap`, `Object#then`, `Object#yield_self`.
55
- # - Tuple/HashShape carriers map to Array/Hash for catalogue
56
- # lookup so a literal `[1, 2, 3].each { ... }` is recognised.
41
+ # - Tuple/HashShape carriers map to Array/Hash for catalogue lookup so a literal `[1, 2, 3].each { ... }`
42
+ # is recognised.
57
43
  #
58
- # Anything outside the catalogue resolves to `:unknown`. The
59
- # catalogue is intentionally narrow: adding entries requires
60
- # confirming, by reading the method's stdlib documentation,
61
- # that the block is not retained. False positives in this
62
- # catalogue would silently weaken the soundness of fact
63
- # retention in later sub-phases.
44
+ # Anything outside the catalogue resolves to `:unknown`. The catalogue is intentionally narrow: adding
45
+ # entries requires confirming, by reading the method's stdlib documentation, that the block is not
46
+ # retained. False positives in this catalogue would silently weaken the soundness of fact retention in
47
+ # later sub-phases.
64
48
  #
65
- # The analyzer is a pure query. It MUST NOT mutate the
66
- # receiver type or scope, MUST NOT raise on unrecognised
67
- # inputs, and MUST be deterministic for a given input.
49
+ # The analyzer is a pure query. It MUST NOT mutate the receiver type or scope, MUST NOT raise on
50
+ # unrecognised inputs, and MUST be deterministic for a given input.
68
51
  module ClosureEscapeAnalyzer
69
52
  module_function
70
53
 
71
54
  # @param receiver_type [Rigor::Type, nil]
72
55
  # @param method_name [Symbol]
73
- # @param environment [Rigor::Environment, nil] reserved for the
74
- # future sub-phase that consults `RBS::Extended` call-timing
75
- # effects; sub-phase 3a ignores it.
56
+ # @param environment [Rigor::Environment, nil] reserved for the future sub-phase that consults
57
+ # `RBS::Extended` call-timing effects; sub-phase 3a ignores it.
76
58
  # @return [Symbol] one of `:non_escaping`, `:escaping`, `:unknown`.
77
59
  def classify(receiver_type:, method_name:, environment: nil) # rubocop:disable Lint/UnusedMethodArgument
78
60
  return :unknown if receiver_type.nil?
@@ -90,14 +72,11 @@ module Rigor
90
72
  class << self
91
73
  private
92
74
 
93
- # Resolve a single concrete class name for catalogue lookup.
94
- # Returns `nil` when the receiver carrier does not name a
95
- # single class (e.g. `Top`, `Dynamic[Top]`, `Union[...]`,
96
- # `Bot`). `Tuple` projects to `Array`; `HashShape` to `Hash`;
97
- # `Singleton[C]` to `C` (so `Integer.times` would resolve as
98
- # a singleton call, but the catalogue today only lists
99
- # instance-side methods on `Integer`, so a hit there would
100
- # be unsurprising — kept for forward consistency).
75
+ # Resolve a single concrete class name for catalogue lookup. Returns `nil` when the receiver carrier
76
+ # does not name a single class (e.g. `Top`, `Dynamic[Top]`, `Union[...]`, `Bot`). `Tuple` projects to
77
+ # `Array`; `HashShape` to `Hash`; `Singleton[C]` to `C` (so `Integer.times` would resolve as a
78
+ # singleton call, but the catalogue today only lists instance-side methods on `Integer`, so a hit
79
+ # there would be unsurprising kept for forward consistency).
101
80
  def receiver_class_name(receiver_type)
102
81
  case receiver_type
103
82
  when Type::Nominal, Type::Singleton then receiver_type.class_name
@@ -107,10 +86,9 @@ module Rigor
107
86
  end
108
87
  end
109
88
 
110
- # `Rigor::Type::Constant` only carries scalar literals
111
- # (`Integer`, `Float`, `String`, `Symbol`, `Range`, booleans,
112
- # `nil`); the carrier explicitly rejects mutable container
113
- # values, so we only project from those scalar shapes here.
89
+ # `Rigor::Type::Constant` only carries scalar literals (`Integer`, `Float`, `String`, `Symbol`,
90
+ # `Range`, booleans, `nil`); the carrier explicitly rejects mutable container values, so we only
91
+ # project from those scalar shapes here.
114
92
  CONSTANT_CLASS_NAMES = {
115
93
  Integer => "Integer",
116
94
  String => "String",
@@ -176,9 +154,8 @@ module Rigor
176
154
  "Enumerator::Lazy" => ENUMERABLE_NON_ESCAPING
177
155
  }.freeze
178
156
 
179
- # Methods that are documented to **retain** the block past the
180
- # call. The block is stored or scheduled, so outer narrowing
181
- # facts on writeable captured locals cannot survive.
157
+ # Methods that are documented to **retain** the block past the call. The block is stored or scheduled,
158
+ # so outer narrowing facts on writeable captured locals cannot survive.
182
159
  ESCAPING = {
183
160
  "Module" => %i[define_method].freeze,
184
161
  "Class" => %i[define_method].freeze,
@@ -9,20 +9,17 @@ module Rigor
9
9
  module Inference
10
10
  # Walks an AST and reports per-node-class coverage of `Rigor::Scope#type_of`.
11
11
  #
12
- # For every visited node the scanner runs `type_of` with a fresh
13
- # `FallbackTracer` and inspects the first recorded event:
12
+ # For every visited node the scanner runs `type_of` with a fresh `FallbackTracer` and inspects the first
13
+ # recorded event:
14
14
  #
15
- # * If the first event's `node_class` matches the visited node's class,
16
- # the engine entered the fallback (else) branch *for this very node* —
17
- # the node is counted as **directly unrecognized**.
18
- # * Otherwise the typer either succeeded outright or recursed into a child
19
- # that itself was unrecognized; the visited node is counted as
20
- # recognized so pass-through wrappers (`ProgramNode`, `StatementsNode`,
15
+ # * If the first event's `node_class` matches the visited node's class, the engine entered the fallback
16
+ # (else) branch *for this very node* — the node is counted as **directly unrecognized**.
17
+ # * Otherwise the typer either succeeded outright or recursed into a child that itself was unrecognized;
18
+ # the visited node is counted as recognized so pass-through wrappers (`ProgramNode`, `StatementsNode`,
21
19
  # `ParenthesesNode`, ...) are not double-counted along with their leaves.
22
20
  #
23
- # This class is intended for tooling probes and CI gates rather than the
24
- # hot inference path: it allocates a tracer per visited node and discards
25
- # the inferred type values.
21
+ # This class is intended for tooling probes and CI gates rather than the hot inference path: it allocates
22
+ # a tracer per visited node and discards the inferred type values.
26
23
  class CoverageScanner
27
24
  class Result < Data.define(:visits, :unrecognized, :events)
28
25
  # @return [Integer] sum of all visits across node classes.
@@ -56,13 +53,11 @@ module Rigor
56
53
  unrecognized = Hash.new(0)
57
54
  events = []
58
55
 
59
- # Build the per-node scope index once per scan so locals bound
60
- # earlier in the program flow into the scope used to type every
61
- # later node. The indexer walks the program with a tracer-less
62
- # StatementEvaluator and propagates the recorded scope down to
63
- # expression-interior nodes the evaluator does not visit. The
64
- # second pass below re-types each node with its own tracer so
65
- # the per-class fallback statistics stay attributable.
56
+ # Build the per-node scope index once per scan so locals bound earlier in the program flow into the
57
+ # scope used to type every later node. The indexer walks the program with a tracer-less
58
+ # StatementEvaluator and propagates the recorded scope down to expression-interior nodes the evaluator
59
+ # does not visit. The second pass below re-types each node with its own tracer so the per-class
60
+ # fallback statistics stay attributable.
66
61
  scope_index = ScopeIndexer.index(root, default_scope: @scope)
67
62
 
68
63
  Source::NodeWalker.each(root) do |node|
@@ -6,22 +6,17 @@ require_relative "../type"
6
6
 
7
7
  module Rigor
8
8
  module Inference
9
- # Returns the inferred return type of a `Prism::DefNode`, or nil
10
- # when no type can be derived (empty body, scope-lookup miss,
11
- # or any failure during inference — caller surfaces "no
12
- # annotation" on a nil).
9
+ # Returns the inferred return type of a `Prism::DefNode`, or nil when no type can be derived (empty body,
10
+ # scope-lookup miss, or any failure during inference caller surfaces "no annotation" on a nil).
13
11
  #
14
12
  # The inferred type is the union of:
15
13
  #
16
14
  # - the body's last-statement type, and
17
- # - the type of every explicit `return value` reachable in the
18
- # body. Nested `def` / lambda / block bodies are return
19
- # barriers — their `return`s do not bubble up to the enclosing
20
- # method.
15
+ # - the type of every explicit `return value` reachable in the body. Nested `def` / lambda / block bodies
16
+ # are return barriers — their `return`s do not bubble up to the enclosing method.
21
17
  #
22
- # Extracted from `Rigor::SigGen::Generator#infer_return_type` so
23
- # `LineTypeCollector` (`rigor annotate`'s def-line annotator)
24
- # and the sig-generator share one source of truth.
18
+ # Extracted from `Rigor::SigGen::Generator#infer_return_type` so `LineTypeCollector` (`rigor annotate`'s
19
+ # def-line annotator) and the sig-generator share one source of truth.
25
20
  module DefReturnTyper
26
21
  RETURN_BARRIER_NODES = [Prism::DefNode, Prism::LambdaNode, Prism::BlockNode].freeze
27
22
  private_constant :RETURN_BARRIER_NODES
@@ -79,9 +74,8 @@ module Rigor
79
74
 
80
75
  scope = scope_index[return_node] || scope_index[args.first]
81
76
  return if scope.nil?
82
- # `return a, b` packs into a Tuple at runtime; the MVP only
83
- # handles the single-value form. Multi-arg returns
84
- # contribute no type to keep the implementation focused.
77
+ # `return a, b` packs into a Tuple at runtime; the MVP only handles the single-value form. Multi-arg
78
+ # returns contribute no type to keep the implementation focused.
85
79
  return unless args.size == 1
86
80
 
87
81
  type = safe_type_of(scope, args.first)
@@ -2,16 +2,13 @@
2
2
 
3
3
  module Rigor
4
4
  module Inference
5
- # ADR-75 v1 cause set — precision-additive provenance for Dynamic[T]
6
- # introduction sites. Each symbol identifies a distinct family of
7
- # reason that an expression widened to Dynamic, surfaced by
8
- # `rigor coverage --protection` so users can distinguish tractable
9
- # holes (e.g. an explicit `untyped` RBS signature) from intractable
10
- # ones (e.g. unsupported syntax).
5
+ # ADR-75 v1 cause set — precision-additive provenance for Dynamic[T] introduction sites. Each symbol
6
+ # identifies a distinct family of reason that an expression widened to Dynamic, surfaced by
7
+ # `rigor coverage --protection` so users can distinguish tractable holes (e.g. an explicit `untyped` RBS
8
+ # signature) from intractable ones (e.g. unsupported syntax).
11
9
  #
12
- # Provenance is a side-channel: it never participates in subtyping,
13
- # consistency, normalization, or erasure, and no diagnostic fires
14
- # from it.
10
+ # Provenance is a side-channel: it never participates in subtyping, consistency, normalization, or
11
+ # erasure, and no diagnostic fires from it.
15
12
  module DynamicOrigin
16
13
  # A gem with no resolvable RBS.
17
14
  EXTERNAL_GEM_WITHOUT_RBS = :external_gem_without_rbs
@@ -21,6 +18,13 @@ module Rigor
21
18
  ANALYZER_BUDGET_CUTOFF = :analyzer_budget_cutoff
22
19
  # Authored `untyped` contract.
23
20
  EXPLICIT_UNTYPED = :explicit_untyped
21
+ # The engine cannot yet infer a value's type although it is not unmodeled syntax and no RBS declared
22
+ # it `untyped`: a resolved user/ancestor method whose return body it cannot fold, or an undeclared
23
+ # method *parameter* with no call-site type flowing in (`def f(x); x.foo`). The lever is inference —
24
+ # parameter inference (ADR-67) or ivar-field typing (ADR-58) — not a hand-written type, so it is an
25
+ # engine gap that routes to that roadmap rather than to "add RBS". (The `_return_` in the name is
26
+ # historical; it now covers the parameter case too.)
27
+ INFERRED_RETURN_UNTYPED = :inferred_return_untyped
24
28
  # Inference fallback on unmodeled construct.
25
29
  UNSUPPORTED_SYNTAX = :unsupported_syntax
26
30
 
@@ -29,20 +33,18 @@ module Rigor
29
33
  FRAMEWORK_DSL_BOUNDARY,
30
34
  ANALYZER_BUDGET_CUTOFF,
31
35
  EXPLICIT_UNTYPED,
36
+ INFERRED_RETURN_UNTYPED,
32
37
  UNSUPPORTED_SYNTAX
33
38
  ].freeze
34
39
 
35
- # ADR-73 P6 / ADR-75 WD2 — tractability: given the cause, can a user
36
- # close this `Dynamic` hole, and on which axis. `coverage --protection`
37
- # surfaces it so a user does not chase a hole a hand-written type
40
+ # ADR-73 P6 / ADR-75 WD2 — tractability: given the cause, can a user close this `Dynamic` hole, and on
41
+ # which axis. `coverage --protection` surfaces it so a user does not chase a hole a hand-written type
38
42
  # cannot fix. Three coarse, action-oriented categories:
39
43
  #
40
- # - `:add_rbs` — write or install RBS (a missing gem signature,
41
- # or an authored `untyped` to tighten).
42
- # - `:enable_plugin`— a framework / DSL boundary; needs a plugin or
43
- # `pre_eval:`, not a hand-written type.
44
- # - `:engine_gap` — not user-closable (a budget cutoff or unmodeled
45
- # syntax); report it.
44
+ # - `:add_rbs` — write or install RBS (a missing gem signature, or an authored `untyped` to
45
+ # tighten).
46
+ # - `:enable_plugin`— a framework / DSL boundary; needs a plugin or `pre_eval:`, not a hand-written type.
47
+ # - `:engine_gap` not user-closable (a budget cutoff or unmodeled syntax); report it.
46
48
  ADD_RBS = :add_rbs
47
49
  ENABLE_PLUGIN = :enable_plugin
48
50
  ENGINE_GAP = :engine_gap
@@ -52,13 +54,14 @@ module Rigor
52
54
  EXPLICIT_UNTYPED => ADD_RBS,
53
55
  FRAMEWORK_DSL_BOUNDARY => ENABLE_PLUGIN,
54
56
  ANALYZER_BUDGET_CUTOFF => ENGINE_GAP,
57
+ INFERRED_RETURN_UNTYPED => ENGINE_GAP,
55
58
  UNSUPPORTED_SYNTAX => ENGINE_GAP
56
59
  }.freeze
57
60
 
58
61
  module_function
59
62
 
60
- # @return [Symbol, nil] the tractability category for a cause, or nil
61
- # when the cause is unknown / absent.
63
+ # @return [Symbol, nil] the tractability category for a cause, or nil when the cause is unknown /
64
+ # absent.
62
65
  def tractability(cause)
63
66
  TRACTABILITY[cause]
64
67
  end