Hi Internals,
Here is an RFC for adding a 'mixed' type to the language:
https://wiki.php.net/rfc/mixed_type_v2
The RFC builds on an earlier draft by Michael Moravec.
Part of the motivation for pursuing this RFC was my recent experience
in upgrading an application to PHP 7.4.
Being able to add types to the application made the code much easier
to reason about, but there were places where I couldn't add type info
due to the lack of mixed. That made it hard to see if that piece of
code had been upgraded (but type info couldn't be added), or if that
code still needed to be upgraded.
cheers
Dan
Ack
Hi Internals,
Here is an RFC for adding a 'mixed' type to the language:
https://wiki.php.net/rfc/mixed_type_v2
The RFC builds on an earlier draft by Michael Moravec.Part of the motivation for pursuing this RFC was my recent experience
in upgrading an application to PHP 7.4.Being able to add types to the application made the code much easier
to reason about, but there were places where I couldn't add type info
due to the lack of mixed. That made it hard to see if that piece of
code had been upgraded (but type info couldn't be added), or if that
code still needed to be upgraded.cheers
Dan
Ack
I am not against this, but now that we have Union types what places are there where the currently available type declarations are insufficient? Resource seems like the only remaining gap where you'd be forced to use mixed
instead of a union.
--Larry Garfield
On Mon, Apr 20, 2020 at 8:52 AM Larry Garfield larry@garfieldtech.com
wrote:
Here is an RFC for adding a 'mixed' type to the language:
https://wiki.php.net/rfc/mixed_type_v2I am not against this, but now that we have Union types what places are
there where the currently available type declarations are insufficient?
Resource seems like the only remaining gap where you'd be forced to use
mixed
instead of a union.I imagine some type combinations get pretty wide. Like, this is verbose AF.
null|bool|int|float|string|array|object|resource
For the long term good of the language I'd prefer type aliases (or typedefs
or usings or whatever you want to call them.
use mixed = null|bool|int|float|string|array|object|resource;
use scalar = null|bool|int|float|string;
use number = int|float;
That said, baking 'mixed' in as an implicit alias of the above isn't
problematic for that future.
-Sara
On Mon, Apr 20, 2020 at 8:52 AM Larry Garfield larry@garfieldtech.com
wrote:Here is an RFC for adding a 'mixed' type to the language:
https://wiki.php.net/rfc/mixed_type_v2I am not against this, but now that we have Union types what places are
there where the currently available type declarations are insufficient?
Resource seems like the only remaining gap where you'd be forced to use
mixed
instead of a union.I imagine some type combinations get pretty wide. Like, this is verbose AF.
null|bool|int|float|string|array|object|resource
Sure, but how often is that an actual description of what the code accepts? I... cannot actually envision what code would actually accept that mess. :-)
With union types and stringable already on the way, I'm not sure what other non-hypothetical use cases would still be that fugly that you'd now need to fall back to mixed
. (I still think intersection types are needed, but that's a separate matter.) There may be, but I cannot think of them.
For the long term good of the language I'd prefer type aliases (or typedefs
or usings or whatever you want to call them.use mixed = null|bool|int|float|string|array|object|resource;
use scalar = null|bool|int|float|string;
use number = int|float;
Concur.
That said, baking 'mixed' in as an implicit alias of the above isn't
problematic for that future.-Sara
Concur.
--Larry Garfield
On Mon, Apr 20, 2020 at 5:17 PM Larry Garfield larry@garfieldtech.com
wrote:
On Mon, Apr 20, 2020 at 8:52 AM Larry Garfield larry@garfieldtech.com
wrote:Here is an RFC for adding a 'mixed' type to the language:
https://wiki.php.net/rfc/mixed_type_v2I am not against this, but now that we have Union types what places are
there where the currently available type declarations are insufficient?
Resource seems like the only remaining gap where you'd be forced to use
mixed
instead of a union.I imagine some type combinations get pretty wide. Like, this is
verbose AF.null|bool|int|float|string|array|object|resource
Sure, but how often is that an actual description of what the code
accepts? I... cannot actually envision what code would actually accept
that mess. :-)
I can think of quite a few:
- var_dump, print_r, more generally debugging/logging functions and
wrappers thereof - json_encode, serialize, and more generally serialization and encoding
functions, as return value as well for the inverse operations - database/nosql related functions (bindParam, bindValue) and as return
value from generic functions like fetch() - Xpath::evaluate
- ldap query functions
And wrappers of these extensions could benefit from passing on the mixed
type explicitly.
With union types and stringable already on the way, I'm not sure what
other non-hypothetical use cases would still be that fugly that you'd now
need to fall back tomixed
. (I still think intersection types are
needed, but that's a separate matter.) There may be, but I cannot think of
them.For the long term good of the language I'd prefer type aliases (or
typedefs
or usings or whatever you want to call them.use mixed = null|bool|int|float|string|array|object|resource;
use scalar = null|bool|int|float|string;
use number = int|float;Concur.
That said, baking 'mixed' in as an implicit alias of the above isn't
problematic for that future.-Sara
Concur.
--Larry Garfield
Hi,
just picking on one of the examples:
- json_encode, serialize, and more generally serialization and encoding
functions, as return value as well for the inverse operations
But how would this work for serializing resources, which is part of mixed?
Seems to me exactly this case would benefit from a, albeit long though
more accurate, actual union type.
Hope that makes sense,
- Markus
But how would this work for serializing resources, which is part of mixed?
The point is that many internal functions accept all types (including
resources),
even though they might not do much useful with some of them.
Besides the functions that Benjamin mentioned, I'd add the *printf family
that accept "mixed" parameters to the list.
Seems to me exactly this case would benefit from a, albeit long though
more accurate, actual union type.
Regarding accuracy, I believe the more types you have in an union type, the
less
important exact accuracy is, at least for return types and properties. For
example
if a function has a return type of mixed, I don't consider it a big deal if
the implementation
doesn't actually return 1 type (e.g. resource, null) in practice.
Máté
Sure, but how often is that an actual description of what the code
accepts? I... cannot actually envision what code would actually accept
that mess. :-)I can think of quite a few:
- var_dump, print_r, more generally debugging/logging functions and
wrappers thereof- json_encode, serialize, and more generally serialization and encoding
functions, as return value as well for the inverse operations- database/nosql related functions (bindParam, bindValue) and as return
value from generic functions like fetch()- Xpath::evaluate
- ldap query functions
And wrappers of these extensions could benefit from passing on the mixed
type explicitly.
Valid examples. It would be helpful to add those to the RFC for clarity.
--Larry Garfield
Hi Larry,
Sure, but how often is that an actual description of what the code
accepts? I... cannot actually envision what code would actually accept
that mess. :-)
For example the recently added get_debug_type() function does, along with
dozens of internal functions. Besides messy code, I'm sure that there are
legitimate use-cases for the mixed type in user-land as well.
use mixed = null|bool|int|float|string|array|object|resource;
use scalar = null|bool|int|float|string;
use number = int|float;
I'm really not a fan of type aliases (at least user-land ones), but I also
agree with Sara that these 3 "global" aliases would come handy. Actually, I
was considering to also propose "scalar" and "number" in a later RFC.
Cheers,
Máté
With union types and stringable already on the way, I'm not sure what other non-hypothetical use cases would still be that fugly that you'd now need to fall back to
mixed
.
For instance:
- the parameter of [a wrapper around]
gettype()
or an is_* function - the return of [a generic implementation of]
ArrayAccess::offsetGet() or Iterator::current(), or of a userland
array_value_first() or array_value_last() function
To me, especially the return type declaration can be useful to ensure
that [every code path of] the implementation returns a value.
--
Guilliam Xavier
As Larry was asking for an example.
The ParameterBag::get() function from Symfony (and others) that allows you
to fetch request params, for example. That's a mixed type that could return
different values, depending on your request body. Yes, I can type for all
possible scalar values + null + array, but that's a bit of a PITA and
phpstan would complain nonetheless, as the return type of theParameterBag
::get() function is "mixed" and we can't change that. Right now we're
annotating "mixed" with a docblock.
So yes, a "mixed" type is greatly appreciated when dealing with user input.
Thanks!
On Mon, Apr 20, 2020 at 6:41 PM Guilliam Xavier guilliam.xavier@gmail.com
wrote:
On Mon, Apr 20, 2020 at 5:17 PM Larry Garfield larry@garfieldtech.com
wrote:With union types and stringable already on the way, I'm not sure what
other non-hypothetical use cases would still be that fugly that you'd now
need to fall back tomixed
.For instance:
- the parameter of [a wrapper around]
gettype()
or an is_* function- the return of [a generic implementation of]
ArrayAccess::offsetGet() or Iterator::current(), or of a userland
array_value_first() or array_value_last() functionTo me, especially the return type declaration can be useful to ensure
that [every code path of] the implementation returns a value.--
Guilliam Xavier
I... cannot actually envision what code would actually accept that mess. :-)
var_dump()
would be one example. Also caches that can store any
userland value would be another reasonably common use.
The general pattern is when you're handling someone else's 'data' and
have no restrictions on what type that data should be. That's actually
the use-case that prompted me to help draft this RFC.
now that we have Union types what places are
there where the currently available type declarations are insufficient?
A type that explicitly allows any type is more forwards compatible
than writing out a union type.
Compare this:
var_dump( mixed $expression [, mixed $... ] ) : void
to:
var_dump( null|bool|int|float|string|array|object|resource $expression
[, null|bool|int|float|string|array|object|resource $... ] ) : void
If/when we add an 'enum' type that is not a child type of any of the
current types, the signature of that function doesn't need to change
if it uses mixed, rather than the written out union type.
Also, the 'fitting on a line' problem.
cheers
Dan
Ack
For the long term good of the language I'd prefer type aliases (or typedefs
or usings or whatever you want to call them.use mixed = null|bool|int|float|string|array|object|resource;
use scalar = null|bool|int|float|string;
use number = int|float;That said, baking 'mixed' in as an implicit alias of the above isn't
problematic for that future.
The scalar
example should be bool|int|float|string
, without null
.
And for mixed
, as already said, we cannot use resource
in union types.
All the more reason to standardize those "aliases" in core?
--
Guilliam Xavier
Le lundi 20 avril 2020, 09:15:24 CEST Sara Golemon a écrit :
use mixed = null|bool|int|float|string|array|object|resource;
use scalar = null|bool|int|float|string;
I’m wondering if null should maybe be left out of these, since ?mixed and ?scalar can be used for this?
--
Côme Chilliet
FusionDirectory - https://www.fusiondirectory.org
On Tue, Apr 21, 2020 at 11:10 AM Côme Chilliet
come.chilliet@fusiondirectory.org wrote:
Le lundi 20 avril 2020, 09:15:24 CEST Sara Golemon a écrit :
use mixed = null|bool|int|float|string|array|object|resource;
use scalar = null|bool|int|float|string;I’m wondering if null should maybe be left out of these, since ?mixed and ?scalar can be used for this?
For mixed, this has been discussed several times, it's defined as the
union of all value types (void aside), including null, according
to its usage in phpDoc (and in Hack, which also has a nonnull type
such that mixed is equivalent to ?nonnull, cf
https://docs.hhvm.com/hack/types/nullable-types).
For scalar, I already replied
(https://externals.io/message/109715#109723) that it should not
include null indeed (according to
https://www.php.net/manual/en/language.types.intro.php and
https://www.php.net/manual/en/function.is-scalar.php).
--
Guilliam Xavier
Hi Internals,
Here is an RFC for adding a 'mixed' type to the language:
https://wiki.php.net/rfc/mixed_type_v2
The RFC builds on an earlier draft by Michael Moravec.Part of the motivation for pursuing this RFC was my recent experience
in upgrading an application to PHP 7.4.Being able to add types to the application made the code much easier
to reason about, but there were places where I couldn't add type info
due to the lack of mixed. That made it hard to see if that piece of
code had been upgraded (but type info couldn't be added), or if that
code still needed to be upgraded.cheers
Dan
Ack--
Hello Danack
Has the type any
been considered? I've discussed that in the
implementation Pull Request with Máté.
Would it be too much to create a sub-voting for the type used here?
Best regards,
Sorry, I don't know what's wrong with my mail client, it just sent the
email with no content. Here's it again.
Hi Dan
Here is an RFC for adding a 'mixed' type to the language:
https://wiki.php.net/rfc/mixed_type_v2
The RFC builds on an earlier draft by Michael Moravec.
I don't have a whole lot to add other than I appreciate this RFC. We
currently can't differentiate between "I didn't bother documenting
this" and "yes, I actually accept all types".
One note: I was wondering if the following code throws an error (it does):
function foo(): mixed {}
foo();
//> Uncaught TypeError: Return value of foo() must be of the type
mixed, none returned
I found the answer in the tests. Might be worth mentioning in the RFC.
Regards,
Ilija
Hey Dan,
this, I consider one of the few concepts which should never make it into PHP.
In particular, the main problem with mixed is that it is a very easy "I have no idea how to type that properly, so just let's use mixed".
And really, in general, except for some debug functions, mixed is just an excuse to not use proper generics. I cannot think of non-debug scenarios where we are juggling truly unknown types where the type is unidirectional.
(Uni-directional means: there is no corresponding getting/forwarding function for an input.)
Mixed is in almost every case just patching the holes in PHPs type system. And as such, I'd rather promote RFCs trying to properly fix the gaps in the type system than supporting mixed.
Mixed is a hack, do not use mixed.
Bob
P.s.: If you want to migrate your types and have an overview of what's already migrated, maybe just add a comment // type-migrated before or similar? But that's seriously not the business of the language.
Am 20.04.2020 um 13:17 schrieb Dan Ackroyd danack@basereality.com:
Hi Internals,
Here is an RFC for adding a 'mixed' type to the language:
https://wiki.php.net/rfc/mixed_type_v2
The RFC builds on an earlier draft by Michael Moravec.Part of the motivation for pursuing this RFC was my recent experience
in upgrading an application to PHP 7.4.Being able to add types to the application made the code much easier
to reason about, but there were places where I couldn't add type info
due to the lack of mixed. That made it hard to see if that piece of
code had been upgraded (but type info couldn't be added), or if that
code still needed to be upgraded.cheers
Dan
Ack
Mixed is in almost every case just patching the holes in PHPs type system.
And as such, I'd rather promote RFCs trying to properly fix the gaps in the
type system than supporting mixed.Mixed is a hack, do not use mixed.
Heya Bob,
I maintain lots of legacy code and I cannot add return types despite being
truly mixed. Mixed is not a hack, it's a scenario that frequently happens.
There are lots of use-cases where we explicitly want to mark it as such as
it truly accepts anything. Would I use it in new code? Pretty much never,
as string|int
would already cover the majority of cases, especially where
ints are represented by strings.
I would love to see mixed being added as it lets me remove a lot of
docblocks that are only added so I can indicate mixed. I disagree that it's
patching holes, it's filling a gap that's currently missing something.
Regards,
Lynn
I would love to see mixed being added as it lets me remove a lot of
docblocks that are only added so I can indicate mixed. I disagree that it's
patching holes, it's filling a gap that's currently missing something.
I realise it's partly a matter of style, but if I were benevolent dictator
of a legacy code base, I'd prefer to keep the docblocks, and mandate that
all uses of "mixed" should include a comment describing what the parameter
/ return type represents / is related to. Similarly, I wouldn't delete a
docblock for a return type of "array", because I'd want more specific
details (either using "type[]" syntax, "list<type>" syntax, or a comment
describing the "shape" of the array).
I'm not as strongly against adding "mixed" to the language as Bob, but I'm
not convinced I'd ever bother using it.
Regards,
Rowan Tommins
[IMSoP]
I'm not as strongly against adding "mixed" to the language as Bob, but I'm
not convinced I'd ever bother using it.
I'm opposed to the use mixed in codebases – I try as best I can to remove
it from any code I come across, and a static analysis tool I've built flags
the use of mixed types whenever a more specific type is preferable. I even
have an opt-in website devoted to tracking the percentage of non-mixed
types in open-source projects, e.g.
https://shepherd.dev/github/sebastianbergmann/phpunit
Nevertheless, I think mixed should be available as a type hint for the
extreme cases mentioned in this thread (e.g. serialisation). A type system
without an explicit mixed type feels incomplete to me.
Bob Weinand wrote:
Mixed is a hack, do not use mixed.
...
As such the introduction of mixed is pretty much necessary.
I'm actually in favor of introducing it.
Matthew Brown wrote:
I'm opposed to the use mixed in codebases ...
A type system without an explicit mixed type feels incomplete to me.
'I am agree with all'.
Mixed is a vital thing....that should be used as little as possible.
Marco Pivetta wrote:
I think making
mixed
very painful to write may be a big advantage.
Everything is a tradeoff, and I think one of the things that PHP does
well right is allowing people to choose their own tradeoffs, rather
than having a "one true way" of doing things in PHP.
Exceptions, eval(), annotations/attributes, and the mixed type are all
things that have a vital place, even though they can be used
inappropriately.
Making something like this painful to use seems a bad choice. It's
different from things like json_last_error()
or preg_last_error()
where doing the easier thing (of not checking those) is always the
wrong thing.
In particular for people like:
Lynn wrote:
I maintain lots of legacy code and I cannot add
return types despite being truly mixed. Mixed is not a
hack, it's a scenario that frequently happens.
making things more painful for people maintaining legacy code seems
like definitely a bad choice.
Gabriel Caruso wrote:
Has the type
any
been considered?
Yes. I think mixed is the better choice for now.
There's just so much widespread use of 'mixed' in PHP core,
extensions, documentation and userland code that even if 'any' were a
slightly better choice long term, taking a choice that would probably
be multiple years before it paid off it's cost, seems bad.
Ilija Tovilo wrote:
One note: I was wondering if the following
code throws an error (it does):
Thanks, updated the RFC.
cheers
Dan
Ack
Hello,
Is there any update on the RFC? Given that there isn't much discussion and 2
weeks have passed, I believe it's safe to move this into a voting phase.
Best regards,
Benas Seliuginas
Benas IML wrote:
Is there any update on the RFC? Given that there isn't much discussion and 2
weeks have passed, ...
The "two weeks" thing is a minimum.
I personally would prefer if most discussions were longer than that
whenever possible.
It's entirely possible for someone to not have time to even look at
PHP internals during any particular two week period, either through
being busy, or being on holiday, or just being fed-up with internals
and not wanting to look at it for a bit.
But yes, as the "Ensure correct signatures of magic methods" RFC is
being held up by this one, the plan is to open voting tomorrow.
cheers
Dan
Ack
Actually,
I forgot that for proper generics implementations, collections etc. will obviously need to specify "allowing any type". As such the introduction of mixed is pretty much necessary.
As in class Foo<A, B> { … } $foo = new Foo<mixed, int>;
As such, I'm actually in favor of introducing it.
Bob
Am 24.04.2020 um 14:11 schrieb Bob Weinand bobwei9@hotmail.com:
Hey Dan,
this, I consider one of the few concepts which should never make it into PHP.
In particular, the main problem with mixed is that it is a very easy "I have no idea how to type that properly, so just let's use mixed".
And really, in general, except for some debug functions, mixed is just an excuse to not use proper generics. I cannot think of non-debug scenarios where we are juggling truly unknown types where the type is unidirectional.
(Uni-directional means: there is no corresponding getting/forwarding function for an input.)Mixed is in almost every case just patching the holes in PHPs type system. And as such, I'd rather promote RFCs trying to properly fix the gaps in the type system than supporting mixed.
Mixed is a hack, do not use mixed.
Bob
P.s.: If you want to migrate your types and have an overview of what's already migrated, maybe just add a comment // type-migrated before or similar? But that's seriously not the business of the language.
Am 20.04.2020 um 13:17 schrieb Dan Ackroyd danack@basereality.com:
Hi Internals,
Here is an RFC for adding a 'mixed' type to the language:
https://wiki.php.net/rfc/mixed_type_v2
The RFC builds on an earlier draft by Michael Moravec.Part of the motivation for pursuing this RFC was my recent experience
in upgrading an application to PHP 7.4.Being able to add types to the application made the code much easier
to reason about, but there were places where I couldn't add type info
due to the lack of mixed. That made it hard to see if that piece of
code had been upgraded (but type info couldn't be added), or if that
code still needed to be upgraded.cheers
Dan
Ack
Actually,
Really had to laugh, reading your previous and then this mail :-)
I forgot that for proper generics implementations, collections etc. will obviously need to specify "allowing any type". As such the introduction of mixed is pretty much necessary.
As in class Foo<A, B> { … } $foo = new Foo<mixed, int>;
As such, I'm actually in favor of introducing it.
Re-quote:
"allowing any type"
That would make the case for the any
type instead of mixed; IMHO much
more clear.
- Markus
I personally would stick to mixed
. It's used extensively in the official PHP
documentation and has grown with the language. Heck, even static analysis tools
and billions of PHPDoc comments (e. g. Laravel, CakePHP, Yii) use mixed
type.
Switching to any
just doesn't feel right.
Oh and well, I also think that mixed
makes more sense.
Best regards,
Benas Seliuginas
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
Actually,
Really had to laugh, reading your previous and then this mail :-)
I forgot that for proper generics implementations, collections etc. will obviously need to specify "allowing any type". As such the introduction of mixed is pretty much necessary.
As in class Foo<A, B> { … } $foo = new Foo<mixed, int>;
As such, I'm actually in favor of introducing it.Re-quote:
"allowing any type"
That would make the case for the
any
type instead of mixed; IMHO much
more clear.
- Markus
Hey Dan,
Hi Internals,
Here is an RFC for adding a 'mixed' type to the language:
https://wiki.php.net/rfc/mixed_type_v2
The RFC builds on an earlier draft by Michael Moravec.Part of the motivation for pursuing this RFC was my recent experience
in upgrading an application to PHP 7.4.Being able to add types to the application made the code much easier
to reason about, but there were places where I couldn't add type info
due to the lack of mixed. That made it hard to see if that piece of
code had been upgraded (but type info couldn't be added), or if that
code still needed to be upgraded.
How much would you like/be adverse to a rector rule that changes mixed
into a long union type (without resource
in it)?
Considering above posts, mixed
is effectively
null|bool|string|int|float|array|object
, and that the language has the
ability to use this type in 8.0, I think making mixed
very painful to
write may be a big advantage.
resource
is still a massive PITA: not sure if it can be removed within
the decade.
Heck, we may even deprecate signature-less parameters and return types in a
very far future ?
How much would you like/be adverse to a rector rule that changes
mixed
into a long union type (withoutresource
in it)?
Considering above posts,
mixed
is effectively
null|bool|string|int|float|array|object|resource
,
At runtime those things are effectively the same, but in the world of types
mixed has its own distinct meaning – I'd be very averse to any sort of
corresponding replacement.
Actually, it's not quite possible to declare a mixed
type using union types given that it's not possible to make properties as callable (please take a look at my "Typed callable properties" post in the mailing list). As such, if we wanted to make a property hold a callable, we would have to fallback to just not using a type hint at all.
Correct me if I'm wrong but this behavior is addressed in the RFC and we can pass callables to properties that are declared as mixed
, right?
Best regards,
Benas Seliuginas
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
How much would you like/be adverse to a rector rule that changes
mixed
into a long union type (withoutresource
in it)?Considering above posts,
mixed
is effectively
null|bool|string|int|float|array|object|resource
,At runtime those things are effectively the same, but in the world of types
mixed has its own distinct meaning – I'd be very averse to any sort of
corresponding replacement.
Hey moliata,
Actually, it's not quite possible to declare a
mixed
type using union
types given that it's not possible to make properties as callable (please
take a look at my "Typed callable properties" post in the mailing list). As
such, if we wanted to make a property hold a callable, we would have to
fallback to just not using a type hint at all.Correct me if I'm wrong but this behavior is addressed in the RFC and we
can pass callables to properties that are declared asmixed
, right?
The only limitation right now is resource
: callable
is always either an
array
, a string
or an object
that implements __invoke
, so
callable
is a subtype of the union type mentioned few posts above.
Marco Pivetta
Hello,
I did some tests and in fact it seems you're right. Thank you for letting me know, didn't know!
Best regards,
Benas Seliuginas
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
Hey moliata,
Actually, it's not quite possible to declare a
mixed
type using union
types given that it's not possible to make properties as callable (please
take a look at my "Typed callable properties" post in the mailing list). As
such, if we wanted to make a property hold a callable, we would have to
fallback to just not using a type hint at all.
Correct me if I'm wrong but this behavior is addressed in the RFC and we
can pass callables to properties that are declared asmixed
, right?The only limitation right now is
resource
:callable
is always either an
array
, astring
or anobject
that implements__invoke
, so
callable
is a subtype of the union type mentioned few posts above.Marco Pivetta