On Tue, Mar 25, 2025 at 11:01 AM Rowan Tommins [IMSoP] <imsop....@rwec.co.uk> wrote:
> > I don't think the language should pretend to support something that it > doesn't > I don't see what the pretending is here - the engine supports declaring that a method must accept a parameter but makes no promises about the type of that parameter, which is what we claim it supports. If people want to use this for generics, then great, but I don't think this should be blocked on the expectation that it is only useful for userland generics (e.g. the Serde use case isn't really generics). > - if the contract is actually enforced by a third-party tool reading > docblocks, put the contract in a docblock: > > /** > * @template T > * @method compareTo(T $other): int; > */ > interface Comparable { > } > > /** @implements Comparable<Number> */ > final class Number implements Comparable { > public function compareTo(Number $other): int { return $this <=> > $other; } > } > > > What happens if there is a bigger contract than just the never parameter, and we want the engine to enforce the rest? For example, the Serde use case given previously. Or, if you had an object store that might occasionally clean up expired items: /** @template T */ interface ObjectStore { /** @param T $object */ public function storeObject(never $object, bool $alsoDoCleanup): void; } If we move the entire contract to the docblock, then the engine cannot be used to enforce the non-never-related parts. --Daniel