Zephir v0.22.0 Release Notes
Release Date: 2026-05-29 // 16 days ago-
โ Added
- โ Added support for variadic functions/methods using the
...operator (e.g.function f(int first, ...rest)) #2025 - ๐ Compiler now recognizes the parser-emitted
yieldAST node (bareyield;,yield expr;,yield key, value;) #1849 - โ Added PHPBench-based runtime benchmarks suites under
tests/Benchmark/#2541
๐ Changed
for k, v in exprnow skips the unreachable branch when the iterand's dynamic type is known #1878
๐ Fixed
- ๐ Fixed dynamic init
new {className}()ignoring constructor visibility, allowing classes with aprotected/privateconstructor to be instantiated from any scope #882 - Fixed
unset(obj->{variable})(dynamic property name) andunset(obj->{"literal"})(string-literal brace syntax) throwingCompilerException: Cannot use expression type: property-dynamic-access in "unset".UnsetStatementnow handlesproperty-dynamic-accessandproperty-string-accessnodes, emitting the newzephir_unset_property_zval()kernel helper for variable keys #808 - ๐ Fixed
continueinsidefor ... inloops over PHPIterator/Traversableobjects producing an infinite loop #2546 - ๐ Fixed
elseifconditions that contain sub-expressions with side effects (such as array element accessmyvar[0]) being evaluated unconditionally before the outerif, causing spurious "Cannot use a scalar value as an array" notices when a preceding branch had already returned #1097 - ๐ Fixed cross-class chained
<static>(and<self>/<parent>) return-type resolution. The same-class case landed in #2537 by substituting the lexical class for the reserved keyword. The cross-class case โother->returnsStatic()->method()whereotheris a local variable typed as a different class โ was still resolved against the call site's lexical class, so the chained method lookup ran on the wrong definition and the build aborted withClass '<EnclosingClass>' does not implement method: '<method>'.MethodCall.phpalready resolves the receiver's$classDefinitionearlier in the function (from$variableVariable->getClassTypes()); the substitution now uses that definition, which is identical to$compilationContext->classDefinitionfor thethisbranch and preserves existing behavior there. #2505
๐ Documentation
- โฌ๏ธ Documented the workaround for
[ClassName, "protectedOrPrivateMethod"]arrays passed as callbacks to PHP higher-order functions (array_reduce,usort,preg_replace_callback, etc.) #2167
- โ Added support for variadic functions/methods using the