--TEST-- Generics extension: nested generic type parameters are correctly erased --DESCRIPTION-- Tests that nested generic annotations such as Collection> and Collection> are fully stripped before parsing, including multiple levels of nesting. --SKIPIF-- --FILE-- name = $name; } } class Collection { private array $items = []; public function add(mixed $item): void { $this->items[] = $item; } public function all(): array { return $this->items; } public function count(): int { return count($this->items); } } class Map { private array $data = []; public function set(mixed $key, mixed $value): void { $this->data[$key] = $value; } public function get(mixed $key): mixed { return $this->data[$key] ?? null; } } // Nested generic: Collection> function buildIndex(Collection> $collections): void { foreach ($collections->all() as $map) { echo $map->get('primary')->name . "\n"; } } // Nested generic: Collection> function sumAll(Collection> $groups): int { $total = 0; foreach ($groups->all() as $group) { $total += array_sum($group); } return $total; } // --- Test 1: Collection> --- $map1 = new Map(); $map1->set('primary', new Widget('foo')); $map2 = new Map(); $map2->set('primary', new Widget('bar')); $collections = new Collection>(); $collections->add($map1); $collections->add($map2); buildIndex($collections); echo $collections->count() . "\n"; // --- Test 2: Collection> --- $groups = new Collection>(); $groups->add([1, 2, 3]); $groups->add([4, 5]); echo sumAll($groups) . "\n"; // --- Test 3: Three levels of nesting --- // Collection>> $inner1 = new Collection(); $inner1->add(new Widget('nested')); $outerMap = new Map>(); $outerMap->set('group', $inner1); $outer = new Collection>>(); $outer->add($outerMap); echo $outer->count() . "\n"; echo $outer->all()[0]->get('group')->all()[0]->name . "\n"; ?> --EXPECT-- foo bar 2 15 1 nested