On Thu, Jan 9, 2020 at 4:06 PM Rowan Tommins <rowan.coll...@gmail.com>
wrote:

> On Thu, 9 Jan 2020 at 14:23, Andreas Hennings <andr...@dqxtech.net> wrote:
>
> > > However, $this is not a real type, and it is unclear what the advantage
> > of specifying $this rather than static would be from a type system level
> > perspective.
> >
> > Perhaps not from a "type system level", but from a more broad "enforced
> > contract" level.
> > E.g. IDEs or code inspection tools can warn if a method will not return
> > $this.
> > This also means recursive calls also need to return $this instead of
> > static.
> >
> > class C {
> >   function foo(): static {
> >     return clone $this;
> >   }
> >   function bar(): $this {
> >     return $this->foo();  // IDE can complain.
> >   }
> > }
> >
>
>
> I think there are two different purposes for annotating return types:
>
> 1) Contracts that tell the caller what values they should expect when
> calling the function.
> 2) Constraints on the implementation which don't affect the caller, but
> allow the author to catch certain bugs.
>
> The primary purpose, in my mind, is (1), with (2) generally coming as a
> side-effect: if your contract is to return an int, then tools can warn you
> when you don't.
>
> All concrete types can be seen this way: scalars, classes, and pseudo-types
> like "iterable" are all contracts that calling code can rely on. "self",
> "parent", and "static" fit into that list fine, because they're ultimately
> specifying a class name.
>
> The special "void" keyword doesn't actually make sense as a contract given
> PHP's calling convention - as far as the calling code's concerned, it's
> equivalent to "null". So it exists only for purpose (2), constraining the
> implementation for the benefit of the function's author.
>
> $this would fit into the same category - as far as calling code is
> concerned it is equivalent to "static", unless they're doing something very
> specific with object identity. This makes it an odd constraint on
> interfaces, for example - DateTimeInterface exists specifically to have
> mutable and immutable implementations, and a return type of $this would
> explicitly prevent that.
>
> If we add ": $this" alongside ": void", I wonder where that takes us next -
> what other constraints on a function can be expressed using that notation
> which aren't contracts on the value seen by the caller? If we don't want to
> explore that question, should we avoid adding ": $this"?
>

An argument could be made that $this does also specify a certain contract
to the caller: That the API may be used fluently or not without change in
functionality. That is

    $foo->setBar();
    $foo->setBaz();

must be strictly equivalent to

    $foo
       ->setBar()
       ->setBaz()
    ;

The same is not the case for a plain "static" type. In fact, I think that
for all other uses of "static" outside of fluent interfaces, not using the
return value would be a programming error.

But still, this kind of contract is not a type-system contract, and I'm not
sure it's a good idea to mix other types of API contracts into the type
system in this fashion.

Regards,
Nikita

Reply via email to