Bug #78635 [Com]: [Arrow function] In combination with a "substr" call it returns empty string

From: Date: Fri, 04 Oct 2019 21:22:58 +0000
Subject: Bug #78635 [Com]: [Arrow function] In combination with a "substr" call it returns empty string
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-223092@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=78635&edit=1 ID: 78635 Comment by: daverandom@php.net Reported by: php-0919 at jan-runte dot de Summary: [Arrow function] In combination with a "substr" call it returns empty string Status: Not a bug Type: Bug Package: Scripting Engine problem Operating System: macOS 10.14.6 PHP Version: 7.4.0RC3 Block user comment: N Private report: N New Comment: Further to the last suggestion above, to retain type safety on the proxy it's also possible to do this: $this->substr = fn(string $str, int ...$chunk) => substr($str, ...$chunk); However, it's also worth noting that simply: $this->substr = 'substr'; ...will probably do the job in that particular case :-) Previous Comments: ------------------------------------------------------------------------ [2019-10-04 21:16:04] requinix@php.net substr() is one of the few functions that alters its behavior based on the number of arguments. https://github.com/php/php-src/blob/php-7.4.0RC3/ext/standard/string.c#L2388 Note the "argc > 2" checks. To properly address that in the arrow function you can use a ternary: $this->substr = fn(string $string, int $start, int $length = null) => func_num_args() == 2 ? substr($string, $start) : substr($string, $start, $length); Or better yet, if you're just proxying substr() then you can ignore the arguments and instead $this->substr = fn() => substr(...func_get_args()); ------------------------------------------------------------------------ [2019-10-04 21:15:40] daverandom@php.net See also https://3v4l.org/j1qXn A (not pretty) work around is https://3v4l.org/Wmqru ------------------------------------------------------------------------ [2019-10-04 21:09:05] daverandom@php.net Thank you for taking the time to write to us, but this is not a bug. Please double-check the documentation available at http://www.php.net/manual/ and the instructions on how to report a bug at http://bugs.php.net/how-to-report.php This is not a bug with arrow functions, strictly speaking it's the expected behaviour of substr(). Your code explicitly passes NULL to the 3rd argument of substr(), which is then cast to int and the call ends up being interpreted as substr('search phrase', 6, 0) - which then correctly returns the empty string. https://3v4l.org/8hKAl I have to close this as "not a bug", however I would completely agree with you if you said this is not intuitive behaviour... it is what it is, though, and it's far too late to fix it now :-/ ------------------------------------------------------------------------ [2019-10-04 20:44:20] php-0919 at jan-runte dot de Description: ------------ Installation: phpbrew install 7.4.0RC3 +neutral +mbstring To implement the string functions in a generically manner the arrow function is the way we go. The test script demonstrate the misbehavior of the arrow function if it uses "substr". Without the use of arrow function all is fine. By "mb_substr" in the other hand we have no problems. It is not related to the reporting bugs: - Bug #71648: [DE] substr('abc', 3) returns string(0) "" for php7 - Bug #68863: Inconsistent return from substr() The arrow function has the issue. Test script: --------------- <?php { trait StringFunctionMapper { public Closure $substr; protected ?string $encoding = null; public function setSingleByte(): void { $this->encoding = null; $this->substr = fn (string $string, int $start, int $length = null) => substr($string, $start, $length); } public function setMultiByte(string $encoding = 'UTF-8'): void { $this->encoding = $encoding; $this->substr = fn (string $string, int $start, int $length = null) => mb_substr($string, $start, $length, $this->encoding); } } $temp = new class () { use StringFunctionMapper; }; $temp->setSingleByte(); var_dump(substr("search phrase", 6), ($temp->substr)("search phrase", 6)); $temp->setMultiByte(); var_dump(mb_substr("search phrase", 6), ($temp->substr)("search phrase", 6)); } Expected result: ---------------- string(7) " phrase" string(7) " phrase" string(7) " phrase" string(7) " phrase" Actual result: -------------- string(7) " phrase" string(0) "" string(7) " phrase" string(7) " phrase" ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=78635&edit=1

« previous php.bugs (#223092) next »