On Wed, Jun 17, 2026, at 4:32 PM, Rob Landers wrote:
Hello internals,
I was reminded of my records RFC today, and one of the features of the
RFC was "short constructors" generally called "primary constructors" in
C#/Kotlin.
They would look like this:
class Point(public int $x, int $id = 0) extends Base($id);
Which is just sugar for this:
class Point extends Base {
public function __construct(public int $x, int $id = 0) {
parent::__construct($id);
}
}
or this:
class Point extends Base {
public int $x;
public function __construct(int $x, int $id = 0) {
$this->x = $x;
parent::__construct($id);
}
}
A class with a primary constructor *may not* have a defined
`__construct` function. Any special initialization must be done with
hooks:
class Temperature(
public float $celsius {
set {
if ($value < -273.15) {
throw new ValueError('below absolute zero');
}
$this->celsius = $value;
}
}
) {}
new Temperature(20.0); // ok
new Temperature(-300.0); // ValueError: below absolute zero
I'm sending this email to the list to gather additional feedback before
pursuing a formal RFC proposal.
— Rob
I would support this, and I agree that KISS is the best way to go for now.
I don't know if it makes sense to include in the initial design, but for reference here's how Kotlin handles construction:
class Person(val name: String, val age: Int) { // Primary constructor, equivalent to promotion and what's proposed here.
init {
// Argument-less code block/method that runs after the primary constructor is assigned.
// This could be useful to include for more complex cases, like where hooks are useful.
}
// Secondary constructor
constructor(name: String): this(name, 0) {
// This constructor gets called first, but is forced to call the primary constructor syntactically.
// Then it can do other stuff if it wants.
}
}
cf: Classes | Kotlin Documentation
I don't think we should include the "secondary constructor calls primary constructor and you have to make sure it works" logic. However, I do think we can/should consider an init block. Though how that interacts with inheritance I'm not sure yet.
Putting non-trivial property hooks inside a constructor promotion is already strongly discouraged, and I would recommend continuing to discourage them even with this syntax. However, that does raise a concern that we would really benefit from some way to allow property hooks to be defined "on their own" on a property, AND link the property to a promoted constructor argument. I'm not sure off hand how we would do that, and it's somewhat tangential to this syntax, but I am pointing it out for completeness.
As for the readonly/hooks incompatibility, honestly, I don't care.
Readonly is frequently problematic, Internals has already rejected making readonly and hooks compatible, and `protected(set)` gets you almost the same rules with none of the conflicts. So I'm good there.
--Larry Garfield