Skip to content

Instantly share code, notes, and snippets.

@veewee
Created September 30, 2022 09:20
Show Gist options
  • Save veewee/3624bd80a4c9d28c4048a8cf51eeb4d5 to your computer and use it in GitHub Desktop.
Save veewee/3624bd80a4c9d28c4048a8cf51eeb4d5 to your computer and use it in GitHub Desktop.
<?php
namespace Psalm\Tests\Template;
use Psalm\Tests\TestCase;
use Psalm\Tests\Traits\ValidCodeAnalysisTestTrait;
class NeverTypeTest extends TestCase
{
use ValidCodeAnalysisTestTrait;
/**
* @return iterable<string,array{code:string,assertions?:array<string,string>,ignored_issues?:list<string>}>
*/
public function providerValidCodeParse(): iterable
{
return [
'neverDuringOptionalConstruction' => [
'code' => '<?php
/**
* @template A
*/
class Config {
/**
* @psalm-assert A is )
* @param (callable(): A)|null $x
*/
public function __construct($x = null)
{}
/**
* @template NewA
* @param (callable(): NewA)|null $x
* @return Config<NewA>
*/
public static function create($x = null)
{
return new self($x);
}
}
$neverA = Config::create();
$neverB = Config::create(null);
$neverC = new Config();
$neverD = new Config(null);
$anyA = Config::create(function () { return "hello"; });
$anyB = new Config(function () { return "hello"; });
',
'assertions' => [
'$neverA' => 'Config<never>',
'$neverB' => 'Config<never>',
'$neverC' => 'Config<never>',
'$neverD' => 'Config<never>',
'$anyA' => 'Config<string>',
'$anyB' => 'Config<string>',
]
],
'conditionalNever' => [
'code' => '<?php
/**
* @template A
*/
class Config {
/**
* @param (callable(): A)|null $x
*/
public function __construct(public $x = null)
{}
}
/**
* @template A
*/
class Client
{
/**
* @param Config<A>|null $config
*/
public function __construct(
private ?Config $config
) {
}
/**
* @return (A is never ? "world" : A)
*/
public function run()
{
$this->config->x ? $this->config->x() : "world";
}
}
$neverConfigA = new Config();
$neverClientA = new Client($neverConfigA);
$neverResultA = $neverClientA->run();
$mixedConfigA = new Config(function () { return "hello"; });
$mixedClientA = new Client($anyConfigA);
$mixedResultA = $neverClientA->run();
',
'assertions' => [
'$neverConfigA' => 'Config<never>',
'$neverClientA' => 'Client<never>',
'$neverResultA' => '"world"',
'$mixedConfigA' => 'Config<string>',
'$mixedClientA' => 'Config<string>',
'$mixedResultA' => 'string',
],
'error_levels' => [],
'php_version' => '8.1',
],
'neverDuringUnion' => [
'code' => '<?php
/**
* @template-covariant T
*/
class Ok
{
/** @param T $v */
public function __construct(
public mixed $v
) {
}
}
class Err
{
public function __construct(
public string $e
) {
}
}
/**
* @template-covariant V
*/
class Result
{
/** @param Ok<V>|Err $val */
private function __construct(
public Ok|Err $val
) {
}
/**
* @template OkType
*
* @param OkType $item
*
* @return self<OkType>
*/
public static function ok($item): self
{
return new self(new Ok($item));
}
/**
* @return self<never>
*/
public static function err(string $error): self
{
return new self(new Err($error));
}
}
$never = Result::err("hello");
$mixed = Result::ok("hello");
',
'assertions' => [
'$never' => 'Result<never>',
'$mixed' => 'Result<string>',
],
'error_levels' => [],
'php_version' => '8.1',
],
];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment