Skip to content

Instantly share code, notes, and snippets.

@theodorejb
Last active August 14, 2020 20:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theodorejb/2d39eb6e13159fc749f728900edfd0d2 to your computer and use it in GitHub Desktop.
Save theodorejb/2d39eb6e13159fc749f728900edfd0d2 to your computer and use it in GitHub Desktop.
Attribute syntax discussion

Discussion

Is the lack of an ending symbol inconsistent?

It is true that statements and declarations in PHP generally have an ending symbol. However, attributes are not a standalone statement or declaration, but rather modifiers on a declaration. They do not stand alone, but are always followed by a declaration with which the metadata is associated. This is similar to the public and static keywords that modify a method, or a type declaration that modifies a parameter. For example, we do not write:

[final] class X {
    [public] function foo([int|float] $bar) {}
}

Attributes without an ending symbol are consistent with how these other declaration modifiers are written:

@@MyAttr("value")
final class X {
    @@Jit
    public function foo(@@Deprecated int|float $bar) {}
}

Is attribute grouping a pro or a con?

Attribute grouping could be considered helpful with the @[], #[], and especially <<>> syntaxes to reduce verbosity when adding multiple attributes to a declaration.

However, it also has the downside of leading to unnecessary diff noise when adding/removing a second attribute on its own line. For example:

#[SomeAttribute("with argument")]
function foo() {}

// after adding second grouped attribute changes to:

#[
    SomeAttribute("with argument"),
    OtherAttr([1, 2, 3]),
]
function foo() {}

To avoid modifying lines for unchanged attributes, a coding style could mandate that the first attribute always be written like this:

#[
    SomeAttribute("with argument"),
]
function foo() {}

But this also adds diff noise since from the beginning two extra lines are needed.

The @@ syntax is equally concise without grouping, and ensures that individual attribute lines can always be added/removed without modifying other attribute lines:

@@SomeAttribute("with parameter")
@@OtherAttr([1, 2, 3]) // this line can be added/removed independently
function foo() {}

Is the benefit of forward compatibility worth it?

The partial forward compatibility of #[] would provide a temporary benefit to library authors, who would be able to reuse the same class as a PHP 8 attribute as well as to store annotation information when the library is used on PHP 7. However, this benefit will be irrelevant once most of the library users upgrade to PHP 8, and the library wants to take advantage of any other PHP 8 syntax.

Even without partial syntax forward compatibility, a library can support both PHP 8 attributes and PHP 7 annotations with a small amount of extra work. A parent class can be used to store/handle docblock annotation info, and a child class can be registered as an attribute for PHP 8 users.

Long term we need to consider whether the #[] syntax would continue to result in confusion with hash comments (which have never been deprecated).

A further downside of the partial forward compatibility is that when code intended for PHP 8 is run on PHP 7, instead of immediately failing it can continue running with different unexpected results. Consider these examples:

class X {
    // This comments out the first parameter entirely in
    // PHP 7, silently leading to different behavior.
    public function __construct(
        #[MyImmutable] public bool $x,
        private bool $flag = false,
    ) {}
}
<?php
// This example echoes the rest of the source code in
// PHP 7 and echoes "Test" in PHP 8.
#[DeprecationReason('reason: <https://some-website/reason?>')]
function main() {}
const APP_SECRET = 'app-secret';
echo "Test\n";
@stefanos82
Copy link

If I had to choose between @@ and @:, I would choose the first one; I don't know why, but the latter does not look appealing to me.

I was wondering...since people seems to feel comfortable with the use of single @ sign, would there be an issue to suggest the use of _@ as a new annotation syntax?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment