Constructor promotion needs a constructor body to assign into, so it is not available on an abstract constructor or in an interface.
abstract class Handler
{
// Fatal: cannot declare promoted property
// outside a constructor, in an abstract constructor
abstract public function __construct(private Logger $l);
}
// and it does not work with variadics:
public function __construct(private int ...$parts) {}
// Fatal error
// what does work: a concrete abstract-class constructor
abstract class Handler
{
public function __construct(protected Logger $l) {}
}
An abstract class with a concrete constructor promotes normally, which covers most of what people actually want — the abstract-constructor case is rare and usually a design that should have been an interface plus a trait. The variadic exclusion is structural: a variadic parameter is an array of values and a promoted property is one value, so there is no consistent thing to assign.