Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:92253 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 12839 invoked from network); 13 Apr 2016 16:53:17 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 13 Apr 2016 16:53:17 -0000 Authentication-Results: pb1.pair.com smtp.mail=morrison.levi@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=morrison.levi@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.192.171 as permitted sender) X-PHP-List-Original-Sender: morrison.levi@gmail.com X-Host-Fingerprint: 209.85.192.171 mail-pf0-f171.google.com Received: from [209.85.192.171] ([209.85.192.171:34876] helo=mail-pf0-f171.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id C1/33-26321-C797E075 for ; Wed, 13 Apr 2016 12:53:17 -0400 Received: by mail-pf0-f171.google.com with SMTP id n1so36736045pfn.2 for ; Wed, 13 Apr 2016 09:53:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:sender:in-reply-to:references:date:message-id:subject :from:to; bh=OtmKI28Yt7etQBG0nAS6UqHbtCdZSY1xQFLXAp5XUhg=; b=A2o2qJ0Lk6SQcSaJpugplXgpBOqbOGlt7ANYI2GAmQVwc23uavTAW2iQQE7mUo+HIn OtqDwL6FEwKTs67t+5XkPHOdbldNZUbwIh9dGESpofCd+V8kHGPpuFrDqiK0hnsBJkJo +HNO/0ZaR7DhIHgZR0WekjqPq6YHYDTIpSjaiBhc0gzldc2USK0fkcaO0IOY8G/Eiuja 3JfZqymNuBOBoxvpUQudFQeAg8esJnBkM7N49WltJOHdugeqTkne9N7ONcdi/lgly9qI 6ap7wKXOINCfddpcdLlfHtCyFYsNGxembqK7Q6umt5cS5k0pvzgbWxp5lMi3RrPhv41e CrUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:sender:in-reply-to:references:date :message-id:subject:from:to; bh=OtmKI28Yt7etQBG0nAS6UqHbtCdZSY1xQFLXAp5XUhg=; b=KoLPDwB56QuS6iBjY9E1YfPsHuQvxn2jRb58806FhxcWASmyJpXX4dmtrsplkStdyW N0BhDcUTi1D80+afZcGkZSy4r9A3vCarczZ+btj2rRZ2M3ua98LP7p9QQKnxfS1toAco rL5soe5V1F0/G0ZRcpxkcvVSBJtKsupYdjiueIDE/1DPUq2ssNIu9moWComQfa1yw4gQ pfs+A5KbeMc7ojahnLlUDvkimkBuybuUNlBn1+fjWYLqCXraeIF81zUq9IJ8Wubo0LHL TNSs/FAN8jO8tI1jn4m9mDPSP+e8aBF2Ypzt4T8kYDE4w5bmnFGm0igu904OaLztIBsx /7gw== X-Gm-Message-State: AOPr4FV0rbHJRi6OAbNRYhTudoWOhsvh/OLtqaxBuu65lNyto3lyX8zZwUvDPLtIQ7GU2hF4jVKre+wOXFutEA== MIME-Version: 1.0 X-Received: by 10.98.19.2 with SMTP id b2mr14304457pfj.93.1460566393971; Wed, 13 Apr 2016 09:53:13 -0700 (PDT) Sender: morrison.levi@gmail.com Received: by 10.66.163.232 with HTTP; Wed, 13 Apr 2016 09:53:13 -0700 (PDT) In-Reply-To: References: Date: Wed, 13 Apr 2016 10:53:13 -0600 X-Google-Sender-Auth: zjY3gUNGuTFZFAP5dV_d-qdsXns Message-ID: To: internals Content-Type: text/plain; charset=UTF-8 Subject: Re: Improving PHP's type system From: levim@php.net (Levi Morrison) Continued (hit send by hotkey accident): On Wed, Apr 13, 2016 at 10:50 AM, Levi Morrison wrote: > First, some background: several versions of PHP ago authors of > functions and methods could only restrict types to the array type or a > class/interface type. We slowly added some other types such as > callable and primitive types. These tools have been invaluable to > those who care about restricting the types of their inputs and > outputs. This type information reduces the code each author has to > write if they want to restrict to working with certain types and it > also provides a form of documentation. Overall these features have > been well received and are considered a good thing to do. > > However, as we have added these new restrictions we still cannot > express exactly what types are permitted in some common cases. > > 1. Return types cannot specify the function will return only type T or Null. > 2. Parameter types cannot express that an iterable type is required. > It's common for functions to work a stream of data and it is > irrelevant if it is an array or a Traversable object. > 3. Parameter types cannot express that that the parameter must > implement two different interfaces. For example, requiring a parameter > to implement both Countable and Traversable cannot be done. > > There are some common work-arounds to these issues: > > - Omit the type information and rely on documentation. > - Check the parameter type inside the function (eg > `assert(is_array($x) || $x instanceof Traversable)`) > - Introduce a new type that embodies the restrictions. If this in an > interface it must be implemented by every object you hope to use the > restriction with. > > In some cases these work-arounds are tolerable. However, some of them > are really painful. > > - Requiring a new supertype is intrusive. Code cannot always be > changed to use the new supertype. For example: > - Upstream projects that would not benefit from your changes. > - Primitives cannot be extended except by altering the engine. > In these cases a new type has to be introduced that proxies > behavior to the underlying object/primitive. > - Relying on documentation can lead to subtle and hard to diagnose > issues when it is used incorrectly. Erroring immediately is sometimes > preferable. > > All of these issues I've outlined can be nicely resolved by adding two > new kinds of types to our system: union and intersection types. A > union type requires the variable to match at least one of the types. > An intersection type requires the variable to match all of the types. > The vertical par symbol (OR) is used for unions and ampersand (AND) is > used for intersections. For example: > > function (A | B $var); would require $var to be either type A or type B. > function (A & B $var); would require $var to be type A and type B. > > To accommodate the common use-case of returning some type or Null we > would need to formally allow `Null` as an explicit type: > > function (): T | Null; > > Since this is a common use case some languages have a short-hand > notation to represent a union with Null: function (): ?T; Examples of such languages include Swift, C#, OCaml and Hack (though the symbol is sometimes in the front and sometimes in the back. Later today I will be submitting RFCs for each of these proposals. Although they can work independently it is helpful to understand the overall goal and how they fit together, which has been the purpose of this email. Feedback for each RFC will belong in the thread for that piece, but discussion about the ideas overall is better suited here.