fix(translator): reject static/instance property redeclaration mismatch (#57) --skip-tests

checkPropertyOverride() compared type, visibility, set-visibility,
readonly and final between a child property and the parent's, but never
Modifiers::STATIC. Redeclaring `public static int $x` as
`public int $x` (or the reverse) was accepted, while Zend fatals with
"Cannot redeclare static A::$x as non static B::$x" (and "Cannot
redeclare non static ... as static ..." in the other direction):
static and instance properties are different kinds of storage and can
never override one another.
master
Alessio Giacobbe 3 days ago committed by GitHub
parent c6e6997db8
commit 0f1efb52a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 12
      phpunit/code/property_nonstatic_mismatch.php
  2. 14
      phpunit/code/property_static_match.php
  3. 12
      phpunit/code/property_static_mismatch.php
  4. 32
      phpunit/src/StaticPropertyOverrideTest.php
  5. 8
      src/Translator.php

@ -0,0 +1,12 @@
<?php
class A
{
public int $x = 1;
}
class B extends A
{
public static int $x = 2;
}
function main() {}

@ -0,0 +1,14 @@
<?php
class A
{
public static int $x = 1;
public int $y = 1;
}
class B extends A
{
public static int $x = 2;
public int $y = 2;
}
function main() {}

@ -0,0 +1,12 @@
<?php
class A
{
public static int $x = 1;
}
class B extends A
{
public int $x = 2;
}
function main() {}

@ -0,0 +1,32 @@
<?php
use TypePhp\Exception\TestError;
/**
* A static property and an instance property are different kinds of storage;
* Zend forbids redeclaring one as the other in either direction ("Cannot
* redeclare static A::$x as non static B::$x" and vice versa).
*/
class StaticPropertyOverrideTest extends BaseTest
{
public function testMatchingStaticnessCompiles(): void
{
$this->compile('property_static_match.php');
}
public function testStaticCannotBecomeInstance(): void
{
$this->exec(
'Cannot redeclare static `A::$x` as non static `B::$x`',
'property_static_mismatch.php',
);
}
public function testInstanceCannotBecomeStatic(): void
{
$this->exec(
'Cannot redeclare non static `A::$x` as static `B::$x`',
'property_nonstatic_mismatch.php',
);
}
}

@ -5407,6 +5407,14 @@ CODE;
"`{$parentClass}::\${$name}`; property shadowing across inheritance is not allowed"); "`{$parentClass}::\${$name}`; property shadowing across inheritance is not allowed");
} }
$matchedOverrides[$name] = true; $matchedOverrides[$name] = true;
// A static property and an instance property are different
// kinds of storage; Zend forbids redeclaring one as the
// other in either direction.
if (($childProp->flags & Modifiers::STATIC) !== ($parentProp->flags & Modifiers::STATIC)) {
$this->fatalError($classStmt, ($parentProp->flags & Modifiers::STATIC)
? "Cannot redeclare static `{$parentClass}::\${$name}` as non static `{$className}::\${$name}`"
: "Cannot redeclare non static `{$parentClass}::\${$name}` as static `{$className}::\${$name}`");
}
// PHP inherits get and set independently. A child may // PHP inherits get and set independently. A child may
// override only one hook, or redeclare the property // override only one hook, or redeclare the property
// without hooks while retaining both parent hooks. // without hooks while retaining both parent hooks.

Loading…
Cancel
Save