On Sun, Jun 22, 2025, at 22:00, Daniel Scherzer wrote: > On Tue, Jun 17, 2025 at 4:26 PM Daniel Scherzer <daniel.e.scher...@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. > > 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