Fix array destructuring from a Traversable

Sequence destructuring compiled its right-hand side straight into
array_pad(), which throws "Argument #1 must be of type array" when a
Traversable is provided:

    {% do [a, b] = items %}

with an IteratorAggregate/Generator for items crashed with a TypeError.
Coerce Traversables via iterator_to_array() before padding, matching
the behavior of the spread, merge, and slice operations which already
accept Traversables.
This commit is contained in:
Ilia Alshanetsky
2026-08-22 12:36:24 -04:00
parent 84c5051151
commit 9de1b3db98
2 changed files with 17 additions and 2 deletions
@@ -57,7 +57,15 @@ class SequenceDestructuringSetBinary extends AbstractBinary
$compiler->raw('$context[')->repr($name)->raw(']');
}
}
$compiler->raw('] = array_pad(')->subcompile($this->getNode('right'))->raw(', ')->repr(\count($this->variables))->raw(', null)');
$compiler->raw('] = array_pad((');
$var = '$'.$compiler->getVarName();
$compiler
->raw($var.' = ')
->subcompile($this->getNode('right'))
->raw(') instanceof \Traversable ? iterator_to_array('.$var.') : '.$var)
->raw(', ')
->repr(\count($this->variables))
->raw(', null)');
}
public function operator(Compiler $compiler): Compiler
+8 -1
View File
@@ -22,6 +22,9 @@ Twig supports the "=" operator (assignment)
{% do {first_name, last_name} = user_map %}{{ first_name }} {{ last_name }}
{% do {name} = user_obj %}{{ name }}
# Array destructuring from a Traversable
{% do [p, q] = pair_traversable %}{{ p }} {{ q }}
# Object destructuring with renaming
{% do {name: userName, email: userEmail} = user %}{{ userName }} {{ userEmail }}
{% do {first_name: first, last_name: last} = user_map %}{{ first }} {{ last }}
@@ -34,7 +37,8 @@ return [
'user_obj' => new class {
public function getName() { return 'Fabien'; }
},
'null_obj' => null
'null_obj' => null,
'pair_traversable' => new ArrayIterator(['Fabien', 'Potencier']),
]
--EXPECT--
4
@@ -54,6 +58,9 @@ Fabien fabien@example.com
Fabien Potencier
Fabien
# Array destructuring from a Traversable
Fabien Potencier
# Object destructuring with renaming
Fabien fabien@example.com
Fabien Potencier