Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:105335 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 53160 invoked from network); 23 Apr 2019 01:37:26 -0000 Received: from unknown (HELO mail-it1-f195.google.com) (209.85.166.195) by pb1.pair.com with SMTP; 23 Apr 2019 01:37:26 -0000 Received: by mail-it1-f195.google.com with SMTP id w15so20756063itc.0 for ; Mon, 22 Apr 2019 15:37:41 -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=msYZVg//AlAZgTBPkgaSdfpBmPGpTM2v9vyxTijq8iY=; b=LDl4M5dlyOdwGfb53Jmiokm2czGvRNGcwKo8ab3nKHdjzfMyWru3QN0i1xN715DEic FKvxLO7I3pTSsJMJXSwiOn2/v0hWyupiwd2ZNigYbCDzWhZRKrG9IgvPduDOvYjY2lpZ wmqKCCJib9vFOQjZ3mKHcb8d1PZXY9RdfYZlIP0efier/4MISNTvadmCMl4cNgAd22F2 rXUHDsLs6D54P0EilOZ4ntg4HR61JdxUWwk90vH3Fm23NDlKuFKF97zAYWhJiTXoEu4i ZPyxuh+dwDCJtWhqbZyVoGoWJeOeKTnW4Bt87TvvABxDvsw8DjKWAcQ+67Q8BJUc5+rH 1Nxg== 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=msYZVg//AlAZgTBPkgaSdfpBmPGpTM2v9vyxTijq8iY=; b=hfZYrvukIBsbZoSp9MsksS0Gfmgnf7uqrFpWx27wJj6gXrlAHFwlrvgU6Vc80fBiCh 1IORcUHS11GUDghOoFY693lea4yHB0EzLMZ32r6qzoHa/wtA9zJX/G6jEX5TV2extM6S Tecv3ZCXZ6dm4bPJ+GtH82mY/KOnVnpsd4pe3eW3RXkMhIkxm9S8jnpKqwg0r6Z5PazF n68PfN/x2daHlXz9z+OupcUEkYXE2U0vmaUfI5V/SRPBr0fwJDL1+oUQ3/Jwkgf2kuMG awdzx77yBYf44J0eGpx8xVzpIGZ0nrV8i+SxJ9EIrjv6hUguOg3xNChBSEBdgC70lIQx eCWg== X-Gm-Message-State: APjAAAXMON9cO13kwi9t+0Ske3VOUIBYZMuyduUFmKBPKceFeiW5DJO5 LXrb6ytqd7DKCm63pz6Hi17Eg3bfu9k4hpbKLZo= X-Google-Smtp-Source: APXvYqwrZZSgXcNnhccARZfcJv1KAGPbp9mLQPIsJeReP8WLRdIhM3eyWo9612UH6rIhKBNkWS7Am0tKr8da8uUzKyM= X-Received: by 2002:a24:4682:: with SMTP id j124mr473301itb.90.1555972660727; Mon, 22 Apr 2019 15:37:40 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Tue, 23 Apr 2019 00:37:29 +0200 Message-ID: To: Larry Garfield Cc: PHP Internals Content-Type: multipart/alternative; boundary="000000000000b915c30587261df9" Subject: Re: [PHP-DEV] Object Type Casting Reloaded From: benjamin.morel@gmail.com (Benjamin Morel) --000000000000b915c30587261df9 Content-Type: text/plain; charset="UTF-8" Hi Larry, thanks for the early feedback! > First thought: I'm all for easy ways to be more type-explicit, so yay on the concept. Glad to hear that! > Second thought: (...) how many use cases for that are there other than function boundaries, which we already have covered? I chose an example where function boundaries are typically not covered: dependency injection containers, which have some generic `get()` method that can return any type. Another one is ORMs: Doctrine's EntityManager::find(), for example, returns a generic `object`. > The second I can see being easily handled by this syntax. The former, how would that look? I guess it could be used this way: foreach ($arrayOfFoo as $foo) { ((Foo) $foo)->bar(); } Although this use case is not the primary motivation for this feature, which is not meant to replace all object type hints. > Third thought: Casting is the wrong name here, and feels also misleading as a syntax. I suspected this would come up, hence the final note; I'm open to suggestions for alternatives. Please note that Java's object casting uses the same syntax, and follows the same semantics of throw-if-not-instance-of. The difference, if I'm not mistaken, is that you can type-hint an object to more generic interface or parent class, or, on the contrary, type-hint it to a more specific sub-class or concrete class to make its members accessible; this part is obviously not needed in PHP as the VM does not care what the type is before attempting to access one of its members. But I'm not sure if the fact that we miss the "conversion" part is enough to justify a change in naming or syntax compared to the Java equivalent? - Ben On Tue, 23 Apr 2019 at 00:03, Larry Garfield wrote: > On Mon, Apr 22, 2019, at 4:47 PM, Benjamin Morel wrote: > > Hi internals, > > > > I'd like to revive an old discussion > about > > object type casting. > > > > The idea would be to allow (ClassName) casting: > > > > $service = (EmailService) $diContainer->get('email.service'); > > > > The above code would throw a TypeError if the value is not an instance of > > the given class. I see the following advantages: > > > > - Type safety: we can be sure that the value is of the correct type or > that > > we'll get an Error. This syntax allows to fail early if the variable > > happens to not be of the expected type, and avoids much more verbose > checks; > > - Static analysis: IDEs and static code analysis tools can now understand > > the type of the variable, without having to resort to `@var` annotations. > > > > These combine into a third advantage: readability. Today's equivalent of > > the above one-liner could be: > > > > /** @var EmailService $service */ > > $service = $diContainer->get('email.service'); > > if (! $service instanceof EmailService) { > > throw new TypeError('Expected instance of EmailService, ...'); > > } > > > > Which is a lot of boilerplate code that could be easily avoided by > > introducing this new syntax. > > > > Before moving forward and working on a formal RFC, I'd like to hear your > > thoughts: what's your early feeling about this? Did I miss other > > discussions around this subject? Are there any technical issues that come > > to mind? Could this feature help the upcoming JIT compiler produce more > > efficient machine code by knowing the type of the variable at compile > time? > > etc. > > > > Note: "casting" might not be the perfect name here as what we're really > > doing is a type check, but this reuses the type casting syntax and > > resembles Java's object casting. > > > > Thank you, > > Ben > > Hi Ben. > > First thought: I'm all for easy ways to be more type-explicit, so yay on > the concept. > > Second thought: That said, how many use cases for that are there other > than function boundaries, which we already have covered? > > I can think of two: foreach() loops and returns where you know the return > type with more specificity than the method you're calling. Example: > > /** @var Foo $foo *// > foreach ($arrayOfFoo as $foo) { > $foo->bar(); > } > > Example from PSR-14, in which you know the object you're getting back MUST > be the same one that's passed in but dispatch() has no return type: > > /** @var Foo $event **/ > $event = $dispatcher->dispatch(new Foo()); > > The second I can see being easily handled by this syntax. The former, how > would that look? > > Third thought: Casting is the wrong name here, and feels also misleading > as a syntax. (float)$anInt means "type coerce this thing into a float", > which cannot error. You're suggesting (Foo)$bar to mean "if this isn't > already a Foo, throw." That's a very different behavior semantic for the > same syntax. Is that a land mine? I would expect (Foo)$bar to mean > "recast $bar into an instance of Foo if possible, and error if not". > Which... I suppose "is it already" is a subcase of that, but it's still not > the behavior I'd expect from that syntax. > > --Larry Garfield > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > > --000000000000b915c30587261df9--