diff --git a/src/CompilerBase.php b/src/CompilerBase.php index fab95bf8..310a79b7 100644 --- a/src/CompilerBase.php +++ b/src/CompilerBase.php @@ -1017,10 +1017,13 @@ class CompilerBase implements PropertyAccessContext protected function getFullClassName(): string { - // 在接口上下文中,$this->class 为空但 $this->interface 已设置, - // `self` 类型声明应解析为接口自身的完整名称。 - $classLike = $this->class !== '' ? $this->class : $this->interface; - return ltrim($this->namespace . '\\' . $classLike, '\\'); + return ltrim($this->namespace . '\\' . $this->class, '\\'); + } + + protected function getFullClassLikeName(): string + { + $name = $this->class !== '' ? $this->class : $this->interface; + return ltrim($this->namespace . '\\' . $name, '\\'); } protected function getFullMethodName(string $fullClassName, string $method): string diff --git a/src/Generator/TypeCheckGenerator.php b/src/Generator/TypeCheckGenerator.php index 16dc4ae3..292967a1 100644 --- a/src/Generator/TypeCheckGenerator.php +++ b/src/Generator/TypeCheckGenerator.php @@ -104,7 +104,7 @@ trait TypeCheckGenerator } if ($name === 'self') { - $class = $this->getFullClassName(); + $class = $this->getFullClassLikeName(); } elseif ($name === 'parent') { $class = $this->classDef->extends ?? ''; } elseif ($name === 'static') { diff --git a/src/Resolver/NameResolutionTrait.php b/src/Resolver/NameResolutionTrait.php index 307117e5..827db4a3 100644 --- a/src/Resolver/NameResolutionTrait.php +++ b/src/Resolver/NameResolutionTrait.php @@ -166,7 +166,7 @@ trait NameResolutionTrait return $this->getTypeFromZendType($typeNameLower); } else { if ($typeName === 'self') { - $class = $this->getFullClassName(); + $class = $this->getFullClassLikeName(); } elseif ($typeName === 'parent') { if (!$this->classDef) { $this->fatalError($type, 'Cannot use "parent" type declaration outside a class'); diff --git a/tests/compiler/namespace/interface-self-return-namespaced.phpt b/tests/compiler/namespace/interface-self-return-namespaced.phpt index cfda0bad..4d05a98a 100644 --- a/tests/compiler/namespace/interface-self-return-namespaced.phpt +++ b/tests/compiler/namespace/interface-self-return-namespaced.phpt @@ -7,6 +7,10 @@ namespace App { interface Chainable { public function chain(): self; + + public function maybe(bool $present): ?self; + + public function combine(self $other): self; } // comment inside a named namespace block (Stmt_Nop) @@ -19,6 +23,16 @@ namespace App { $this->log[] = 'chain'; return $this; } + + public function maybe(bool $present): ?self + { + return $present ? $this : null; + } + + public function combine(Chainable $other): self + { + return $this; + } } } @@ -28,9 +42,15 @@ namespace { $w = new \App\Widget(); var_dump($w->chain()->chain() instanceof \App\Chainable); var_dump(count($w->log)); + var_dump($w->maybe(true) instanceof \App\Chainable); + var_dump($w->maybe(false)); + var_dump($w->combine(new \App\Widget()) === $w); } } ?> --EXPECT-- bool(true) int(2) +bool(true) +NULL +bool(true)