Skip to content

Language: IS_REPEATABLE attributes + ReflectionAttribute::isRepeated() — compile rejects valid repeats (zend_attributes.c) #6912

Description

@PurHur

Summary

User attributes declared with Attribute::IS_REPEATABLE must allow multiple instances on the same target, and ReflectionAttribute::isRepeated() must report whether each instance is a duplicate of an earlier one on that target. This compiler rejects all repeated attributes at compile time and does not register isRepeated() on the builtin ReflectionAttribute class.

php-src-strict: match Zend/zend_attributes.c (zend_is_attribute_repeated, zend_mark_attribute_repeatable) and ext/reflection/php_reflection.c (ReflectionAttribute::isRepeated).

Repro (verified 2026-06-06, Docker php-compiler:22.04-dev)

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
php bin/vm.php test/repro/maintainer_attr_isrepeated2.php
php test/repro/maintainer_attr_isrepeated2.php
'
Runtime Result
Zend PHP 8.2 2 / rep0 / norep1 (isRepeated() true only on first of duplicate pair)
VM CompileError: Attribute "Rep" must not be repeated

Root cause sketch: lib/Compiler/AttributeNames.php::assertNoDuplicates() always fatals on duplicate names without reading the attribute class flags for IS_REPEATABLE (128). lib/VM/BuiltinClasses.php registers ReflectionAttribute with getName / getArguments / newInstance only — no isRepeated.

Related repro

Bitmask ctor args using named Attribute:: constants (non-literal fold) fail separately — see #6907 (sibling issue filed this run).

php-src reference

Area File
Repeatable flag on #[Attribute] Zend/zend_attributes.c — zend_mark_attribute_repeatable
Compile-time duplicate guard Zend/zend_compile.c — zend_is_attribute_repeated
Reflection API ext/reflection/php_reflection.c — ReflectionAttribute::isRepeated

Implementation (PHP-in-PHP)

  1. Compiler: when collecting attribute names on a target, skip assertNoDuplicates fatals for classes whose registered Attribute flags include IS_REPEATABLE; store instance index for reflection.
  2. VM: add ReflectionAttribute::isRepeated(): bool on builtin class entry; populate from compile metadata in lib/VM/ReflectionSupport.php.
  3. JIT/AOT: mirror metadata in reflection tables (same path as getName / newInstance, Language: ReflectionAttribute::newInstance() — JIT/AOT (phase 2 of #3206, ext/reflection/php_reflection.c) #4598).

Done when

  • test/repro/maintainer_attr_isrepeated2.php matches Zend on VM
  • First repeated instance: isRepeated() === true; second+: false (Zend parity)
  • test/compliance/cases/language/attribute_is_repeatable.phpt added
  • ./script/ci-fast.sh --filter attribute_is_repeatable green

Verification

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
vendor/bin/phpunit test/compliance/VMTest.php --filter attribute_is_repeatable
'

Pairs with umbrella #4392 (attributes); claim this slice only.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:compilerCompiler / CFG / JITarea:vmVirtual machineenhancementNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-2:languagePhase 2 – language features

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions