-
Notifications
You must be signed in to change notification settings - Fork 464
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Closes phpstan/phpstan#5508 Closes phpstan/phpstan#10254 Closes phpstan/phpstan#10732
- Loading branch information
1 parent
ca41b7d
commit 6d64074
Showing
5 changed files
with
234 additions
and
0 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
<?php | ||
|
||
namespace Bug10254; | ||
|
||
use Closure; | ||
use RuntimeException; | ||
use function PHPStan\Testing\assertType; | ||
|
||
/** | ||
* @template T | ||
*/ | ||
class Option { | ||
/** | ||
* @param T $value | ||
*/ | ||
private function __construct(private mixed $value) | ||
{ | ||
} | ||
|
||
/** | ||
* @template Tv | ||
* @param Tv $value | ||
* @return self<Tv> | ||
*/ | ||
public static function some($value): self | ||
{ | ||
return new self($value); | ||
} | ||
|
||
/** | ||
* @template Tu | ||
* | ||
* @param (Closure(T): Tu) $closure | ||
* | ||
* @return Option<Tu> | ||
*/ | ||
public function map(Closure $closure): self | ||
{ | ||
return new self($closure($this->unwrap())); | ||
} | ||
|
||
/** | ||
* @return T | ||
*/ | ||
public function unwrap() | ||
{ | ||
if ($this->value === null) { | ||
throw new RuntimeException(); | ||
} | ||
|
||
return $this->value; | ||
} | ||
|
||
/** | ||
* @template To | ||
* @param self<To> $other | ||
* @return self<array{0: T, 1: To}> | ||
*/ | ||
public function zip(self $other) | ||
{ | ||
return new self([ | ||
$this->unwrap(), | ||
$other->unwrap() | ||
]); | ||
} | ||
} | ||
|
||
|
||
function (): void { | ||
$value = Option::some(1) | ||
->zip(Option::some(2)); | ||
|
||
assertType('Bug10254\\Option<array{int, int}>', $value); | ||
|
||
$value1 = $value->map(function ($value) { | ||
assertType('int', $value[0]); | ||
assertType('int', $value[1]); | ||
return $value[0] + $value[1]; | ||
}); | ||
|
||
assertType('Bug10254\\Option<int>', $value1); | ||
|
||
$value2 = $value->map(function ($value): int { | ||
assertType('int', $value[0]); | ||
assertType('int', $value[1]); | ||
return $value[0] + $value[1]; | ||
}); | ||
|
||
assertType('Bug10254\\Option<int>', $value2); | ||
|
||
}; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<?php | ||
|
||
namespace Bug5508; | ||
|
||
use function PHPStan\Testing\assertType; | ||
|
||
/** | ||
* @template TKey as array-key | ||
* @template TValue | ||
*/ | ||
class Collection | ||
{ | ||
/** | ||
* @var array<TKey, TValue> | ||
*/ | ||
protected $items = []; | ||
|
||
/** | ||
* @param array<TKey, TValue> $items | ||
* @return void | ||
*/ | ||
public function __construct($items) | ||
{ | ||
$this->items = $items; | ||
} | ||
|
||
/** | ||
* @template TMapValue | ||
* | ||
* @param callable(TValue, TKey): TMapValue $callback | ||
* @return self<TKey, TMapValue> | ||
*/ | ||
public function map(callable $callback) | ||
{ | ||
$keys = array_keys($this->items); | ||
|
||
$items = array_map($callback, $this->items, $keys); | ||
|
||
return new self(array_combine($keys, $items)); | ||
} | ||
|
||
/** | ||
* @return array<TKey, TValue> | ||
*/ | ||
public function all() | ||
{ | ||
return $this->items; | ||
} | ||
} | ||
|
||
function (): void { | ||
$result = (new Collection(['book', 'cars']))->map(function($category) { | ||
return $category; | ||
})->all(); | ||
|
||
assertType('array<int, string>', $result); | ||
}; |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?php | ||
|
||
namespace Bug10732; | ||
|
||
/** | ||
* @template-covariant TValue | ||
*/ | ||
class Collection | ||
{ | ||
/** | ||
* Create a new collection. | ||
* | ||
* @param list<TValue> $items | ||
* @return void | ||
*/ | ||
public function __construct(protected array $items = []) {} | ||
|
||
/** | ||
* Run a map over each of the items. | ||
* | ||
* @template TMapValue | ||
* | ||
* @param callable(TValue): TMapValue $callback | ||
* @return static<TMapValue> | ||
*/ | ||
public function map(callable $callback) | ||
{ | ||
return new self(array_map($callback, $this->items)); | ||
} | ||
} | ||
|
||
/** | ||
* I'd expect this to work? | ||
* | ||
* @param Collection<array<string, mixed>> $collection | ||
* @return Collection<array<string, mixed>> | ||
*/ | ||
function current(Collection $collection): Collection | ||
{ | ||
return $collection->map(fn(array $item) => $item); | ||
} | ||
|
||
/** | ||
* Removing the Typehint works | ||
* | ||
* @param Collection<array<string, mixed>> $collection | ||
* @return Collection<array<string, mixed>> | ||
*/ | ||
function removeTypeHint(Collection $collection): Collection | ||
{ | ||
return $collection->map(fn($item) => $item); | ||
} | ||
|
||
/** | ||
* Typehint works for simple type | ||
* | ||
* @param Collection<string> $collection | ||
* @return Collection<string> | ||
*/ | ||
function simplerType(Collection $collection): Collection | ||
{ | ||
return $collection->map(fn(string $item) => $item); | ||
} | ||
|
||
/** | ||
* Typehint works for arrays | ||
* | ||
* @param array<string, array<string, mixed>> $collection | ||
* @return array<string, array<string, mixed>> | ||
*/ | ||
function useArraysInstead(array $collection): array | ||
{ | ||
return array_map( | ||
fn(array $item) => $item, | ||
$collection, | ||
); | ||
} |