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

Reply via email to