This reverts commit 94ee4f9834.
The commit was a bit too late to be included in PHP 8.2 RC1. Given it's a massive ABI break, we decide to postpone the change to PHP 8.3.
RFC: https://wiki.php.net/rfc/dnf_types
This allows to combine union and intersection types together in the following form (A&B)|(X&Y)|T but not of the form (X|A)&(Y|B) or (X|A)&(Y|B)|T.
* Improve union type parsing
Co-authored-by: Sara Golemon <pollita@php.net>
This does a compile time transformation of ``iterable`` into ``Traversable|array`` which simplifies some of the LSP variance handling.
The arginfo generation script from stubs is updated to produce a union type when it encounters the type ``iterable``
Extension functions which do not regenerate the arginfo, or write them manually are still supported by mimicking the compile time transformation while registering the function.
Type Reflection is preserved for single ``iterable`` (and ``?iterable``) to produce a ReflectionNamedType with name ``iterable``, however usage of ``iterable`` in union types will be converted to ``array|Traversable``
Recorded errors may be attached to the wrong cached script when a fatal error
occurs during recording. This happens because the fatal error will cause a
bailout, which may prevent the recorded errors from being freed. If an other
script is compiled after bailout, or if a class is linked after bailout, the
recorded errors will be attached to it.
This change fixes this by freeing recorded errors before executing shutdown
functions.
Fixes GH-8063
I don't believe there's a reason anymore to first resolve all
delayed variance obligations, and then report errors if any are
left. We can report errors directly when resolving obligations.
We can't take ownership of the delayed autoload table here. It is
important that pending classes get loaded before resolving variance
of any nested classed, as they might actually be lower in the
hierarchy.
Produce a sensible error message for the case where inheritance
should fail. There is still a remaining issue that we sometimes
fail inheritance while we should not.
Traits do not support interfaces, so we should not implement
Stringable on them.
Also check the __toString() return type in the same way other
magic methods do, otherwise we would now miss the check in the
trait case.
- for packed arrays we store just an array of zvals without keys.
- the elements of packed array are accessible throuf as ht->arPacked[i]
instead of ht->arData[i]
- in addition to general ZEND_HASH_FOREACH_* macros, we introduced similar
familied for packed (ZEND_HASH_PACKED_FORECH_*) and real hashes
(ZEND_HASH_MAP_FOREACH_*)
- introduced an additional family of macros to access elements of array
(packed or real hashes) ZEND_ARRAY_ELEMET_SIZE, ZEND_ARRAY_ELEMET_EX,
ZEND_ARRAY_ELEMET, ZEND_ARRAY_NEXT_ELEMENT, ZEND_ARRAY_PREV_ELEMENT
- zend_hash_minmax() prototype was changed to compare only values
Because of smaller data set, this patch may show performance improvement
on some apps and benchmarks that use packed arrays. (~1% on PHP-Parser)
TODO:
- sapi/phpdbg needs special support for packed arrays (WATCH_ON_BUCKET).
- zend_hash_sort_ex() may require converting packed arrays to hash.
It's possible for delayed early binding opcodes to get optimized
away if they are "unreachable". However, we still need to attempt
early binding for them. (In some cases we also corrupt the early
binding list outright during optimization, which is how I got here.)
Fix this by storing information about delayed early binding
independently of DECLARE_CLASS_DELAYED opcodes, so early binding is
performed even after the opcode has been dropped.
Same as with other exceptions during inheritance, convert those
thrown during delayed class loading into fatal errors. We can't
properly deal with such exceptions, as inheritance cannot be
gracefully aborted at this point.
Fixes oss-fuzz #39405.
We shouldn't try to load further classes if one autoload throws.
This fixes oss-fuzz #38881, though I believe there are still two
deeper issues here: 1) Why do we allow autoloading with an active
exception? 2) Exception save & restore should probably also save
and restore the exception opline.
When adding the #[ReturnTypeWillChange] attribute in namespaced
code, you also need to use ReturnTypeWillChange, otherwise it
will be silently ignored and may result in confusion. Change the
deprecation message to suggest #[\ReturnTypeWillChange], which
will always work.
Closes GH-7454.
Just like during normal shutdown, we should set EG(active)=0
during the partial preloading shutdown, to make sure that no
user code can run.
We need to slightly tweak inheritance class loading to still
pick the right code path.
Currently, CE_CACHE on strings is only used with opcache interned strings. This
patch extends usage to non-opcache interned strings as well. This means that
most type strings can now make use of CE_CACHE even if opcache is not loaded,
which allows us to remove TYPE_HAS_CE kind, and fix some discrepancies
depending on whether a type stores a resolved or non-resolved name.
There are two cases where CE_CACHE will not be used:
* When opcache is not used and a permanent interned string (that is not an
internal class name) is used as a type name during the request. In this case
we can't allocate a map_ptr index for the permanent string, as it would be
not be in the permanent map_ptr index space.
* When opcache is used but the script is not cached (e.g. eval'd code or
opcache full). If opcache is used, we can't allocate additional map_ptr
indexes at runtime, because they may conflict with indexes allocated by
opcache.
In these two cases we would end up not using CE caching for property types
(argument/return types still have the separate cache slot).
It is very hard to determine in advance whether class linking will
fail due to missing dependencies in variance checks (#7314 attempts
this). This patch takes an alternative approach where we try to
perform inheritance on a copy of the class (zend_lazy_class_load)
and then restore the original class if inheritance fails. The fatal
error in that case is recorded and thrown as a warning later.
Closes GH-7319.
Instead always use the unlinked_uses table, which is already used
if opcache is used. Not much point in having a different mechanism
for the non-opcache case.
Currently, classes that can't be linked get moved back into the original script
and are not preloaded. As such classes may be referenced from functions that
did get preloaded, there is a preload autoload mechanism to load them at
runtime.
Since PHP 8.1, we can safely preload unlinked classes, which will then go
through usual lazy loading. This means that we no longer need the preload
autoload mechanism. However, we need to be careful not to modify any hash
table buckets in-place, and should create new buckets for lazy loaded classes.
When running without opcache, static_members_table is shared with
default_static_members_table. This is visible in reflection output,
because ReflectionProperty::getDefaultValue() will return the
current value, rather than the default value.
Address this by never sharing the table, which matches the behavior
we already see under opcache.
Fixes bug #80821.
Closes GH-7299.
Convert zend_hash_find_ex(..., 1) to zend_hash_find_known_hash(...)
Convert zend_hash_find_ex(..., 0) to zend_hash_find(...)
Also add serializable changes to UPGRADING.INTERNALS summary
Add support for readonly properties, for which only a single
initializing assignment from the declaring scope is allowed.
RFC: https://wiki.php.net/rfc/readonly_properties_v2
Closes GH-7089.
This prevents serialization and unserialization of a class and its
children in a way that does not depend on the zend_class_serialize_deny
and zend_class_unserialize_deny handlers that will be going away
in PHP 9 together with the Serializable interface.
In stubs, `@not-serializable` can be used to set this flag.
This patch only uses the new flag for a handful of Zend classes,
converting the remainder is left for later.
Closes GH-7249.
Fixes bug #81111.
Subtyping relationships established on internal classes are always
going to hold (if we ignore Windows), so there is no need to
explicitly track them.
This fixes an assertion failure in GH-7251.
If we have an UNRESOLVED result, simply register all classes that
occur in either of the types. I believe that's equivalent to what
we're currently doing in a more complicated way.
Now that inheritance can throw deprecations again, these may be
converted to exception by a custom error handler. In this case
we need to convert the exception to a fatal error, as inheritance
cannot safely throw in the general case.
mixed should be behaving the same way as no type here, and not
require X to be autoloaded. Everything apart from "void" is trivially
covariant to "mixed".
Userland property infos are no longer duplicated since PHP 7.4, when we
stopped setting SHADOW flags on inherited private properties. Stop duplicating
internal property infos as well.
This requires switching class destruction to work in reverse order, as child
classes may be reusing structures from parent classes, and as such should be
destroyed first.
Since 3e6b447979 it is again possible to have
warnings (deprecations) during inheritance, and more such functionality is
likely in the future. This is a problem, because such warnings will only be
shown on the first request if the opcache inheritance cache is used. This
currently causes test failures in --repeat builds.
Fix this by uplifting the error recording functionality from opcache to Zend,
and then using it to persist a warning trace in the inheritance cache, which
can then be used to replay the warnings on subsequent executions.
The never type can be used to indicate that a function never
returns, for example because it always unwinds.
RFC: https://wiki.php.net/rfc/noreturn_type
Closes GH-6761.
This PR corrects misspellings identified by the check-spelling action.
The misspellings have been reported at jsoref@b6ba3e2#commitcomment-48946465
The action reports that the changes in this PR would make it happy: jsoref@602417c
Closes GH-6822.
This is generalization of idea, that was previously usesd for caching
resolution of class_entries in zend_type. Now very similar mechanizm is
used for general zend_string into zend_class_entry resolution.
Interned zend_string with IS_STR_CLASS_NAME_MAP_PTR GC_FLAG uses its
refcount to adress corresponding zend_class_entry cache slot.
The refcount keeps an offset to this slot from CG(map_ptr_base).
Flag may be checked by ZSTR_HAS_CE_CACHE(str), cache slot may be read by
ZSTR_GET_CE_CACHE(str) and set by ZSTR_SET_CE_CACHE(str, ce).
When a method is inherited, the static variables will now always
use the initial values, rather than the values at the time of
inheritance. As such, behavior no longer depends on whether
inheritance happens before or after a method has been called.
This is implemented by always keeping static_variables as the
original values, and static_variables_ptr as the modified copy.
Closes GH-6705.
This is a new transparent technology that eliminates overhead of PHP class inheritance.
PHP classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.
Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).
The patch shows 8% improvement on Symphony "Hello World" app.
We're starting to see a mix between uses of zend_bool and bool.
Replace all usages with the standard bool type everywhere.
Of course, zend_bool is retained as an alias.
This is a bit annoying: When preloading is used, types might be
resolved during inheritance checks, so we need to deal with CE
types rather than just NAME types everywhere.
We need to perform trait scope fixup for both methods involved
in the inheritance check. For that purpose we already need to
thread through a separate fn scope through the entire inheritance
checking machinery.