xref: /PHP-8.2/Zend/tests/closure_041.phpt (revision 7aacc705)
1--TEST--
2Closure 041: Rebinding: preservation of previous scope when not given as arg unless impossible
3--FILE--
4<?php
5
6/* It's impossible to preserve the previous scope when doing so would break
7 * the invariants that, for non-static closures, having a scope is equivalent
8 * to having a bound instance. */
9
10$staticUnscoped = static function () {
11    echo "scoped to A: "; var_dump(isset(A::$priv));
12    echo "bound: ", isset($this)?get_class($this):"no";
13};
14
15$nonstaticUnscoped = function () {
16    echo "scoped to A: "; var_dump(isset(A::$priv));
17    echo "bound: ", isset($this)?get_class($this):"no";
18};
19
20class A {
21    private static $priv = 7;
22    function getClosure() {
23        return function () {
24            echo "scoped to A: "; var_dump(isset(A::$priv));
25            echo "bound: ", isset($this)?get_class($this):"no";
26        };
27    }
28    function getStaticClosure() {
29        return static function () {
30            echo "scoped to A: "; var_dump(isset(A::$priv));
31            echo "bound: ", isset($this)?get_class($this):"no";
32        };
33    }
34}
35class B extends A {}
36
37$a = new A();
38$staticScoped = $a->getStaticClosure();
39$nonstaticScoped = $a->getClosure();
40
41echo "Before binding", "\n";
42$staticUnscoped(); echo "\n";
43$nonstaticUnscoped(); echo "\n";
44$staticScoped(); echo "\n";
45$nonstaticScoped(); echo "\n";
46
47echo "After binding, no instance", "\n";
48$d = $staticUnscoped->bindTo(null); $d(); echo "\n";
49$d = $nonstaticUnscoped->bindTo(null); $d(); echo "\n";
50$d = $staticScoped->bindTo(null); $d(); echo "\n";
51$d = $nonstaticScoped->bindTo(null); var_dump($d); echo "\n";
52
53echo "After binding, with same-class instance for the bound ones", "\n";
54$d = $staticUnscoped->bindTo(new A);
55$d = $nonstaticUnscoped->bindTo(new A); $d(); echo " (should be scoped to dummy class)\n";
56$d = $staticScoped->bindTo(new A);
57$d = $nonstaticScoped->bindTo(new A); $d(); echo "\n";
58
59echo "After binding, with different instance for the bound ones", "\n";
60$d = $nonstaticUnscoped->bindTo(new B); $d(); echo " (should be scoped to dummy class)\n";
61$d = $nonstaticScoped->bindTo(new B); $d(); echo "\n";
62
63echo "Done.\n";
64?>
65--EXPECTF--
66Before binding
67scoped to A: bool(false)
68bound: no
69scoped to A: bool(false)
70bound: no
71scoped to A: bool(true)
72bound: no
73scoped to A: bool(true)
74bound: A
75After binding, no instance
76scoped to A: bool(false)
77bound: no
78scoped to A: bool(false)
79bound: no
80scoped to A: bool(true)
81bound: no
82
83Warning: Cannot unbind $this of closure using $this in %s on line %d
84NULL
85
86After binding, with same-class instance for the bound ones
87
88Warning: Cannot bind an instance to a static closure in %s on line %d
89scoped to A: bool(false)
90bound: A (should be scoped to dummy class)
91
92Warning: Cannot bind an instance to a static closure in %s on line %d
93scoped to A: bool(true)
94bound: A
95After binding, with different instance for the bound ones
96scoped to A: bool(false)
97bound: B (should be scoped to dummy class)
98scoped to A: bool(true)
99bound: B
100Done.
101