[GIT-PULLS] [php-src] PR #23305: Elide provably-passing return type checks at compile time

[email protected] (staabm)
Newsgroups php.git-pulls
Message-ID <[email protected]>
Pull Request: https://github.com/php/php-src/pull/23305
Author: staabm

disclaimer: this change was generated by claude opus. I have little experience with php-src development

----

Without the opcache optimizer every 'return <expr>;' in a typed function executes ZEND_VERIFY_RETURN_TYPE. Skip emitting it when the check provably always passes:

- expressions whose opcode always produces a specific type accepted by the return type: comparisons, instanceof, isset/empty and boolean operators produce bool; concatenation produces string;
- 'return $this->prop;' where the property is declared in the class being compiled and its type is a subtype of the return type. Property types are invariant under inheritance, and typed property reads always yield conforming values: uninitialized reads throw before the return, and __get()/get-hook results are verified against the property type. Only same-class declarations are visible during method compilation, which keeps the proof local.

Closures are excluded (Closure::bind can rebind scopes), as are by-ref returns, generators, union/intersection property types and context-dependent return types (static, callable). Coercion semantics are preserved by requiring the value type set to be a subset of the return type set (e.g. an int property returned as float still emits the check).

Getter-style code drops one opcode per return; 'return $x === null;' style predicates drop the check entirely.

----


before PR

```
➜  php-src git:(elide-return) ✗ ./sapi/cli/php_old -n -dopcache.enable_cli=0 return_type_check_elision_repro.php
PHP 8.6.0-dev
iterations=5000000 rounds=7 calls_per_round=40000000

case            best(s)     avg(s)      sink
--------------------------------------------------
getter-direct   0.358463    0.359450    280000000
getter-control  0.409889    0.412215    280000000
cmp-direct      0.462745    0.465084    39999990
cmp-control     0.529274    0.532243    39999990

Direct/control ratio inside each pair (best time, lower is better):
getter           0.8745x
cmp              0.8743x
```

after PR

```
➜  php-src git:(elide-return) ✗ ./sapi/cli/php -n -dopcache.enable_cli=0 return_type_check_elision_repro.php
PHP 8.6.0-dev
iterations=5000000 rounds=7 calls_per_round=40000000

case            best(s)     avg(s)      sink
--------------------------------------------------
getter-direct   0.337137    0.337611    280000000
getter-control  0.415257    0.416750    280000000
cmp-direct      0.448156    0.451637    39999990
cmp-control     0.536600    0.539734    39999990

Direct/control ratio inside each pair (best time, lower is better):
getter           0.8119x
cmp              0.8352x
```

using [return_type_check_elision_repro.php](https://gist.github.com/staabm/127abcf5aafc47d0b178eda39e525ad2)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.