psl icon indicating copy to clipboard operation
psl copied to clipboard

`Type\nonnull()` is not narrowed by phpstan

Open bendavies opened this issue 1 year ago • 3 comments

Describe the bug Type\nonnull() is not narrowed by phpstan

To Reproduce

<?php

require __DIR__.'/../vendor/autoload.php';

use Psl\Type;

/**
 * @template T
 *
 * @param T|null $value
 *
 * @ara-assert nonnull $value
 *
 * @psalm-assert T $value
 *
 * @ara-return nonnull
 *
 * @return ($value is null ? never : T)
 */
function assertNotNull(mixed $value): mixed
{

}

function a(?int $i): void
{
    \PHPStan\dumpType($i);
    \PHPStan\dumpType(assertNotNull($i));
}

function b(?int $i): void
{
    \PHPStan\dumpType($i);
    \PHPStan\dumpType(Type\nonnull()->assert($i));
}

Expected behavior First method shows a way (provided by @ondrejmirtes) that this can work in phpstan. The second method use Type\nonnull().

The dumped types here should be int|null followed by int for both dumpTypes. but we get:

  27     Dumped type: int|null
  28     Dumped type: int
  33     Dumped type: int|null
  34     Dumped type: mixed

The Psl version of the function "narrows" int|null to mixed, not int

bendavies avatar Sep 05 '24 21:09 bendavies

You need to dump the type on the line after the assert.

ondrejmirtes avatar Sep 06 '24 03:09 ondrejmirtes

This works as expected:

function b(?int $i): void
{
    \PHPStan\dumpType($i);
    Type\nonnull()->assert($i);
    \PHPStan\dumpType($i);
}

The fact that the returned value is not correctly inferred might be a bug in PHPStan.

ondrejmirtes avatar Sep 06 '24 03:09 ondrejmirtes

Thanks for looking like that. However, all the other PSL types work like i posted in the OP.

i.e. this does not need the dump to be on the line after the insert This works:

function c(?int $i): void
{
    \PHPStan\dumpType($i);
    \PHPStan\dumpType(Type\int()->assert($i));
}

Is this maybe what https://github.com/php-standard-library/phpstan-extension/blob/1.0.x/src/Type/AssertTypeSpecifyingExtension.php is handling, and is not working for Type\nonnull() for some reason?

bendavies avatar Sep 06 '24 08:09 bendavies