Skip to content

[POC][RFC] Nullable Casting (and settype()) #3764

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed

[POC][RFC] Nullable Casting (and settype()) #3764

wants to merge 2 commits into from

Conversation

guilliamxavier
Copy link
Contributor

@guilliamxavier guilliamxavier commented Jan 26, 2019

Just trying to initiate some movement for https://wiki.php.net/rfc/nullable-casting (including settype() as requested in https://externals.io/message/102997#102999) 🙂

/cc @rentalhost (author of the RFC)

I made some choices open to discussion, for example not supporting (?unset) at all but allowing settype($x, '?null') with a notice (which I found simpler for a start).

The new tests are essentially minimally-modified copies of existing ones.

Questions:

  • How to test the OPcache part?
  • How to evaluate the impact on performance?
  • Is defining a new T_NULLABLE_<TYPE>_CAST token for each T_<TYPE>_CAST (except T_UNSET_CAST) like I did, the "right" way?
  • Would adding a new "ZEND_AST_NULLABLE_CAST" node and/or a new "ZEND_NULLABLE_CAST" opcode be better than extending the existing ZEND_AST_CAST and ZEND_CAST with the ZEND_TYPE_NULLABLE flag like I did?

@petk petk added the RFC label Jan 26, 2019
Copy link
Contributor

@carusogabriel carusogabriel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Zend/tests/cast_to_array-nullable.phpt test is been considering as a new Binary file for some reason

@guilliamxavier
Copy link
Contributor Author

guilliamxavier commented Jan 27, 2019

@carusogabriel This is expected.

It's because the file contains some NUL character (in the --EXPECTF-- section, output of a var_dump() of "\0"). GitHub does not show the contents in its diff view but you can click the "View file" button: at line 67 I see string(1) "" but there is actually an invisible NUL between the quotes (see e.g. https://3v4l.org/luX7q, and also https://3v4l.org/j1Q3D).

It was copied as-is from the existing Zend/tests/cast_to_array.phpt (diff between the two files: https://www.diffchecker.com/Zqoo2T6f). Same for the cast_to_object and cast_to_string tests.

(BTW there is a trailing space in ext/tokenizer/tests/token_get_all_variation8-nullable.phpt after <?php at line 21: it was copied as-is from the existing token_get_all_variation8.phpt and is even actually tested at line 43, and I didn't want to introduce extra changes in this PR. Which is why I also didn't change the existing in %s line %d to in %s on line %d in Zend/tests/cast_to_string[-nullable].phpt.)

@guilliamxavier guilliamxavier changed the base branch from master to PHP-7.4 February 2, 2019 17:19
@guilliamxavier
Copy link
Contributor Author

Update: the RFC is now under discussion on internals@: https://externals.io/message/105122

@nikic
Copy link
Member

nikic commented Jan 9, 2020

FWIW re-reading that internals thread, the reception is somewhat mixed, but I think it still makes sense to put the RFC to voting.

@guilliamxavier
Copy link
Contributor Author

@nikic: Thanks for your time. But now we have union types (which I consider much more important than nullable casting, by the way!), so people will probably want the RFC to include the (int|null) $x syntax, and then what about e.g. (int|string) $x or (int|string|null) $x?

Anyway I didn't (and won't) have the time to keep this PR up to date, so it wasn't really making sense to let it open...

@rentalhost
Copy link

@guilliamxavier casting with union types seems a bit confuses and restrict.

For instance, (Foo|Bar) $foobar should be instanceof Foo or instanceof Bar?
Same for your example (int|string|null) $x will returns what exactly? Since (bool) $x will returns a bool.

So I still thinks that nullable casting will works better and will match with an existing feature like typed properties and parameters.

@guilliamxavier
Copy link
Contributor Author

@rentalhost: Casting is only to primitive types, so (Foo|Bar) $foobar would not be a possible cast, just like (Foo) $foobar is not.
As for hypothetical (int|string|null) $x I suppose it could follow the same logic as https://wiki.php.net/rfc/union_types_v2#coercive_typing_mode but I don't want to think too much about it. As I said, "people will probably want" various things (that I personally wouldn't necessarily).

@nikic
Copy link
Member

nikic commented Jan 9, 2020

Good point about the union types. There could indeed be a reasonable expectation that once (?T) is supported, it works with everything allowed in type declarations.

If we had generics (haha), we could do a C++ style cast that would automatically support all types and have the same semantics as weak type coercions:

declare(strict_types=0);
function cast<T>($val): T {
    return $val;
}

$x = cast<?int>($y);
$foo = cast<int|float>($bar);

@rentalhost
Copy link

@guilliamxavier do you think it could be happen at 8.0?

@guilliamxavier
Copy link
Contributor Author

@rentalhost: unlikely, given the lack of consensus (and the increasing divergence of type declarations [now with union types] vs casts [fixed tokens])... But actually I find nikic's idea more promising

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants