Class: Rigor::Type::StructInstance

Inherits:
Object
  • Object
show all
Includes:
AcceptanceRouter, PlainLattice, ValueSemantics
Defined in:
lib/rigor/type/struct_instance.rb

Overview

A ‘Struct.new` value instance (ADR-48 Struct follow-up) —`Point.new(1, 2)`. The mutable sibling of DataInstance: a closed, total, class-tagged member map (member name -> value type), HashShape-shaped but nominal.

Unlike DataInstance, a ‘Struct` instance is mutable — `s.x = v`, `s = v`, and escape can invalidate the member map. The folding tier therefore only projects member reads off a fresh instance (the transient receiver of a `.new(…).x` / `.with(…).x` chain, which provably cannot have been mutated between materialisation and the read); a read off a stored binding degrades to `Dynamic` rather than fold a possibly-stale member value. Promoting the fold to mutation-free bound locals is the deferred slice 3 (see ADR).

That mutability-gating lives in the dispatch tier (‘StructFolding`), not the carrier: the carrier itself just records the member map. Like DataInstance, non-folded methods project to the `Struct` nominal (or the tagged class) through RbsDispatch’s ‘receiver_descriptor`, so non-member calls resolve without mis-firing undefined-method.

Equality and hashing are structural over the (member -> type) map and the class name.

See docs/adr/48-data-struct-value-folding.md § “Struct follow-up”.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ValueSemantics

included

Methods included from AcceptanceRouter

#accepts

Methods included from PlainLattice

#bot, #dynamic, #top

Constructor Details

#initialize(members, class_name = nil) ⇒ StructInstance

Returns a new instance of StructInstance.

Parameters:

  • members (Hash{Symbol => Rigor::Type})

    ordered member -> type map. Every declared member is present (Struct instances are total).

  • class_name (String, nil) (defaults to: nil)

    the tagging class name, or nil for an instance of an anonymous ‘Struct.new(…)` class.



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/rigor/type/struct_instance.rb', line 41

def initialize(members, class_name = nil)
  unless members.is_a?(Hash) && members.each_key.all?(Symbol)
    raise ArgumentError, "members must be a Hash with Symbol keys, got #{members.inspect}"
  end
  unless class_name.nil? || (class_name.is_a?(String) && !class_name.empty?)
    raise ArgumentError, "class_name must be a non-empty String or nil, got #{class_name.inspect}"
  end

  @members = members.dup.freeze
  @class_name = class_name&.freeze
  freeze
end

Instance Attribute Details

#class_nameObject (readonly)

Returns the value of attribute class_name.



35
36
37
# File 'lib/rigor/type/struct_instance.rb', line 35

def class_name
  @class_name
end

#membersObject (readonly)

Returns the value of attribute members.



35
36
37
# File 'lib/rigor/type/struct_instance.rb', line 35

def members
  @members
end

Instance Method Details

#describe(verbosity = :short) ⇒ Object



65
66
67
68
# File 'lib/rigor/type/struct_instance.rb', line 65

def describe(verbosity = :short)
  rendered = members.map { |name, type| "#{name}: #{type.describe(verbosity)}" }
  "#{class_name || 'Struct'}(#{rendered.join(', ')})"
end

#erase_to_rbsObject

Erases to the tagging class nominal (conservative: the structural members are not RBS-expressible as a class instance). The anonymous case erases to the ‘Struct` supertype.



73
74
75
76
77
78
# File 'lib/rigor/type/struct_instance.rb', line 73

def erase_to_rbs
  name = class_name
  return "Struct" if name.nil?

  name
end

#inspectObject



88
89
90
# File 'lib/rigor/type/struct_instance.rb', line 88

def inspect
  "#<Rigor::Type::StructInstance #{describe(:short)}>"
end

#member_namesArray<Symbol>

Returns ordered member names.

Returns:

  • (Array<Symbol>)

    ordered member names.



55
56
57
# File 'lib/rigor/type/struct_instance.rb', line 55

def member_names
  members.keys
end

#member_type(name) ⇒ Rigor::Type?

Returns the member’s value type, or nil when the name is not a declared member.

Returns:

  • (Rigor::Type, nil)

    the member’s value type, or nil when the name is not a declared member.



61
62
63
# File 'lib/rigor/type/struct_instance.rb', line 61

def member_type(name)
  members[name]
end