# RFC: First Class Callables in constant expressions

- Thread: https://externals.io/message/126217
- Original archive: https://news-web.php.net/php.internals/126217
- Started by tim@bastelstu.be on 2025-01-22T14:35:50+00:00
- Messages: 9
- RFC: Support Closures in constant expressions (Implemented (PHP 8.5)) — https://externals.io/rfc/closures_in_const_expr.md
- RFC: First Class Callables in constant expressions (Implemented (PHP 8.5)) — https://externals.io/rfc/fcc_in_const_expr.md
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #126217 — tim@bastelstu.be — 2025-01-22T14:35:50+00:00

URL: https://externals.io/message/126217#126217

Hi

Volker and I would like to start discussion on our RFC to support "First 
Class Callables in constant expressions".

Please find the following resources for your reference:

- RFC: https://wiki.php.net/rfc/fcc_in_const_expr
- Implementation: https://github.com/php/php-src/pull/17213

- The related "Support Closures in constant expressions" RFC: 
https://wiki.php.net/rfc/closures_in_const_expr
- The "Support Closures in constant expressions" discussion: 
https://externals.io/message/125872

Best regards
Tim Düsterhus

---

## #126251 — Larry Garfield — 2025-01-30T23:58:24+00:00

URL: https://externals.io/message/126217#126251 · In reply to: #126217

> Hi
>
> Volker and I would like to start discussion on our RFC to support "First 
> Class Callables in constant expressions".
>
> Please find the following resources for your reference:
>
> - RFC: https://wiki.php.net/rfc/fcc_in_const_expr
> - Implementation: https://github.com/php/php-src/pull/17213
>
> - The related "Support Closures in constant expressions" RFC: 
> https://wiki.php.net/rfc/closures_in_const_expr
> - The "Support Closures in constant expressions" discussion: 
> https://externals.io/message/125872
>
> Best regards
> Tim Düsterhus

I don't know how to interpret the radio silence from the list, but this seems like an obvious and good follow-on to the previous RFC and has my support.

--Larry Garfield

---

## #126253 — Arvids Godjuks — 2025-01-31T10:04:54+00:00

URL: https://externals.io/message/126217#126253 · In reply to: #126251

> 
> > […]
>
> I don't know how to interpret the radio silence from the list, but this
> seems like an obvious and good follow-on to the previous RFC and has my
> support.
>
> --Larry Garfield
>

Ship it.
Fin.
;)
-- 

Arvīds Godjuks
+371 26 851 664
arvids.godjuks@gmail.com
Telegram: @psihius https://t.me/psihius

---

## #126256 — tim@bastelstu.be — 2025-01-31T11:03:38+00:00

URL: https://externals.io/message/126217#126256 · In reply to: #126251

Hi

Am 2025-01-31 00:58, schrieb Larry Garfield:
> I don't know how to interpret the radio silence from the list, but this 
> seems like an obvious and good follow-on to the previous RFC and has my 
> support.

We also interpreted the lack of responses as “this is an obvious 
follow-up and I don't have any questions or concerns”, especially since 
FCC support also came up in the discussion of the Closure RFC and was 
split into a separate RFC primarily to give each of these features the 
proper attention with regard to implementation and edge cases. In 
hindsight this was the correct decision, since the implementation for 
FCC was much more complicated and edge-casey than initially expected, 
whereas Closures were reasonably straight forward.

Best regards
Tim Düsterhus

---

## #126263 — Larry Garfield — 2025-01-31T22:36:47+00:00

URL: https://externals.io/message/126217#126263 · In reply to: #126256

> Hi
>
> Am 2025-01-31 00:58, schrieb Larry Garfield:
> > […]
>
> We also interpreted the lack of responses as “this is an obvious 
> follow-up and I don't have any questions or concerns”, especially since 
> FCC support also came up in the discussion of the Closure RFC and was 
> split into a separate RFC primarily to give each of these features the 
> proper attention with regard to implementation and edge cases. In 
> hindsight this was the correct decision, since the implementation for 
> FCC was much more complicated and edge-casey than initially expected, 
> whereas Closures were reasonably straight forward.
>
> Best regards
> Tim Düsterhus

Purely out of curiosity and for educational value, what was so complicated about it?  I would have expected it to be straightforward.

--Larry Garfield

---

## #126270 — tim@bastelstu.be — 2025-02-02T13:38:32+00:00

URL: https://externals.io/message/126217#126270 · In reply to: #126263

Hi

Am 2025-01-31 23:36, schrieb Larry Garfield:
> Purely out of curiosity and for educational value, what was so 
> complicated about it?  I would have expected it to be straightforward.

FCC internally are effectively treated as function calls with a funny 
parameter list. This means that all valid ways to perform a function 
call are valid ways to create a FCC. And likewise do all constraints of 
a function call also apply to creating a function call. FCCs in 
const-expr need to replicate those semantics as applicable. For us this 
means: A FCC in a parameter default value behaves, as if the assignment 
was the first line in the function body. Likewise must a FCC in a 
property default value behave as if it was assigned in the first line of 
the constructor body.

And then amongst others you have the following (edge-)cases to take into 
account:

- All kinds of expressions can be used as a function name (this RFC 
excludes those for simplicity).
- A FCC can resolve to a dynamic function when __call() or 
__callStatic() is implemented (this RFC excludes those for simplicity).
- Static methods can directly be called on a trait (this is deprecated, 
but supported by the RFC).
- Calls to free-standing functions need to take the global namespace 
fallback into account (which will be cached for each individual call, 
which has funny effects when the function in the same namespace gets 
defined after some of the calls already executed at least once).
- Visibility and names needs to be resolved correctly, including 
references to `self` and `static`.

For regular closures (i.e. the first RFC) it was as simple as: Disallow 
`use` and require `static` and you're done. They are much less 
context-dependent.

Best regards
Tim Düsterhus

---

## #126272 — Rob Landers — 2025-02-02T14:35:12+00:00

URL: https://externals.io/message/126217#126272 · In reply to: #126217

> Hi
> 
> Volker and I would like to start discussion on our RFC to support "First 
> Class Callables in constant expressions".
> 
> Please find the following resources for your reference:
> 
> - RFC: https://wiki.php.net/rfc/fcc_in_const_expr
> - Implementation: https://github.com/php/php-src/pull/17213
> 
> - The related "Support Closures in constant expressions" RFC: 
> https://wiki.php.net/rfc/closures_in_const_expr
> - The "Support Closures in constant expressions" discussion: 
> https://externals.io/message/125872
> 
> Best regards
> Tim Düsterhus
> 

Hey Tim,

My only concern with the RFC is something a bit silly. If I understand correctly, this will be a constant expression:

fn(string $foo) => print $foo

But this will not:

(fn(string $foo) => print $foo)(...)

despite them both basically being the same thing.

It is an incredibly small inconsistency (imho), but other than that, ship it.

— Rob

---

## #126293 — Volker Dusch — 2025-02-05T11:03:14+00:00

URL: https://externals.io/message/126217#126293 · In reply to: #126217

> - RFC: https://wiki.php.net/rfc/fcc_in_const_expr
> - Implementation: https://github.com/php/php-src/pull/17213


With the two weeks discussion time elapsing later today and given the
feedback we received, we plan to open the vote tomorrow pending any
major concerns.

Kind Regards,
Volker

-- 
Volker Dusch
Head of Engineering
Tideways GmbH
Königswinterer Str. 116
53227 Bonn
https://tideways.io/imprint

Sitz der Gesellschaft: Bonn
Geschäftsführer: Benjamin Außenhofer (geb. Eberlei)
Registergericht: Amtsgericht Bonn, HRB 22127

---

## #126295 — tim@bastelstu.be — 2025-02-05T12:17:03+00:00

URL: https://externals.io/message/126217#126295 · In reply to: #126272

Hi

Am 2025-02-02 15:35, schrieb Rob Landers:
> My only concern with the RFC is something a bit silly. If I understand 
> correctly, this will be a constant expression:

You understood that correctly.

> It is an incredibly small inconsistency (imho), but other than that, 
> ship it.

I wouldn't call it an inconsistency, it's natural that the allowed 
expressions in a constant-expression context are limited. This 
limitation is mentioned in the second bullet point of the “Constraints” 
section: Only the "basic form" of first-class callables is supported, 
mainly to keep the implementation simple, due to the limited usefulness 
of the more complex function call variants when limited to 
constant-expressions. As an "escape hatch", it's always possible to 
wrote a proper closure that just forwards the calls to the desired 
method.

It will also result in a useful error message that is consistent with 
dynamic new-expressions within const-expr context:

     Fatal error: Cannot use dynamic function name in constant expression 
in test5.php on line 3

and for new-expressions:

     $ cat test5.php
     <?php

     const Foo = new (Foo)();
     $ sapi/cli/php test5.php

     Fatal error: Cannot use dynamic class name in constant expression in 
test5.php on line 3

Best regards
Tim Düsterhus
