doc-en icon indicating copy to clipboard operation
doc-en copied to clipboard

Impossible intersection types are not checked at compile time

Open Kenny1911 opened this issue 1 year ago • 7 comments

Description

The following code:

<?php

class Foo {}

class Bar {}

function test(Foo&Bar $arg): void {}

https://3v4l.org/sKIr0

I use intersection type Foo&Bar for function argument.

Actually, there is no type that would be comparable to Foo&Bar. Therefore, Foo&Bar is equivalent to the type never.

If i use never in argument type, PHP Fatal Error will be thrown. But if i use Foo&Bar, no error will occur.

Resulted in this output:

Nothing

But I expected this output instead:

PHP Fatal error:  Foo&Bar cannot be used as a parameter type

PHP Version

PHP 8.3.11

Operating System

Ubuntu 20.04

Kenny1911 avatar Sep 01 '24 16:09 Kenny1911

Hi @Kenny1911. This is something static analysis can help you with. IMO, this doesn't need solving in the PHP engine, as it will just add more runtime burden. @Girgias thoughts?

https://phpstan.org/r/a1a9efce-9725-40d1-818a-595a25e65c12

iluuu1994 avatar Sep 01 '24 16:09 iluuu1994

@iluuu1994 , however PHP does check int&float, for example. Is it difficult to check this as well?

vudaltsov avatar Sep 01 '24 16:09 vudaltsov

however PHP does check int&float, for example

That's not quite the same:

Fatal error: Type int cannot be part of an intersection type

The engine makes assertions about members of intersection types being class types.

I'm not sure about hard, but at least for Foo&Bar, it would necessarily have to happen at runtime, when both types are available.

iluuu1994 avatar Sep 01 '24 16:09 iluuu1994

@iluuu1994 , however PHP does check int&float, for example. Is it difficult to check this as well?

Yes, as currently class-types are not loaded at compile time except where necessary (for variance checks).

Changing this behaviour would at least require an RFC to allow the engine to autoload classes where previously it was not required.

Checking for int&float is easy as they are built-in types.

Girgias avatar Sep 01 '24 16:09 Girgias

Right. Given this would either require to:

  1. delay the type check until both types are loaded, for which he have no trigger
  2. change behavior and autoload prematurely

I don't think this should be solved.

iluuu1994 avatar Sep 01 '24 17:09 iluuu1994

I agree to WONTFIX, but we should probably improve the documentation on intersection types.

cmb69 avatar Sep 01 '24 18:09 cmb69

Just to note, that this is described in the type declaration page of the documentation.

Girgias avatar Sep 09 '24 15:09 Girgias