1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Fix #4955 - catch invalid passing class constant where templated class string expected

This commit is contained in:
Matt Brown 2021-01-11 00:28:44 -05:00 committed by Daniil Gentili
parent 398f5f9970
commit dfb82b8487
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
2 changed files with 43 additions and 6 deletions

View File

@ -132,7 +132,7 @@ class TemplateStandinTypeReplacer
if ($atomic_type instanceof Atomic\TTemplateParam
&& isset($template_result->template_types[$atomic_type->param_name][$atomic_type->defining_class])
) {
$a = self::handleTemplateParamStandin(
return self::handleTemplateParamStandin(
$atomic_type,
$key,
$input_type,
@ -147,12 +147,10 @@ class TemplateStandinTypeReplacer
$depth,
$had_template
);
return $a;
}
if ($atomic_type instanceof Atomic\TTemplateParamClass
&& isset($template_result->template_types[$atomic_type->param_name])
&& isset($template_result->template_types[$atomic_type->param_name][$atomic_type->defining_class])
) {
if ($replace) {
return self::handleTemplateParamClassStandin(
@ -796,8 +794,6 @@ class TemplateStandinTypeReplacer
$atomic_types = [];
$atomic_types[] = $class_string;
if ($input_type && !$template_result->readonly) {
$valid_input_atomic_types = [];
@ -857,6 +853,25 @@ class TemplateStandinTypeReplacer
);
}
}
} else {
$template_type = $template_result->template_types
[$atomic_type->param_name]
[$atomic_type->defining_class];
foreach ($template_type->getAtomicTypes() as $atomic_type) {
if ($atomic_type instanceof Atomic\TNamedObject) {
$atomic_types[] = new Atomic\TClassString(
$atomic_type->value,
$atomic_type
);
} elseif ($atomic_type instanceof Atomic\TObject) {
$atomic_types[] = new Atomic\TClassString();
}
}
}
if (!$atomic_types) {
$atomic_types[] = $class_string;
}
return $atomic_types;

View File

@ -810,6 +810,28 @@ class FunctionClassStringTemplateTest extends TestCase
}',
'error_message' => 'Closure(object):void'
],
'preventClassStringInPlaceOfTemplatedClassString' => [
'<?php
class ImageFile {}
class MusicFile {}
/**
* @template T of object
*/
interface FileManager {
/**
* @param class-string<T> $instance
* @return T
*/
public function create(string $instance) : object;
}
/** @param FileManager<ImageFile> $m */
function foo(FileManager $m) : void {
$m->create(MusicFile::class);
}',
'error_message' => 'InvalidArgument'
],
];
}
}