Skip to content

Property hooks cause an infinite recursion in traits #15240

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dlsrc opened this issue Aug 5, 2024 · 1 comment · Fixed by #15245
Closed

Property hooks cause an infinite recursion in traits #15240

dlsrc opened this issue Aug 5, 2024 · 1 comment · Fixed by #15245

Comments

@dlsrc
Copy link

dlsrc commented Aug 5, 2024

Description

If I put the hook code in a class, everything works as expected:

<?php

class TestClass {
    public int $foo {
        set(int $foo) {
            if ($foo > 10) {
                $this->foo = 10;
            }
            elseif ($foo < 1) {
                $this->foo = 1;
            }
            else {
                $this->foo = $foo;
            }
        }
    }

    public function __construct() {
        $this->foo = 1;
    }

    public function __toString() {
        return (string) $this->foo;
    }
}

$test = new TestClass;
$test->foo = 400;
print $test;

Result is:

10

Ok.
But if I need to use a trait:

<?php

trait TestTrait {
    public int $foo {
        set(int $foo) {
            if ($foo > 10) {
                $this->foo = 10;
            }
            elseif ($foo < 1) {
                $this->foo = 1;
            }
            else {
                $this->foo = $foo;
            }
        }
    }
}

class TestClass {
    use TestTrait;

    public function __construct() {
        $this->foo = 1;
    }

    public function __toString() {
        return (string) $this->foo;
    }
}

$test = new TestClass;
$test->foo = 400;
print $test;

Resulted in this output:

PHP Fatal error:  Uncaught Error: Maximum call stack size of 8339456 bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? in /var/www/hosts/pub/tests/test.php:5
#0 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
#1 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
#2 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
#3 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
#4 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
#5 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
.
.
.
#9815 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
#9816 /var/www/hosts/pub/tests/test.php(37): TestClass->$foo::set()
#9817 /var/www/hosts/pub/tests/test.php(45): TestClass->__construct()
#9818 {main}
  thrown in /var/www/hosts/pub/tests/test.php on line 5

But I expected this output instead:

10

PHP Version

PHP 8.4.0alpha4

Operating System

RHEL9 and Windows10

@iluuu1994
Copy link
Member

Thank you for the report. Minimal reproducer:

trait T {
    public $prop {
        set => $value;
    }
}

class C {
    use T;
}

$c = new C;
$c->prop = 42;
var_dump($c->prop);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants