Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:115740 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 3905 invoked from network); 15 Aug 2021 22:34:25 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 15 Aug 2021 22:34:25 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 2B7C11804B4 for ; Sun, 15 Aug 2021 16:06:14 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-ej1-f45.google.com (mail-ej1-f45.google.com [209.85.218.45]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sun, 15 Aug 2021 16:06:12 -0700 (PDT) Received: by mail-ej1-f45.google.com with SMTP id w5so28595447ejq.2 for ; Sun, 15 Aug 2021 16:06:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=GKZBuBhDaJB7KaEeNyDe9ZRn02FiNVCGcereD0q75kw=; b=vTN8WgZtcZKCGwRWXGN/Iud0Gp3wVd9/ISdwB+a3GUQrz2NBU5lCCyYAA3aIbU0WGZ NaeXdW8vPbhRz2q55aJjqnUahGP5fMPBwgsVzOGi8gNuC1XBYHR1qKgg2D0lV7OLYoTp Dh/4uN0XGO1tvX2bK86aYhpyGNGUfMz15sZ2GbLe5eSL1LBxFz1mYMMcedu9RLOdzzhi Ljr8qZFrzg0fKdJYJcDXHsMgfkmUuhEOUNnrsTGW78RAo/wDqC+psexbqctxD2qNiwB2 ATICUqQV8AnnO3JHqbrl+ERSOjkSWgFud0w1PV6ljbqnmnJyw+qr9egZmluGcCqsICJv aRVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=GKZBuBhDaJB7KaEeNyDe9ZRn02FiNVCGcereD0q75kw=; b=imRQvw74n7hpXTh7/Y8DdIRSipdW8Vj8CzeijAiVNGRTxJlXS0coGLb85KGBQZcbCz CdWWhG7rdO2JwNR+ErbaJAw1pqkrU5h48s37YImQ43chXDEdrlGsC5enYhveDyOhBeT9 03MJicBgKZdxbxMFiEnoMKTGMD9IF7Rqfv3qevwLT6GZ51mBLMKqX91s8EIzNuylmTbi tzQxyPXJpODEc0g3gCRp3JTJ7JFCoCrV7lHVZOg00Nh/8rt7+VoV1HRaYHN1tFKIquWr VwBJTxFDOPvbVrL2DKoBtz3mHvvYjpHnL55y4/4gpqnMNMgUYxW5ot3Oz+bzQ1zOzrSG bz5w== X-Gm-Message-State: AOAM5321U+2yg1iHanGRf3BO+TMeQo762GBMxU02pLyITG2FsWYDbSeb a3OgkljpP+Q65VULyzumtDDr+OIs9HYsV/s4wv8= X-Google-Smtp-Source: ABdhPJxqQH14d5GhticUcvUErp0MmIaiXM1Co2niA+oCRIWTGSSrqZHB9G2vIAtn4/kMNg9MAxjDX7808GKr4QNUGbI= X-Received: by 2002:a17:907:384:: with SMTP id ss4mr7852366ejb.430.1629068771576; Sun, 15 Aug 2021 16:06:11 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Mon, 16 Aug 2021 01:06:00 +0200 Message-ID: To: Jordan LeDoux Cc: PHP internals Content-Type: multipart/alternative; boundary="00000000000071cd3205c9a121af" Subject: Re: [PHP-DEV] [RFC] Never For Argument Types From: drealecs@gmail.com (=?UTF-8?Q?Alexandru_P=C4=83tr=C4=83nescu?=) --00000000000071cd3205c9a121af Content-Type: text/plain; charset="UTF-8" On Sat, Aug 14, 2021, 01:27 Jordan LeDoux wrote: > Hey internals, > > I've been working on the draft for my operator overloading RFC, and in > doing so I encountered a separate change that I would like to see. > > That is, the use of `never` as an argument type for interfaces. Since > arguments in PHP are contravariant to preserve Liskov substitution, `never` > as the bottom type should indicate that implementing classes can require > any type combination they want. This is in fact consistent with type theory > and set theory, and is how the bottom type is treated in several other > languages. > > In this case, the bottom type would be used to indicate covariant parameter > polymorphism while not conflicting with LSP. > > This would provide a sort of minimal form of generics to PHP without the > issues that actual generics present from an implementation perspective. It > would not, however, restrict or hinder any future RFC for generics. > > This is at the first draft stage, and I currently have the RFC on a github > repo to allow for easy contribution and collaboration. > > Any feedback is greatly appreciated. > Hey Jordan, From type perspective, this sounds good. But, in my view, types should be checked statically. For inheritance, when defining a method, both the parameters and return types are nicely checked statically and that's good. On the other side, when calling a method, due to the dynamic nature of PHP, there is no simple way of checking it statically. For example, if an interface is defining a method with a parameter of type string and an implementation is changing the parameter type to a string|int union, the caller that have a knowledge about the interface (that accepts only string) can call it with an integer and everything will work fine. It's kind of the same situation and this will too be flagged by the IDEs and static analysis tools. From a usage design perspective, this is bad, in my view. If caller knows about the interface only, that is to ensure decoupling and this breaks it. I was hoping that, at some point, we would be able to validate that arguments types match parameters types statically, to avoid the continuous runtime cost for it. Maybe this can already be done, with some changes, when arguments are properties defined with types. When variables will have types and/or when variables will be "final"/"constants", more static checks could be implemented. Adding another exception to this behavior might not be the best idea if we might move towards removing the behavior. Coming back to the interface decoupling topic, that's exactly why interfaces should be used, to allow polymorphism. If I see an interface that was created just so it can be implemented by multiple classes but the caller doesn't use the interface but it uses the actual classes, I call it out as that is the wrong abstraction and the interface should just be removed. Your example with ArrayAccess is similar with this; when using it, you know exactly what implementation you have. The interface is not helping here related to polymorphism but it is actually required to allow a language construct related to the engine itself, to translate accessing an object with the same syntax as for an array. If the 4 functions would have been magic methods, without an interface, you would not have this problem. Your example with CollectionInterface is exactly a place where I would say the interface is unnecessary because you already know the implementation, since you call it with the correct type. Just keeping the classes not having to implement the interface would work just fine. If you want to enforce method names on all Collection classes, you can do that with other tools for static analysis, including code reviews; not with the Interface. Sorry for the long reply but my means to make it shorted are limited and I'm using a smartphone only in this period (being in vacation). Alex --00000000000071cd3205c9a121af--