Skip to content

Commit

Permalink
Process @psalm-this-out on __construct() as well
Browse files Browse the repository at this point in the history
Fixes #9649
  • Loading branch information
weirdan committed Feb 11, 2024
1 parent ceaea62 commit def0489
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
use Psalm\Internal\Analyzer\FunctionLikeAnalyzer;
use Psalm\Internal\Analyzer\NamespaceAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MethodCallReturnTypeFetcher;
use Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MethodVisibilityAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer;
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
Expand All @@ -21,6 +22,7 @@
use Psalm\Internal\MethodIdentifier;
use Psalm\Internal\Type\TemplateResult;
use Psalm\Internal\Type\TemplateStandinTypeReplacer;
use Psalm\Internal\Type\TypeExpander;
use Psalm\Issue\AbstractInstantiation;
use Psalm\Issue\DeprecatedClass;
use Psalm\Issue\ImpureMethodCall;
Expand Down Expand Up @@ -58,6 +60,7 @@

use function array_map;
use function array_values;
use function count;
use function in_array;
use function md5;
use function preg_match;
Expand Down Expand Up @@ -429,6 +432,8 @@ private static function analyzeNamedConstructor(

$declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id);

$method_storage = null;

if ($declaring_method_id) {
$method_storage = $codebase->methods->getStorage($declaring_method_id);

Expand Down Expand Up @@ -500,6 +505,7 @@ private static function analyzeNamedConstructor(
}

$generic_param_types = null;
$self_out_candidate = null;

if ($storage->template_types) {
foreach ($storage->template_types as $template_name => $base_type) {
Expand Down Expand Up @@ -537,9 +543,49 @@ private static function analyzeNamedConstructor(
'had_template' => true,
]);
}

if ($method_storage && $method_storage->self_out_type) {
$self_out_candidate = $method_storage->self_out_type;

if ($template_result->lower_bounds) {
$self_out_candidate = TypeExpander::expandUnion(
$codebase,
$self_out_candidate,
$fq_class_name,
null,
$storage->parent_class,
true,
false,
false,
true,
);
}

$self_out_candidate = MethodCallReturnTypeFetcher::replaceTemplateTypes(
$self_out_candidate,
$template_result,
$method_id,
count($stmt->getArgs()),
$codebase,
);

$self_out_candidate = TypeExpander::expandUnion(
$codebase,
$self_out_candidate,
$fq_class_name,
$fq_class_name,
$storage->parent_class,
true,
false,
false,
true,
);
$statements_analyzer->node_data->setType($stmt, $self_out_candidate);
}
}

if ($generic_param_types) {
// XXX: what if we need both?
if ($generic_param_types && !$self_out_candidate) {
$result_atomic_type = new TGenericObject(
$fq_class_name,
$generic_param_types,
Expand Down
20 changes: 20 additions & 0 deletions tests/ThisOutTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,26 @@ public function getData(): array { return $this->data; }
'$data3===' => 'list<2|3>',
],
],
'provideDefaultTypeToTypeArguments' => [
'code' => <<<'PHP'
<?php
/** @template T of 'idle'|'running' */
class App {
/** @psalm-this-out self<'idle'> */
public function __construct() {}
/**
* @psalm-if-this-is self<'idle'>
* @psalm-this-out self<'running'>
*/
public function start(): void {}
}
$app = new App();
PHP,
'assertions' => [
'$app===' => "App<'idle'>",
],
],
];
}
}

0 comments on commit def0489

Please sign in to comment.