Module: Rigor::Builtins::PredefinedConstantRefinements
- Defined in:
- lib/rigor/builtins/predefined_constant_refinements.rb
Overview
Refined types for predefined Ruby / stdlib constants whose upstream RBS signatures are broader than the constants’ documented runtime invariants.
Resolution is two-tiered:
**Tier 1 — exact-value whitelist** (‘FOLDED_CONSTANTS`): Constants whose value is bit-for-bit identical across every Ruby version and platform are folded to `Constant`: the `Math::PI` / `Math::E` math constants (C’s ‘M_PI` / `M_E`) and the four IEEE 754 binary64 magnitude constants `Float::INFINITY` / `::MAX` / `::MIN` / `::EPSILON` (each a single format-mandated bit pattern). Add new entries only when the value is truly cross-implementation invariant AND compares reflexively under `==` — the latter is why `Float::NAN` is deliberately EXCLUDED: `NaN == NaN` is `false`, so a `Constant` would violate the `Type::Constant` `==` / `eql?` / `hash` contract (it would hash equal to itself yet compare unequal), corrupting type-equality and union dedup. The binary64 integer shape parameters (`Float::DIG` / `MANT_DIG` / `MAX_EXP` / …) are intentionally NOT folded: upstream RBS hedges them as “Usually defaults to …”, and as plain `Integer`s they fall through Tier 2 to the RBS type harmlessly. `Complex::I` is deferred (no complex-fold consumer).
**Tier 2 — runtime String inspection**: For any other constant, the module resolves it via ‘const_get` against the analyzer’s own Ruby runtime. Core / stdlib constants (e.g. ‘RUBY_VERSION`, `RUBY_PLATFORM`) are always loaded into the analyzer process; project-defined constants are not (they live only in ASTs), so their `const_get` raises `NameError` and the lookup falls through to the RBS type tier.
For a successfully resolved ‘String` value:
-
empty string → no refinement (fall through to RBS ‘String`)
-
a Ruby numeric literal → ‘numeric-string`
-
non-empty otherwise → ‘non-empty-string`
**Exclusion set** (‘RUNTIME_INSPECTION_EXCLUDED`): String constants that appear non-empty in the current runtime but are documented to be potentially empty in some build configuration or alternative implementation. Exclusions are populated by scanning Ruby’s C source (version.c, etc.) and RBS comments for any constant whose documentation says “may be empty” or “platform-specific default”. None are known today; the set exists as a safety net.
This module is consulted by ‘Environment#constant_for_name` BEFORE the RBS constant-type table (widest types) but AFTER in-source constant writes (the user’s own ‘Math::PI = 0.0` takes precedence via the lexical-candidate walk in `ExpressionTyper`).
Class Method Summary collapse
-
.lookup(name) ⇒ Rigor::Type?
Refined type, or nil to fall through.
Class Method Details
.lookup(name) ⇒ Rigor::Type?
Returns refined type, or nil to fall through.
102 103 104 |
# File 'lib/rigor/builtins/predefined_constant_refinements.rb', line 102 def self.lookup(name) FOLDED_CONSTANTS[name] || inspect_runtime_string(name) end |