php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #73717 return-types with NULL not handeled properly
Submitted: 2016-12-11 21:07 UTC Modified: 2016-12-17 15:06 UTC
From: spam2 at rhsoft dot net Assigned:
Status: Verified Package: Scripting Engine problem
PHP Version: 7.0.14 OS:
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2016-12-11 21:07 UTC] spam2 at rhsoft dot net
Description:
------------
Fatal error: Uncaught TypeError: Return value of cl_forum::thread_last_timestamp() must be of the type integer, null returned in /mnt/data/www/thelounge.net/contentlounge/cms/modules/forum/api_forum.php:487

why in the world do i need return (int) here in no-strict-types mode
the whole purpose of the return type would be to save the manual casting

Test script:
---------------
  public function thread_last_timestamp(int $thread_id=0): int
  {
   switch($thread_id)
   {
    case 0:  return $this->db->fetch_row($this->db->query('select' . SQL_SMALL_CACHE . 'max(fo_post_timestamp) from ' . sql_prefix . 'forum_posts;', 1, 0))[0];
    default: return $this->db->fetch_row($this->db->query('select' . SQL_SMALL_CACHE . 'max(fo_post_timestamp) from ' . sql_prefix . 'forum_posts where fo_post_tid=' . $thread_id . ';', 1, 0))[0];
   }
  }


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-12-11 23:52 UTC] cmb@php.net
-Status: Open +Status: Verified -Type: Bug +Type: Documentation Problem
 [2016-12-11 23:52 UTC] cmb@php.net
The "Return Type Declarations" RFC explains the reasoning in the section "Disallowing NULL on Return Types"[1]. Apparantly, this info is missing in the  manual proper.

[1] https://wiki.php.net/rfc/return_types#disallowing_null_on_return_types
 [2016-12-12 10:33 UTC] spam2 at rhsoft dot net
well, and both, not allow NULL in return types as well as for params makes the whole typing for int practically unuseable - the same way as float allows int because it's a subset in non-strict-mode NULL should be casted to 0 (int) or false (bool) because otherwise you have to still use (int)$foo and (bool)$foo in your whole code and instead save overhead because the implicit casting you add overhead by the enforced casting of return values in userland code
 [2016-12-12 10:36 UTC] spam2 at rhsoft dot net
luckily at least that below is no longer true because in PHP7 *you must* use int and not integer

// Int is not a valid type declaration
function answer(): int {
    return 42;
}
answer();

Catchable fatal error: Return value of answer() must be an instance of int, integer returned in %s on line %d
 [2016-12-12 11:58 UTC] cmb@php.net
It doesn't make sense to discuss the behavior *here*, because changing it would require an RFC anyway, see <https://wiki.php.net/rfc/howto>.

> // Int is not a valid type declaration

But it is, see <https://3v4l.org/Qoic7>.
 [2016-12-12 12:10 UTC] spam2 at rhsoft dot net
>> // Int is not a valid type declaration
> But it is, see <https://3v4l.org/Qoic7>

what do you see there? what i said "luckily no longer true"
frankly i quoted the RFC you linked to!

change it to integer and you get
Fatal error: Uncaught TypeError: Return value of answer() must be an instance of integer, integer returned

which means you must use "int" and not "integer" and playing around with function typehints shows clearly a incosistence in the RFC's and the real implementations anyways
 [2016-12-12 22:58 UTC] cmb@php.net
> frankly i quoted the RFC you linked to!

Ah, I see. Indeed, the *example* with the `integer` type declaration has been superseded by the "Scalar Type Declarations" RFC[1], which introduced the `int` type declaration. Note that both RFCs had partially been authored at the same time.

> […] and playing around with function typehints shows clearly a incosistence in the RFC's and the real implementations anyways

On an, admittedly, quick glance I haven't been able to find further inconsistencies. Could you please point them out?


[1] <https://wiki.php.net/rfc/scalar_type_hints_v5>
 [2016-12-12 23:19 UTC] spam2 at rhsoft dot net
well try the behavior of types in function params with PHP 5.6 and 7.0 - it was enough while starting palying around that i wrote a internal list mail that our software from now on requires PHP 7.0 unconditional

PHP 5.6 seems to behave like PHP 7.0 with strict mode enabled instead of doing any casting, maybe i just was confused with things like below and gave up

"must be an instance of integer, integer returned" is serious bullshit - really!

return/parameter casting with disabled strict mode when NULL ends in a fatal error instead cast to false/0/'' for scalar types at the end makes the features completly unusable and non-helpful because you gain nothing when you have to cast manually *and* add engine overhead instead get rid of userland casting, burden it to the engine and hope that new versions of PHP/ZendEngine/opcache and even JIT may bring a performance benefit by handle it in C code
 [2016-12-12 23:22 UTC] spam2 at rhsoft dot net
to make it short and clear:

with declare(strict_types=1); throwing fatal errors is fine in case of NULL
with default or declare(strict_types=1); it makes a lot of new language features useless at all
 [2016-12-12 23:26 UTC] spam2 at rhsoft dot net
- with default or declare(strict_types=1);
+ with default or declare(strict_types=0);
 [2016-12-17 15:06 UTC] cmb@php.net
> PHP 5.6 seems to behave like PHP 7.0 with strict mode enabled
> instead of doing any casting, maybe i just was confused with
> things like below and gave up
>
> "must be an instance of integer, integer returned" is serious
> bullshit - really!

Patches are welcome. :-)
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC