Skip to content

Commit 8fca348

Browse files
committed
fix generic alias bare-usage resolution and data-provider parameter signatures
1 parent cb9b9a6 commit 8fca348

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

src/Type/UsefulTypeAliasResolver.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,28 @@ private function resolveLocalTypeAlias(string $aliasName, NameScope $nameScope):
114114

115115
try {
116116
$unresolvedAlias = $localTypeAliases[$aliasName];
117-
$resolvedAliasType = $unresolvedAlias->resolve($this->typeNodeResolver);
117+
118+
// For a generic alias used bare (no type args provided), check whether every
119+
// declared template param has a default value. When they all do, we can
120+
// resolve immediately to a fully-concrete type by passing an empty args list to
121+
// resolveWithArgs() — which then falls back to each param's declared default.
122+
// When at least one param has no default, we keep the raw TemplateType
123+
// placeholders so that MissingTypehintCheck::getRawGenericTypeAliasesUsage()
124+
// can detect the bare-usage error ("does not specify its types: T").
125+
if ($unresolvedAlias->isGeneric()) {
126+
$allHaveDefaults = true;
127+
foreach ($unresolvedAlias->getTemplateTagValueNodes() as $tvn) {
128+
if ($tvn->default === null) {
129+
$allHaveDefaults = false;
130+
break;
131+
}
132+
}
133+
$resolvedAliasType = $allHaveDefaults
134+
? $unresolvedAlias->resolveWithArgs($this->typeNodeResolver, [])
135+
: $unresolvedAlias->resolve($this->typeNodeResolver);
136+
} else {
137+
$resolvedAliasType = $unresolvedAlias->resolve($this->typeNodeResolver);
138+
}
118139
} catch (CircularTypeAliasDefinitionException) {
119140
$resolvedAliasType = new CircularTypeAliasErrorType();
120141
}

tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static function dataOverridingFinalMethod(): array
5656
}
5757

5858
#[DataProvider('dataOverridingFinalMethod')]
59-
public function testOverridingFinalMethod(int $phpVersion, string $contravariantMessage): void
59+
public function testOverridingFinalMethod(int $phpVersion, string $contravariantMessage, string $covariantMessage): void
6060
{
6161
$errors = [
6262
[
@@ -322,7 +322,7 @@ public function testVariadicParameterIsAlwaysOptional(): void
322322
}
323323

324324
#[DataProvider('dataOverridingFinalMethod')]
325-
public function testBug3403(int $phpVersion): void
325+
public function testBug3403(int $phpVersion, string $contravariantMessage, string $covariantMessage): void
326326
{
327327
$this->phpVersionId = $phpVersion;
328328
$this->analyse([__DIR__ . '/data/bug-3403.php'], []);

0 commit comments

Comments
 (0)