Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:119396 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 52638 invoked from network); 23 Jan 2023 15:39:45 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 23 Jan 2023 15:39:45 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id C341318037F for ; Mon, 23 Jan 2023 07:39:44 -0800 (PST) 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.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,HTML_MESSAGE,RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS19151 66.111.4.0/24 X-Spam-Virus: No X-Envelope-From: Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Mon, 23 Jan 2023 07:39:44 -0800 (PST) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id E54BF5C0130 for ; Mon, 23 Jan 2023 10:39:43 -0500 (EST) Received: from imap44 ([10.202.2.94]) by compute1.internal (MEProxy); Mon, 23 Jan 2023 10:39:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ollie.codes; h= cc:content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm3; t=1674488383; x=1674574783; bh=tVhWZUo329 VhyVZSmZDbBJbVSfJnHRPC99iZoTOqhgg=; b=XVA+9h5GxV9MEOZxL6jMTVEacC yfEUN/jEurcAscu50SCVwkeOZ74ZdNQ3ypD/jvROxG/lHbOzy3LBQe7OAmtNmvZ4 fux3/A+7JjbMjswffdgiCRUpcRE8TqohIT/tAElf/ZeTAq2DV+aPEFzHu9SPqzTf gB+vxOKa4jEYfj6VYBMPkEOlsviU9/1s7FD+TSJQMwxJl1RIFQFl4kEl6x6D/k96 B/xyLke5lTxEEnICaeMmjAJxdA7f3YOZMiPyQfh0t2y0HyECo3jnzjifZvk1DOOR lGMCxFnk6q4jqJbGGeBYlWkBlrLnM1ZnH6FxKo8/8YgyMDMDrsuksxBZZHwA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:date:feedback-id :feedback-id:from:from:in-reply-to:in-reply-to:message-id :mime-version:references:reply-to:sender:subject:subject:to:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; t=1674488383; x=1674574783; bh=tVhWZUo329VhyVZSmZDbBJbVSfJn HRPC99iZoTOqhgg=; b=nq82N44sO2cx4I1K3GQZXLgfHQvxJqVTqNh+3SiT/ewU wNGvGubtsIdIfYhUWXs4l5ZlPjdPrbzqeb/EmEnHEwepmhMvvtRZeNH7ETTVN70q cm9ZSAozrUv6ZPvhYf6dv7GphMjdxrw83sqXdI3OdYQKnpPOf+Bnr0N3kpLxCoGR 0pnyi6sLOPRKTaj8CO2Yr6hlx9g7TUAYpu2kJYYwg0x/ezzNwHxq5L+le6AKSD2m PqHf8U14wF5VyU/H/ZPj2XiGmuAaw+wcxyXcvBrD+RNGqHSxml7zXY8dwwKOMCGH w9oEl5WWMii9ooZQ6jTBBqEXQUzddWAx49K1sIZqnQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedruddukedgieejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefofgggkfgjfhffhffvufgtsegrtd erreerredtnecuhfhrohhmpedfqfhllhhivgcutfgvrggufdcuoehphhhpseholhhlihgv rdgtohguvghsqeenucggtffrrghtthgvrhhnpeetueevtddufefhkeeiheetueeiffevle ffgfejgeelteeiveffkeevtddtudehheenucffohhmrghinhepghhithhhuhgsrdgtohhm pdhphhhprdhnvghtnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilh hfrhhomhepphhhphesohhllhhivgdrtghouggvsh X-ME-Proxy: Feedback-ID: i835c46d5:Fastmail Received: by mailuser.nyi.internal (Postfix, from userid 501) id 7BD4336A0073; Mon, 23 Jan 2023 10:39:43 -0500 (EST) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.9.0-alpha0-85-gd6d859e0cf-fm-20230116.001-gd6d859e0 Mime-Version: 1.0 Message-ID: <99bc38dc-3d62-4a1e-a99c-e5daab3d779f@app.fastmail.com> In-Reply-To: <88a59c46-9261-43f1-874d-ffc2f9caff32@app.fastmail.com> References: <8f530a4a-bf48-4259-877e-16ebf8082936@app.fastmail.com> <88a59c46-9261-43f1-874d-ffc2f9caff32@app.fastmail.com> Date: Mon, 23 Jan 2023 15:39:23 +0000 To: =?UTF-8?Q?Bj=C3=B6rn_Larsson?= Content-Type: multipart/alternative; boundary=af095631bcde449aad3cda872ea471d2 Subject: Re: [PHP-DEV] Introduce the abiltiy to use the first-call-callable syntax on non-static methods, statically From: php@ollie.codes ("Ollie Read") --af095631bcde449aad3cda872ea471d2 Content-Type: text/plain You are absolutely correct. I guess the solution would be to handle it differently in this case. Creating a closure from a static method would be fine, as it creates a static closure, but when attempting to create a static closure from a non-static method, it would instead return a closure that errors if it isn't bound to an appropriate object. You'd most likely want to restrict this to public methods only, which would help with the security issues. There's already a check there that throws an error, so we can already tell the difference there, but the tricky part will be in the returned closure. Perhaps something like "BindingClosure" that throws the static error when attempting to call it unbound, or better yet, a more descriptive error about it requiring binding. Would that be feasible? On Sun, Jan 22, 2023, at 8:36 PM, Larry Garfield wrote: > On Sun, Jan 22, 2023, at 11:45 AM, Ollie Read wrote: > > Hello all, > > > > I've created a feature request issue on GitHub (here: > > https://github.com/php/php-src/issues/10414), but I have been advised > > that it's best to post here. > > > > What I would like to introduce/suggest, is the ability to create a > > closure from a method using the first-class-callable syntax (eg: > > MyClass::aMethod(...)), for a non-static method, statically. > > > > Currently, the following code causes an error. > > > > ``` > > class Test { > > public function test(): string { return 'test'; } > > } > > > > $closure = Test::test(...); > > ``` > > > > I understand why the error is thrown, but, and I'm unsure of the > > specifics regarding this, I think we could delay the error until the > > closure was called. The reason for this, is that closures can be bound, > > so if you followed on from the code above, you could do the following: > > > > ``` > > $closure->bindTo(new Test); > > $closure(); > > ``` > > > > The above would bind the closure in $closure to the scope of an object, > > which in this case, is the class that the method belongs to. > > > > The best example I can think, for this, would be when filter a > > collection of instances. If you were using a collection library, you > > would currently have something like the following: > > > > ``` > > $collection->filter(function (Str $string) { > > return !$string->empty(); > > }); > > ``` > > > > Whereas it would be much nicer to have the following: > > > > ``` > > $collection->filter(Str::empty(...)); > > ``` > > > > In this situation, the collection library would be responsible for > > binding the closure to the value it is iterating. > > So you'd implement this yourself elsewhere? > > class Str { > public function empty(): bool { ... } > } > > I don't see in this example how this is any better than what is already currently possible: > > class Str { > public static function empty(Str $s): bool { ... } > } > > $collection->filter(Str::empty(...)); > > > I have limited experience with PHPs source, and C in general, but my > > understanding would be that if we were creating a closure, we would > > skip the check for the static method. The code responsible for handling > > the closure call would most require some additional functionality to > > check if it was bound to a valid instance, returning an error if it > > isn't, and then returning an error if it isn't bound at all and the > > method isn't static. > > > > The more I think about it, the more I think this may require a new type > > of Closure, or at least a runtime applied interface, to help developers > > determine whether a closure was created using first-class-callable > > syntax. > > This is, I think, the important part here, and would be a prerequisite. Right now there's no way (as far as I know) to differentiate a closure that is callable from one that would be callable if it were bound to an object. That's generally not a huge deal in practice as unbound closures are not often used, but what you're suggesting would make them much more likely. Also, a static closure cannot be bound, so you cannot just blindly bind whatever callable you're passed to $this, in your example. (Besides, blindly binding a closure to $this sounds like a great security hole.) > > So for some variant of this to work, I think you'd first need to think through how to (easily and without dipping into reflection) determine if a closure object is bindable (static or not) and if it's already bound. Once that's figured out, then we can see what, if any, short-hand way to make a not-yet-bound closure makes sense. (Which could be FCC syntax or not, I don't know.) > > --Larry Garfield > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > > --- Best Regards, *Ollie Read* --af095631bcde449aad3cda872ea471d2--