Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
- RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute
- Implementation: https://github.com/php/php-src/pull/18817
--Daniel
Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
- RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute
- Implementation: https://github.com/php/php-src/pull/18817
--Daniel
Interesting. I’d also argue for the inverse more than this, though. I’d like for my attributes to be validated during compilation instead of delayed to runtime -- which, it isn’t actually. Runtime validation ONLY happens when calling ->newInstance() on ReflectionAttribute, and never before then. So, only when an attribute is actually read during reflection is it validated. Further, if you never actually instantiate it ... it is never actually validated (i.e., just looking for the presence of an attribute, not the details).
— Rob
Von meinem iPhone gesendet
Am 18.06.2025 um 11:26 schrieb Rob Landers rob@bottled.codes:
Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
- RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute
- Implementation: https://github.com/php/php-src/pull/18817
--Daniel
Interesting. I’d also argue for the inverse more than this, though. I’d like for my attributes to be validated during compilation instead of delayed to runtime -- which, it isn’t actually. Runtime validation ONLY happens when calling ->newInstance() on ReflectionAttribute, and never before then. So, only when an attribute is actually read during reflection is it validated. Further, if you never actually instantiate it ... it is never actually validated (i.e., just looking for the presence of an attribute, not the details).
As Daniel’s rfc mentions you need to differentiate between compiler and userland attributes.
The compiler attributes are validated at compile time not dueing newInstance.
— Rob
Von meinem iPhone gesendet
Am 18.06.2025 um 11:26 schrieb Rob Landers rob@bottled.codes:
Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
- RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute
- Implementation: https://github.com/php/php-src/pull/18817
--Daniel
Interesting. I’d also argue for the inverse more than this, though. I’d like for my attributes to be validated during compilation instead of delayed to runtime -- which, it isn’t actually. Runtime validation ONLY happens when calling ->newInstance() on ReflectionAttribute, and never before then. So, only when an attribute is actually read during reflection is it validated. Further, if you never actually instantiate it ... it is never actually validated (i.e., just looking for the presence of an attribute, not the details).
As Daniel’s rfc mentions you need to differentiate between compiler and userland attributes.
The compiler attributes are validated at compile time not dueing newInstance.
— Rob
Just as an information:
We are at the moment in the proces of setting up a registry for userland attributes at the PHP-FIG.
For more information regarding that check out https://github.com/php-fig/fig-standards/pull/1331
Cheers
Andreas
--
Andreas Heigl
Von meinem iPhone gesendet
Am 18.06.2025 um 11:26 schrieb Rob Landers rob@bottled.codes:
Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
- RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute
- Implementation: https://github.com/php/php-src/pull/18817
--Daniel
Interesting. I’d also argue for the inverse more than this, though. I’d like for my attributes to be validated during compilation instead of delayed to runtime -- which, it isn’t actually. Runtime validation ONLY happens when calling ->newInstance() on ReflectionAttribute, and never before then. So, only when an attribute is actually read during reflection is it validated. Further, if you never actually instantiate it ... it is never actually validated (i.e., just looking for the presence of an attribute, not the details).
As Daniel’s rfc mentions you need to differentiate between compiler and userland attributes.
The compiler attributes are validated at compile time not dueing newInstance.
— Rob
Yes, but when would it check it during runtime? It doesn't say in the RFC. From what I can tell, it effectively disables the attribute, unless someone happens to enumerate and instantiate all the attributes (which is unlikely).
— Rob
On Wed, Jun 18, 2025 at 1:28 AM Daniel Scherzer daniel.e.scherzer@gmail.com
wrote:
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
Hi Daniel,
While I'm in favor of the RFC, I'd more like to see the default behavior of
internal and userland attributes adjusted to work the same, with both
having delayed validation enabled by default. Treating core attributes
differently doesn't make sense to me.
So, if that's someone you're willing to work on, I'd very much prefer that.
But if there are downsides to this approach or if this is too
complicated for other reasons, this attribute is a net positive in my book
to make forward compatibility possible.
One note on the example code:
class Base {
class Child extends Parent {
\
Parent isn't a valid class name, and I think you wanted to extend from Base
here? I'd prefer the example to compile so that they can be used for
documentation later on where possible.
Kind Regards,
Volker
--
Volker Dusch
Head of Engineering
Tideways GmbH
Königswinterer Str. 116
53227 Bonn
https://tideways.io/imprint
Sitz der Gesellschaft: Bonn
Geschäftsführer: Benjamin Außenhofer (geb. Eberlei)
Registergericht: Amtsgericht Bonn, HRB 22127
On Wed, Jun 18, 2025 at 5:22 AM Volker Dusch volker@tideways-gmbh.com
wrote:
On Wed, Jun 18, 2025 at 1:28 AM Daniel Scherzer <
daniel.e.scherzer@gmail.com> wrote:I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.Hi Daniel,
One note on the example code:
class Base {
class Child extends Parent {
\Parent isn't a valid class name, and I think you wanted to extend from
Base here? I'd prefer the example to compile so that they can be used for
documentation later on where possible.Kind Regards,
Volker
Fixed, thanks.
Hi Volker
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.While I'm in favor of the RFC, I'd more like to see the default behavior of internal and userland attributes adjusted to work the same, with both having delayed validation enabled by default. Treating core attributes differently doesn't make sense to me.
So, if that's someone you're willing to work on, I'd very much prefer that.
I wouldn't support that, because internal attributes with effects are
not usually instantiated.
class C {
#[\SensitiveParameter] // This doesn't actually do anything, only
works on parameters
public $prop;
}
I would get no indication that this attribute doesn't behave as I
expect. We have at least a few attributes with confusable targets
(SensitiveParameter, Override, Deprecated, NoDiscard). User attributes
can't have effects without at least reading them through reflection,
although granted they don't necessarily need to be instantiated, and
so might also not trigger the error.
Ilija
Le mer. 18 juin 2025 à 23:49, Ilija Tovilo tovilo.ilija@gmail.com a
écrit :
Hi Volker
On Wed, Jun 18, 2025 at 2:23 PM Volker Dusch volker@tideways-gmbh.com
wrote:On Wed, Jun 18, 2025 at 1:28 AM Daniel Scherzer <
daniel.e.scherzer@gmail.com> wrote:I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.While I'm in favor of the RFC, I'd more like to see the default behavior
of internal and userland attributes adjusted to work the same, with both
having delayed validation enabled by default. Treating core attributes
differently doesn't make sense to me.So, if that's someone you're willing to work on, I'd very much prefer
that.
I 100% agree with what Volker posted here.
I wouldn't support that, because internal attributes with effects are
not usually instantiated.
class C {
#[\SensitiveParameter] // This doesn't actually do anything, only
works on parameters
public $prop;
}I would get no indication that this attribute doesn't behave as I
expect. We have at least a few attributes with confusable targets
(SensitiveParameter, Override, Deprecated, NoDiscard). User attributes
can't have effects without at least reading them through reflection,
although granted they don't necessarily need to be instantiated, and
so might also not trigger the error.
These considerations work exactly the same for userland attributes: if I
use #[Whatever] on a location that is not allowed by the declaration of the
attribute, nothing will ever tell me at runtime, because nobody will ever
try to read that attribute on that unexpected location.
Yet, this "silent" behavior is by design, because that's the core of the
"attributes are declarative metadata" promise. If you make them be enforced
by the engine, then this promise falls apart and attributes become way less
useful.
The correct solution to the validation problem is to use a static analyzer.
There, one can easily spot that some attributes are not correctly placed,
and one can then also ignore the report of the SA tool, because eg
#[Deprecated] is used on a class on purpose for that library (e.g. for the
forward compat use case).
The exception to the declarative nature of attributes that is currently
allowed for engine-provided ones is detrimental to me: it allows turning
them into "syntax hacks" basically (=engine-enforced-thus-not-declarative
rules).
To paraphrase Volker, I'm in favor of the RFC, but only if we cannot agree
on the need for internal and userland attributes to have the same
conceptual roots (truly declarative ones).
Cheers,
Nicolas
On Tue, Jun 17, 2025 at 4:26 PM Daniel Scherzer daniel.e.scherzer@gmail.com
wrote:
Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
- RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute
- Implementation: https://github.com/php/php-src/pull/18817
--Daniel
It seems a common point of discussion is the difference in behavior between
internal and userland attributes, so I wanted to clarify a few things:
- Userland attributes are always metadata, in part because of the backwards
and forward compatibility that those attributes provide - the
attribute does not need to exist in order to be used, it just needs to
exist (and target the location) when you call
ReflectionAttribute::newInstance() to instantiate - Internal attributes are a mix between metadata and a way to plug into the
engine. There were already existing ways to plug into the engine (e.g.
using magic methods or implementing the Countable or ArrayAccess
interfaces) but attributes provided a way to plug into the engine when you
don't just want to add a function override, but rather something else (like
indicating a parameter should be redacted in backtraces with
#[\SensitiveParameter]
). It would probably be impossible to do that
securely with a userland attribute and userland error handler that manually
redacted things... - Attributes were designed to have good compatibility - the syntax chosen
for PHP 8.0 was, in prior versions of PHP, used for comments - so any code
with attributes could also work in PHP 7.4, just without the metadata.
Similarly, by not validating userland attributes until they are accessed
with reflection, you can add an attribute that does not exist yet (e.g. if
using different versions of a library) with minimal complications. - Internal attributes are validated at compile time - because they can be.
Internal attributes tell the engine to do something, and it makes sense (at
least to me) that if the engine cannot do that thing, there should be an
error without needing to wait for ReflectionAttribute::newInstance() to be
called.
But, the validation of internal attributes at compile time means that they
lose the compatibility features of userland attributes, and that is what
this RFC is trying to address. To be clear, I think the difference in
behavior between userland and internal attributes is a) fundamentally based
on the difference in capabilities (pure metadata vs engine behavior) and b)
something that should not be changed without significant further
investigation.
This new #[\DelayedTargetValidation]
is meant to simplify things, and to
partially unify the behavior of the errors - if you are getting any errors
from internal attributes and want to suppress them at compile time, just
add the new attribute everywhere.
-Daniel
Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
- RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute
- Implementation: https://github.com/php/php-src/pull/18817
--Daniel
It seems a common point of discussion is the difference in behavior between internal and userland attributes, so I wanted to clarify a few things:
- Userland attributes are always metadata, in part because of the backwards and forward compatibility that those attributes provide - the attribute does not need to exist in order to be used, it just needs to exist (and target the location) when you call ReflectionAttribute::newInstance() to instantiate
- Internal attributes are a mix between metadata and a way to plug into the engine. There were already existing ways to plug into the engine (e.g. using magic methods or implementing the Countable or ArrayAccess interfaces) but attributes provided a way to plug into the engine when you don't just want to add a function override, but rather something else (like indicating a parameter should be redacted in backtraces with
#[\SensitiveParameter]
). It would probably be impossible to do that securely with a userland attribute and userland error handler that manually redacted things...- Attributes were designed to have good compatibility - the syntax chosen for PHP 8.0 was, in prior versions of PHP, used for comments - so any code with attributes could also work in PHP 7.4, just without the metadata. Similarly, by not validating userland attributes until they are accessed with reflection, you can add an attribute that does not exist yet (e.g. if using different versions of a library) with minimal complications.
- Internal attributes are validated at compile time - because they can be. Internal attributes tell the engine to do something, and it makes sense (at least to me) that if the engine cannot do that thing, there should be an error without needing to wait for ReflectionAttribute::newInstance() to be called.
But, the validation of internal attributes at compile time means that they lose the compatibility features of userland attributes, and that is what this RFC is trying to address. To be clear, I think the difference in behavior between userland and internal attributes is a) fundamentally based on the difference in capabilities (pure metadata vs engine behavior) and b) something that should not be changed without significant further investigation.
I don’t think this is quite right. Because non-existent attributes can be used, if you use attributes in your library, you already know to only ever, and I mean only ever, instantiate your own attributes. Attempting to instantiate someone else’s attributes can result in crashes. This means any delayed attributes will most likely never be validated by anything.
This new
#[\DelayedTargetValidation]
is meant to simplify things, and to partially unify the behavior of the errors - if you are getting any errors from internal attributes and want to suppress them at compile time, just add the new attribute everywhere.-Daniel
I don’t think this is “forward compatibility”, this is completely disabling the attribute.
— Rob
On Tue, Jun 17, 2025 at 4:26 PM Daniel Scherzer <
daniel.e.scherzer@gmail.com> wrote:Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
- RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute
- Implementation: https://github.com/php/php-src/pull/18817
--Daniel
It seems a common point of discussion is the difference in behavior
between internal and userland attributes, so I wanted to clarify a few
things:
- Userland attributes are always metadata, in part because of the
backwards and forward compatibility that those attributes provide - the
attribute does not need to exist in order to be used, it just needs to
exist (and target the location) when you call
ReflectionAttribute::newInstance() to instantiate- Internal attributes are a mix between metadata and a way to plug into
the engine. There were already existing ways to plug into the engine (e.g.
using magic methods or implementing the Countable or ArrayAccess
interfaces) but attributes provided a way to plug into the engine when you
don't just want to add a function override, but rather something else (like
indicating a parameter should be redacted in backtraces with
#[\SensitiveParameter]
). It would probably be impossible to do that
securely with a userland attribute and userland error handler that manually
redacted things...- Attributes were designed to have good compatibility - the syntax chosen
for PHP 8.0 was, in prior versions of PHP, used for comments - so any code
with attributes could also work in PHP 7.4, just without the metadata.
Similarly, by not validating userland attributes until they are accessed
with reflection, you can add an attribute that does not exist yet (e.g. if
using different versions of a library) with minimal complications.- Internal attributes are validated at compile time - because they can be.
Internal attributes tell the engine to do something, and it makes sense (at
least to me) that if the engine cannot do that thing, there should be an
error without needing to wait for ReflectionAttribute::newInstance() to be
called.But, the validation of internal attributes at compile time means that they
lose the compatibility features of userland attributes, and that is what
this RFC is trying to address. To be clear, I think the difference in
behavior between userland and internal attributes is a) fundamentally based
on the difference in capabilities (pure metadata vs engine behavior) and b)
something that should not be changed without significant further
investigation.I don’t think this is quite right. Because non-existent attributes can be
used, if you use attributes in your library, you already know to only ever,
and I mean only ever, instantiate your own attributes. Attempting to
instantiate someone else’s attributes can result in crashes. This means any
delayed attributes will most likely never be validated by anything.
Symfony instantiates arbitrary attributes,
https://github.com/symfony/symfony/pull/40307 - and while delayed
attributes may not end up being validated, that is a feature, not a bug -
the goal is that the validation not be performed at compile time, and so it
was either delay to runtime, or not do the validation at all.
This new
#[\DelayedTargetValidation]
is meant to simplify things, and to
partially unify the behavior of the errors - if you are getting any errors
from internal attributes and want to suppress them at compile time, just
add the new attribute everywhere.-Daniel
I don’t think this is “forward compatibility”, this is completely
disabling the attribute.— Rob
So I guess my use of "forward compatibility" was a bit confusing. This
allows a library to be backwards compatible (using PHP 8.6 attribute
targets but running on PHP 8.5 without errors) by making the language
forward compatible (allowing PHP 8.5 to process 8.6 attribute targets
without errors, by delaying those errors). The attribute is not disabled at
all though.
- If the attribute is used in a place where it would do anything (i.e.
there wouldn't be an error about being a bad target) then that attribute is
used as normal, and #[\DelayedTargetValidation] does not affect it - If the attribute is used in a place where it would error, then it already
cannot do anything, and #[\DelayedTargetValidation] just delays the error -
the attribute is already going to be inactive anyway
-Daniel
__
Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
- RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute
- Implementation: https://github.com/php/php-src/pull/18817
--Daniel
It seems a common point of discussion is the difference in behavior between internal and userland attributes, so I wanted to clarify a few things:
- Userland attributes are always metadata, in part because of the backwards and forward compatibility that those attributes provide - the attribute does not need to exist in order to be used, it just needs to exist (and target the location) when you call ReflectionAttribute::newInstance() to instantiate
- Internal attributes are a mix between metadata and a way to plug into the engine. There were already existing ways to plug into the engine (e.g. using magic methods or implementing the Countable or ArrayAccess interfaces) but attributes provided a way to plug into the engine when you don't just want to add a function override, but rather something else (like indicating a parameter should be redacted in backtraces with
#[\SensitiveParameter]
). It would probably be impossible to do that securely with a userland attribute and userland error handler that manually redacted things...- Attributes were designed to have good compatibility - the syntax chosen for PHP 8.0 was, in prior versions of PHP, used for comments - so any code with attributes could also work in PHP 7.4, just without the metadata. Similarly, by not validating userland attributes until they are accessed with reflection, you can add an attribute that does not exist yet (e.g. if using different versions of a library) with minimal complications.
- Internal attributes are validated at compile time - because they can be. Internal attributes tell the engine to do something, and it makes sense (at least to me) that if the engine cannot do that thing, there should be an error without needing to wait for ReflectionAttribute::newInstance() to be called.
But, the validation of internal attributes at compile time means that they lose the compatibility features of userland attributes, and that is what this RFC is trying to address. To be clear, I think the difference in behavior between userland and internal attributes is a) fundamentally based on the difference in capabilities (pure metadata vs engine behavior) and b) something that should not be changed without significant further investigation.
I don’t think this is quite right. Because non-existent attributes can be used, if you use attributes in your library, you already know to only ever, and I mean only ever, instantiate your own attributes. Attempting to instantiate someone else’s attributes can result in crashes. This means any delayed attributes will most likely never be validated by anything.
Symfony instantiates arbitrary attributes, https://github.com/symfony/symfony/pull/40307 - and while delayed attributes may not end up being validated, that is a feature, not a bug - the goal is that the validation not be performed at compile time, and so it was either delay to runtime, or not do the validation at all.
This new
#[\DelayedTargetValidation]
is meant to simplify things, and to partially unify the behavior of the errors - if you are getting any errors from internal attributes and want to suppress them at compile time, just add the new attribute everywhere.-Daniel
I don’t think this is “forward compatibility”, this is completely disabling the attribute.
— Rob
So I guess my use of "forward compatibility" was a bit confusing. This allows a library to be backwards compatible (using PHP 8.6 attribute targets but running on PHP 8.5 without errors) by making the language forward compatible (allowing PHP 8.5 to process 8.6 attribute targets without errors, by delaying those errors). The attribute is not disabled at all though.
- If the attribute is used in a place where it would do anything (i.e. there wouldn't be an error about being a bad target) then that attribute is used as normal, and #[\DelayedTargetValidation] does not affect it
- If the attribute is used in a place where it would error, then it already cannot do anything, and #[\DelayedTargetValidation] just delays the error - the attribute is already going to be inactive anyway
-Daniel
Hmmm... I still don't get it. If you scan your codebase for these attributes (maybe using something like https://github.com/olvlvl/composer-attribute-collector) and then instantiate them ... then you are right back where you started. You'll end up getting the same validation errors you'd normally get. But I don't know why you'd do such a thing. You can use \NoDiscard today, but if you try to instantiate it -- it will crash without a polyfill. There are attributes used only by IDEs (like \Pure
) and attempting to instantiate them will crash. This is why you don't instantiate attributes you don't own.
By adding this, you force all framework to try instantiating these built-in attributes; and scanning for them. This increases the bug surface, boot times, and maintenance cost ... to basically end up right where we started.
I just don't see the point of this. I think the problem is real, I just don't think this is the right solution.
Instead, it would probably be simpler to backport a change to earlier versions of PHP that simply allows the future target without validation; or to do a two phase rollout of a target change (minor + 1: add the target without validation, then minor + 2, enable validation); or choose a different name.
Another alternative would be to simply write code for the minimum version of PHP you support. For example, if you want to use the pipe operator, you either need to support 8.5 as a minimum, or not use it.
— Rob
Hi Daniel, internals,
On Wed, Jun 18, 2025, 02:29 Daniel Scherzer daniel.e.scherzer@gmail.com
wrote:
Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
How about completely disabling errors caused by a bad target at compile
time?
And just ignore the attribute, that can be validated at runtime if needed.
IDEs and static code analysis would show the problem and that might be
enough.
--
Alex
On Sun, Jun 22, 2025 at 10:24 PM Alexandru Pătrănescu drealecs@gmail.com
wrote:
Hi Daniel, internals,
On Wed, Jun 18, 2025, 02:29 Daniel Scherzer daniel.e.scherzer@gmail.com
wrote:Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.How about completely disabling errors caused by a bad target at compile
time?
And just ignore the attribute, that can be validated at runtime if needed.
IDEs and static code analysis would show the problem and that might be
enough.--
Alex
If you mean to always disable those errors, that is exactly what I
responded to above - https://news-web.php.net/php.internals/127734.
Basically, internal attributes are not pure metadata but also trigger
engine behavior, while userland attributes are metadata (and the attributes
don't even need to exist to be used!). Thus, there is a benefit to compile
time errors, since otherwise you don't know that the engine behavior isn't
being triggered.
This attribute completely disables errors caused by a bad target at compile
time whenever the new #[\DelayedTargetValidation] is applied. This gives
the best of both worlds
- you get errors if you misuse an internal attribute
- you can suppress those errors intentionally if you have a reason (e.g.
forward compatibility), and just delay the validation until runtime
Since I proposed this RFC, a proposal to support #[\Override]
on
properties has been discussed (https://news-web.php.net/php.internals/127831),
highlighting the benefits of this #[\DelayedTargetValidation] attribute.
E.g. if we add it in 8.5, then when a later version adds #[\Override], a
library can apply #[\Override] to properties without requiring a newer
version of PHP.
-Daniel
On Tue, Jun 17, 2025 at 4:26 PM Daniel Scherzer daniel.e.scherzer@gmail.com
wrote:
Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
- RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute
- Implementation: https://github.com/php/php-src/pull/18817
--Daniel
This discussion has been ongoing for more than 2 weeks, and from what I can
see there have only been 2 concerns/suggestions raised:
- Going in the opposite direction and validating userland attributes at
compile time too - this is counter to the design of attributes, which are
meant to be easy to apply and can even be used when the specified attribute
does not exist, with errors only raised when attributes are parsed. - Avoid the need for the
#[\DelayedTargetValidation]
attribute by
changing the default behavior - I (and others) have responded about why
this would be problematic, and I have updated the RFC to include changing
the default behavior as a rejected feature with an explanation of the
issues.
If there is no further feedback, I intend to start a vote in a few days.
-Daniel
Hi
If there is no further feedback, I intend to start a vote in a few days.
Looking at your #[\Deprecated] for traits RFC
(https://externals.io/message/127912):
How will #[\DelayedTargetValidation] interact with the validator
of
zend_internal_attribute
? Would applying #[\DelayedTargetValidation] +
#[\Deprecated] on a regular class error or not?
Best regards
Tim Düsterhus
Hi
If there is no further feedback, I intend to start a vote in a few days.
Looking at your #[\Deprecated] for traits RFC
(https://externals.io/message/127912):How will #[\DelayedTargetValidation] interact with the
validator
of
zend_internal_attribute
? Would applying #[\DelayedTargetValidation] +
#[\Deprecated] on a regular class error or not?Best regards
Tim Düsterhus
For validators, an extra flag is passed to the validator to indicate if
target validation should be disabled, in which case the errors about
targeting the wrong type of thing (e.g. a non-trait in the case of
#[\Deprecated]) are suppressed until runtime as well. Thanks for pointing
this out - I actually hadn't done this properly, fixed it now - take a look
at the "errors_from_validator.phpt" and "validator_success.phpt" test cases
in the PR.
The reasoning here is exactly the same - validators are used to verify that
an attribute is being used on things that are appropriate, just like
targets. While the only current (non-zend_test) validator is for dynamic
properties, and it is less likely that there will be a future where the
validator accepts more things, we shouldn't assume that things will never
change, e.g. I wouldn't object to allowing #[\AllowDynamicProperties] for
read-only classes. But this will also set the stage for the #[\Deprecated]
validator - that validator will enforce that a zend_class_entry is for a
trait, but if validation is delayed then it will allow using #[\Deprecated]
on interfaces or classes and the error being delaying until runtime.
-Daniel
On Tue, Jun 17, 2025 at 4:26 PM Daniel Scherzer daniel.e.scherzer@gmail.com
wrote:
Hi internals,
I'd like to start the discussion for a new RFC about adding a
#[\DelayedTargetValidation]
attribute.
- RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute
- Implementation: https://github.com/php/php-src/pull/18817
--Daniel
I plan to start voting in the next few days if there is no additional
feedback.
-Daniel