You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Support for array class constants (e.g. const BAR = [1, 2, 3];, including nested and keyed arrays). The value is materialized on the class entry as a persistent immutable array (readable from PHP), and self::CONST resolves to it in Zephir code #2533
Full union return type support, enforced by the engine just like a hand-written PHP union return type. Any combination of classes and/or scalar types is now emitted into the compiled extension's arginfo (via ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX / ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX), so -> <Model> | <Row> | null, -> int | string, -> <Foo> | int, etc. are reported by Reflection and enforced at runtime. Previously only int | false / T | null carried a return type and every other union silently emitted none #2428
Changed
Cached method/static calls now reuse the resolved function handler instead of repeating the method-table lookup in populate_fcic(), shaving ~6–10% off per-call dispatch in hot loops (measured via tests/Benchmark/CallDispatchBench.php) #1510
BC: methods declared with a multi-type union return now carry an enforced return type in the compiled extension. PHP subclasses that override such a method must declare a compatible (equal or narrower) return type, where previously the missing return type made any override valid #2428
Fixed
Fixed let self::prop = ""; (assigning an empty string to a static property) failing to compile. The generated ZVAL_EMPTY_STRING was passed the bare variable name instead of its address #2409
Fixed double-quoted string escapes not matching PHP: \u{XXXX} Unicode codepoints are now UTF-8 encoded (previously emitted literally), and \xHH no longer absorbs following hex digits (e.g. "\x41BC" is now "ABC"). Out-of-range codepoints (> U+10FFFF) and a \x with no hex digit are emitted safely instead of producing malformed C #2030
Fixed assigning a non-constant boolean expression to a dynamic property (e.g. let this->{key} = value > 5;) failing to compile with a cryptic ? error; it now branches at runtime like a regular property. The remaining ? placeholders in Backend::updateArray() and PHP-constant resolution were replaced with descriptive messages #1790
Fixed hexadecimal literals (e.g. 0xffffffff << 32, 0xff + 1) raising "A non-numeric value encountered" during constant folding. Numeric literals are now decoded to real ints before folding in the bitwise and arithmetical operators #2014
Fixed array writes to a property holding an ArrayAccess object converting it to a plain array. let this->prop[key] = value; now calls the object's offsetSet(), and a chained let this->prop[a][b] = value; now mirrors native PHP exactly (fetches offsetGet() once and raises the "Indirect modification of overloaded element" notice) instead of replacing the object #2465
Fixed integer arithmetic with a dynamic operand losing int64 precision (e.g. 1000000000000000000 + var rounded through a double). The result of zephir_get_numberval() is now cast to (zend_long) in integer contexts #2010
Fixed [ERROR] Unknown char when a char/uchar variable is used as an array literal item (e.g. return [ch1, ch2];). Such items are now boxed as their byte (integer) value #1988
Fixed a false Unreachable code warning on a guard reading a variable that holds a constant before a loop but is reassigned inside the loop body (e.g. let x = false; for ... { if x { ... } let x = true; }). The constant-folding unreachability check is now skipped inside loops #1170
Subtraction with a - glued to a digit (e.g. range(0, len-1), arr[0]-1) no longer raises Syntax error; the parser now treats - after a value as a binary operator instead of the sign of a negative literal #2011
Fixed Undefined array key "variable" when assigning to a nested object property (e.g. let this->bar->data = value;). The inner object is now resolved into a temporary and the assignment is handled as a regular object-property write #2532
Fixed the static type-inference pass leaking debug output (StaticTypeInference=... / STI=...) to stdout during compilation when it met a variable type or expression node it did not enumerate (e.g. reassigning a var holding a (object) cast). Such cases now silently degrade the variable to dynamic #1877
Fixed concat-assign (let this->prop .= value) on object properties overwriting the property instead of appending to it; the current value is now read and concatenated #2063
Fixed a false Reached end of the method without returning a valid type error for a method ending in an exhaustive switch (one with a default clause that returns/throws on every path) #1706
Fixed char/uchar return values sign-extending when the byte exceeds 127 (e.g. 0x8A returned -118 instead of 138). Char returns are now cast to unsigned char to preserve byte semantics #1291
Fixed external dependency classes (external-dependencies in config.json) not being found on case-sensitive filesystems. The .zep path was lower-cased wholesale, so a PSR-4 class such as Phalcon\Support\Collection looked for support/collection.zep instead of Support/Collection.zep. The path is now resolved using the namespace casing as written, falling back to the lower-cased path for backward compatibility #2499
Fixed [ERROR] Unknown type: ... when declaring a local with an expression default value (e.g. var x = i + 1;, concat, ternary, method calls). Declaration defaults now infer their type through the same path as let assignments #2394
Fixed generated PHP stubs dropping all but the first class in a union return type (e.g. -> <Model> | <Row> | null produced Model|null instead of Model|Row|null) #2428
Fixed capturing a scalar string-typed variable in a closure via use() emitting ZVAL_STRING on a zend_string * and failing to compile; it now boxes with ZVAL_STR and the captured value is treated as a zval inside the closure body #2562
Fixed default values not being readable through Reflection for parameters that have a class type, such as <Foo> bar = null. Before this getDefaultValue() threw an error and isDefaultValueAvailable() returned false. These parameters now use ZEND_ARG_OBJ_TYPE_MASK, which keeps the default value, instead of ZEND_ARG_OBJ_INFO#2564
Fixed class-constant parameter defaults (e.g. string cipher = self::DEFAULT_CIPHER) not being readable through Reflection. The static-constant-access default was not folded, so the arg_info stored "null" and getDefaultValue() returned null instead of the constant's value. The constant is now folded to its scalar literal for the arg_info, mirroring how the property declaration and method body already resolve it. Follow-up to #2566#2564
Fixed instanceof not narrowing the type inside the guarded block. Calling a method that exists only on the subtype, as in if (x instanceof Sub) { x->subMethod(); }, no longer fails generation with a "does not implement method" error. The narrowed type applies only inside the if block #2565
zephir generate now fails with a clear error when a concrete class does not implement an abstract method inherited from an abstract parent, instead of letting the engine raise "Cannot instantiate abstract class" only at runtime #1628
Fixed Unknown type ... error when a property combines a {get}/{set} shortcut with a @var docblock that includes the variable name (e.g. @var int $foo). The generated accessor now uses only the type, dropping the variable name and any description #2543
Fixed a fatal error when a class constant is initialized from a predefined PHP constant (e.g. const BAR = PHP_VERSION_ID;). Such constants are now folded to their literal value at compile time instead of crashing on the unavailable runtime resolution path #2542
This discussion was created from the release 0.23.0.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Added
const BAR = [1, 2, 3];, including nested and keyed arrays). The value is materialized on the class entry as a persistent immutable array (readable from PHP), andself::CONSTresolves to it in Zephir code #2533ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX/ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX), so-> <Model> | <Row> | null,-> int | string,-> <Foo> | int, etc. are reported by Reflection and enforced at runtime. Previously onlyint | false/T | nullcarried a return type and every other union silently emitted none #2428Changed
populate_fcic(), shaving ~6–10% off per-call dispatch in hot loops (measured viatests/Benchmark/CallDispatchBench.php) #1510Fixed
let self::prop = "";(assigning an empty string to a static property) failing to compile. The generatedZVAL_EMPTY_STRINGwas passed the bare variable name instead of its address #2409\u{XXXX}Unicode codepoints are now UTF-8 encoded (previously emitted literally), and\xHHno longer absorbs following hex digits (e.g."\x41BC"is now"ABC"). Out-of-range codepoints (> U+10FFFF) and a\xwith no hex digit are emitted safely instead of producing malformed C #2030let this->{key} = value > 5;) failing to compile with a cryptic?error; it now branches at runtime like a regular property. The remaining?placeholders inBackend::updateArray()and PHP-constant resolution were replaced with descriptive messages #17900xffffffff << 32,0xff + 1) raising "A non-numeric value encountered" during constant folding. Numeric literals are now decoded to real ints before folding in the bitwise and arithmetical operators #2014ArrayAccessobject converting it to a plain array.let this->prop[key] = value;now calls the object'soffsetSet(), and a chainedlet this->prop[a][b] = value;now mirrors native PHP exactly (fetchesoffsetGet()once and raises the "Indirect modification of overloaded element" notice) instead of replacing the object #24651000000000000000000 + varrounded through adouble). The result ofzephir_get_numberval()is now cast to(zend_long)in integer contexts #2010[ERROR] Unknown charwhen achar/ucharvariable is used as an array literal item (e.g.return [ch1, ch2];). Such items are now boxed as their byte (integer) value #1988Unreachable codewarning on a guard reading a variable that holds a constant before a loop but is reassigned inside the loop body (e.g.let x = false; for ... { if x { ... } let x = true; }). The constant-folding unreachability check is now skipped inside loops #1170-glued to a digit (e.g.range(0, len-1),arr[0]-1) no longer raisesSyntax error; the parser now treats-after a value as a binary operator instead of the sign of a negative literal #2011Undefined array key "variable"when assigning to a nested object property (e.g.let this->bar->data = value;). The inner object is now resolved into a temporary and the assignment is handled as a regular object-property write #2532StaticTypeInference=.../STI=...) to stdout during compilation when it met a variable type or expression node it did not enumerate (e.g. reassigning a var holding a(object)cast). Such cases now silently degrade the variable to dynamic #1877let this->prop .= value) on object properties overwriting the property instead of appending to it; the current value is now read and concatenated #2063Reached end of the method without returning a valid typeerror for a method ending in an exhaustiveswitch(one with adefaultclause that returns/throws on every path) #1706char/ucharreturn values sign-extending when the byte exceeds 127 (e.g.0x8Areturned-118instead of138). Char returns are now cast tounsigned charto preserve byte semantics #1291external-dependenciesinconfig.json) not being found on case-sensitive filesystems. The.zeppath was lower-cased wholesale, so a PSR-4 class such asPhalcon\Support\Collectionlooked forsupport/collection.zepinstead ofSupport/Collection.zep. The path is now resolved using the namespace casing as written, falling back to the lower-cased path for backward compatibility #2499[ERROR] Unknown type: ...when declaring a local with an expression default value (e.g.var x = i + 1;, concat, ternary, method calls). Declaration defaults now infer their type through the same path asletassignments #2394-> <Model> | <Row> | nullproducedModel|nullinstead ofModel|Row|null) #2428string-typed variable in a closure viause()emittingZVAL_STRINGon azend_string *and failing to compile; it now boxes withZVAL_STRand the captured value is treated as a zval inside the closure body #2562<Foo> bar = null. Before thisgetDefaultValue()threw an error andisDefaultValueAvailable()returnedfalse. These parameters now useZEND_ARG_OBJ_TYPE_MASK, which keeps the default value, instead ofZEND_ARG_OBJ_INFO#2564string cipher = self::DEFAULT_CIPHER) not being readable through Reflection. Thestatic-constant-accessdefault was not folded, so the arg_info stored"null"andgetDefaultValue()returnednullinstead of the constant's value. The constant is now folded to its scalar literal for the arg_info, mirroring how the property declaration and method body already resolve it. Follow-up to #2566 #2564instanceofnot narrowing the type inside the guarded block. Calling a method that exists only on the subtype, as inif (x instanceof Sub) { x->subMethod(); }, no longer fails generation with a "does not implement method" error. The narrowed type applies only inside theifblock #2565zephir generatenow fails with a clear error when a concrete class does not implement an abstract method inherited from an abstract parent, instead of letting the engine raise "Cannot instantiate abstract class" only at runtime #1628Unknown type ...error when a property combines a{get}/{set}shortcut with a@vardocblock that includes the variable name (e.g.@var int $foo). The generated accessor now uses only the type, dropping the variable name and any description #2543const BAR = PHP_VERSION_ID;). Such constants are now folded to their literal value at compile time instead of crashing on the unavailable runtime resolution path #2542This discussion was created from the release 0.23.0.
Beta Was this translation helpful? Give feedback.
All reactions