common icon indicating copy to clipboard operation
common copied to clipboard

Compile Error: Constant expression contains invalid operations

Open oleg-andreyev opened this issue 3 years ago • 9 comments

Bug Report

Compile Error: Constant expression contains invalid operations

Q A
BC Break no
Version 2.11.2

Summary

Entity with following method

class A {
    public function getActivePriceOverrideForCompany(
        Company $company,
        DateTimeImmutable $activeAt = new DateTimeImmutable('today')
    ): ?PriceOverride { ... }
}

as result getting proxy like this:

public function getActivePriceOverrideForCompany(\App\Entity\Company $company, \DateTimeImmutable $activeAt = DateTimeImmutable::__set_state(array(
   'date' => '2022-05-03 00',
   'timezone_type' => 3,
   'timezone' => 'UTC',
))): ?\App\Entity\PriceOverride { ... }
  1. Proxy is invalid
  2. Even if the code will be correct, proxy will be invalid on the next day.

This will work:

class A {
    public function getActivePriceOverrideForCompany(
        Company $company,
        ?DateTimeImmutable $activeAt = null
    ): ?PriceOverride { ... }
}

oleg-andreyev avatar May 03 '22 12:05 oleg-andreyev

Transferring to doctrine/common since that is where the code that generate proxies is located.

greg0ire avatar May 03 '22 17:05 greg0ire

So far the only sensible way I've figured to get default's value definition from \ReflectionParameter is via its __toString method: https://3v4l.org/Tlt2m#v8.1.8 I went down the rabbit hole and unfortunately reflection itself is doing some dark magic to format the default value, including exporting AST: https://github.com/php/php-src/blob/3331832b04041d93f92a8a9a60602326e7ae9d2f/ext/reflection/php_reflection.c#L612-L655

Summing up: in my opinion we've reached limits of what we can achieve with current proxy generation but I'd like to hear a second thought @doctrine/doctrinecore

malarzm avatar Aug 02 '22 20:08 malarzm

Pinging @Ocramius for his opinion on the matter - TBH ORM should really drop doctrine/common proxies and start using proxy-manager for this.

alcaeus avatar Aug 03 '22 06:08 alcaeus

Even with proxy-manager, default expressions containing object instantiations aren't really supported yet.

That would require moving away from reflection, and instead use something like roave/better-reflection (more complexity/runtime overhead) or raw nikic/php-parser (loads of work to be done).

I completely missed the RFC (https://wiki.php.net/rfc/new_in_initializers): would've raised my concern there.

Ocramius avatar Aug 03 '22 07:08 Ocramius

BTW, that is one of the largest areas of concern why ocramius/proxy-manager does not support PHP 8.1 yet: probably need a good week of focused work, which won't happen this year.

Ocramius avatar Aug 03 '22 07:08 Ocramius

New initializers are accessible as source code via reflection. I specifically asked Nikita to allow this for such use cases. See https://3v4l.org/F2bjF

nicolas-grekas avatar Aug 03 '22 08:08 nicolas-grekas

See https://github.com/php/php-src/pull/7540

nicolas-grekas avatar Aug 03 '22 08:08 nicolas-grekas

Oh, and I submitted support for them at https://github.com/Ocramius/ProxyManager/pull/755

nicolas-grekas avatar Aug 03 '22 08:08 nicolas-grekas

Hah, so parsing __toString it is, that's what I feared. Thanks @nicolas-grekas for your work in ProxyManager, we should be able to port it here 👍

malarzm avatar Aug 03 '22 17:08 malarzm