Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type\nonnull() is not narrowed by phpstan #486

Open
bendavies opened this issue Sep 5, 2024 · 3 comments
Open

Type\nonnull() is not narrowed by phpstan #486

bendavies opened this issue Sep 5, 2024 · 3 comments
Assignees
Labels
Type: Bug Inconsistencies or issues which will cause an issue or problem for users or implementors.

Comments

@bendavies
Copy link

bendavies commented Sep 5, 2024

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 bendavies added the Type: Bug Inconsistencies or issues which will cause an issue or problem for users or implementors. label Sep 5, 2024
@ondrejmirtes
Copy link
Contributor

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

@ondrejmirtes
Copy link
Contributor

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.

@bendavies
Copy link
Author

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Bug Inconsistencies or issues which will cause an issue or problem for users or implementors.
Projects
None yet
Development

No branches or pull requests

3 participants