Static return type, and the fluent interface that inherits

A fluent method returning self tells the analyser the base class, so every chained call on a subclass loses its type after the first link.

abstract class Query
{
    public function where(string $c): static
    {
        $this->conditions[] = $c;

        return $this;
    }
}

final class OrderQuery extends Query
{
    public function paid(): static { /* ... */ }
}

(new OrderQuery())->where('total > 0')->paid();
// with self: the analyser says Query has no method paid()

static as a return type is late static binding expressed in the signature, and it is only valid as a return type — never for a parameter or a property, because there is no meaningful binding at those positions. The runtime already behaved this way; what changed in 8.0 is that the type system can say so, which turns a docblock that everybody wrote into something checked.