-
Notifications
You must be signed in to change notification settings - Fork 7.9k
adds support for DNF types in internal functions and properties #11969
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
Merged
Merged
Changes from 12 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
fedfc72
adds failing test case for #10120
ju1ius 25db0dd
adds support for DNF types in internal functions and properties
ju1ius e076543
adds workaround for #11883
ju1ius 3c9c292
makes _ZEND_TYPE_NAME_BIT and _ZEND_TYPE_LITERAL_NAME_BIT exclusive
ju1ius 02ee5f7
addresses PR comments
ju1ius b9cebe9
properly releases memory for dynamic property type
ju1ius 39e62c2
don't zet _ZEND_TYPE_NAME_BIT for union types
ju1ius 9748f30
addresses PR comments
ju1ius 92284c7
fixup! properly releases memory for dynamic property type
ju1ius 36b86e7
adds a method to test union type arginfo registration
ju1ius d948c74
removes workarounds for #11883
ju1ius 6866898
fixes wrong arginfo.h hash after rebase
ju1ius 71f1b66
adds zend_ prefix to normalize_internal_type
ju1ius e8c5abf
passes the module type to register_dynamic_function_entries()
ju1ius File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -884,11 +884,115 @@ static void le_throwing_resource_dtor(zend_resource *rsrc) | |
zend_throw_exception(NULL, "Throwing resource destructor called", 0); | ||
} | ||
|
||
static ZEND_METHOD(_ZendTestClass, takesUnionType) | ||
{ | ||
zend_object *obj; | ||
ZEND_PARSE_PARAMETERS_START(1, 1); | ||
Z_PARAM_OBJ(obj) | ||
ZEND_PARSE_PARAMETERS_END(); | ||
// we have to perform type-checking to avoid arginfo/zpp mismatch error, | ||
bool type_matches = ( | ||
instanceof_function(obj->ce, zend_standard_class_def) | ||
|| | ||
instanceof_function(obj->ce, zend_ce_iterator) | ||
); | ||
if (!type_matches) { | ||
zend_string *ty = zend_type_to_string(execute_data->func->internal_function.arg_info->type); | ||
zend_argument_type_error(1, "must be of type %s, %s given", ty->val, obj->ce->name->val); | ||
zend_string_release(ty); | ||
RETURN_THROWS(); | ||
} | ||
|
||
RETURN_NULL(); | ||
} | ||
|
||
// Returns a newly allocated DNF type `Iterator|(Traversable&Countable)`. | ||
// | ||
// We need to generate it "manually" because gen_stubs.php does not support codegen for DNF types ATM. | ||
static zend_type create_test_dnf_type(void) { | ||
kocsismate marked this conversation as resolved.
Show resolved
Hide resolved
|
||
zend_string *class_Iterator = zend_string_init_interned("Iterator", sizeof("Iterator") - 1, true); | ||
zend_alloc_ce_cache(class_Iterator); | ||
zend_string *class_Traversable = ZSTR_KNOWN(ZEND_STR_TRAVERSABLE); | ||
zend_string *class_Countable = zend_string_init_interned("Countable", sizeof("Countable") - 1, true); | ||
zend_alloc_ce_cache(class_Countable); | ||
// | ||
zend_type_list *intersection_list = malloc(ZEND_TYPE_LIST_SIZE(2)); | ||
intersection_list->num_types = 2; | ||
intersection_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(class_Traversable, 0, 0); | ||
intersection_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(class_Countable, 0, 0); | ||
zend_type_list *union_list = malloc(ZEND_TYPE_LIST_SIZE(2)); | ||
union_list->num_types = 2; | ||
union_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(class_Iterator, 0, 0); | ||
union_list->types[1] = (zend_type) ZEND_TYPE_INIT_INTERSECTION(intersection_list, 0); | ||
return (zend_type) ZEND_TYPE_INIT_UNION(union_list, 0); | ||
} | ||
|
||
static void register_ZendTestClass_dnf_property(zend_class_entry *ce) { | ||
zend_string *prop_name = zend_string_init_interned("dnfProperty", sizeof("dnfProperty") - 1, true); | ||
zval default_value; | ||
ZVAL_UNDEF(&default_value); | ||
zend_type type = create_test_dnf_type(); | ||
zend_declare_typed_property(ce, prop_name, &default_value, ZEND_ACC_PUBLIC, NULL, type); | ||
} | ||
|
||
// arg_info for `zend_test_internal_dnf_arguments` | ||
// The types are upgraded to DNF types in `register_dynamic_function_entries()` | ||
static zend_internal_arg_info arginfo_zend_test_internal_dnf_arguments[] = { | ||
{(const char*)(uintptr_t)(1), {0}, NULL}, // return-type | ||
{"arg", {0}, NULL} | ||
}; | ||
|
||
static ZEND_NAMED_FUNCTION(zend_test_internal_dnf_arguments) | ||
{ | ||
zend_object *obj; | ||
ZEND_PARSE_PARAMETERS_START(1, 1); | ||
Z_PARAM_OBJ(obj) | ||
ZEND_PARSE_PARAMETERS_END(); | ||
// we have to perform type-checking to avoid arginfo/zpp mismatch error, | ||
bool type_matches = ( | ||
instanceof_function(obj->ce, zend_ce_iterator) | ||
|| ( | ||
instanceof_function(obj->ce, zend_ce_traversable) | ||
&& instanceof_function(obj->ce, zend_ce_countable) | ||
) | ||
); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if it makes sense to provide an API to parse a param from a zend_type, but that's unrelated to this. :) |
||
if (!type_matches) { | ||
zend_string *ty = zend_type_to_string(arginfo_zend_test_internal_dnf_arguments[1].type); | ||
zend_argument_type_error(1, "must be of type %s, %s given", ty->val, obj->ce->name->val); | ||
zend_string_release(ty); | ||
RETURN_THROWS(); | ||
} | ||
|
||
RETURN_OBJ_COPY(obj); | ||
} | ||
|
||
static const zend_function_entry dynamic_function_entries[] = { | ||
{ | ||
.fname = "zend_test_internal_dnf_arguments", | ||
.handler = zend_test_internal_dnf_arguments, | ||
.arg_info = arginfo_zend_test_internal_dnf_arguments, | ||
.num_args = 1, | ||
.flags = 0, | ||
}, | ||
ZEND_FE_END, | ||
}; | ||
|
||
static void register_dynamic_function_entries(void) { | ||
// return-type is at index 0 | ||
arginfo_zend_test_internal_dnf_arguments[0].type = create_test_dnf_type(); | ||
arginfo_zend_test_internal_dnf_arguments[1].type = create_test_dnf_type(); | ||
ju1ius marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// | ||
zend_register_functions(NULL, dynamic_function_entries, NULL, MODULE_PERSISTENT); | ||
} | ||
|
||
PHP_MINIT_FUNCTION(zend_test) | ||
{ | ||
register_dynamic_function_entries(); | ||
|
||
zend_test_interface = register_class__ZendTestInterface(); | ||
|
||
zend_test_class = register_class__ZendTestClass(zend_test_interface); | ||
register_ZendTestClass_dnf_property(zend_test_class); | ||
zend_test_class->create_object = zend_test_class_new; | ||
zend_test_class->get_static_method = zend_test_class_static_method_get; | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
--TEST-- | ||
DNF types for internal functions | ||
--EXTENSIONS-- | ||
zend_test | ||
spl | ||
reflection | ||
--FILE-- | ||
<?php | ||
|
||
$rf = new \ReflectionFunction('zend_test_internal_dnf_arguments'); | ||
var_dump((string)$rf->getReturnType()); | ||
$paramType = $rf->getParameters()[0]->getType(); | ||
var_dump((string)$paramType); | ||
|
||
try { | ||
zend_test_internal_dnf_arguments(new stdClass); | ||
} catch (\Throwable $err) { | ||
echo $err->getMessage(), "\n"; | ||
} | ||
|
||
$obj = new \ArrayIterator([]); | ||
$result = zend_test_internal_dnf_arguments($obj); | ||
var_dump($result); | ||
|
||
?> | ||
--EXPECT-- | ||
string(32) "Iterator|(Traversable&Countable)" | ||
string(32) "Iterator|(Traversable&Countable)" | ||
zend_test_internal_dnf_arguments(): Argument #1 ($arg) must be of type Iterator|(Traversable&Countable), stdClass given | ||
object(ArrayIterator)#5 (1) { | ||
["storage":"ArrayIterator":private]=> | ||
array(0) { | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.