Skip to content

Impossible intersection types are not checked at compile time #3706

Open
@Kenny1911

Description

@Kenny1911

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

Activity

iluuu1994

iluuu1994 commented on Sep 1, 2024

@iluuu1994
Member

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

vudaltsov

vudaltsov commented on Sep 1, 2024

@vudaltsov
Contributor

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

iluuu1994

iluuu1994 commented on Sep 1, 2024

@iluuu1994
Member

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.

Girgias

Girgias commented on Sep 1, 2024

@Girgias
Member

@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.

iluuu1994

iluuu1994 commented on Sep 1, 2024

@iluuu1994
Member

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.

cmb69

cmb69 commented on Sep 1, 2024

@cmb69
Member

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

transferred this issue fromphp/php-srcon Sep 1, 2024
changed the title [-]Argument type is intersection, comprised of the classes without common parent[/-] [+]Impossible intersection types are not checked at compile time[/+] on Sep 1, 2024
Girgias

Girgias commented on Sep 9, 2024

@Girgias
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @iluuu1994@cmb69@vudaltsov@Girgias@Kenny1911

        Issue actions

          Impossible intersection types are not checked at compile time · Issue #3706 · php/doc-en