Edit report at https://bugs.php.net/bug.php?id=64276&edit=1

 ID:                 64276
 Updated by:         larue...@php.net
 Reported by:        r dot wilczek at web-appz dot de
 Summary:            Traits changed behaviour on importing conflicting
                     properties
-Status:             Open
+Status:             Feedback
 Type:               Bug
 Package:            Reflection related
 Operating System:   Linux x86_64
 PHP Version:        5.4.12
 Block user comment: N
 Private report:     N

 New Comment:

Please try using this snapshot:

  http://snaps.php.net/php5.4-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/




Previous Comments:
------------------------------------------------------------------------
[2013-02-22 13:11:44] r dot wilczek at web-appz dot de

Description:
------------
with PHP 5.4.12 (or 5.4.11), PHP silently changed it's behaviour on importing 
conflicting properties from traits.

Below are PHPUnit-Testcases, which all pass on PHP 5.4.10 and fail on PHP 
5.4.12:

Test script:
---------------
public function testTraitOverwritesClassPropertiesOnConflict()
{
    // Temporarily disable E_STRICT
    $oldLevel = error_reporting();
    error_reporting($oldLevel ^ E_STRICT);

    $trait = 'trait %1$s {
       /**
        * Comes from %1$s
        */
       private $foo;
    }';

    $importer = 'class %1$s {
       use %2$s;

       /**
        * Comes from %1$s
        */
       private $foo;
    }';

    $traitName    = 'trait' . uniqid();
    $importerName = 'importer' . uniqid();


    eval(sprintf($trait, $traitName));
    eval(sprintf($importer, $importerName, $traitName));

    $importerFoo = new \ReflectionProperty($importerName, 'foo');
    $traitFoo    = new \ReflectionProperty($traitName, 'foo');

    try {
        $this->assertSame(
            $traitFoo->getDocComment(), $importerFoo->getDocComment()
        );
        // reenable E_STRICT on success
        error_reporting($oldLevel);
    } catch (\PHPUnit_Framework_AssertionFailedError $e) {
        // reenabe E_STRICT on failure
        error_reporting($oldLevel);
        throw $e;
    }
}

public function testTraitOverwritesTraitPropertiesOnConflict()
{
    // Temporarily disable E_STRICT
    $oldLevel = error_reporting();
    error_reporting($oldLevel ^ E_STRICT);

    $trait = 'trait %1$s {
       /**
        * Comes from %1$s
        */
       private $foo;
    }';

    $importer = 'trait %1$s {
       use %2$s;

       /**
        * Comes from %1$s
        */
       private $foo;
    }';

    $traitName    = 'trait' . uniqid();
    $importerName = 'importer' . uniqid();

    eval(sprintf($trait, $traitName));
    eval(sprintf($importer, $importerName, $traitName));

    $importerFoo = new \ReflectionProperty($importerName, 'foo');
    $traitFoo    = new \ReflectionProperty($traitName, 'foo');

    try {
        $this->assertSame(
            $traitFoo->getDocComment(), $importerFoo->getDocComment()
        );
        // reenable E_STRICT on success
        error_reporting($oldLevel);
    } catch (\PHPUnit_Framework_AssertionFailedError $e) {
        // reenabe E_STRICT on failure
        error_reporting($oldLevel);
        throw $e;
    }
}

public function testLastUsedTraitWinsOnConflictingProperties()
{
    // Temporarily disable E_STRICT
    $oldLevel = error_reporting();
    error_reporting($oldLevel ^ E_STRICT);

    $traitA = 'trait %1$s {
       /**
        * Comes from %1$s
        */
       private $foo;
    }';

    $traitB = 'trait %1$s {
       /**
        * Comes from %1$s
        */
       private $foo;
    }';

    $importer = 'class %1$s {
       use %2$s, %3$s; // traitB wins, because it is listed as last trait.

       /**
        * Comes from %1$s
        */
       private $foo;
    }';

    $traitAName    = 'traitA' . uniqid();
    $traitBName    = 'traitB' . uniqid();
    $importerName = 'importer' . uniqid();

    eval(sprintf($traitA, $traitAName));
    eval(sprintf($traitB, $traitBName));
    eval(sprintf($importer, $importerName, $traitAName, $traitBName));

    $importerFoo = new \ReflectionProperty($importerName, 'foo');
    $traitAFoo    = new \ReflectionProperty($traitAName, 'foo');
    $traitBFoo    = new \ReflectionProperty($traitBName, 'foo');

    try {
        $this->assertSame(
            $traitBFoo->getDocComment(), $importerFoo->getDocComment()
        );
        // reenable E_STRICT on success
        error_reporting($oldLevel);
    } catch (\PHPUnit_Framework_AssertionFailedError $e) {
        // reenabe E_STRICT on failure
        error_reporting($oldLevel);
        throw $e;
    }
}


Expected result:
----------------
OK (3 tests, 3 assertions)

Actual result:
--------------
There were 3 failures:

1) Test::testTraitOverwritesClassPropertiesOnConflict
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
 /**
-        * Comes from trait51276de9547be
+        * Comes from importer51276de95480e
         */

/tmp/Test.php:212

2) Test::testTraitOverwritesTraitPropertiesOnConflict
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
 /**
-        * Comes from trait51276de9555e4
+        * Comes from importer51276de955645
         */

/tmp/Test.php:258

3) Test::testLastUsedTraitWinsOnConflictingProperties
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
 /**
-        * Comes from traitB51276de955ef1
+        * Comes from importer51276de955f43
         */

/tmp/Test.php:316

FAILURES!
Tests: 3, Assertions: 3, Failures: 3.



------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=64276&edit=1

Reply via email to