fix: 修复生成器返回类型 #31
Merged
韩天峰
merged 3 commits from compiler-keep-generator-retype-covariance into master 1 month ago
9 changed files with 313 additions and 7 deletions
@ -0,0 +1,14 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
interface GeneratorReturnContract |
||||||
|
{ |
||||||
|
public function values(): \Generator; |
||||||
|
} |
||||||
|
|
||||||
|
class GeneratorReturnImplementation implements GeneratorReturnContract |
||||||
|
{ |
||||||
|
public function values(): iterable |
||||||
|
{ |
||||||
|
yield 1; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,57 @@ |
|||||||
|
--TEST-- |
||||||
|
generator re-yielding array elements via foreach with \Generator return type |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
|
||||||
|
function main() |
||||||
|
{ |
||||||
|
$g = test([1, 2, 3]); |
||||||
|
var_dump($g); |
||||||
|
foreach ($g as $value) |
||||||
|
{ |
||||||
|
var_dump($value); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function test(array $array): \Generator |
||||||
|
{ |
||||||
|
foreach ($array as $value) |
||||||
|
{ |
||||||
|
yield $value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// main(); |
||||||
|
?> |
||||||
|
--EXPECTF-- |
||||||
|
object(FiberGenerator)#%d (9) { |
||||||
|
["callback":"FiberGenerator":private]=> |
||||||
|
object(Closure)#%d (2) { |
||||||
|
["function"]=> |
||||||
|
string(19) "stdClass::{closure}" |
||||||
|
["this"]=> |
||||||
|
object(stdClass)#%d (1) { |
||||||
|
["box"]=> |
||||||
|
resource(%d) of type (php::box) |
||||||
|
} |
||||||
|
} |
||||||
|
["fiber":"FiberGenerator":private]=> |
||||||
|
NULL |
||||||
|
["current":"FiberGenerator":private]=> |
||||||
|
NULL |
||||||
|
["key":"FiberGenerator":private]=> |
||||||
|
NULL |
||||||
|
["valid":"FiberGenerator":private]=> |
||||||
|
bool(false) |
||||||
|
["state":"FiberGenerator":private]=> |
||||||
|
int(0) |
||||||
|
["yield_count":"FiberGenerator":private]=> |
||||||
|
int(0) |
||||||
|
["next_index":"FiberGenerator":private]=> |
||||||
|
int(0) |
||||||
|
["return_value":"FiberGenerator":private]=> |
||||||
|
NULL |
||||||
|
} |
||||||
|
int(1) |
||||||
|
int(2) |
||||||
|
int(3) |
||||||
@ -0,0 +1,53 @@ |
|||||||
|
--TEST-- |
||||||
|
generator return type accepts \Generator for methods, nullable and union variants |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
|
||||||
|
class Box |
||||||
|
{ |
||||||
|
public function gen(array $array): \Generator |
||||||
|
{ |
||||||
|
foreach ($array as $value) { |
||||||
|
yield $value * 2; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function nullableGen(array $array): ?\Generator |
||||||
|
{ |
||||||
|
foreach ($array as $value) { |
||||||
|
yield $value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function unionGen(array $array): \Generator|\Iterator |
||||||
|
{ |
||||||
|
foreach ($array as $value) { |
||||||
|
yield $value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main() |
||||||
|
{ |
||||||
|
$b = new Box(); |
||||||
|
foreach ($b->gen([1, 2, 3]) as $v) { |
||||||
|
var_dump($v); |
||||||
|
} |
||||||
|
$g = nullableGen([4, 5]); |
||||||
|
foreach ($g as $v) { |
||||||
|
var_dump($v); |
||||||
|
} |
||||||
|
$u = unionGen([6, 7]); |
||||||
|
foreach ($u as $v) { |
||||||
|
var_dump($v); |
||||||
|
} |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
int(2) |
||||||
|
int(4) |
||||||
|
int(6) |
||||||
|
int(4) |
||||||
|
int(5) |
||||||
|
int(6) |
||||||
|
int(7) |
||||||
@ -0,0 +1,96 @@ |
|||||||
|
--TEST-- |
||||||
|
generator methods implementing interfaces with iterable, nullable and union return types |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
interface GenInterface |
||||||
|
{ |
||||||
|
public function gen(array $array): \Generator; |
||||||
|
} |
||||||
|
|
||||||
|
interface IterableInterface |
||||||
|
{ |
||||||
|
public function it(array $array): iterable; |
||||||
|
|
||||||
|
public function narrowed(array $array): iterable; |
||||||
|
} |
||||||
|
|
||||||
|
interface NullableInterface |
||||||
|
{ |
||||||
|
public function nullable(array $array): ?\Generator; |
||||||
|
} |
||||||
|
|
||||||
|
interface UnionInterface |
||||||
|
{ |
||||||
|
public function union(array $array): \Generator|\Iterator; |
||||||
|
} |
||||||
|
|
||||||
|
class Box implements GenInterface, IterableInterface, NullableInterface, UnionInterface |
||||||
|
{ |
||||||
|
public function gen(array $array): \Generator |
||||||
|
{ |
||||||
|
foreach ($array as $value) { |
||||||
|
yield $value * 2; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function it(array $array): iterable |
||||||
|
{ |
||||||
|
foreach ($array as $value) { |
||||||
|
yield $value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function narrowed(array $array): \Generator |
||||||
|
{ |
||||||
|
foreach ($array as $value) { |
||||||
|
yield $value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function nullable(array $array): ?\Generator |
||||||
|
{ |
||||||
|
foreach ($array as $value) { |
||||||
|
yield $value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function union(array $array): \Generator|\Iterator |
||||||
|
{ |
||||||
|
foreach ($array as $value) { |
||||||
|
yield $value; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main() |
||||||
|
{ |
||||||
|
$box = new Box(); |
||||||
|
foreach ($box->gen([1, 2, 3]) as $v) { |
||||||
|
var_dump($v); |
||||||
|
} |
||||||
|
foreach ($box->it([4, 5]) as $v) { |
||||||
|
var_dump($v); |
||||||
|
} |
||||||
|
foreach ($box->narrowed([10, 11]) as $v) { |
||||||
|
var_dump($v); |
||||||
|
} |
||||||
|
foreach ($box->nullable([6, 7]) as $v) { |
||||||
|
var_dump($v); |
||||||
|
} |
||||||
|
foreach ($box->union([8, 9]) as $v) { |
||||||
|
var_dump($v); |
||||||
|
} |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
int(2) |
||||||
|
int(4) |
||||||
|
int(6) |
||||||
|
int(4) |
||||||
|
int(5) |
||||||
|
int(10) |
||||||
|
int(11) |
||||||
|
int(6) |
||||||
|
int(7) |
||||||
|
int(8) |
||||||
|
int(9) |
||||||
@ -0,0 +1,38 @@ |
|||||||
|
--TEST-- |
||||||
|
generator method implementing an interface that declares \Generator return type |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
interface T |
||||||
|
{ |
||||||
|
public function test(array $array): \Generator; |
||||||
|
} |
||||||
|
|
||||||
|
class TestClass implements T |
||||||
|
{ |
||||||
|
public function test(array $array): \Generator |
||||||
|
{ |
||||||
|
foreach ($array as $value) { |
||||||
|
yield $value; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main() |
||||||
|
{ |
||||||
|
$test = new TestClass; |
||||||
|
$g = $test->test([1, 2, 3]); |
||||||
|
// TypePHP generators return a \FiberGenerator which implements Iterator |
||||||
|
// but is NOT the Zend \Generator class. |
||||||
|
var_dump($g instanceof \Generator); |
||||||
|
var_dump($g instanceof \Iterator); |
||||||
|
foreach ($g as $value) { |
||||||
|
var_dump($value); |
||||||
|
} |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
bool(false) |
||||||
|
bool(true) |
||||||
|
int(1) |
||||||
|
int(2) |
||||||
|
int(3) |
||||||
Loading…
Reference in new issue