fix(compiler): scope interface self type resolution

pull/22/head
韩天峰 1 month ago
parent f9516c43c9
commit 6162185bd7
  1. 11
      src/CompilerBase.php
  2. 2
      src/Generator/TypeCheckGenerator.php
  3. 2
      src/Resolver/NameResolutionTrait.php
  4. 20
      tests/compiler/namespace/interface-self-return-namespaced.phpt

@ -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

@ -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') {

@ -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');

@ -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)

Loading…
Cancel
Save