# Idea: Warning about named parameters with a missing constructor?

- Thread: https://externals.io/message/112083
- Original archive: https://news-web.php.net/php.internals/112083
- Started by tyson andre on 2020-10-20T23:00:43+00:00
- Messages: 2
- RFC: Named Arguments (Implemented (PHP 8.0)) — https://externals.io/rfc/named_params.md
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #112083 — tyson andre — 2020-10-20T23:00:43+00:00

URL: https://externals.io/message/112083#112083

Hi internals,

Currently, if there is no constructor, php handles it just like `__construct(...$args) {}`,
both for positional and named parameters. Is there any interest in changing that to be a deprecation warning if one or more parameters are passed?
(or if 1 or more named parameters are passed)

The default behavior of missing constructors would result in somewhat surprising behavior
for `new $className(paramName: 123)` if this was used unexpectedly
(silently ignoring it)
(Desired behavior would be to deprecate/warn/throw)

```
php > class A {}
php > var_export(new A(paramName: 123));
A::__set_state(array(
))
php > var_export(new stdClass(paramName: 123));
(object) array(
)
php > var_export(new stdClass(123));
(object) array(
)
```

(I don't think https://wiki.php.net/rfc/named_params mentioned this
(the current behavior follows from handling of extra positional parameters),
and this mistake is probably unlikely in practice,
but if it were to occur it would very likely be a bug)

PHP already throws ArgumentCountError for passing too many parameters for internal methods
so the default method not throwing is a surprise. I haven't yet looked into how much code would break if this were changed.

Aside: If a static analyzer such as Phan, Psalm, or PHPStan are set up, those bugs could be detected easily,
so the impact seems low, but I wonder if this type of bug could cause confusion (or feel unexpected)
for those who are more familiar with other languages than they are with php.

Thanks,
- Tyson

---

## #112088 — Nikita Popov — 2020-10-21T10:15:17+00:00

URL: https://externals.io/message/112083#112088 · In reply to: #112083

On Wed, Oct 21, 2020 at 1:01 AM tyson andre <tysonandre775@hotmail.com>
wrote:

> Hi internals,
>
> Currently, if there is no constructor, php handles it just like
> `__construct(...$args) {}`,
> both for positional and named parameters. Is there any interest in
> changing that to be a deprecation warning if one or more parameters are
> passed?
> (or if 1 or more named parameters are passed)
>
> The default behavior of missing constructors would result in somewhat
> surprising behavior
> for `new $className(paramName: 123)` if this was used unexpectedly
> (silently ignoring it)
> (Desired behavior would be to deprecate/warn/throw)
>
> ```
> php > class A {}
> php > var_export(new A(paramName: 123));
> A::__set_state(array(
> ))
> php > var_export(new stdClass(paramName: 123));
> (object) array(
> )
> php > var_export(new stdClass(123));
> (object) array(
> )
> ```
>
> (I don't think https://wiki.php.net/rfc/named_params mentioned this
> (the current behavior follows from handling of extra positional
> parameters),
> and this mistake is probably unlikely in practice,
> but if it were to occur it would very likely be a bug)
>
> PHP already throws ArgumentCountError for passing too many parameters for
> internal methods
> so the default method not throwing is a surprise. I haven't yet looked
> into how much code would break if this were changed.
>
> Aside: If a static analyzer such as Phan, Psalm, or PHPStan are set up,
> those bugs could be detected easily,
> so the impact seems low, but I wonder if this type of bug could cause
> confusion (or feel unexpected)
> for those who are more familiar with other languages than they are with
> php.
>
> Thanks,
> - Tyson
>

Thanks for bringing this up Tyson!

There's two ways to interpret how this works:
1. We're calling an implicit constructor with signature __construct() {},
in which case unknown named args should not be accepted.
2. We're calling an implicit constructor with signature
__construct(...$args) {}, in which case unknown named args should be
accepted.

I believe we should be following 1. here and have put up
https://github.com/php/php-src/pull/6364 to fix this issue. (This actually
happens to match what we were doing prior to PHP 8, I changed the signature
of the pass function for unrelated reasons without considering this
interaction.)

As to the case of normal positional arguments, I agree that we should move
towards making that an error as well, but this will need a deprecation
phase, as it is long standing behavior. There's also the more general
question of passing additional arguments to userland functions, but that
one is a lot more controversial.

Regards,
Nikita
