Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126896 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 80A1E1A00BC for ; Fri, 21 Mar 2025 14:33:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1742567432; bh=tadVmsK3wrtB7TEDdUSqPBxng58wME9I1d5N652TDpg=; h=Date:Subject:To:References:From:In-Reply-To:From; b=HMaI1s65LvifqtjnLG64J810M1jIjj+LC6PtV6yIb40SPscRMv0NN4ccnTyyeIviQ 2N8Fzd9cNvGGeikklksr0aH1iKWcIFKDEUwAJvn5UpxapHCmNd+Fp3HHkH7k9bFe82 v5nGXv2c3wji1dPznpdmIwVM/7A3KOmvgt4Tg/QPdfo2beTuTu4dbQtsGmjHQy425l lDz1ZapyAwuWv15KXctRfmaTIq7r1i8pCSJ8v4NjKkE+eqI+6FSEaESilPkmsU41UU et59bdZrAuZzX0HTmAN8ALanWMnidVIXod8YQhZDQ7YBJZE2B1/flFVvxkme//w5RL dPlZMOR2GbNfQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id D056E180081 for ; Fri, 21 Mar 2025 14:30:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from fout-a6-smtp.messagingengine.com (fout-a6-smtp.messagingengine.com [103.168.172.149]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 21 Mar 2025 14:30:31 +0000 (UTC) Received: from phl-compute-10.internal (phl-compute-10.phl.internal [10.202.2.50]) by mailfout.phl.internal (Postfix) with ESMTP id 8E2591382CE2 for ; Fri, 21 Mar 2025 10:33:01 -0400 (EDT) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-10.internal (MEProxy); Fri, 21 Mar 2025 10:33:01 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rwec.co.uk; h=cc :content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm1; t=1742567581; x=1742653981; bh=Nc4tKyM8Qx pUQm0gwXca6FSeDeu0R9Dlh2xjArmePBY=; b=s106BwqCkPbyBc8A3TI7yUxiOU ODajrfdsQETkp5PuKMyDt+/gJ6go/tqjq490886azGq0dnD7wFZbDAIGFeWnTHsn CGyB8IrbOiBQQTOIszrtVBy26FFdGNWPZ08Y7ZZejYCrF3XwJkof7fWxPqRALXzD ROc7YGaQ/x8NeJGvl3MHaazyWtL1LXnyu8fzxqfH5IKWxqDdXd6nctCQQgQ7f6hA 6cjpv51/xSk/F00wLFfAcCLxYIOAXfOy+SunVHrYVKLSr95NReVQr/qL3L7qYL6X 99RkooMAJjYRyEyHkBlt3kg04JxN5h74kZ72LXINlTJAdBcPra31rWrkYTiQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t= 1742567581; x=1742653981; bh=Nc4tKyM8QxpUQm0gwXca6FSeDeu0R9Dlh2x jArmePBY=; b=z2L9Oc0/2LvG0SzzppedY4MQKIX4/bDz+fJzjiFcltiHcGMw469 V7CWXyN/EIOR17PU3L0XUj6F/MuwxqO0V2FnKeGs8t3HGVUMRmD3tJnvYtMtjlyP iw34gnHWUHebd4yVgtKoKgl8a7ar6pBKfi+kKjpAGYI9lVTW4G6yWcy98NmZ63eA Bhyi2dAQt/9j/2T4M7sLRqHY40O2U/iN5tVjnE841ggNCf4wkayZZBPFR1IEoy2d QAQ+CQaL9Eogf7EFsSKTRc/Ogf/nMQuxVjIUpov9uoZINCfj8SrJDI8S4AsIj5i2 XyCxi164JHfui5U5Vf5T3uGByznfvJ6/MDA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdduhedufeehucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggv pdfurfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucenucfjughrpegtkf ffgggfuffvfhfhjgesrgdtreertddvjeenucfhrhhomhepfdftohifrghnucfvohhmmhhi nhhsucglkffoufhorfgnfdcuoehimhhsohhprdhphhhpsehrfigvtgdrtghordhukheqne cuggftrfgrthhtvghrnhepheetleeiiefgueduieeuieffvdevheduueefkeejuefgffef tdeitdegtedtleetnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilh hfrhhomhepihhmshhophdrphhhphesrhifvggtrdgtohdruhhkpdhnsggprhgtphhtthho pedupdhmohguvgepshhmthhpohhuthdprhgtphhtthhopehinhhtvghrnhgrlhhssehlih hsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: id5114917:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Fri, 21 Mar 2025 10:33:00 -0400 (EDT) Content-Type: multipart/alternative; boundary="------------f70bfYRgiATANg96j7f1pWCd" Message-ID: Date: Fri, 21 Mar 2025 14:32:58 +0000 Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PHP-DEV] [RFC] [Discussion] Never parameters To: internals@lists.php.net References: Content-Language: en-GB In-Reply-To: From: imsop.php@rwec.co.uk ("Rowan Tommins [IMSoP]") This is a multi-part message in MIME format. --------------f70bfYRgiATANg96j7f1pWCd Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 21/03/2025 11:50, Tim Düsterhus wrote: > Am 2025-03-20 21:27, schrieb Matt Fonda: >> If an interface adds a method but makes no promises about what >> parameters >> it accepts, then why is it part of the interface in the first place--why >> add a method that can't be used? > > It would more cleanly allow for userland / PHPDoc-based generics, > while still providing some engine-enforced type safety. Consider this > example (not sure if I got the syntax completely right): > >     /** @template T */ >     interface Comparable { >         /** @param T $other */ >         public function compareTo(never $other): int; >     } > >     /** @implements Comparable */ >     final class Number implements Comparable { >         public function compareTo(Number $other): int { return $this > <=> $other; } >     } I think I agree with Matt on this: the interface isn't making any usable promises about that method. In this example, Comparable is a kind of "abstract interface" - in order to actually make use of it, you need to specialise it. Declaring that a class implements a template interface is like inheriting an abstract method: either you fill in the type parameter ("class Foo implements Comparable { ... }"), or the class is also a template ("class Foo implements Comparable { ... }") I don't think the language should pretend to support something that it doesn't - 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 */     final class Number implements Comparable {         public function compareTo(Number $other): int { return $this <=> $other; }     } -- Rowan Tommins [IMSoP] --------------f70bfYRgiATANg96j7f1pWCd Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit
On 21/03/2025 11:50, Tim Düsterhus wrote:
Am 2025-03-20 21:27, schrieb Matt Fonda:
If an interface adds a method but makes no promises about what parameters
it accepts, then why is it part of the interface in the first place--why
add a method that can't be used?

It would more cleanly allow for userland / PHPDoc-based generics, while still providing some engine-enforced type safety. Consider this example (not sure if I got the syntax completely right):

    /** @template T */
    interface Comparable {
        /** @param T $other */
        public function compareTo(never $other): int;
    }

    /** @implements Comparable<Number> */
    final class Number implements Comparable {
        public function compareTo(Number $other): int { return $this <=> $other; }
    }


I think I agree with Matt on this: the interface isn't making any usable promises about that method.

In this example, Comparable is a kind of "abstract interface" - in order to actually make use of it, you need to specialise it. 

Declaring that a class implements a template interface is like inheriting an abstract method: either you fill in the type parameter ("class Foo implements Comparable<Foo> { ... }"), or the class is also a template ("class Foo<A> implements Comparable<A> { ... }")


I don't think the language should pretend to support something that it doesn't - 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; }
    }


-- 
Rowan Tommins
[IMSoP]
--------------f70bfYRgiATANg96j7f1pWCd--