xref: /PHP-7.4/Zend/tests/closure_041.phpt (revision 28cf0807)
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); $d(); echo "\n";
52// $d is still non-static
53$d->bindTo($d);
54
55echo "After binding, with same-class instance for the bound ones", "\n";
56$d = $staticUnscoped->bindTo(new A);
57$d = $nonstaticUnscoped->bindTo(new A); $d(); echo " (should be scoped to dummy class)\n";
58$d = $staticScoped->bindTo(new A);
59$d = $nonstaticScoped->bindTo(new A); $d(); echo "\n";
60
61echo "After binding, with different instance for the bound ones", "\n";
62$d = $nonstaticUnscoped->bindTo(new B); $d(); echo " (should be scoped to dummy class)\n";
63$d = $nonstaticScoped->bindTo(new B); $d(); echo "\n";
64
65echo "Done.\n";
66--EXPECTF--
67Before binding
68scoped to A: bool(false)
69bound: no
70scoped to A: bool(false)
71bound: no
72scoped to A: bool(true)
73bound: no
74scoped to A: bool(true)
75bound: A
76After binding, no instance
77scoped to A: bool(false)
78bound: no
79scoped to A: bool(false)
80bound: no
81scoped to A: bool(true)
82bound: no
83
84Deprecated: Unbinding $this of closure is deprecated in %s on line %d
85scoped to A: bool(true)
86bound: no
87After binding, with same-class instance for the bound ones
88
89Warning: Cannot bind an instance to a static closure in %s on line %d
90scoped to A: bool(false)
91bound: A (should be scoped to dummy class)
92
93Warning: Cannot bind an instance to a static closure in %s on line %d
94scoped to A: bool(true)
95bound: A
96After binding, with different instance for the bound ones
97scoped to A: bool(false)
98bound: B (should be scoped to dummy class)
99scoped to A: bool(true)
100bound: B
101Done.
102