Class: Rigor::Type::StructInstance

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

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 mutables.x = v, s[:x] = 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[top] 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

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.



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/rigor/type/struct_instance.rb', line 36

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_nameString? (readonly)

Returns the value of attribute class_name.

Returns:

  • (String, nil)


30
31
32
# File 'lib/rigor/type/struct_instance.rb', line 30

def class_name
  @class_name
end

#membersHash[Symbol, Type::t] (readonly)

Returns the value of attribute members.

Returns:

  • (Hash[Symbol, Type::t])


30
31
32
# File 'lib/rigor/type/struct_instance.rb', line 30

def members
  @members
end

Instance Method Details

#==Boolean

Parameters:

  • other (Object)

Returns:

  • (Boolean)


308
# File 'sig/rigor/type.rbs', line 308

def ==: (untyped other) -> bool

#acceptsAcceptsResult

Parameters:

  • other (Type::t)
  • mode: (accepts_mode)

Returns:



307
# File 'sig/rigor/type.rbs', line 307

def accepts: (Type::t other, ?mode: accepts_mode) -> AcceptsResult

#botTrinary

Returns:



305
# File 'sig/rigor/type.rbs', line 305

def bot: () -> Trinary

#describe(verbosity = :short) ⇒ String

Parameters:

  • verbosity (Symbol) (defaults to: :short)

Returns:

  • (String)


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

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

#dynamicTrinary

Returns:



306
# File 'sig/rigor/type.rbs', line 306

def dynamic: () -> Trinary

#erase_to_rbsString

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.

Returns:

  • (String)


67
68
69
70
71
72
# File 'lib/rigor/type/struct_instance.rb', line 67

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

  name
end

#hashInteger

Returns:

  • (Integer)


309
# File 'sig/rigor/type.rbs', line 309

def hash: () -> Integer

#inspectString

Returns:

  • (String)


82
83
84
# File 'lib/rigor/type/struct_instance.rb', line 82

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

#member_namesArray<Symbol>

Returns ordered member names.

Returns:

  • (Array<Symbol>)

    ordered member names.



50
51
52
# File 'lib/rigor/type/struct_instance.rb', line 50

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.

Parameters:

  • name (Symbol)

Returns:

  • (Rigor::Type, nil)

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



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

def member_type(name)
  members[name]
end

#topTrinary

Returns:



304
# File 'sig/rigor/type.rbs', line 304

def top: () -> Trinary