# RFC: Ensure correct signatures of magic methods

- Status: Implemented (PHP 8.0)
- Authors: Gabriel Caruso (carusogabriel@php.net)
- Date: 2020-04-05
- Version: 1.0
- Target: PHP 8.0
- Implementation: https://github.com/php/php-src/pull/4177
- Original: https://wiki.php.net/rfc/magic-methods-signature
- Page: https://externals.io/rfc/magic-methods-signature
- 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

## Votes

### Ensure correct signatures of magic methods (closed)

Yes: 45 · No: 2

Voters: alcaeus (Yes), asgrim (Yes), ashnazg (Yes), beberlei (Yes), bmajdak (Yes), brzuchal (Yes), bwoebi (Yes), carusogabriel (Yes), colinodell (Yes), dams (Yes), danack (Yes), daverandom (Yes), duncan3dc (Yes), duodraco (Yes), galvao (Yes), geekcom (Yes), girgias (Yes), heiglandreas (Yes), jasny (Yes), jbnahan (Yes), jhdxr (No), kalle (Yes), kguest (Yes), klaussilveira (Yes), kocsismate (Yes), marandall (Yes), marcio (Yes), mariano (Yes), mcmic (Yes), mike (Yes), narf (Yes), ocramius (Yes), patrickallaert (Yes), pierrick (Yes), ramsey (Yes), ruudboon (Yes), santiagolizardo (Yes), sergey (Yes), sirsnyder (Yes), stas (No), svpernova09 (Yes), tandre (Yes), trowski (Yes), wyrihaximus (Yes), yunosh (Yes), zeev (Yes), zimt (Yes)

## Discussions on the mailing list

- [\[RFC\] \[DISCUSSION\] Ensure correct magic methods' signatures when typed](https://externals.io/message/109542.md) — started on 2020-04-05, 23 messages
- [\[VOTE\] Ensure correct signatures of magic methods](https://externals.io/message/110301.md) — started on 2020-05-29, 10 messages
- [Drop warning about non-public magic methods](https://externals.io/message/110980.md) — started on 2020-07-13, 5 messages

---

## Introduction

It is currently possible to write magic methods that have signatures that don't match the signature expected, such as *\_\_clone(): float* or *\_\_isset(): Closure*.

This behavior of allowing incorrect signatures was reported as [a bug](https://bugs.php.net/69718).

As ensuring magic methods have correct signatures is a backward compatible break for code that currently has incorrect signatures, this change would only be appropriate in a major PHP release.

## Motivation

PHP's Magic Methods is something that PHP provides allowing developers to track and act on specific changes of behavior of a certain class. Given that fact, the same should ensure that the end-users are using these methods consistently across different codebases.

Since the introduction of types in PHP 7.0, only the checks list below were introduced to make sure that developers are using PHP's magic methods correctly:

- *\_\_clone()* return type: <https://3v4l.org/Ub54p>
- *\_\_construct()* return type: <https://3v4l.org/CCL11>
- *\_\_destruct()* return type: <https://3v4l.org/HNkgW>
- *\_\_toString()* return type: <https://3v4l.org/jIg7b/rfc#git-php-master>

For PHP 8, this RFC aims to expand these checks.

## Proposal

This RFC proposes to add parameter and return types checks per the following details. Other magic methods will be not modified.

The proposal follows the [Magic Methods documentation](https://php.net/oop5.magic).

```php
Foo::__call(string $name, array $arguments): mixed;
 
Foo::__callStatic(string $name, array $arguments): mixed;
 
Foo::__clone(): void;
 
Foo::__debugInfo(): ?array;
 
Foo::__get(string $name): mixed;
 
Foo::__invoke(mixed $arguments): mixed;
 
Foo::__isset(string $name): bool;
 
Foo::__serialize(): array;
 
Foo::__set(string $name, mixed $value): void;
 
Foo::__set_state(array $properties): object;
 
Foo::__sleep(): array;
 
Foo::__unserialize(array $data): void;
 
Foo::__unset(string $name): void;
 
Foo::__wakeup(): void;
```

**Note:** The *\_\_construct()* and *\_\_destruct()* methods won't suffer any changes. They won't allow *void* as a return type given the fact that (almost) all languages, including PHP, don't have the concept of Constructors and Destructors “returning” something after their execution.

## Backward Incompatible Changes

### To Magic Methods without types declared

None.

### To Magic Methods with the wrong signatures

Magic methods' signatures not matching the ones listed above, an error will be thrown, a *Fatal Error* more specific, following the errors of the same kind that are placed today.

## RFC Impact

Scraping the top 1000 Composer packages (using Nikita's [script](https://gist.github.com/nikic/a2bfa3e2f604f66115c3e4b8963a6c72)), [the results](https://gist.github.com/carusogabriel/e0b36e7cd9e6846e04f79008cb7e35d6) show only 7 occurrences of not matching signatures.

Luckily, none of them is a problem as *\_\_call()*, *\_\_callStatic()* and *\_\_get()* do not have checks at this time.

Even with a *mixed* RFC that wouldn't be a problem, as [a specific type can override it](https://github.com/php/php-src/blob/ad7e93a023a9/Zend/tests/type_declarations/mixed/inheritance/mixed_return_inheritance_success2.phpt), by the Liskov Substitution Principle.

## Future Scope

This RFC only aims to add checks for the methods' signatures but as a Future Scope, a runtime check of what is been returning in the methods could be added, same as

- *\_\_serialize()*: <https://3v4l.org/HLiTj>
- *\_\_toString()*: <https://3v4l.org/Dbe6G>
- *\_\_debugInfo()*: <https://3v4l.org/0EEPh>
- *\_\_sleep()*: <https://3v4l.org/dH96A>

## Voting

Voting started on 2020-05-29 at 18h (CEST) and ends on 2020-06-19 at 18h (CEST).

**Vote: Ensure correct signatures of magic methods** — Yes: 45 · No: 2 (closed)

## External resources

\- Discussion thread: <https://externals.io/message/109542>
