Skip to content

Language: define('LIT') inside function warns Constant already defined — Zend silent (re-#204, zend_builtin_functions.c) #32039

Description

@PurHur

Category

Language · php-src-strict / define() compile-time prescan

Problem

define('NAME', literal) inside a user function (or method) emits Constant NAME already defined on VM/JIT. Zend 8.2.32 registers the constant once and is silent.

Top-level define('NAME', literal) and define($runtimeName, literal) already match Zend. The extra warning is the compile-time prescan (Compiler::prescanDefineFuncCall / storeCompileTimeGlobalConst, issue #204) seeding the constant, then the still-emitted runtime define() / TYPE_DECLARE_GLOBAL_CONST trying again when the function runs.

Probed 2026-08-18 @ 87cba84dc2 — Zend 8.2.32 vs php bin/vm.php / php bin/jit.php.

Repro Zend 8.2.32 VM/JIT
function f() { define('C', 1); } f(); silent; defined('C')===true Warning: Constant C already defined (attributed to the call site of f(), not the define() line)
file-scope define('C', 1); silent silent ✓
define('C'.'X', 1); (runtime name) silent silent ✓

php-src reference

PHP implementation target

  • lib/Compiler.phpprescanDefineFuncCall / tryCompileDefineAsGlobalConst: do not seed the runtime constant table for define() that will still run inside a function body; either elide the runtime call xor skip prescan, never both
  • ext/standard/define_.php — runtime define() should remain the php-src-strict path for non-elided calls
  • lib/VM.php TYPE_DECLARE_GLOBAL_CONST — same uniqueness as Zend zend_register_constant
  • No new runtime/*.c

Repro

./script/docker-exec.sh -- bash -lc 'php bin/vm.php test/repro/maintainer_gap_define_inside_function.php'
./script/docker-exec.sh -- bash -lc 'php bin/jit.php test/repro/maintainer_gap_define_inside_function.php'
./script/docker-exec.sh -- bash -lc 'php test/repro/maintainer_gap_define_inside_function.php'  # Zend baseline
<?php
error_reporting(E_ALL);
function probe_define(): void
{
    define('PROBE_C_ISOLATED', 1);
    echo 'defined_ci=', var_export(defined('probe_c_isolated'), true), "\n";
    echo 'defined_CS=', var_export(defined('PROBE_C_ISOLATED'), true), "\n";
}
probe_define();

Done when

  • VM/JIT: define('LIT', …) inside a function/method is silent on first execution (Zend); second call still warns already defined
  • File-scope and runtime-name define() unchanged (already green)
  • defined('LIT') / constant('LIT') still see the value after the first call
  • Compliance .phpt under test/compliance/cases/language/
  • php-src-strict; no php-compiler-strict shortcut that leaves the runtime define() in the function and pre-registers the constant

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 machinebugSomething isn't workingimplementation-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