From 64fdac33e86ac7f9d6f10c0a9d5310af843cd854 Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Sun, 25 Apr 2021 10:45:43 -0400 Subject: [PATCH] Fix #5641 - types should always be comparable to themselves --- .../Type/Comparator/ScalarTypeComparator.php | 6 ++ tests/TypeComparatorTest.php | 81 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 tests/TypeComparatorTest.php diff --git a/src/Psalm/Internal/Type/Comparator/ScalarTypeComparator.php b/src/Psalm/Internal/Type/Comparator/ScalarTypeComparator.php index a00da2ccf..c6ec7fe3f 100644 --- a/src/Psalm/Internal/Type/Comparator/ScalarTypeComparator.php +++ b/src/Psalm/Internal/Type/Comparator/ScalarTypeComparator.php @@ -265,6 +265,12 @@ class ScalarTypeComparator return true; } + if ($container_type_part instanceof TNonFalsyString + && $input_type_part instanceof TNonFalsyString + ) { + return true; + } + if ($container_type_part instanceof TNonFalsyString && $input_type_part instanceof TNonEmptyString ) { diff --git a/tests/TypeComparatorTest.php b/tests/TypeComparatorTest.php new file mode 100644 index 000000000..98da10b6b --- /dev/null +++ b/tests/TypeComparatorTest.php @@ -0,0 +1,81 @@ +file_provider = new \Psalm\Tests\Internal\Provider\FakeFileProvider(); + + $config = new TestConfig(); + + $providers = new \Psalm\Internal\Provider\Providers( + $this->file_provider, + new \Psalm\Tests\Internal\Provider\FakeParserCacheProvider() + ); + + $this->project_analyzer = new \Psalm\Internal\Analyzer\ProjectAnalyzer( + $config, + $providers + ); + } + + /** + * @dataProvider getAllBasicTypes + */ + public function testTypeAcceptsItself(string $type_string): void + { + $type_1 = \Psalm\Type::parseString($type_string); + $type_2 = \Psalm\Type::parseString($type_string); + + $this->assertTrue( + \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy( + $this->project_analyzer->getCodebase(), + $type_1, + $type_2 + ) + ); + } + + /** + * @return array + */ + public function getAllBasicTypes(): array + { + // these types are not valid without generics attached + $basic_generic_types = [ + 'key-of' => true, + 'arraylike-object' => true, + 'value-of' => true, + 'class-string-map' => true, + 'int-mask-of' => true, + 'int-mask' => true, + 'pure-Closure' => true, + ]; + + $basic_types = array_diff_key( + \Psalm\Internal\Type\TypeTokenizer::PSALM_RESERVED_WORDS, + $basic_generic_types, + [ + 'open-resource' => true, // unverifiable + 'mysql-escaped-string' => true, // deprecated + 'non-empty-countable' => true, // bit weird, maybe a bug? + ] + ); + return array_map( + function ($type) { + return [$type]; + }, + array_keys($basic_types) + ); + } +}