phpstan/phpstan

Use of instanceof does not infer correct intersection type

Closed this issue ยท 5 comments

Bug report

If I have a property of type class-string<Model&One&Two&Three> and try to assign a class string of a Model that has previously been checked if it as instance of One, Two and Three, phpstan reports the type for the Model to be class-string<Model>&class-string<One>&class-string<Three>&class-string<Two>.

Code snippet that reproduces the problem

https://phpstan.org/r/d90507d3-8e31-456b-85fe-56e9571aabc6

Expected output

I would expect the outcome to be class-string<Model&One&Two&Three> instead of class-string<Model>&class-string<One>&class-string<Three>&class-string<Two>.

I also had a variation of this reporting where the code is practically the same, but phpstan inferred the type class-string<Model>|class-string<One>|class-string<Three>|class-string<Two> instead. I cannot tell why the playground gives a different result - but both results appear wrong to me.

Possibly related: phpstan/phpstan-phpunit#131

@lupinitylabs After the latest push in 1.8.x, PHPStan now reports different result with your code snippet:

@@ @@
 PHP 8.0 โ€“ 8.1 (1 error)
 ==========
 
-11: Property HelloWorld::$class (class-string<Model&One&Three&Two>|null) does not accept class-string<Model>&class-string<One>&class-string<Three>&class-string<Two>.
+11: Property HelloWorld::$class (class-string<Model&One&Three&Two>|null) does not accept class-string<Model&One&Three&Two>|(class-string<Model>&class-string<One>&class-string<Three>&class-string<Two>).
 
 PHP 7.1 โ€“ 7.4 (3 errors)
 ==========
@@ @@
 
  8: Promoted properties are supported only on PHP 8.0 and later.
 11: Accessing ::class constant on an expression is supported only on PHP 8.0 and later.
-11: Property HelloWorld::$class (class-string<Model&One&Three&Two>|null) does not accept class-string<Model>&class-string<One>&class-string<Three>&class-string<Two>.
+11: Property HelloWorld::$class (class-string<Model&One&Three&Two>|null) does not accept class-string<Model&One&Three&Two>|(class-string<Model>&class-string<One>&class-string<Three>&class-string<Two>).
Full report

PHP 8.0 โ€“ 8.1 (1 error)

Line Error
11 `Property HelloWorld::$class (class-string<Model&One&Three&Two>

PHP 7.1 โ€“ 7.4 (3 errors)

Line Error
8 Promoted properties are supported only on PHP 8.0 and later.
11 Accessing ::class constant on an expression is supported only on PHP 8.0 and later.
11 `Property HelloWorld::$class (class-string<Model&One&Three&Two>

@lupinitylabs After the latest push in 1.8.x, PHPStan now reports different result with your code snippet:

@@ @@
-PHP 8.0 โ€“ 8.1 (1 error)
+PHP 8.0 โ€“ 8.1
 ==========
 
-11: Property HelloWorld::$class (class-string<Model&One&Three&Two>|null) does not accept class-string<Model>&class-string<One>&class-string<Three>&class-string<Two>.
+No errors
 
-PHP 7.1 โ€“ 7.4 (3 errors)
+PHP 7.1 โ€“ 7.4 (2 errors)
 ==========
 
  8: Promoted properties are supported only on PHP 8.0 and later.
-11: Accessing ::class constant on an expression is supported only on PHP 8.0 and later.
-11: Property HelloWorld::$class (class-string<Model&One&Three&Two>|null) does not accept class-string<Model>&class-string<One>&class-string<Three>&class-string<Two>.
+11: Accessing ::class constant on an expression is supported only on PHP 8.0 and later.
Full report

PHP 8.0 โ€“ 8.1

No errors

PHP 7.1 โ€“ 7.4 (2 errors)

Line Error
8 Promoted properties are supported only on PHP 8.0 and later.
11 Accessing ::class constant on an expression is supported only on PHP 8.0 and later.

/cc @rvanvelzen Regression test please :)

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.