Skip to content

Wrong resolving of generics inside try/catch block #6353

@honzatrtik

Description

@honzatrtik

Code snippet that reproduces the problem

https://phpstan.org/r/ecf86117-177b-439c-b8e3-4e3040a8b6e2

Ends with
Function fromCallbackThatCanThrow() should return Option<T> but returns Option<*NEVER*>.

Additionally, if we set return values to variable as follows:

/**
 * @template T
 * @param callable():T $fn
 * @return Option<T>
 */
function fromCallbackThatCanThrow(callable $fn) {
	try {
		$a = some($fn());
	} catch (Throwable $failure) {
		$a = none();
	}
	return $a;
};

https://phpstan.org/r/dca44c7f-7e85-4f99-a66c-0b4629a25901

then the reported error is even more confusing:
Function fromCallbackThatCanThrow() should return Option<T> but returns Option<*NEVER*>|Option<T>.

If never is subtype of T (its universal subtype - bottom type, so it should be) and T is covariant, then Option<never> should be also subtype of Option<T>. So Option<never>| Option<T> should be Option<T>

Expected output

No errors should be reported

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions