psalm: Dog/Cat/Animal generic snafu should not be allowed

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

/**
 * @template T
 */
class Collection {
    /**
     * @param T $t
     */
    public function add($t) : void {}
}

/**
 * @param Collection<Animal> $list
 */
function addAnimal(Collection $list) : void {
    $list->add(new Cat());
}

/**
 * @param Collection<Dog> $list
 */
function takesDogList(Collection $list) : void {
    addAnimal($list); // this should be an error
}

Expected: InvalidArgument when passing Collection<Dog> to Collection<Animal> Actual: No issue

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 29 (15 by maintainers)

Most upvoted comments

Oh yeah, if/when that RFC’s accepted I’ll happily update the syntax!

Unfortunately, this should be an error since getSound could alter the collection and add an instance of any other class extending Animal. There are languages that ignore this for convenience but if you want to be safe you’d have to clone the collection or prove that the collection is not altered.