Psalm: yield from $iterable should not be acceptable in a mutation-free context.

Created on 2 Sep 2020  路  4Comments  路  Source: vimeo/psalm

The following should warn about yield from $iter: https://psalm.dev/r/1818600288

bug

All 4 comments

I found these snippets:


https://psalm.dev/r/1818600288

<?php

final class MutatingIterator implements IteratorAggregate {
    public function getIterator(): ArrayIterator {
       print_r('mutating');

       return new ArrayIterator(['foo', 'bar']);   
    }
}

/**
 * @psalm-pure
 */
function foo(iterable $iter): iterable {   
    yield from $iter;
}

$e = foo(new MutatingIterator());

print_r($e);
Psalm output (using commit 6f92846):

No issues!

Another example could be yielding from another generator: https://psalm.dev/r/ad4907e3d4

I found these snippets:


https://psalm.dev/r/ad4907e3d4

<?php

/**
 * @psalm-pure
 */
function foo(iterable $iter): iterable {   
    yield from $iter;
}

/** @return Generator<mixed,int> */
function f() {
    yield 123;
    yield 234;
}
$_e = foo(f());
Psalm output (using commit 73f6fcd):

No issues!

Would it make sense to introduce a pure-iterator and a regular iterator similar to the callable types introduced in v3.15?

The reason why I ask is for functions like these:
https://psalm.dev/r/1818600288

In this case, map looks like a pure function (at least if you write it in regular arrays), but the iterable part might make it inpure if you mess up the getIterator() function.

This way you can also make distinctions between iterators that have:

  • static (pure) data like read-only in-memory arrays (or an IteratorAggregate which yields from this array)
  • inpure data from e.g. an external data source
Was this page helpful?
0 / 5 - 0 ratings

Related issues

staabm picture staabm  路  3Comments

vudaltsov picture vudaltsov  路  3Comments

LeSuisse picture LeSuisse  路  3Comments

muglug picture muglug  路  3Comments

ErikBooijCB picture ErikBooijCB  路  4Comments