Created
September 30, 2022 09:20
-
-
Save veewee/3624bd80a4c9d28c4048a8cf51eeb4d5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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