On 16/03/2023 22:14, Larry Garfield wrote:
Wouldn't the functionality described boil down to essentially just
materializing into a few extra lines in the constructor? At least to my
ignorant non-engine brain it seems straightforward to have this:
$a = 1;
$b = 2;
$c = 3;
$o = new class ($a, $b) use ($c) {
public function __construct(private int $a, private int $b) {}
public function something() {}
}
Desugar to this:
$c = class ($a, $b) use ($c) {
private $c;
public function __construct(private int $a, private int $b) {
$this->c = 3; // By value only, so this should be fine?
}
public function something() {}
}
Not quite - as Ilija pointed out, the class definition gets compiled
once, but the capture needs to happen for every instance, with
(potentially) different values of $c. In other words, $c needs to be
injected as a constructor argument, not a constant in the class definition.
That's still fine, in principle - you can compile to this:
$o = class ($a, $b, $c) {
public function __construct(private int $a, private int $b, private $c) {
}
public function something() {}
}
Or once constructor promotion is de-sugared as well, this:
$o = class ($a, $b, $c) {
private int $a;
private int $b;
private $c;
public function __construct($a, $b, $c) {
$this->a = $a; // from constructor promotion
$this->b = $b; // from constructor promotion
$this->c = $c; // from use() statement
// other lines from body of constructor go here
}
public function something() {}
}
It just introduces a lot of extra cases to handle:
* If there's no constructor, create one
* If there is a constructor with other arguments, merge the argument
lists; since there will then be an explicit argument list to "new
class()", merge those lists as well
* Maybe different handling if those other arguments are already using
constructor promotion, as in this example
* If there are existing lines in the constructor body, combine those
with the auto-generated assignments
Which is why I'm thinking a first implementation would be reasonable
which just took this approach:
* "new class" can either have an argument list or a use() statement, not
both
* the use() statement generates a constructor at the top of the class
* if the class body already contains a constructor, the compiler will
complain that you have two methods named "__construct"
Regards,
--
Rowan Tommins
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php