Skip to content

Generics method signatures FP with reportMaybesInMethodSignatures #2950

@dktapps

Description

@dktapps

Bug report

It looks like previous generics have some kind of state corruption bug that affects the resolution of generic classes analysed later on.

This bug requires that reportMaybesInMethodSignatures is set to true, so it can't be reproduced on the playground.

Version is 0.12.9.

Code snippet that reproduces the problem

<?php

declare(strict_types=1);

namespace pocketmine\entity2;

use function array_filter;

class BlockFactory{
	/** @var \SplFixedArray<int> */
	private static $fullList = null;

	public static function isRegistered(int $id) : bool{
		$b = self::$fullList[$id << 4]; //removing this line makes problem go away
		return $b !== null;
	}
}

class Attribute{
	public function getId() : int{ return 0; }

	public function isSyncable() : bool{ return false; }
	
	public function isDesynchronized() : bool{ return false; }
	
	public function getValue() : float{ return 0.0; }
	
	public function setValue(float $f) : self{ return $this; }
}

/**
 * @phpstan-implements \ArrayAccess<int, float>
 */
class AttributeMap implements \ArrayAccess{
	/** @var Attribute[] */
	private $attributes = [];

	public function addAttribute(Attribute $attribute) : void{
		$this->attributes[$attribute->getId()] = $attribute;
	}

	public function getAttribute(int $id) : ?Attribute{
		return $this->attributes[$id] ?? null;
	}

	/**
	 * @return Attribute[]
	 */
	public function getAll() : array{
		return $this->attributes;
	}

	/**
	 * @return Attribute[]
	 */
	public function needSend() : array{
		return array_filter($this->attributes, function(Attribute $attribute){
			return $attribute->isSyncable() and $attribute->isDesynchronized();
		});
	}

	/**
	 * @param int $offset
	 */
	public function offsetExists($offset) : bool{
		return isset($this->attributes[$offset]);
	}

	/**
	 * @param int $offset
	 */
	public function offsetGet($offset) : float{
		return $this->attributes[$offset]->getValue();
	}

	/**
	 * @param int   $offset
	 * @param float $value
	 */
	public function offsetSet($offset, $value) : void{
		$this->attributes[$offset]->setValue($value);
	}

	/**
	 * @param int $offset
	 */
	public function offsetUnset($offset) : void{
		throw new \RuntimeException("Could not unset an attribute from an attribute map");
	}
}

Playground doesn't reproduce, but it'll stop the bot complaining: https://phpstan.org/r/c280a23a-c4b2-46b7-a54f-476ca5dd27df

Analysis on level 8 with reportMaybesInMethodSignatures as true.

Expected output

No errors.

Actual output

 ------ ---------------------------------------------------------------------- 
  Line   test2.php                                                             
 ------ ---------------------------------------------------------------------- 
  74     Parameter #1 $offset (int) of method                                  
         pocketmine\entity2\AttributeMap::offsetGet() should be contravariant  
         with parameter $offset (mixed) of method                              
         ArrayAccess<int,float>::offsetGet()                                   
  82     Parameter #1 $offset (int) of method                                  
         pocketmine\entity2\AttributeMap::offsetSet() should be contravariant  
         with parameter $offset (mixed) of method                              
         ArrayAccess<int,float>::offsetSet()                                   
  82     Parameter #2 $value (float) of method                                 
         pocketmine\entity2\AttributeMap::offsetSet() should be contravariant  
         with parameter $value (mixed) of method                               
         ArrayAccess<int,float>::offsetSet()                                   
 ------ ---------------------------------------------------------------------- 

 [ERROR] Found 3 errors                                                           

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions