rigortype 0.4.7 → 0.4.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 (268) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/data/core_overlay/bigdecimal.rbs +33 -0
  4. data/data/core_overlay/resolv.rbs +30 -0
  5. data/data/gem_overlay/activesupport/core_ext.rbs +29 -0
  6. data/data/gem_overlay/addressable/addressable.rbs +40 -0
  7. data/docs/handbook/01-getting-started.md +1 -1
  8. data/docs/handbook/11-sig-gen.md +35 -0
  9. data/docs/install.md +20 -0
  10. data/docs/manual/01-installation.md +67 -26
  11. data/docs/manual/02-cli-reference.md +307 -91
  12. data/docs/manual/03-configuration.md +41 -3
  13. data/docs/manual/04-diagnostics.md +5 -4
  14. data/docs/manual/08-skills.md +11 -0
  15. data/docs/manual/09-editor-integration.md +8 -0
  16. data/docs/manual/14-rails-quickstart.md +1 -1
  17. data/docs/manual/19-effect-labels.md +3 -4
  18. data/docs/manual/plugins/rigor-actionpack.md +15 -6
  19. data/docs/manual/plugins/rigor-activesupport-core-ext.md +3 -0
  20. data/docs/manual/plugins/rigor-sorbet.md +17 -3
  21. data/lib/rigor/analysis/check_rules/always_raises_shield.rb +147 -0
  22. data/lib/rigor/analysis/check_rules/call_facts.rb +58 -0
  23. data/lib/rigor/analysis/check_rules/declaration_sourced_guard.rb +8 -0
  24. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +13 -2
  25. data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +6 -0
  26. data/lib/rigor/analysis/check_rules/plugin_api_surface.rb +195 -0
  27. data/lib/rigor/analysis/check_rules/published_constant_guard.rb +40 -11
  28. data/lib/rigor/analysis/check_rules/rbs_receiver_surface.rb +27 -1
  29. data/lib/rigor/analysis/check_rules/replaced_singleton_defs.rb +96 -0
  30. data/lib/rigor/analysis/check_rules/rule_ids.rb +8 -1
  31. data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +1 -1
  32. data/lib/rigor/analysis/check_rules.rb +598 -99
  33. data/lib/rigor/analysis/crash_signature.rb +43 -1
  34. data/lib/rigor/analysis/dependency_recorder.rb +233 -76
  35. data/lib/rigor/analysis/incremental.rb +11 -1
  36. data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +2 -1
  37. data/lib/rigor/analysis/incremental_session.rb +279 -37
  38. data/lib/rigor/analysis/reachability/plugin_roots.rb +6 -3
  39. data/lib/rigor/analysis/rule_catalog.rb +37 -1
  40. data/lib/rigor/analysis/run_cache_key.rb +27 -3
  41. data/lib/rigor/analysis/run_disclosure_credit.rb +26 -6
  42. data/lib/rigor/analysis/runner/buffer_pool_dispatcher.rb +4 -0
  43. data/lib/rigor/analysis/runner/declaration_position.rb +7 -7
  44. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +72 -20
  45. data/lib/rigor/analysis/runner/effect_envelope_pass.rb +3 -8
  46. data/lib/rigor/analysis/runner/pool_coordinator.rb +26 -5
  47. data/lib/rigor/analysis/runner/project_pre_passes.rb +4 -37
  48. data/lib/rigor/analysis/runner.rb +222 -39
  49. data/lib/rigor/analysis/self_call_resolution_recorder.rb +61 -22
  50. data/lib/rigor/analysis/worker_session.rb +42 -41
  51. data/lib/rigor/bleeding_edge.rb +19 -4
  52. data/lib/rigor/cache/file_digest.rb +39 -31
  53. data/lib/rigor/cache/incremental_snapshot.rb +66 -7
  54. data/lib/rigor/cache/rbs_descriptor.rb +37 -2
  55. data/lib/rigor/cache/rbs_environment.rb +5 -1
  56. data/lib/rigor/cli/baseline_command.rb +15 -2
  57. data/lib/rigor/cli/check_command.rb +4 -2
  58. data/lib/rigor/cli/effects_snapshot_command.rb +8 -1
  59. data/lib/rigor/cli/lens_command.rb +17 -2
  60. data/lib/rigor/cli/sig_gen_command.rb +8 -0
  61. data/lib/rigor/cli/skill_describe.rb +1 -0
  62. data/lib/rigor/cli.rb +5 -2
  63. data/lib/rigor/config_audit.rb +32 -18
  64. data/lib/rigor/configuration/severity_profile.rb +9 -0
  65. data/lib/rigor/configuration.rb +32 -5
  66. data/lib/rigor/effects/collector.rb +53 -21
  67. data/lib/rigor/environment/bundle_sig_discovery.rb +63 -28
  68. data/lib/rigor/environment/constant_type_cache_holder.rb +5 -0
  69. data/lib/rigor/environment/default_libraries.rb +17 -0
  70. data/lib/rigor/environment/deferred_signature_plan.rb +104 -6
  71. data/lib/rigor/environment/hkt_registry_holder.rb +6 -0
  72. data/lib/rigor/environment/rbs_collection_discovery.rb +123 -8
  73. data/lib/rigor/environment/rbs_coverage_report.rb +12 -11
  74. data/lib/rigor/environment/rbs_hierarchy.rb +6 -0
  75. data/lib/rigor/environment/rbs_loader.rb +312 -63
  76. data/lib/rigor/environment.rb +131 -35
  77. data/lib/rigor/inference/acceptance.rb +50 -15
  78. data/lib/rigor/inference/alias_mutation_floor/foreign_locals.rb +117 -0
  79. data/lib/rigor/inference/alias_mutation_floor/memos.rb +85 -0
  80. data/lib/rigor/inference/alias_mutation_floor/reach.rb +119 -0
  81. data/lib/rigor/inference/alias_mutation_floor/site_collector.rb +252 -0
  82. data/lib/rigor/inference/alias_mutation_floor.rb +339 -0
  83. data/lib/rigor/inference/anonymous_meta_class.rb +18 -0
  84. data/lib/rigor/inference/block_auto_splat.rb +1 -1
  85. data/lib/rigor/inference/block_run_count.rb +9 -2
  86. data/lib/rigor/inference/builtins/array_catalog.rb +2 -2
  87. data/lib/rigor/inference/callee_mutation_chain.rb +1 -1
  88. data/lib/rigor/inference/captured_locals.rb +2 -0
  89. data/lib/rigor/inference/census_foreign_block.rb +354 -0
  90. data/lib/rigor/inference/clause_widening.rb +1 -1
  91. data/lib/rigor/inference/closure_escape_analyzer.rb +11 -4
  92. data/lib/rigor/inference/construction_escape.rb +56 -15
  93. data/lib/rigor/inference/declaration_walk.rb +4 -0
  94. data/lib/rigor/inference/def_node_resolver.rb +32 -14
  95. data/lib/rigor/inference/def_return_typer.rb +1 -1
  96. data/lib/rigor/inference/definer_resolution.rb +15 -7
  97. data/lib/rigor/inference/definers_index.rb +72 -16
  98. data/lib/rigor/inference/error_info.rb +16 -0
  99. data/lib/rigor/inference/expression_typer.rb +1459 -287
  100. data/lib/rigor/inference/flow_tracer.rb +31 -14
  101. data/lib/rigor/inference/fork_map.rb +3 -0
  102. data/lib/rigor/inference/fresh_frame_blocks.rb +52 -1
  103. data/lib/rigor/inference/global_write_census.rb +8 -6
  104. data/lib/rigor/inference/in_effect_refinements.rb +7 -0
  105. data/lib/rigor/inference/indexed_narrowing.rb +57 -8
  106. data/lib/rigor/inference/ivar_writer_census.rb +106 -11
  107. data/lib/rigor/inference/key_presence_guard.rb +51 -25
  108. data/lib/rigor/inference/last_line/self_evidence.rb +30 -0
  109. data/lib/rigor/inference/last_line.rb +5 -2
  110. data/lib/rigor/inference/loop_value_record.rb +63 -15
  111. data/lib/rigor/inference/match_rebinding/frame.rb +11 -0
  112. data/lib/rigor/inference/match_rebinding/yielding_match.rb +74 -18
  113. data/lib/rigor/inference/match_rebinding.rb +21 -8
  114. data/lib/rigor/inference/method_dispatcher/block_folding.rb +43 -29
  115. data/lib/rigor/inference/method_dispatcher/class_keyed_block_params.rb +65 -0
  116. data/lib/rigor/inference/method_dispatcher/core_enumerable_receiver.rb +44 -0
  117. data/lib/rigor/inference/method_dispatcher/declared_constructor.rb +151 -0
  118. data/lib/rigor/inference/method_dispatcher/facet_distribution.rb +1 -1
  119. data/lib/rigor/inference/method_dispatcher/imprecise_argument.rb +2 -2
  120. data/lib/rigor/inference/method_dispatcher/interface_shape.rb +181 -0
  121. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +12 -0
  122. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +409 -67
  123. data/lib/rigor/inference/method_dispatcher/self_substitute.rb +1 -1
  124. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +384 -64
  125. data/lib/rigor/inference/method_dispatcher/singleton_type_params.rb +104 -0
  126. data/lib/rigor/inference/method_dispatcher.rb +66 -18
  127. data/lib/rigor/inference/method_parameter_binder.rb +136 -56
  128. data/lib/rigor/inference/module_function_state/spellings.rb +2 -2
  129. data/lib/rigor/inference/module_function_state.rb +13 -2
  130. data/lib/rigor/inference/multi_target_binder.rb +1 -1
  131. data/lib/rigor/inference/mutation_widening.rb +44 -4
  132. data/lib/rigor/inference/narrowing.rb +201 -27
  133. data/lib/rigor/inference/operand_effects.rb +43 -2
  134. data/lib/rigor/inference/optimistic_origin.rb +133 -8
  135. data/lib/rigor/inference/origin_lookup.rb +1 -1
  136. data/lib/rigor/inference/precision_scanner.rb +1 -1
  137. data/lib/rigor/inference/project_method_ownership.rb +28 -10
  138. data/lib/rigor/inference/project_patched_methods.rb +65 -13
  139. data/lib/rigor/inference/project_patched_scanner.rb +120 -25
  140. data/lib/rigor/inference/project_patched_visibility.rb +39 -3
  141. data/lib/rigor/inference/rbs_type_translator.rb +68 -15
  142. data/lib/rigor/inference/receiver_writer_call.rb +67 -0
  143. data/lib/rigor/inference/recursion_rebinding.rb +157 -0
  144. data/lib/rigor/inference/refined_dispatch/constructed_class.rb +56 -18
  145. data/lib/rigor/inference/refined_dispatch/own_method.rb +51 -17
  146. data/lib/rigor/inference/refined_dispatch.rb +13 -0
  147. data/lib/rigor/inference/reflective_ivar_write.rb +19 -11
  148. data/lib/rigor/inference/remover_holder_scan.rb +76 -22
  149. data/lib/rigor/inference/scope_indexer/class_cvars_collector.rb +13 -6
  150. data/lib/rigor/inference/scope_indexer/declared_param_writes.rb +12 -11
  151. data/lib/rigor/inference/scope_indexer/ivar_contributions.rb +188 -28
  152. data/lib/rigor/inference/scope_indexer/mixin_accumulator.rb +136 -9
  153. data/lib/rigor/inference/scope_indexer.rb +2079 -183
  154. data/lib/rigor/inference/self_call_ivar_writes.rb +26 -7
  155. data/lib/rigor/inference/self_preserving_block.rb +87 -0
  156. data/lib/rigor/inference/singleton_hook_decline.rb +41 -6
  157. data/lib/rigor/inference/singleton_object_constant.rb +32 -2
  158. data/lib/rigor/inference/statement_evaluator.rb +970 -250
  159. data/lib/rigor/inference/string_mutation.rb +14 -0
  160. data/lib/rigor/inference/synthetic_method_scanner.rb +35 -11
  161. data/lib/rigor/inference/toplevel_def_census.rb +14 -6
  162. data/lib/rigor/inference/unknown_store_widening.rb +1 -1
  163. data/lib/rigor/inference/untyped_rejoin.rb +1 -1
  164. data/lib/rigor/inference/void_tail_summary.rb +29 -10
  165. data/lib/rigor/lens/claims/comparison.rb +78 -0
  166. data/lib/rigor/lens/claims/request.rb +131 -0
  167. data/lib/rigor/lens/claims/type_reader.rb +216 -0
  168. data/lib/rigor/lens/claims.rb +208 -0
  169. data/lib/rigor/lens/contract_reader.rb +5 -0
  170. data/lib/rigor/lens/document.rb +1 -1
  171. data/lib/rigor/lens/file_reader.rb +21 -8
  172. data/lib/rigor/lens/run.rb +8 -0
  173. data/lib/rigor/lens.rb +1 -1
  174. data/lib/rigor/library_probe.rb +68 -0
  175. data/lib/rigor/memo_audit.rb +282 -0
  176. data/lib/rigor/plugin/base.rb +15 -2
  177. data/lib/rigor/plugin/io_boundary.rb +25 -3
  178. data/lib/rigor/plugin/manifest.rb +7 -3
  179. data/lib/rigor/plugin/registry.rb +13 -2
  180. data/lib/rigor/plugin/trust_policy.rb +46 -0
  181. data/lib/rigor/protection/mutation_cache.rb +4 -1
  182. data/lib/rigor/reflection/constant_ancestors.rb +79 -22
  183. data/lib/rigor/reflection/declaration_collectors.rb +55 -0
  184. data/lib/rigor/reflection/declarations.rb +58 -0
  185. data/lib/rigor/reflection/project_method.rb +177 -0
  186. data/lib/rigor/reflection.rb +2 -0
  187. data/lib/rigor/rooted_glob.rb +18 -1
  188. data/lib/rigor/run_scoped_slots.rb +20 -20
  189. data/lib/rigor/scope/discovery_index.rb +149 -2
  190. data/lib/rigor/scope/resolution_chain/relevance.rb +14 -1
  191. data/lib/rigor/scope/resolution_chain.rb +900 -55
  192. data/lib/rigor/scope.rb +307 -34
  193. data/lib/rigor/sig_gen/bot_proposal_guard.rb +306 -0
  194. data/lib/rigor/sig_gen/classification.rb +14 -1
  195. data/lib/rigor/sig_gen/generator.rb +222 -13
  196. data/lib/rigor/sig_gen/method_candidate.rb +14 -0
  197. data/lib/rigor/sig_gen/observation_collector.rb +11 -2
  198. data/lib/rigor/sig_gen/platform_guarded_files.rb +184 -0
  199. data/lib/rigor/sig_gen/skip_reason_catalog.rb +47 -0
  200. data/lib/rigor/sig_gen/writer.rb +21 -0
  201. data/lib/rigor/sig_gen.rb +1 -0
  202. data/lib/rigor/source/forwardable_delegators.rb +122 -0
  203. data/lib/rigor/source/node_children.rb +13 -0
  204. data/lib/rigor/type/combinator.rb +164 -8
  205. data/lib/rigor/type/interface.rb +60 -0
  206. data/lib/rigor/type.rb +1 -0
  207. data/lib/rigor/type_of_memo/serving.rb +99 -0
  208. data/lib/rigor/type_of_memo/stats.rb +43 -0
  209. data/lib/rigor/type_of_memo.rb +337 -0
  210. data/lib/rigor/typing_state.rb +1094 -0
  211. data/lib/rigor/version.rb +1 -1
  212. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/view_assigns.rb +2 -2
  213. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +57 -25
  214. data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +3 -6
  215. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +25 -1
  216. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +16 -6
  217. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +4 -2
  218. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +2 -1
  219. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +130 -30
  220. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +20 -5
  221. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +7 -4
  222. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +49 -13
  223. data/plugins/rigor-activerecord/sig/active_record/relation.rbs +19 -5
  224. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +4 -2
  225. data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +13 -5
  226. data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +29 -0
  227. data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_collector.rb +15 -21
  228. data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_discoverer.rb +1 -6
  229. data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +4 -2
  230. data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +12 -2
  231. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +6 -0
  232. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +199 -1
  233. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +3 -2
  234. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +4 -4
  235. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +209 -2
  236. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +146 -7
  237. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +52 -34
  238. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +80 -3
  239. data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_collector.rb +16 -16
  240. data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_discoverer.rb +1 -6
  241. data/sig/rigor/analysis/check_rules/rule_walk.rbs +6 -0
  242. data/sig/rigor/analysis/fact_store.rbs +2 -3
  243. data/sig/rigor/cache/descriptor.rbs +14 -0
  244. data/sig/rigor/environment.rbs +4 -1
  245. data/sig/rigor/plugin/base.rbs +53 -19
  246. data/sig/rigor/plugin/interfaces.rbs +51 -0
  247. data/sig/rigor/plugin/io_boundary.rbs +2 -3
  248. data/sig/rigor/plugin/node_context.rbs +21 -0
  249. data/sig/rigor/reflection.rbs +37 -0
  250. data/sig/rigor/scope.rbs +22 -3
  251. data/sig/rigor/trinary.rbs +1 -0
  252. data/sig/rigor/type.rbs +9 -3
  253. data/sig/rigor.rbs +3 -2
  254. data/skills/rigor-ask/SKILL.md +1 -0
  255. data/skills/rigor-project-init/references/01-detect.md +1 -0
  256. data/skills/rigor-project-init/references/03-baseline-and-bugs.md +5 -1
  257. data/skills/rigor-project-init/references/06-agent-contract.md +4 -4
  258. data/skills/rigor-rbs-contract/SKILL.md +147 -0
  259. data/skills/rigor-rbs-contract/references/01-finding-candidates.md +212 -0
  260. data/skills/rigor-rbs-contract/references/02-contract-rules.md +157 -0
  261. data/skills/rigor-rbs-contract/references/03-target-own-code.md +90 -0
  262. data/skills/rigor-rbs-contract/references/04-target-gem-rbs-collection.md +210 -0
  263. data/skills/rigor-rbs-contract/references/05-declaration-mutants.md +182 -0
  264. data/skills/rigor-rbs-setup/SKILL.md +3 -1
  265. data/skills/rigor-type-oracle/SKILL.md +26 -1
  266. data/skills/rigor-type-oracle/references/02-agents-md-fragment.md +4 -3
  267. metadata +48 -2
  268. data/lib/rigor/inference/memo_audit.rb +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 983cf341f34d4407d6d06ab2b0bf50260f5b52a4f6e29c61ce0042123ab833cc
4
- data.tar.gz: 17ea6b8b13033e507d0e7570913ab2609c830c9a5cfa706cfe055b6857d315f5
3
+ metadata.gz: d2aa3cbe98e027e6ed461d3252980ae558778e4df0b2c78f658b848e73b13d8b
4
+ data.tar.gz: 611f238af77124e90cab5844f65be0720898b93469eb7a908d1e82eb4d9a1177
5
5
  SHA512:
6
- metadata.gz: 0cd85174733cb61860d33f5636e81ac5d19972f9e6bd66fc6282d1aa7330735f8a57a067e1cfa81071632a45a0ca123f607be5b5bda7b3b32153fb8069328dfc
7
- data.tar.gz: 64ecfde3bfe3eaef83ff44fa6ee1ca72bf6f353648c55a354726e60a87203012f907ce5406dc162289ff2a99056cf8b2962a79f636d5e7dd93cf16ec2b00e8d2
6
+ metadata.gz: 8b82ef7bdde5d2f8ca978379190effc8730bd6dcb7224207282b9b820d06a2853cc61f87314ad6b8b7a0d81351f3aedd869d1f8449bb6f75e74f83baa56590b8
7
+ data.tar.gz: fe1685b7aad2412ea38090bdc53e350972c25522036330375eba7424457e086057018bad9827c35c1e4e0c65ca48d496bb54e5a8f58f0213668f4609053c7fdd
data/README.md CHANGED
@@ -20,6 +20,8 @@ rigor check app lib # find bugs in the code you already have
20
20
  global `-g` install keeps it off your project's pins. See
21
21
  [Get started](#get-started-in-one-prompt).)
22
22
 
23
+ If your project's bundle also lists `rbs` (directly, or through Steep or `rbs_rails`), the `rbs` that `gem:rigortype` puts on `PATH` can shadow it; see the [install guide's note on `rbs` shadowing](docs/install.md#case-a--mise-is-available-recommended).
24
+
23
25
  No annotations required, no runtime dependency, no changes to your
24
26
  code — and any RBS you do add, Rigor reads and uses. Rigor parses Ruby
25
27
  with
@@ -232,7 +234,7 @@ rigor docs --list # list every bundled page
232
234
 
233
235
  ## Status
234
236
 
235
- Current release: **`v0.4.7`** (2026-11-03) — on the
237
+ Current release: **`v0.4.8`** (2026-11-15) — on the
236
238
  `0.4.x` line, continuing the evaluation era opened by `v0.2.0`, the first
237
239
  publicly-announced (general / evaluation) release. The line publishes
238
240
  an enumerated [compatibility surface](docs/compatibility.md) as a
@@ -0,0 +1,33 @@
1
+ # Rigor core overlay — supplemental core signatures.
2
+ #
3
+ # --- BigDecimal precision readers (issue #2969) ---
4
+ #
5
+ # rbs 4.2 ships `stdlib/bigdecimal/0/big_decimal.rbs` without `precision`, `scale`,
6
+ # `precision_scale` or `n_significant_digits`, and the bigdecimal gem's own `sig/` (4.1.3)
7
+ # omits them too, so `BigDecimal("1.5").precision` reported `call.undefined-method` on correct code.
8
+ #
9
+ # Upstream: bigdecimal 4.1.3 `ext/bigdecimal/bigdecimal.c` registers the four readers as instance
10
+ # methods (`rb_define_method(rb_cBigDecimal, "precision", ...)`, and likewise for the other three).
11
+ # Their documented results: `precision -> integer` (decimal digits), `scale -> integer`,
12
+ # `precision_scale -> [integer, integer]`, and `n_significant_digits -> integer`.
13
+ #
14
+ # bigdecimal is a bundled gem, not a default library, so this file is gated on it
15
+ # (`Rigor::Environment::RbsLoader::LIBRARY_SUPPLEMENT_CORE_OVERLAYS`). Without the library the file would
16
+ # open a phantom `BigDecimal` that nothing else declares.
17
+ #
18
+ # The methods sit on a module the class includes, not as direct `def`s, so a later rbs or a project
19
+ # `sig/` that declares one of them directly overrides it instead of raising
20
+ # `DuplicatedMethodDefinitionError` (the same shape as `process.rbs` and `ruby41_core_overlay`).
21
+
22
+ module RigorCoreOverlay
23
+ module BigDecimalPrecision
24
+ def precision: () -> Integer
25
+ def scale: () -> Integer
26
+ def precision_scale: () -> [Integer, Integer]
27
+ def n_significant_digits: () -> Integer
28
+ end
29
+ end
30
+
31
+ class BigDecimal
32
+ include RigorCoreOverlay::BigDecimalPrecision
33
+ end
@@ -29,3 +29,33 @@ class Resolv
29
29
  def initialize: (?(Array[Resolv::Hosts | Resolv::DNS] | Hash[Symbol, untyped])? resolvers, ?use_ipv6: bool?) -> untyped
30
30
  | ...
31
31
  end
32
+
33
+ # --- Resolv::DNS#getresources / #getresource / #each_resource ---
34
+ #
35
+ # `rbs` declares the three typeclass lookups as answering the base class
36
+ # whatever the typeclass argument names:
37
+ #
38
+ # def getresources: (dns_name name, singleton(Resolv::DNS::Query) typeclass) -> Array[Resolv::DNS::Resource]
39
+ #
40
+ # so `dns.getresources(d, Resolv::DNS::Resource::IN::MX).map(&:exchange)`
41
+ # false-fires `call.undefined-method` (`exchange` is declared on
42
+ # `Resolv::DNS::Resource::MX`, not on `Resource`). At runtime every returned
43
+ # record is an instance of the typeclass (rigortype/rigor#2828).
44
+ #
45
+ # The overlay prepends a generic overload binding `T` from `singleton(T)`, so
46
+ # the answer is `Array[Resolv::DNS::Resource::IN::MX]`. An argument the
47
+ # binder cannot read as a class object under the `Resource` bound leaves `T`
48
+ # unbound, and the base overload (`| ...`) still accepts every `Query`
49
+ # typeclass the upstream signature does.
50
+ class Resolv
51
+ class DNS
52
+ def each_resource: [T < Resolv::DNS::Resource] (Resolv::DNS::dns_name name, singleton(T) typeclass) { (T) -> void } -> void
53
+ | ...
54
+
55
+ def getresource: [T < Resolv::DNS::Resource] (Resolv::DNS::dns_name name, singleton(T) typeclass) -> T
56
+ | ...
57
+
58
+ def getresources: [T < Resolv::DNS::Resource] (Resolv::DNS::dns_name name, singleton(T) typeclass) -> Array[T]
59
+ | ...
60
+ end
61
+ end
@@ -347,6 +347,35 @@ class Float
347
347
  def gigabytes: () -> Float
348
348
  end
349
349
 
350
+ # ---------------------------------------------------------------
351
+ # NumericWithFormat — ActiveSupport's `core_ext/numeric/conversions`, included into Integer, Float and
352
+ # BigDecimal. Declared on the module and included, not as a `def` on each class, so a project `sig/` that
353
+ # declares `Integer#to_fs` itself overrides it instead of raising `DuplicatedMethodDefinitionError` (the
354
+ # `process.rbs` shape). Not pure: the Symbol formats read `I18n` for their locale. An Integer or String
355
+ # format is `to_s(format)`, and no format is `to_s`, so every form answers a String. `options` is any
356
+ # Hash-like value: ActiveSupport calls `symbolize_keys` on it, so String keys and a HashWithIndifferentAccess
357
+ # are both valid.
358
+ # ---------------------------------------------------------------
359
+
360
+ module ActiveSupport
361
+ module NumericWithFormat
362
+ def to_fs: (?(Symbol | Integer | String | nil) format, ?Hash[untyped, untyped]? options) -> String
363
+ def to_formatted_s: (?(Symbol | Integer | String | nil) format, ?Hash[untyped, untyped]? options) -> String
364
+ end
365
+ end
366
+
367
+ class Integer
368
+ include ActiveSupport::NumericWithFormat
369
+ end
370
+
371
+ class Float
372
+ include ActiveSupport::NumericWithFormat
373
+ end
374
+
375
+ class BigDecimal
376
+ include ActiveSupport::NumericWithFormat
377
+ end
378
+
350
379
  # ---------------------------------------------------------------
351
380
  # ActiveSupport::Duration — issue #632
352
381
  # ---------------------------------------------------------------
@@ -0,0 +1,40 @@
1
+ # Addressable — `rbs collection` correction overlay (issue #2857).
2
+ #
3
+ # gem_rbs_collection's `gems/addressable/*/addressable.rbs` declares
4
+ # `Addressable::URI.parse` as `(String | URI uri) -> instance`, but
5
+ # `Addressable::URI.parse(nil)` returns nil, so `Addressable::URI.parse(x)`
6
+ # on a `String?` — the mastodon `fetch_link_card_service.rb` shape — drew a
7
+ # false `call.argument-type-mismatch` on correct code.
8
+ #
9
+ # Unlike the activesupport overlay this directory does NOT ride the ADR-72
10
+ # `:missing` gate: it loads only when `rbs collection` supplies the gem's
11
+ # RBS (`:rbs_collection` coverage — `Environment::GEM_OVERLAY_COVERAGE_SOURCES`).
12
+ # The deferred-signature plan (#2422) then composes this declaration over the
13
+ # collection's copy as an overload continuation, so `parse(nil)` binds nil
14
+ # while `parse(String | URI)` keeps the URI answer and a `String?` argument
15
+ # mismatches nothing. Under `:missing` coverage — no sigs at all — the
16
+ # overlay stays unloaded on purpose: this partial `Addressable::URI`
17
+ # declaration would make every member it omits (`host`, `path`, …) a false
18
+ # `call.undefined-method`, which is worse than the `Dynamic` silence a
19
+ # sig-less gem already has.
20
+ module Addressable
21
+ class URI
22
+ # Two arms, URI-carrying first — the order is load-bearing, not cosmetic.
23
+ # `Addressable::URI` is RBS-known but not loadable in the analyzer's host
24
+ # process, so `NilClass`-vs-`Addressable::URI` acceptance answers `maybe`,
25
+ # and the overload selector's strict pass takes the FIRST maybe-match: a
26
+ # leading `(::NilClass)` arm would shadow this one and type
27
+ # `parse(existing_uri)` as `nil`. With the URI arm first it answers `yes`
28
+ # and wins; `nil` still reaches the second arm.
29
+ #
30
+ # `::NilClass`, not the `nil` keyword: they accept the same arguments, but
31
+ # RBS types `nil` as `Types::Bases::Nil`, which the
32
+ # `call.argument-type-mismatch` non-nil channel reads as "undecidable →
33
+ # admits", silently dropping `Addressable::URI.parse(123)`. `NilClass` is
34
+ # a `ClassInstance`, so the channel still refutes what no overload admits.
35
+ #
36
+ # The collection's own `(String | URI uri) -> instance` stays reachable as
37
+ # the `| ...` fallback the deferred plan appends.
38
+ def self.parse: (String | URI uri) -> URI | (::NilClass) -> nil
39
+ end
40
+ end
@@ -59,7 +59,7 @@ mise use gem:rigortype
59
59
  With mise activated in your shell, `rigor` is on your `PATH`. The
60
60
  gem is named `rigortype` (the name `rigor` was taken on RubyGems);
61
61
  the executable it installs is `rigor`. If you already have Ruby
62
- 4.0, `gem install rigortype` works too.
62
+ 4.0, `gem install rigortype` works too. If the project's bundle lists `rbs`, the `rbs` that `gem:rigortype` puts on `PATH` can shadow it; see the [install guide's note on `rbs` shadowing](../install.md#case-a--mise-is-available-recommended).
63
63
 
64
64
  For shell activation and shims, `asdf`, and developing inside a
65
65
  container, see [Installing Rigor](../manual/01-installation.md);
@@ -164,6 +164,32 @@ The `sig.skipped.*` reasons are:
164
164
  inline and in `sig/`, and the two disagree. A refusal:
165
165
  `--write` and `--check` exit `1`. See
166
166
  [Methods declared inline](#methods-declared-inline).
167
+ - `sig.skipped.overridden-bot` — the method's body never
168
+ returns (its inferred return is `bot`), and the analysed
169
+ code defines the method again, with `def` or
170
+ `define_method`: in a subclass, signed or not, in a class
171
+ that includes the method's module, in a module included
172
+ later or prepended, or as an extending class's own
173
+ singleton method. `bot` would describe only the base body
174
+ the overrides replace. A class left with nothing to write
175
+ because of this is still written as an empty class, so its
176
+ subclasses keep their signatures, unless your `sig/` or a
177
+ gem's signatures already declare it.
178
+ - `sig.skipped.abstract-method` — the method's inferred return
179
+ is `bot` from an abstract-style raise: `NotImplementedError`,
180
+ an error class named `Abstract…` or `NotImplemented…`, or a
181
+ message that asks for the method to be implemented or
182
+ overridden, or to define it by name ("please define
183
+ about"; not "you must define a block"). The
184
+ implementations may live outside the analysed code, as in a
185
+ plugin gem, so no `bot` is proposed.
186
+ - `sig.skipped.template-method` — the method's inferred return
187
+ is `bot`, its body does not end in a direct `raise`, `fail`,
188
+ `throw`, `exit` or `abort`, and it calls a method the
189
+ analysed code overrides or declares abstract, directly or
190
+ through self-dispatched calls. The call is matched by name,
191
+ whatever the receiver. A `bot` that ends in a direct
192
+ `throw` or a raise nothing overrides is still proposed.
167
193
  - `sig.skipped.top-level-def` — a plain top-level `def`, which
168
194
  defines a private `Object` method. sig-gen lists it (file,
169
195
  method name and this reason in `--format=json`) but writes no
@@ -185,6 +211,15 @@ The `sig.skipped.*` reasons are:
185
211
  down with it. The rest of the signatures are unaffected;
186
212
  the skipped method is reported on stderr, and it is worth
187
213
  reporting to us.
214
+ - `sig.skipped.platform-guarded` — the method is defined in
215
+ a file Ruby loads only under a `RUBY_ENGINE`,
216
+ `RUBY_PLATFORM` or `defined?(…)` require guard (the
217
+ `if RUBY_ENGINE == 'truffleruby'` → `require
218
+ "stackprof/truffleruby"` shape), so it is not an ordinary
219
+ definition for every platform. sig-gen withholds the
220
+ proposal when another scanned file also defines the
221
+ method, or when the inferred return is `bot` — the shape
222
+ a raising stub takes (#3035).
188
223
 
189
224
  ### Tighter returns keep the declared parameters
190
225
 
data/docs/install.md CHANGED
@@ -109,6 +109,26 @@ A user-wide `~/.config/mise/config.toml` entry for `gem:rigortype`
109
109
  keeps applying outside this project. Mention it if it names an older
110
110
  version, but do not edit global config without the user's consent.
111
111
 
112
+ `gem:rigortype` also puts an `rbs` on `PATH`: mise wraps every
113
+ executable the gem's dependencies install, and that wrapper runs with
114
+ rigortype's private `GEM_HOME`. When `rbs` is in the project's bundle
115
+ (`Gemfile.lock` lists it, directly or through Steep or `rbs_rails`)
116
+ and the bundle uses the default path, `bundle exec rbs` runs the
117
+ wrapper instead of the project's `rbs`. A git-sourced gem then fails
118
+ with `is not yet checked out` under rigortype's `GEM_HOME`. A bundle
119
+ installed under a configured path such as `vendor/bundle` is not
120
+ affected, because `bundle exec` puts that path's `bin` first. Only
121
+ when `Gemfile.lock` lists `rbs`, run `mise exec -- bundle exec which
122
+ rbs` (the shell you are in has not picked up the new tool yet, so a
123
+ bare `bundle exec which rbs` can miss it). If it prints a path under
124
+ `installs/gem-rigortype/`, tell the user, and tell them the fix is
125
+ local to this checkout: `bundle config set --local path vendor/bundle`
126
+ followed by `bundle install` writes an untracked `.bundle/config`
127
+ (teammates and CI keep the default path), puts the bundle in
128
+ `vendor/`, and makes Rigor read each bundled gem's shipped `sig/`
129
+ (ADR-27). Offer it; do not change the bundle path without their
130
+ consent.
131
+
112
132
  Then verify:
113
133
 
114
134
  ```sh
@@ -28,6 +28,14 @@ so nothing is lost by installing it separately.
28
28
  > [Rails quickstart](14-rails-quickstart.md)). The channels below
29
29
  > are the manual route.
30
30
 
31
+ > **Only trying Rigor in VS Code?** When the
32
+ > [Rigor extension](../../editors/vscode/README.md) finds no `rigor`,
33
+ > it offers to install one into its own storage, using a Ruby 4.0
34
+ > already on the machine (or one `mise install ruby@4.0` provides).
35
+ > That install serves the editor only and is never used for a project
36
+ > that pins `rigortype`; for the command line and CI, use a channel
37
+ > below.
38
+
31
39
  ### Set up in your language
32
40
 
33
41
  The prompt above is plain natural language — your agent follows the
@@ -269,6 +277,8 @@ A few things worth knowing if you have not used mise before:
269
277
  The gem is `rigortype`; the executable it installs (and the only
270
278
  command you run) is `rigor`.
271
279
 
280
+ If the project's bundle lists `rbs`, the `rbs` that `gem:rigortype` puts on `PATH` can shadow the project's own; see the [install guide's note on `rbs` shadowing](../install.md#case-a--mise-is-available-recommended).
281
+
272
282
  ### Putting `rigor` on your PATH
273
283
 
274
284
  Installing the tool is not enough on its own — `rigor` reaches your
@@ -356,8 +366,63 @@ gem install rigortype
356
366
  `asdf` has no general-purpose gem backend, so the gem itself is
357
367
  installed with `gem install` rather than an `asdf` command. `mise`
358
368
  (above) is the more integrated option because its `gem:` backend
359
- records the gem in the same config that records Ruby, and — as the
360
- next section explains — keeps the two from interfering.
369
+ records the gem in the same config that records Ruby, and — as
370
+ [Simple alternative](#simple-alternative--gem-install) explains —
371
+ keeps the two from interfering.
372
+
373
+ ## Secondary — a pinned bundle
374
+
375
+ The rule at the top of this chapter is about your *application's*
376
+ `Gemfile` — the one Bundler resolves against your app's gems, and whose
377
+ entries `Bundler.require` loads at boot. It is not a rule against
378
+ Bundler. A `Gemfile` holding nothing but Rigor, resolved separately and
379
+ selected with `BUNDLE_GEMFILE`, keeps every property the prohibition
380
+ exists to protect: your application's dependency graph never meets
381
+ Rigor's, and your application's Ruby is never constrained by Rigor's.
382
+
383
+ Commit it, with its `Gemfile.lock`, at `.github/rigor/`, the path Rigor's
384
+ CI template uses. The VS Code extension runs it (discovery kind
385
+ `pinned-bundle`, under a Ruby it finds the way it does for its managed
386
+ Rigor, preferring one that matches the lockfile's `RUBY VERSION` or
387
+ the Gemfile's `ruby` line; `rigor.server.bundleGemfile` names another
388
+ location), and never a different Rigor while it pins one.
389
+ `rigor doctor` does not recognise it yet
390
+ ([#2751](https://github.com/rigortype/rigor/issues/2751)):
391
+
392
+ ```ruby
393
+ # .github/rigor/Gemfile
394
+ source "https://rubygems.org"
395
+ ruby ">= 4.0.0", "< 4.1"
396
+ gem "rigortype", "~> 0.4"
397
+ ```
398
+
399
+ Each command has to run under a Ruby 4.0, which is usually not your
400
+ project's Ruby, so select it on the command line:
401
+
402
+ ```sh
403
+ # with mise
404
+ BUNDLE_GEMFILE=.github/rigor/Gemfile mise exec ruby@4.0 -- bundle install
405
+ BUNDLE_GEMFILE=.github/rigor/Gemfile mise exec ruby@4.0 -- bundle exec rigor check
406
+ # with rbenv
407
+ BUNDLE_GEMFILE=.github/rigor/Gemfile RBENV_VERSION=4.0.5 bundle exec rigor check
408
+ ```
409
+
410
+ A `.ruby-version` inside `.github/rigor/` does not select it, because
411
+ Rigor runs from the project root, and neither does a Bundler binstub,
412
+ whose `#!/usr/bin/env ruby` runs the project's Ruby.
413
+
414
+ The same pin then serves local runs and CI, Dependabot can keep it
415
+ current (see [Pinning Rigor's version](11-ci.md#pinning-rigors-version)
416
+ in the CI chapter), and it is where a third-party Rigor plugin gem
417
+ goes. What it does **not** do is provide Ruby: every `bundle exec`
418
+ must already run under a Ruby 4.0, which the `ruby` line checks. Only
419
+ `rigortype` is pinned exactly; the lockfile records the dependency
420
+ versions Bundler resolved when you installed.
421
+
422
+ It is more moving parts than `mise use --pin gem:rigortype`, which
423
+ records the version and the Ruby in one place and needs no `bundle
424
+ exec`. Reach for it when your team already runs everything through
425
+ Bundler, or needs a plugin gem — not as a first choice.
361
426
 
362
427
  ## Simple alternative — gem install
363
428
 
@@ -386,30 +451,6 @@ reach it. A `gem install` under a Ruby 4.0 you never switch away from
386
451
  is perfectly fine; one that shares a Ruby with projects you switch
387
452
  between is a footgun.
388
453
 
389
- ## If you want Bundler to manage the version
390
-
391
- The rule at the top of this chapter is about your *application's*
392
- `Gemfile` — the one Bundler resolves against your app's gems, and whose
393
- entries `Bundler.require` loads at boot. It is not a rule against
394
- Bundler. A `Gemfile` holding nothing but Rigor, resolved separately and
395
- selected with `BUNDLE_GEMFILE`, keeps every property the prohibition
396
- exists to protect: your application's dependency graph never meets
397
- Rigor's, and your application's Ruby is never constrained by Rigor's.
398
-
399
- That arrangement — a `Gemfile` under `.github/rigor/`, plus the
400
- Dependabot config that keeps it current — is written up under
401
- [Pinning Rigor's version](11-ci.md#pinning-rigors-version) in the CI
402
- chapter. Nothing about it is CI-specific:
403
-
404
- ```sh
405
- BUNDLE_GEMFILE=.github/rigor/Gemfile bundle exec rigor check
406
- ```
407
-
408
- It is more moving parts than `mise use --pin gem:rigortype`, which
409
- records the same version in one line and needs no `bundle exec`. Reach
410
- for it when your team already runs everything through Bundler and wants
411
- Rigor on the same footing — not as a first choice.
412
-
413
454
  ## Nix
414
455
 
415
456
  If you use Nix, Rigor's flake exposes the executable as a package,