TypePHP 编译器
https://swoole.com/aot/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
9.9 KiB
9.9 KiB
AOT/PHP Incompatibility List
This document lists only the key areas in which the current AOT compiler is incompatible with or more restrictive than standard PHP.
Program structure
- Executable statements are not allowed at global scope; only static constructs
such as declarations,
use,declare, and constant definitions are allowed. - Function declarations are not allowed inside functions or methods.
- Named class declarations are not allowed inside functions or methods.
- Binary mode must define a global
main(). main()may either take no parameters or have the signature(int $argc, array $argv).main()must returnvoid.
Declarations and types
- Variable variables
$$varare not supported. - PHP 8.5
#[NoDiscard]is not supported yet. - The PHP 8.5
(void)cast is supported for explicitly discarding a value; the operand is still evaluated and its side effects are preserved, and the cast cannot be used in value contexts such as assignments, returns, arguments, or conditions. - Support for PHP 8.5
clone()/ clone-with requires the linkedlibphpto be version 8.5 or later. Public and dynamic properties, private/protected/readonly properties, property hooks, call ordering, error propagation, and callable paths are all covered by PHPT tests. - PHP 8.4 property hooks are compiled into AOT getters/setters and register the corresponding Zend hook metadata; direct property reads/writes, Reflection, and object iteration are all supported. Taking a reference to a hooked property is currently not supported.
- Interface property hooks do not currently support an explicitly declared
setparameter; use the implicit setter value parameter. - PHP 8.4 Reflection Lazy Objects cannot be used with TypePHP AOT classes. AOT
classes are registered as persistent internal classes, and Zend's
zend_object_make_lazy()explicitly rejects internal classes. Zend PHP user classes loaded dynamically at runtime are not subject to this restriction. private(set)andprotected(set)asymmetric property visibility is supported, including constructor property promotion. Zend-backed objects perform the scope check through the PHP 8.4+ class-level object handler and preserve the promoted / set-visibility / implicit-final reflection flags; Native objects enforce the equivalent scope rules through compile-time access checks.- Final properties declared through constructor promotion are supported, but
TypePHP requires an explicit
public,protected, orprivatemodifier; PHP 8.5's implicitly public form,final int $value, is not accepted. As a TypePHP extension, this syntax is independent of the PHP source-syntax version supported by the linkedlibphpand remains available when using a PHP 8.4libphp.so. - TypePHP forbids attributes on global or namespaced constant declarations; PHP 8.5 global constant attributes are out of scope. Class constant attributes are not affected by this restriction.
- A
.stub.phpfile only declares Zend ABI symbols supplied by external C++ and must not use#[Native]on its classes. Native Class object layouts must be generated and owned by the TypePHP compiler. - Returning by reference from closures or arrow functions is not supported.
- PHP 8.5
static functionexpressions in global constants, class constants, parameter defaults, or property defaults are not supported yet. Closures nested inside initializer expressions are likewise rejected at compile time. __construct()may not have a return value.- A parameter with a default value may not appear before a required parameter (PHP permits this legacy pattern but treats the former parameter as required).
- Variadic parameters by reference
&...$argsare not supported. - Union, intersection, and nullable types are still represented as
mixed/anyin C++, but the static analysis phase uses known expression types to reject definitely incompatible arguments, return values, and property assignments ahead of time; dynamic values still retain their runtime type checks. - Once a local variable's type has been statically inferred as a concrete native type, reassigning it to an incompatible type within the same scope is not supported.
declare
declare(ticks=...)is not supported.declare(encoding=...)accepts onlyUTF-8.declare(strict_types=...)accepts onlystrict_types=1.- No other
declaredirectives are supported.
Calls and references
exit(message: $value)is available as a TypePHP named-argument extension; it enters the same exit path as the positional formexit($value).- TypePHP uses strict argument-count rules: non-variadic functions do not accept
extra arguments beyond the declared signature, and
func_get_args()does not implicitly relax the signature. - Reference parameters and write-back semantics are supported for ordinary functions, ordinary methods, and native direct calls with known signatures; do not mistakenly describe the compiler's internal cross-trait dynamic-dispatch limitation as "TypePHP does not support reference parameters".
- Closures and arrow functions do not support reference parameters.
- Reference assignment cannot create a reference from a complex static-property expression.
- Calls whose argument signature cannot be determined at compile time — dynamic
calls, closure calls, and the like — cannot convert reference parameters
automatically;
refval()or the equivalent keyword methodtoRef()must be used explicitly. refval()/toRef()only accept variables, array elements, or object properties.- A call that uses argument unpacking followed by named arguments falls back to dynamic dispatch and cannot use the native call path.
Object model
- Reserved keyword methods such as
toInt(),toString(), andtoArray()are resolved before ordinary object methods; an application method of the same name that takes arguments is not called with ordinary object-method semantics. toAny()andtoRef()are non-overridable TypePHP keyword methods, and ordinary class-like declarations must not define methods with these names (method names are case-insensitive, per PHP rules). A Native class may only explicitly define atoAny()conversion method returningmixed/any; no implicit conversion is provided. Native classes do not supporttoRef().- Fixed-layout typed properties that are not explicitly initialized use the
zero value of their type and do not preserve Zend PHP's full uninitialized
state; expressions such as
??that depend on the uninitialized state may therefore behave differently. - A subclass may not shadow a parent's private property with a
privateproperty of the same name;public/protecteddeclarations of the same name are treated as the same inherited property slot and must still satisfy the type, visibility, andreadonlycompatibility requirements. - Dynamic writes to typed properties still use strict type checks. When the right-hand side cannot be determined at compile time, TypePHP preserves a runtime check rather than falling back to Zend weak scalar conversion.
- Native Classes use a separate fixed-layout object model. They cannot be used
as ordinary Zend Objects, PHP array keys/values, or arbitrary
mixedvalues, and they restrict dynamic members, references, static/readonly members, and several operators. See Native Class Object Design for the complete boundary.
Expressions and control flow
- A
matcharm condition may not itself be amatchexpression. - The value target in a by-reference
foreachmay only be a variable. foreachlist destructuring does not support binding elements by reference.- On the non-
int/boollowering path, every non-emptyswitchcase must end inreturn,break,continue,exit, orthrow; do not rely on implicit PHP case fallthrough. The nativeint/boolswitch path can currently retain C++ fallthrough, so project code should terminate every non-empty case explicitly. - Appending, inserting,
unset(), and wholesale replacement ofstd::vector,std::map, andstd::ordered_mapare forbidden during aforeach; non-structural updates of existing elements can still be done with assignment operators. - Fixed native typed object properties cannot be freely
unset()with PHP's standard uninitialized-property semantics. - Calling
unset()on a native-typed variable does not delete the variable as it would in standard PHP.
Runtime dynamic capabilities
- Ordinary Zend objects and dynamic class expressions support runtime
::classand class-constant lookup. Native Classes still require the relevant class target to be known at compile time. static::classis not supported in positions that require a compile-time constant class name.__CLASS__may only be used within aclassdefinition (PHP allows it elsewhere and returns an empty string).__TRAIT__may only be used within atraitdefinition (PHP allows it elsewhere and returns an empty string).- Dynamic property chains, dynamic class names, dynamic function names, and
dynamic callbacks all go through the Zend runtime fallback and are not
guaranteed to be natively optimized; reference parameters of dynamic calls
still require an explicit
refval()ortoRef(). Closure::bind(),Closure::bindTo(), andClosure::call()are not supported. A closure cannot be rebound to an object or class scope in AOT code.- All source files must be encoded as
UTF-8.
Generators
TypePHP generators use FiberGenerator rather than Zend Generator. Code must
therefore not rely on instanceof Generator, ReflectionGenerator, Zend
Generator's internal object layout, or identical exception traces. Generators
do not support returning by reference, by-reference yield, by-reference
foreach, by-reference parameters, or variadic parameters. Fiber and Generator
are not currently supported by the WASI target. See
Generators for the complete boundary.