Hi Josh,

I'd recommend looking at https://github.com/php/php-src/pull/5156 (linked to in 
your RFC's reference) when implementing this PR.
Additionally, I didn't see if this was brought up - PHP already has a class 
which is falsifiable - SimpleXMLElement.

You can see the source of ext/simplexml/simplexml.c for `_IS_BOOL`

```
static int sxe_object_cast_ex(zend_object *readobj, zval *writeobj, int type)
{
        php_sxe_object *sxe;
        xmlChar        *contents = NULL;
        xmlNodePtr          node;
        int rv;

        sxe = php_sxe_fetch_object(readobj);

        if (type == _IS_BOOL) {
                node = php_sxe_get_first_node(sxe, NULL);
                if (node) {
                        ZVAL_TRUE(writeobj);
                } else {
                        ZVAL_BOOL(writeobj, !sxe_prop_is_empty(readobj));
                }
                return SUCCESS;
        }
```

```
static php_sxe_object* php_sxe_object_new(zend_class_entry *ce, zend_function 
*fptr_count)
        intern->zo.handlers = &sxe_object_handlers;
// ... elsewhere in ext/simplexml/simplexml.c
        sxe_object_handlers.cast_object = sxe_object_cast;
```

The default handlers would be overridden, so this would probably need to fall 
back to the original handlers for types other than bool.
Also, this might need to copy all of the handlers from the parent class entry's 
zend_object_handlers,
to meet the expected behavior of other cast types and other magic behaviors 
from SimpleXMLElement and other classes continuing to work.

>From the perspective of static analysis, a few things to note:
- Static analyzers such as psalm/phan currently deliberately don't bother 
handling the possibility that `object` can be false even after it was checked 
for falsiness.
  There's hundreds of other things that could be implemented, and adding the 
special casing and performance overhead checking for FFI objects and 
SimpleXMLElement, subclasses of those is currently low priority compared to 
those things.

  Code using SimpleXMLElement/FFI is generally limited to a few files in 
practice.

  Definitely possible for analyzers to support this for known base classes, 
though, and the priority would increase if the RFC passed.

  I am a maintainer of Phan.
- For BC reasons, internal data structures such as ArrayObject probably 
wouldn't get changed in any php release
   (e.g. could break code using falsiness check instead of null check).
   So this might lead to inconsistencies with newer extensions if half of the 
data structures treat emptiness as false and half don't.
- This feature may end up getting adopted in cases where it's convenient but 
turns out prone to accidental bugs and later is deprecated and removed.
  For example, 
https://stackoverflow.com/questions/25031236/if-elem-vs-elem-is-not-none was 
seen in python

  (e.g. `if (!$this->resultSetObject) { $this->resultSetObject = 
slow_db_operation(); }`
  would not behave the way people would previously expect for most objects 
(executed repeatedly instead of once))

```
<?php
function test(SimpleXMLElement $e) {
    // False positive RedundantCondition in psalm
    if ($e) {
    }
}
``` 

> And I don’t know of a way to add an interface to new stdClass() - but thought 
> this might be a valid use case:

`stdClass` isn't a final class. I assume they meant this

```
class EmptyStdClass extends stdClass implements Falsifiable {
    public function __toBool() { return false; }
}
function example(stdClass $s) {
    if (!$s) { throw new Exception("Previously impossible"); }
}
```

Thanks,
- Tyson
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to