Skip to content

Commit

Permalink
Regression tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed May 18, 2024
1 parent ca41b7d commit 6d64074
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 0 deletions.
2 changes: 2 additions & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/list-type.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2835.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2443.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5508.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-10254.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2750.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2850.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2863.php');
Expand Down
91 changes: 91 additions & 0 deletions tests/PHPStan/Analyser/data/bug-10254.php
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);

};
57 changes: 57 additions & 0 deletions tests/PHPStan/Analyser/data/bug-5508.php
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);
};
7 changes: 7 additions & 0 deletions tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -276,4 +276,11 @@ public function testBug5592(): void
$this->analyse([__DIR__ . '/data/bug-5592.php'], []);
}

public function testBug10732(): void
{
$this->checkExplicitMixed = true;
$this->checkNullables = true;
$this->analyse([__DIR__ . '/data/bug-10732.php'], []);
}

}
77 changes: 77 additions & 0 deletions tests/PHPStan/Rules/Functions/data/bug-10732.php
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,
);
}

0 comments on commit 6d64074

Please sign in to comment.