Skip to content

Commit 3fe1b9f

Browse files
committed
Fix staticness inference
1 parent 0da4e6f commit 3fe1b9f

File tree

9 files changed

+187
-4
lines changed

9 files changed

+187
-4
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
PFA of static method is static
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public static function f($a) {
8+
var_dump($a);
9+
}
10+
}
11+
12+
$f = C::f(?);
13+
echo new ReflectionFunction($f), "\n";
14+
$f(1);
15+
16+
$f = (new C)->f(?);
17+
echo new ReflectionFunction($f), "\n";
18+
$f(1);
19+
20+
// Warns
21+
var_dump($f->bindTo(new C));
22+
23+
?>
24+
--EXPECTF--
25+
Closure [ <user> static public method {closure:pfa:%s:9} ] {
26+
@@ %s 9 - 9
27+
28+
- Parameters [1] {
29+
Parameter #0 [ <required> $a ]
30+
}
31+
}
32+
33+
int(1)
34+
Closure [ <user> static public method {closure:pfa:%s:13} ] {
35+
@@ %s 13 - 13
36+
37+
- Parameters [1] {
38+
Parameter #0 [ <required> $a ]
39+
}
40+
}
41+
42+
int(1)
43+
44+
Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d
45+
NULL
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
PFA of instance method is not static
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public function f($a) {
8+
var_dump($this, $this === $a);
9+
}
10+
}
11+
12+
$c = new C();
13+
$f = $c->f(?);
14+
echo new ReflectionFunction($f), "\n";
15+
$f($c);
16+
17+
$c2 = new C();
18+
$f->bindTo($c2)($c2);
19+
20+
?>
21+
--EXPECTF--
22+
Closure [ <user> public method {closure:pfa:%s:10} ] {
23+
@@ %s 10 - 10
24+
25+
- Parameters [1] {
26+
Parameter #0 [ <required> $a ]
27+
}
28+
}
29+
30+
object(C)#%d (0) {
31+
}
32+
bool(true)
33+
object(C)#%d (0) {
34+
}
35+
bool(true)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
PFA of standalone function is static
3+
--FILE--
4+
<?php
5+
6+
function f($a) {
7+
var_dump($a);
8+
}
9+
10+
$f = f(?);
11+
echo new ReflectionFunction($f), "\n";
12+
$f(1);
13+
14+
// Warns
15+
var_dump($f->bindTo(new class {}));
16+
17+
?>
18+
--EXPECTF--
19+
Closure [ <user> static function {closure:pfa:%s:7} ] {
20+
@@ %s 7 - 7
21+
22+
- Parameters [1] {
23+
Parameter #0 [ <required> $a ]
24+
}
25+
}
26+
27+
int(1)
28+
29+
Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d
30+
NULL
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
PFA of non-static closure is not static
3+
--FILE--
4+
<?php
5+
6+
$c = function ($a) {
7+
try {
8+
var_dump($this, $this === $a);
9+
} catch (Error $e) {
10+
var_dump(null, false);
11+
}
12+
};
13+
14+
$f = $c(?);
15+
echo new ReflectionFunction($f), "\n";
16+
$f($c);
17+
18+
$c2 = new class {};
19+
$f->bindTo($c2)($c2);
20+
21+
?>
22+
--EXPECT--
23+
Closure [ <user> function {closure:pfa:%s:11} ] {
24+
@@ %s 11 - 11
25+
26+
- Bound Variables [1] {
27+
Variable #0 [ $fn ]
28+
}
29+
30+
- Parameters [1] {
31+
Parameter #0 [ <required> $a ]
32+
}
33+
}
34+
35+
NULL
36+
bool(false)
37+
object(class@anonymous)#3 (0) {
38+
}
39+
bool(true)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
PFA of static closure is static
3+
--FILE--
4+
<?php
5+
6+
$c = static function ($a) {
7+
var_dump($a);
8+
};
9+
10+
$f = $c(?);
11+
echo new ReflectionFunction($f), "\n";
12+
$f(1);
13+
14+
// Warns
15+
var_dump($f->bindTo(new class {}));
16+
17+
?>
18+
--EXPECTF--
19+
Closure [ <user> static function {closure:pfa:%s:7} ] {
20+
@@ %s 7 - 7
21+
22+
- Bound Variables [1] {
23+
Variable #0 [ $fn ]
24+
}
25+
26+
- Parameters [1] {
27+
Parameter #0 [ <required> $a ]
28+
}
29+
}
30+
31+
int(1)
32+
33+
Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d
34+
NULL
File renamed without changes.
File renamed without changes.
File renamed without changes.

Zend/zend_partial.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@
5454

5555
#define Z_IS_PLACEHOLDER_P(p) (Z_TYPE_P(p) == _IS_PLACEHOLDER)
5656

57-
static zend_always_inline bool zp_is_static_closure(const zend_function *function) {
58-
return ((function->common.fn_flags & (ZEND_ACC_STATIC|ZEND_ACC_CLOSURE)) == (ZEND_ACC_STATIC|ZEND_ACC_CLOSURE));
57+
static zend_always_inline bool zp_is_non_static_closure(const zend_function *function) {
58+
return ((function->common.fn_flags & (ZEND_ACC_STATIC|ZEND_ACC_CLOSURE)) == ZEND_ACC_CLOSURE);
5959
}
6060

6161
static zend_never_inline ZEND_COLD void zp_args_underflow(
@@ -965,7 +965,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
965965
NULL, params_ast, lexical_vars_ast, stmts_ast,
966966
return_type_ast, attributes_ast);
967967

968-
if (Z_TYPE_P(this_ptr) != IS_OBJECT || zp_is_static_closure(function)) {
968+
if (Z_TYPE_P(this_ptr) != IS_OBJECT && !zp_is_non_static_closure(function)) {
969969
((zend_ast_decl*)closure_ast)->flags |= ZEND_ACC_STATIC;
970970
}
971971

@@ -1116,7 +1116,7 @@ void zend_partial_create(zval *result, zval *this_ptr, zend_function *function,
11161116
called_scope = Z_CE_P(this_ptr);
11171117
}
11181118

1119-
if (Z_TYPE_P(this_ptr) == IS_OBJECT && !zp_is_static_closure(function)) {
1119+
if (Z_TYPE_P(this_ptr) == IS_OBJECT && !zp_is_non_static_closure(function)) {
11201120
ZVAL_COPY_VALUE(&object, this_ptr);
11211121
} else {
11221122
ZVAL_UNDEF(&object);

0 commit comments

Comments
 (0)