Skip to content

Commit 273731f

Browse files
committed
Add Zend class/interface arginfo stubs
We also change `Generator::throw()` to expect a `Throwable` in the first place, and we now throw a TypeError instead of returning `false` from `Exception::getTraceAsString()`.
1 parent 5c24f80 commit 273731f

15 files changed

+386
-128
lines changed

Zend/tests/generators/throw_not_an_exception.phpt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ $gen->throw(new stdClass);
1212

1313
?>
1414
--EXPECTF--
15-
Fatal error: Uncaught Error: Cannot throw objects that do not implement Throwable in %s:%d
15+
Fatal error: Uncaught TypeError: Generator::throw() expects parameter 1 to be Throwable, object given in %s:%d
1616
Stack trace:
17-
#0 [internal function]: gen()
18-
#1 %s(%d): Generator->throw(Object(stdClass))
19-
#2 {main}
17+
#0 %s(%d): Generator->throw(Object(stdClass))
18+
#1 {main}
2019
thrown in %s on line %d

Zend/zend_closures.c

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "zend_objects.h"
2727
#include "zend_objects_API.h"
2828
#include "zend_globals.h"
29+
#include "zend_closures_arginfo.h"
2930

3031
#define ZEND_CLOSURE_PRINT_NAME "Closure object"
3132

@@ -591,32 +592,12 @@ ZEND_COLD ZEND_METHOD(Closure, __construct)
591592
}
592593
/* }}} */
593594

594-
ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_bindto, 0, 0, 1)
595-
ZEND_ARG_INFO(0, newthis)
596-
ZEND_ARG_INFO(0, newscope)
597-
ZEND_END_ARG_INFO()
598-
599-
ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_bind, 0, 0, 2)
600-
ZEND_ARG_INFO(0, closure)
601-
ZEND_ARG_INFO(0, newthis)
602-
ZEND_ARG_INFO(0, newscope)
603-
ZEND_END_ARG_INFO()
604-
605-
ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_call, 0, 0, 1)
606-
ZEND_ARG_INFO(0, newthis)
607-
ZEND_ARG_VARIADIC_INFO(0, parameters)
608-
ZEND_END_ARG_INFO()
609-
610-
ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_fromcallable, 0, 0, 1)
611-
ZEND_ARG_INFO(0, callable)
612-
ZEND_END_ARG_INFO()
613-
614595
static const zend_function_entry closure_functions[] = {
615-
ZEND_ME(Closure, __construct, NULL, ZEND_ACC_PRIVATE)
616-
ZEND_ME(Closure, bind, arginfo_closure_bind, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
617-
ZEND_MALIAS(Closure, bindTo, bind, arginfo_closure_bindto, ZEND_ACC_PUBLIC)
618-
ZEND_ME(Closure, call, arginfo_closure_call, ZEND_ACC_PUBLIC)
619-
ZEND_ME(Closure, fromCallable, arginfo_closure_fromcallable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
596+
ZEND_ME(Closure, __construct, arginfo_class_Closure___construct, ZEND_ACC_PRIVATE)
597+
ZEND_ME(Closure, bind, arginfo_class_Closure_bind, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
598+
ZEND_MALIAS(Closure, bindTo, bind, arginfo_class_Closure_bindTo, ZEND_ACC_PUBLIC)
599+
ZEND_ME(Closure, call, arginfo_class_Closure_call, ZEND_ACC_PUBLIC)
600+
ZEND_ME(Closure, fromCallable, arginfo_class_Closure_fromCallable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
620601
ZEND_FE_END
621602
};
622603

Zend/zend_closures.stub.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
Class Closure
4+
{
5+
private function __construct() {}
6+
7+
/** @return ?Closure */
8+
static function bind(Closure $closure, ?object $newthis, $newscope = UNKNOWN) {}
9+
10+
/** @return ?Closure */
11+
function bindTo(?object $newthis, $newscope = UNKNOWN) {}
12+
13+
function call(object $newthis, ...$parameters) {}
14+
15+
/** @return Closure */
16+
function fromCallable(callable $callable) {}
17+
}

Zend/zend_closures_arginfo.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* This is a generated file, edit the .stub.php file instead. */
2+
3+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure___construct, 0, 0, 0)
4+
ZEND_END_ARG_INFO()
5+
6+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure_bind, 0, 0, 2)
7+
ZEND_ARG_OBJ_INFO(0, closure, Closure, 0)
8+
ZEND_ARG_TYPE_INFO(0, newthis, IS_OBJECT, 1)
9+
ZEND_ARG_INFO(0, newscope)
10+
ZEND_END_ARG_INFO()
11+
12+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure_bindTo, 0, 0, 1)
13+
ZEND_ARG_TYPE_INFO(0, newthis, IS_OBJECT, 1)
14+
ZEND_ARG_INFO(0, newscope)
15+
ZEND_END_ARG_INFO()
16+
17+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure_call, 0, 0, 1)
18+
ZEND_ARG_TYPE_INFO(0, newthis, IS_OBJECT, 0)
19+
ZEND_ARG_VARIADIC_INFO(0, parameters)
20+
ZEND_END_ARG_INFO()
21+
22+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure_fromCallable, 0, 0, 1)
23+
ZEND_ARG_INFO(0, callable)
24+
ZEND_END_ARG_INFO()

Zend/zend_exceptions.c

Lines changed: 24 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "zend_vm.h"
2828
#include "zend_dtrace.h"
2929
#include "zend_smart_str.h"
30+
#include "zend_exceptions_arginfo.h"
3031

3132
ZEND_API zend_class_entry *zend_ce_throwable;
3233
ZEND_API zend_class_entry *zend_ce_exception;
@@ -631,7 +632,8 @@ ZEND_METHOD(exception, getTraceAsString)
631632

632633
trace = zend_read_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_TRACE), 1, &rv);
633634
if (Z_TYPE_P(trace) != IS_ARRAY) {
634-
RETURN_FALSE;
635+
zend_type_error("trace is not an array");
636+
return;
635637
}
636638
ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) {
637639
if (Z_TYPE_P(frame) != IS_ARRAY) {
@@ -759,14 +761,14 @@ ZEND_METHOD(exception, __toString)
759761

760762
/** {{{ Throwable method definition */
761763
static const zend_function_entry zend_funcs_throwable[] = {
762-
ZEND_ABSTRACT_ME(throwable, getMessage, NULL)
763-
ZEND_ABSTRACT_ME(throwable, getCode, NULL)
764-
ZEND_ABSTRACT_ME(throwable, getFile, NULL)
765-
ZEND_ABSTRACT_ME(throwable, getLine, NULL)
766-
ZEND_ABSTRACT_ME(throwable, getTrace, NULL)
767-
ZEND_ABSTRACT_ME(throwable, getPrevious, NULL)
768-
ZEND_ABSTRACT_ME(throwable, getTraceAsString, NULL)
769-
ZEND_ABSTRACT_ME(throwable, __toString, NULL)
764+
ZEND_ABSTRACT_ME(throwable, getMessage, arginfo_class_Throwable_getMessage)
765+
ZEND_ABSTRACT_ME(throwable, getCode, arginfo_class_Throwable_getCode)
766+
ZEND_ABSTRACT_ME(throwable, getFile, arginfo_class_Throwable_getFile)
767+
ZEND_ABSTRACT_ME(throwable, getLine, arginfo_class_Throwable_getLine)
768+
ZEND_ABSTRACT_ME(throwable, getTrace, arginfo_class_Throwable_getTrace)
769+
ZEND_ABSTRACT_ME(throwable, getPrevious, arginfo_class_Throwable_getPrevious)
770+
ZEND_ABSTRACT_ME(throwable, getTraceAsString, arginfo_class_Throwable_getTraceAsString)
771+
ZEND_ABSTRACT_ME(throwable, __toString, arginfo_class_Throwable___toString)
770772
ZEND_FE_END
771773
};
772774
/* }}} */
@@ -781,39 +783,24 @@ static const zend_function_entry zend_funcs_throwable[] = {
781783
* And never try to change the state of exceptions and never implement anything
782784
* that gives the user anything to accomplish this.
783785
*/
784-
ZEND_BEGIN_ARG_INFO_EX(arginfo_exception___construct, 0, 0, 0)
785-
ZEND_ARG_INFO(0, message)
786-
ZEND_ARG_INFO(0, code)
787-
ZEND_ARG_INFO(0, previous)
788-
ZEND_END_ARG_INFO()
789-
790786
static const zend_function_entry default_exception_functions[] = {
791-
ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
792-
ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC)
793-
ZEND_ME(exception, __wakeup, NULL, ZEND_ACC_PUBLIC)
794-
ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
795-
ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
796-
ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
797-
ZEND_ME(exception, getLine, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
798-
ZEND_ME(exception, getTrace, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
799-
ZEND_ME(exception, getPrevious, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
800-
ZEND_ME(exception, getTraceAsString, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
801-
ZEND_ME(exception, __toString, NULL, 0)
787+
ZEND_ME(exception, __clone, arginfo_class_Exception___clone, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
788+
ZEND_ME(exception, __construct, arginfo_class_Exception___construct, ZEND_ACC_PUBLIC)
789+
ZEND_ME(exception, __wakeup, arginfo_class_Exception___wakeup, ZEND_ACC_PUBLIC)
790+
ZEND_ME(exception, getMessage, arginfo_class_Exception_getMessage, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
791+
ZEND_ME(exception, getCode, arginfo_class_Exception_getCode, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
792+
ZEND_ME(exception, getFile, arginfo_class_Exception_getFile, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
793+
ZEND_ME(exception, getLine, arginfo_class_Exception_getLine, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
794+
ZEND_ME(exception, getTrace, arginfo_class_Exception_getTrace, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
795+
ZEND_ME(exception, getPrevious, arginfo_class_Exception_getPrevious, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
796+
ZEND_ME(exception, getTraceAsString, arginfo_class_Exception_getTraceAsString, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
797+
ZEND_ME(exception, __toString, arginfo_class_Exception___toString, 0)
802798
ZEND_FE_END
803799
};
804800

805-
ZEND_BEGIN_ARG_INFO_EX(arginfo_error_exception___construct, 0, 0, 0)
806-
ZEND_ARG_INFO(0, message)
807-
ZEND_ARG_INFO(0, code)
808-
ZEND_ARG_INFO(0, severity)
809-
ZEND_ARG_INFO(0, filename)
810-
ZEND_ARG_INFO(0, lineno)
811-
ZEND_ARG_INFO(0, previous)
812-
ZEND_END_ARG_INFO()
813-
814801
static const zend_function_entry error_exception_functions[] = {
815-
ZEND_ME(error_exception, __construct, arginfo_error_exception___construct, ZEND_ACC_PUBLIC)
816-
ZEND_ME(error_exception, getSeverity, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
802+
ZEND_ME(error_exception, __construct, arginfo_class_ErrorException___construct, ZEND_ACC_PUBLIC)
803+
ZEND_ME(error_exception, getSeverity, arginfo_class_ErrorException_getSeverity, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
817804
ZEND_FE_END
818805
};
819806
/* }}} */

Zend/zend_exceptions.stub.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
interface Throwable
4+
{
5+
/** @return string */
6+
function getMessage();
7+
8+
/** @return int */
9+
function getCode();
10+
11+
/** @return string */
12+
function getFile();
13+
14+
/** @return int */
15+
function getLine();
16+
17+
/** @return array */
18+
function getTrace();
19+
20+
/** @return ?Throwable */
21+
function getPrevious();
22+
23+
/** @return string */
24+
function getTraceAsString();
25+
26+
/** @return string */
27+
function __toString();
28+
}
29+
30+
class Exception implements Throwable
31+
{
32+
final private function __clone() {}
33+
34+
function __construct(string $message = UNKNOWN, int $code = 0, ?Throwable $previous = null) {}
35+
36+
function __wakeup() {}
37+
38+
/** @return string */
39+
final function getMessage() {}
40+
41+
/** @return int */
42+
final function getCode() {}
43+
44+
/** @return string */
45+
final function getFile() {}
46+
47+
/** @return int */
48+
final function getLine() {}
49+
50+
/** @return array */
51+
final function getTrace() {}
52+
53+
/** @return ?Throwable */
54+
final function getPrevious() {}
55+
56+
/** @return string */
57+
final function getTraceAsString() {}
58+
59+
/** @return string */
60+
function __toString() {}
61+
}
62+
63+
class ErrorException extends Exception
64+
{
65+
function __construct(string $message = UNKNOWN, int $code = 0, int $severity = E_ERROR, string $filename = UNKNOWN, int $lineno = 0, ?Throwable $previous = null) {}
66+
67+
final function getSeverity() {}
68+
}

Zend/zend_exceptions_arginfo.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* This is a generated file, edit the .stub.php file instead. */
2+
3+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Throwable_getMessage, 0, 0, 0)
4+
ZEND_END_ARG_INFO()
5+
6+
#define arginfo_class_Throwable_getCode arginfo_class_Throwable_getMessage
7+
8+
#define arginfo_class_Throwable_getFile arginfo_class_Throwable_getMessage
9+
10+
#define arginfo_class_Throwable_getLine arginfo_class_Throwable_getMessage
11+
12+
#define arginfo_class_Throwable_getTrace arginfo_class_Throwable_getMessage
13+
14+
#define arginfo_class_Throwable_getPrevious arginfo_class_Throwable_getMessage
15+
16+
#define arginfo_class_Throwable_getTraceAsString arginfo_class_Throwable_getMessage
17+
18+
#define arginfo_class_Throwable___toString arginfo_class_Throwable_getMessage
19+
20+
#define arginfo_class_Exception___clone arginfo_class_Throwable_getMessage
21+
22+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Exception___construct, 0, 0, 0)
23+
ZEND_ARG_TYPE_INFO(0, message, IS_STRING, 0)
24+
ZEND_ARG_TYPE_INFO(0, code, IS_LONG, 0)
25+
ZEND_ARG_OBJ_INFO(0, previous, Throwable, 1)
26+
ZEND_END_ARG_INFO()
27+
28+
#define arginfo_class_Exception___wakeup arginfo_class_Throwable_getMessage
29+
30+
#define arginfo_class_Exception_getMessage arginfo_class_Throwable_getMessage
31+
32+
#define arginfo_class_Exception_getCode arginfo_class_Throwable_getMessage
33+
34+
#define arginfo_class_Exception_getFile arginfo_class_Throwable_getMessage
35+
36+
#define arginfo_class_Exception_getLine arginfo_class_Throwable_getMessage
37+
38+
#define arginfo_class_Exception_getTrace arginfo_class_Throwable_getMessage
39+
40+
#define arginfo_class_Exception_getPrevious arginfo_class_Throwable_getMessage
41+
42+
#define arginfo_class_Exception_getTraceAsString arginfo_class_Throwable_getMessage
43+
44+
#define arginfo_class_Exception___toString arginfo_class_Throwable_getMessage
45+
46+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ErrorException___construct, 0, 0, 0)
47+
ZEND_ARG_TYPE_INFO(0, message, IS_STRING, 0)
48+
ZEND_ARG_TYPE_INFO(0, code, IS_LONG, 0)
49+
ZEND_ARG_TYPE_INFO(0, severity, IS_LONG, 0)
50+
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
51+
ZEND_ARG_TYPE_INFO(0, lineno, IS_LONG, 0)
52+
ZEND_ARG_OBJ_INFO(0, previous, Throwable, 1)
53+
ZEND_END_ARG_INFO()
54+
55+
#define arginfo_class_ErrorException_getSeverity arginfo_class_Throwable_getMessage

Zend/zend_generators.c

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "zend_exceptions.h"
2424
#include "zend_generators.h"
2525
#include "zend_closures.h"
26+
#include "zend_generators_arginfo.h"
2627

2728
ZEND_API zend_class_entry *zend_ce_generator;
2829
ZEND_API zend_class_entry *zend_ce_ClosedGeneratorException;
@@ -1007,7 +1008,7 @@ ZEND_METHOD(Generator, throw)
10071008
zend_generator *generator;
10081009

10091010
ZEND_PARSE_PARAMETERS_START(1, 1)
1010-
Z_PARAM_ZVAL(exception)
1011+
Z_PARAM_OBJECT_OF_CLASS(exception, zend_ce_throwable);
10111012
ZEND_PARSE_PARAMETERS_END();
10121013

10131014
Z_TRY_ADDREF_P(exception);
@@ -1172,26 +1173,15 @@ zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *ob
11721173
}
11731174
/* }}} */
11741175

1175-
ZEND_BEGIN_ARG_INFO(arginfo_generator_void, 0)
1176-
ZEND_END_ARG_INFO()
1177-
1178-
ZEND_BEGIN_ARG_INFO_EX(arginfo_generator_send, 0, 0, 1)
1179-
ZEND_ARG_INFO(0, value)
1180-
ZEND_END_ARG_INFO()
1181-
1182-
ZEND_BEGIN_ARG_INFO_EX(arginfo_generator_throw, 0, 0, 1)
1183-
ZEND_ARG_INFO(0, exception)
1184-
ZEND_END_ARG_INFO()
1185-
11861176
static const zend_function_entry generator_functions[] = {
1187-
ZEND_ME(Generator, rewind, arginfo_generator_void, ZEND_ACC_PUBLIC)
1188-
ZEND_ME(Generator, valid, arginfo_generator_void, ZEND_ACC_PUBLIC)
1189-
ZEND_ME(Generator, current, arginfo_generator_void, ZEND_ACC_PUBLIC)
1190-
ZEND_ME(Generator, key, arginfo_generator_void, ZEND_ACC_PUBLIC)
1191-
ZEND_ME(Generator, next, arginfo_generator_void, ZEND_ACC_PUBLIC)
1192-
ZEND_ME(Generator, send, arginfo_generator_send, ZEND_ACC_PUBLIC)
1193-
ZEND_ME(Generator, throw, arginfo_generator_throw, ZEND_ACC_PUBLIC)
1194-
ZEND_ME(Generator, getReturn,arginfo_generator_void, ZEND_ACC_PUBLIC)
1177+
ZEND_ME(Generator, rewind, arginfo_class_Generator_rewind, ZEND_ACC_PUBLIC)
1178+
ZEND_ME(Generator, valid, arginfo_class_Generator_valid, ZEND_ACC_PUBLIC)
1179+
ZEND_ME(Generator, current, arginfo_class_Generator_current, ZEND_ACC_PUBLIC)
1180+
ZEND_ME(Generator, key, arginfo_class_Generator_key, ZEND_ACC_PUBLIC)
1181+
ZEND_ME(Generator, next, arginfo_class_Generator_next, ZEND_ACC_PUBLIC)
1182+
ZEND_ME(Generator, send, arginfo_class_Generator_send, ZEND_ACC_PUBLIC)
1183+
ZEND_ME(Generator, throw, arginfo_class_Generator_throw, ZEND_ACC_PUBLIC)
1184+
ZEND_ME(Generator, getReturn,arginfo_class_Generator_getReturn, ZEND_ACC_PUBLIC)
11951185
ZEND_FE_END
11961186
};
11971187

Zend/zend_generators.stub.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
final class Generator implements Iterator
4+
{
5+
function rewind(): void {}
6+
7+
function valid(): bool {}
8+
9+
function current() {}
10+
11+
function key() {}
12+
13+
function next(): void {}
14+
15+
function send($value) {}
16+
17+
function throw(Throwable $exception) {}
18+
19+
function getReturn() {}
20+
}

0 commit comments

Comments
 (0)