Skip to content

Commit

Permalink
Fix invariance composition
Browse files Browse the repository at this point in the history
  • Loading branch information
jiripudil committed Dec 6, 2022
1 parent 2ca6118 commit ca86a9c
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 18 deletions.
4 changes: 4 additions & 0 deletions src/Type/Generic/TemplateTypeVariance.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ public function compose(self $other): self
return self::createInvariant();
}

if ($this->invariant()) {
return self::createInvariant();
}

return $other;
}

Expand Down
24 changes: 20 additions & 4 deletions tests/PHPStan/Rules/Generics/MethodSignatureVarianceRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ public function testRule(): void
35,
],
[
'Template type X is declared as covariant, but occurs in contravariant position in parameter k of method MethodSignatureVariance\Covariant\C::a().',
'Template type X is declared as covariant, but occurs in invariant position in parameter k of method MethodSignatureVariance\Covariant\C::a().',
35,
],
[
'Template type X is declared as covariant, but occurs in invariant position in parameter l of method MethodSignatureVariance\Covariant\C::a().',
35,
],
[
Expand Down Expand Up @@ -91,9 +95,13 @@ public function testRule(): void
65,
],
[
'Template type X is declared as covariant, but occurs in contravariant position in return type of method MethodSignatureVariance\Covariant\C::l().',
'Template type X is declared as covariant, but occurs in invariant position in return type of method MethodSignatureVariance\Covariant\C::l().',
68,
],
[
'Template type X is declared as covariant, but occurs in invariant position in return type of method MethodSignatureVariance\Covariant\C::m().',
71,
],
]);

$this->analyse([__DIR__ . '/data/method-signature-variance-contravariant.php'], [
Expand Down Expand Up @@ -122,7 +130,11 @@ public function testRule(): void
35,
],
[
'Template type X is declared as contravariant, but occurs in covariant position in parameter l of method MethodSignatureVariance\Contravariant\C::a().',
'Template type X is declared as contravariant, but occurs in invariant position in parameter k of method MethodSignatureVariance\Contravariant\C::a().',
35,
],
[
'Template type X is declared as contravariant, but occurs in invariant position in parameter l of method MethodSignatureVariance\Contravariant\C::a().',
35,
],
[
Expand Down Expand Up @@ -154,7 +166,11 @@ public function testRule(): void
65,
],
[
'Template type X is declared as contravariant, but occurs in covariant position in return type of method MethodSignatureVariance\Contravariant\C::m().',
'Template type X is declared as contravariant, but occurs in invariant position in return type of method MethodSignatureVariance\Contravariant\C::l().',
68,
],
[
'Template type X is declared as contravariant, but occurs in invariant position in return type of method MethodSignatureVariance\Contravariant\C::m().',
71,
],
]);
Expand Down
190 changes: 176 additions & 14 deletions tests/PHPStan/Type/Generic/GenericObjectTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,94 @@ public function dataGetReferencedTypeArguments(): array
),
],
],
'param: Out<Invariant<T>>' => [
TemplateTypeVariance::createContravariant(),
new GenericObjectType(D\Out::class, [
new GenericObjectType(D\Invariant::class, [
$templateType('T'),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
'param: In<Invariant<T>>' => [
TemplateTypeVariance::createContravariant(),
new GenericObjectType(D\In::class, [
new GenericObjectType(D\Invariant::class, [
$templateType('T'),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
'param: Invariant<Out<T>>' => [
TemplateTypeVariance::createContravariant(),
new GenericObjectType(D\Invariant::class, [
new GenericObjectType(D\Out::class, [
$templateType('T'),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
'param: Invariant<In<T>>' => [
TemplateTypeVariance::createContravariant(),
new GenericObjectType(D\Invariant::class, [
new GenericObjectType(D\In::class, [
$templateType('T'),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
'param: In<Invariant<Out<T>>>' => [
TemplateTypeVariance::createContravariant(),
new GenericObjectType(D\In::class, [
new GenericObjectType(D\Invariant::class, [
new GenericObjectType(D\Out::class, [
$templateType('T'),
]),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
'param: Out<Invariant<In<T>>>' => [
TemplateTypeVariance::createContravariant(),
new GenericObjectType(D\Out::class, [
new GenericObjectType(D\Invariant::class, [
new GenericObjectType(D\In::class, [
$templateType('T'),
]),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
'return: Invariant<T>' => [
TemplateTypeVariance::createCovariant(),
new GenericObjectType(D\Invariant::class, [
Expand Down Expand Up @@ -544,20 +632,6 @@ public function dataGetReferencedTypeArguments(): array
),
],
],
'return: Out<Invariant<T>>' => [
TemplateTypeVariance::createCovariant(),
new GenericObjectType(D\Out::class, [
new GenericObjectType(D\Invariant::class, [
$templateType('T'),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
'return: In<T>' => [
TemplateTypeVariance::createCovariant(),
new GenericObjectType(D\In::class, [
Expand Down Expand Up @@ -628,6 +702,94 @@ public function dataGetReferencedTypeArguments(): array
),
],
],
'return: Out<Invariant<T>>' => [
TemplateTypeVariance::createCovariant(),
new GenericObjectType(D\Out::class, [
new GenericObjectType(D\Invariant::class, [
$templateType('T'),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
'return: In<Invariant<T>>' => [
TemplateTypeVariance::createCovariant(),
new GenericObjectType(D\In::class, [
new GenericObjectType(D\Invariant::class, [
$templateType('T'),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
'return: Invariant<Out<T>>' => [
TemplateTypeVariance::createCovariant(),
new GenericObjectType(D\Invariant::class, [
new GenericObjectType(D\Out::class, [
$templateType('T'),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
'return: Invariant<In<T>>' => [
TemplateTypeVariance::createCovariant(),
new GenericObjectType(D\Invariant::class, [
new GenericObjectType(D\In::class, [
$templateType('T'),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
'return: In<Invariant<Out<T>>>' => [
TemplateTypeVariance::createCovariant(),
new GenericObjectType(D\In::class, [
new GenericObjectType(D\Invariant::class, [
new GenericObjectType(D\Out::class, [
$templateType('T'),
]),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
'return: Out<Invariant<In<T>>>' => [
TemplateTypeVariance::createCovariant(),
new GenericObjectType(D\Out::class, [
new GenericObjectType(D\Invariant::class, [
new GenericObjectType(D\In::class, [
$templateType('T'),
]),
]),
]),
[
new TemplateTypeReference(
$templateType('T'),
TemplateTypeVariance::createInvariant(),
),
],
],
];
}

Expand Down

0 comments on commit ca86a9c

Please sign in to comment.