class T::Enum

def self.enums(&blk)

def self.enums(&blk)
  raise "enums cannot be defined for T::Enum" if self == T::Enum
  raise "Enum #{self} was already initialized" if @fully_initialized
  raise "Enum #{self} is still initializing" if @started_initializing
  @started_initializing = true
  @values = T.let(nil, T.nilable(T::Array[T.attached_class]))
  yield
  @mapping = T.let(nil, T.nilable(T::Hash[SerializedVal, T.attached_class]))
  @mapping = {}
  # Freeze the Enum class and bind the constant names into each of the instances.
  self.constants(false).each do |const_name|
    instance = self.const_get(const_name, false)
    if !instance.is_a?(self)
      raise "Invalid constant #{self}::#{const_name} on enum. " \
        "All constants defined for an enum must be instances itself (e.g. `Foo = new`)."
    end
    instance._bind_name(const_name)
    serialized = instance.serialize
    if @mapping.include?(serialized)
      raise "Enum values must have unique serializations. Value '#{serialized}' is repeated on #{self}."
    end
    @mapping[serialized] = instance
  end
  @values.freeze
  @mapping.freeze
  orphaned_instances = T.must(@values) - @mapping.values
  if !orphaned_instances.empty?
    raise "Enum values must be assigned to constants: #{orphaned_instances.map {|v| v.instance_variable_get('@serialized_val')}}"
  end
  @fully_initialized = true
end