From 1b235d076906d5fae64d16ce7b11cf7589158a75 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Tue, 25 Aug 2026 20:43:21 +0800 Subject: [PATCH] test(compiler): reject mixed cache lifetime IDs --- phpunit/src/CompilerBaseApiTest.php | 14 ++++++++++++++ src/CompilerBase.php | 18 +++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/phpunit/src/CompilerBaseApiTest.php b/phpunit/src/CompilerBaseApiTest.php index db39cc17..29c56ccc 100644 --- a/phpunit/src/CompilerBaseApiTest.php +++ b/phpunit/src/CompilerBaseApiTest.php @@ -98,6 +98,20 @@ class CompilerBaseApiTest extends TestCase $this->assertSame([], $this->getPropertyValue('persistentFuncMap')); } + public function testMethodCacheRejectsMismatchedLifetimeDomains(): void + { + $this->setPropertyValue('classMap', ['LateKnownClass' => 0]); + $this->setPropertyValue('classIndex', 1); + $this->setPropertyValue('persistentFuncMap', ['LateKnownClass::run' => 0]); + $this->setPropertyValue('persistentFuncIndex', 1); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage( + 'Cache lifetime mismatch for LateKnownClass::run: method ID 0 is persistent, class ID 0 is request-local', + ); + $this->invokeMethod('getMethodPtr', 'LateKnownClass', 'run'); + } + private function fixturePath(string $file): string { return __DIR__ . '/../code/compiler_api/' . $file; diff --git a/src/CompilerBase.php b/src/CompilerBase.php index 607ab094..92756a84 100644 --- a/src/CompilerBase.php +++ b/src/CompilerBase.php @@ -1426,10 +1426,22 @@ class CompilerBase implements PropertyAccessContext protected function getMethodPtr(string $class, string $method): string { - $funcId = $this->getFuncId($class . '::' . $method); + $key = $class . '::' . $method; + $funcId = $this->getFuncId($key); $classId = $this->getClassId($class); - // 方法的稳定性与所属类一致,因此 class_id 必定落在同一张表中 - $helper = isset($this->persistentFuncMap[$class . '::' . $method]) ? 'get_persistent_method' : 'get_method'; + $persistentMethod = isset($this->persistentFuncMap[$key]); + $persistentClass = isset($this->persistentClassMap[$class]); + if ($persistentMethod !== $persistentClass) { + throw new \LogicException(sprintf( + 'Cache lifetime mismatch for %s: method ID %d is %s, class ID %d is %s', + $key, + $funcId, + $persistentMethod ? 'persistent' : 'request-local', + $classId, + $persistentClass ? 'persistent' : 'request-local', + )); + } + $helper = $persistentMethod ? 'get_persistent_method' : 'get_method'; return $helper . '(' . $funcId . ', ' . $this->getLiteralString($method) . ', ' . $classId . ', ' . $this->getLiteralString($class) . ')'; }