-
Notifications
You must be signed in to change notification settings - Fork 7.7k
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
Add ReflectionReference::getRefcount() #4380
Conversation
And don't return null for rc=1 references. Leave it to the user to decide whether or not they want to consider these as references or not.
Good idea, I'll try this once it's merged! (I'm using devilbox-php-fpm-7-4 to run my experiments :) ) |
Merged as 428cfdd. Please report back if there's issues ... we still have time to change the design here :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to have ReflectionReference NOT increase the refcount?
We could just snapshot Z_REF(intern->obj)
when creating the instance?
Yes, this could mean that you could snapshot, destroy the ref, and still use the ReflectionReference.
But I think that's OK, at least better than the other unexpected side-effect described in https://bugs.php.net/77951
@@ -6190,7 +6190,7 @@ ZEND_METHOD(reflection_reference, fromArrayElement) | |||
} | |||
|
|||
/* Treat singleton reference as non-reference. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this line should be removed too :)
It's possible, but I think having a ReflectionReference that refers to a no longer existing reference may be rather unexpected. For example there may then be two ReflectionReference instances returning the same ID (one of them referring to a dead reference whose address was reused). It would also preclude future API extensions that need to access the contents of the reference. I think that once again it is better to leave this choice to the user -- if they don't want the ReflectionReference to hold the reference, destroy it. More or less do
What is the unexpected side-effect? (Edit: Ah okay, I see what you mean.) |
I get that but I fail to see where this could matter: one doesn't inspect structures and destroys them at the same time. See e.g.
I think that's not a desired extension: when you create the reflector, you DO have access to both the reference and its value. If one wants to do something with them, one should just keep them around. Having them in the reflector too wouldn't open anything not doable without. |
I meant value here in a more general sense as in everything part of the reference (which is the value itself, the refcount, referenced typed properties and some GC information). This is already a problem with the From my perspective keeping hold of the reference is both more consistent overall and more powerful in what can be done -- it gives you both the option of tracking current state (keep ReflectionReference and query later) or getting the state at construction (query state and discard ReflectionReference). |
Here is my trouble: $a = [0, 1];
foreach ($a as &$v) {
}
$a[] = &$v;
$b = [];
$b[] = &$b;
$a[] = $b;
unset($b);
var_dump(ReflectionReference::fromArrayElement($a, 0)->getRefcount());
var_dump(ReflectionReference::fromArrayElement($a[3], 0)->getRefcount());
$b = $a;
$b[0] = 123;
var_dump($a[0]); // echoes int(0)
$b = $a[3];
$b[0] = 123;
var_dump($a[3][0]); // echoes int(123) Apparently, both refs have the same refcount, but they behave differently. How do I differentiate both, without modifying an array copy, which is incompatible with typed properties? |
I managed to detect the situation by mutating the ref when it is an array with refcount=1 |
@nicolas-grekas Took me a while to understand this ... turns out we have a special-case for exactly that case in place here: Lines 1968 to 1970 in 92d6720
I'm not sure what to do about this. I don't think it should fall to you to detect this hack, and it might not work in the future (typed arrays). Thanks to the |
For typed arrays, maybe they would be implemented as objects, so this wouldn't affect the
that would make sense to me, because this is really unexpected (from the pov of ReflectionReference), and while I have a test case that reminds me about this, many will not know and fall into the trap. |
And don't return null for rc=1 references. Leave it to the user to decide whether or not they want to consider these as references or not.
This is for https://bugs.php.net/bug.php?id=78263. /cc @nicolas-grekas