Module: Rigor::Inference::Acceptance

Defined in:
lib/rigor/inference/acceptance.rb

Overview

Shared dispatch table for ‘Rigor::Type#accepts(other, mode:)`.

The acceptance query answers “is ‘other` passable to `self` at a method-parameter or assignment boundary?”. It uses gradual-typing rules from docs/type-specification/value-lattice.md and the acceptance contract in docs/internal-spec/internal-type-api.md.

Each concrete type’s ‘accepts` method delegates here so the case-analysis stays in one place. Type instances remain thin value objects; routing logic lives in the inference layer.

Slice 4 phase 2c implements the ‘:gradual` mode in full and reserves `:strict` for later slices (the entry point raises ArgumentError on strict for now). The table covers the leaf and combinator types added through phase 2b: Top, Bot, Dynamic, Nominal, Singleton, Constant, and Union.

Slice 5 registers the shape carriers ‘Tuple` and `HashShape`. Tuple/HashShape acceptance compares per-position element types (covariant) and per-key entry types (depth covariant), including HashShape required/optional/closed-extra-key policy. When the receiver side is a generic `Nominal[Array, [E]]` or `Nominal[Hash, [K, V]]` the shape is projected to its underlying nominal so the existing generic-acceptance pipeline continues to apply; the converse direction (a Tuple receiver accepting a generic Array) stays conservative because the analyzer cannot verify arity from a raw nominal alone. rubocop:disable Metrics/ModuleLength

Class Method Summary collapse

Class Method Details

.accepts(self_type, other_type, mode: :gradual) ⇒ Rigor::Type::AcceptsResult

Parameters:

  • self_type (Rigor::Type)
  • other_type (Rigor::Type)
  • mode (Symbol) (defaults to: :gradual)

    ‘:gradual` (default) or `:strict`.

Returns:

Raises:

  • (ArgumentError)


43
44
45
46
47
48
49
50
51
52
53
# File 'lib/rigor/inference/acceptance.rb', line 43

def accepts(self_type, other_type, mode: :gradual)
  raise ArgumentError, "Acceptance mode #{mode.inspect} is not implemented yet" unless mode == :gradual

  return Type::AcceptsResult.yes(mode: mode, reasons: "Bot is the empty type") if other_type.is_a?(Type::Bot)
  if other_type.is_a?(Type::Dynamic)
    return Type::AcceptsResult.yes(mode: mode, reasons: "gradual: Dynamic[T] passes any boundary")
  end
  return accepts_union_other(self_type, other_type, mode) if other_type.is_a?(Type::Union)

  accepts_one(self_type, other_type, mode)
end