Readonly: Containers And Collections

Basics

Readonly values cannot be written to normal container types(such asvec, Vector, or dict):

class Foo {}
function container_example(readonly Foo $x) : void {
  $container = vec[];
  $container[] = $x; // error, $x is readonly
}
Typechecker output
File "/home/example/readonly_container_example.hack", line 9, characters 18-19:
This expression is readonly, but the collection you're modifying is mutable, which isn't allowed. (Parsing[1002])

To use readonly values within a container, you can either declare the values in an array literal, or declare an array type (i.e. vec or dict) as readonly and append to it. Note that the entire container literal is readonly if any of its contents are readonly.

class Foo {}
function container_example2(readonly Foo $x) : void {
  $container = readonly vec[]; // container is now a readonly vec
  $container_literal = vec[new Foo(), readonly new Foo()]; // $container_literal is readonly
}

Foreaching over a readonly container results in readonly values:

class Foo {
  public function __construct(public int $prop) {}
}
function container_foreach(readonly vec<Foo> $vec): void {
  foreach($vec as $elem) {
    $elem->prop = 3; // error, $elem is readonly
  }
}
Typechecker output
File "/home/example/readonly_container_foreach.hack", line 11, characters 5-19:
This expression is readonly, its members cannot be modified (Parsing[1002])

Readonly and Collection types

Readonly has only limited support with object collection types like Vector, Map and Pair. Specifically, you can declare readonly collection literals of readonly values to create a readonly collection type (i.e a readonly Vector<Foo>), but since collection types themselves are mutable objects, you cannot append to or modify a readonly collection.

class Foo {}
function collection_example(): void {
  $v = Vector { new Foo(), readonly new Foo() }; // $v is readonly since at least one of its contents is readonly
  $v[] = new Foo(); // error, $v is readonly and not a value type, so it cannot be appended
}
Typechecker output
File "/home/example/readonly_collection_example.hack", line 9, characters 3-4:
This value is readonly, its properties cannot be modified (Typing[4409])