Permalink
Browse files
Fix #2387 - ensure docblock return types are checked
- Loading branch information
|
@@ -731,6 +731,15 @@ public static function checkReturnType( |
|
|
$parent_class |
|
|
); |
|
|
|
|
|
if ($fleshed_out_return_type->check( |
|
|
$function_like_analyzer, |
|
|
$storage->return_type_location, |
|
|
$storage->suppressed_issues, |
|
|
[] |
|
|
) === false) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
if ($classlike_storage && $context->self && $function->name) { |
|
|
$class_template_params = MethodCallAnalyzer::getClassTemplateParams( |
|
|
$codebase, |
|
|
|
@@ -260,6 +260,7 @@ public function checkGenericParams( |
|
|
} |
|
|
|
|
|
$expected_type_params = $class_storage->template_types ?: []; |
|
|
$expected_param_covariants = $class_storage->template_covariants; |
|
|
} else { |
|
|
$expected_type_params = [ |
|
|
'TKey' => [ |
|
@@ -305,7 +306,9 @@ public function checkGenericParams( |
|
|
$suppressed_issues, |
|
|
$phantom_classes, |
|
|
$inferred, |
|
|
$prevent_template_covariance |
|
|
$source instanceof \Psalm\Internal\Analyzer\MethodAnalyzer |
|
|
&& $source->getMethodName() !== '__construct' |
|
|
&& empty($expected_param_covariants[$i]) |
|
|
) === false) { |
|
|
return false; |
|
|
} |
|
|
|
@@ -7,6 +7,7 @@ |
|
|
use Psalm\StatementsSource; |
|
|
use Psalm\Type; |
|
|
use Psalm\Type\Union; |
|
|
use Psalm\Storage\MethodStorage; |
|
|
|
|
|
class TTemplateParam extends \Psalm\Type\Atomic |
|
|
{ |
|
@@ -169,16 +170,20 @@ public function check( |
|
|
&& isset($class_storage->template_covariants[$template_offset]) |
|
|
&& $class_storage->template_covariants[$template_offset] |
|
|
) { |
|
|
if ($source instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer |
|
|
&& $source->getFunctionLikeStorage()->mutation_free |
|
|
$method_storage = $source instanceof \Psalm\Internal\Analyzer\MethodAnalyzer |
|
|
? $source->getFunctionLikeStorage() |
|
|
: null; |
|
|
|
|
|
if ($method_storage instanceof MethodStorage |
|
|
&& $method_storage->mutation_free |
|
|
&& !$method_storage->mutation_free_inferred |
|
|
) { |
|
|
// do nothing |
|
|
} else { |
|
|
if (\Psalm\IssueBuffer::accepts( |
|
|
new \Psalm\Issue\InvalidTemplateParam( |
|
|
'Template param ' . $this->param_name . ' of ' |
|
|
. $this->defining_class . ' is marked covariant and cannot be used' |
|
|
. ' as input to a function', |
|
|
. $this->defining_class . ' is marked covariant and cannot be used here', |
|
|
$code_location |
|
|
), |
|
|
$source->getSuppressedIssues() |
|
|
|
@@ -82,7 +82,7 @@ public function __construct() { |
|
|
/** @param Foo<array{foo: string}> $_ */ |
|
|
function expectsShape($_): void {}', |
|
|
], |
|
|
'allowPassingToCovariantCollection' => [ |
|
|
'allowPassingToCovariantCollectionWithoutExtends' => [ |
|
|
'<?php |
|
|
abstract class Animal { |
|
|
abstract public function getSound() : string; |
|
@@ -454,6 +454,49 @@ function sendFoo($gen): void { |
|
|
sendFoo($gen);', |
|
|
'error_message' => 'InvalidArgument', |
|
|
], |
|
|
'preventCovariantParamMappingToInvariant' => [ |
|
|
'<?php |
|
|
/** @template T */ |
|
|
class InvariantReference |
|
|
{ |
|
|
/** @var T */ |
|
|
private $value; |
|
|
|
|
|
/** @param T $value */ |
|
|
public function __construct($value) |
|
|
{ |
|
|
$this->value = $value; |
|
|
} |
|
|
|
|
|
/** @return T */ |
|
|
public function get() |
|
|
{ |
|
|
return $this->value; |
|
|
} |
|
|
} |
|
|
|
|
|
/** |
|
|
* @template-covariant T |
|
|
*/ |
|
|
class C |
|
|
{ |
|
|
/** @var InvariantReference<T> */ |
|
|
private InvariantReference $reference; |
|
|
|
|
|
/** @param InvariantReference<T> $reference */ |
|
|
public function __construct(InvariantReference $reference) |
|
|
{ |
|
|
$this->reference = $reference; |
|
|
} |
|
|
|
|
|
/** @return InvariantReference<T> */ |
|
|
public function getReference() : InvariantReference |
|
|
{ |
|
|
return $this->reference; |
|
|
} |
|
|
}', |
|
|
'error_message' => 'InvalidTemplateParam' |
|
|
], |
|
|
]; |
|
|
} |
|
|
} |
|
@@ -382,17 +382,17 @@ public function add($item): void |
|
|
class FooFacade |
|
|
{ |
|
|
/** |
|
|
* @template T |
|
|
* @template T as object |
|
|
* @param T $item |
|
|
*/ |
|
|
public function add($item): void |
|
|
public function add(object $item): void |
|
|
{ |
|
|
$foo = $this->ensureFoo([$item]); |
|
|
$foo->add($item); |
|
|
} |
|
|
|
|
|
/** |
|
|
* @template T |
|
|
* @template T as object |
|
|
* @param array<mixed,T> $items |
|
|
* @return Foo<T> |
|
|
*/ |
|
|
0 comments on commit
1e3ecb5