static return type does not exist yet, and self is not it

A fluent method returning self promises the class it is declared in, not the class it is called on — so a subclass inherits a method whose signature lies about what it returns.

abstract class Query
{
    public function where(string $c): self   // NOT the subclass
    {
        $this->conditions[] = $c;

        return $this;
    }
}

// the 7.4 workaround: annotate what the engine cannot express
/**
 * @return static
 */
public function where(string $c)
{
    // ...
}

static as a return type arrives in 8.0. Until then the honest arrangement is no native type and a @return static docblock, which PHPStan and PhpStorm both understand even though the engine does not. Declaring self and hoping is the version that breaks: a subclass’s fluent chain type-checks to the parent, and the analyser then rejects a perfectly correct call to a method the subclass added.