Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for @template-contravariant #1492

Closed
wants to merge 4 commits into from

Conversation

autaut03
Copy link

@autaut03 autaut03 commented Jul 1, 2022

new GenericObjectType(C\Contravariant::class, [new ObjectType('DateTimeInterface')]),
new GenericObjectType(C\Contravariant::class, [new ObjectType('DateTime')]),
TrinaryLogic::createMaybe(),
],
[
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I also add some data sets to dataGetReferencedTypeArguments?

@autaut03
Copy link
Author

autaut03 commented Jul 1, 2022

Also, the tests are failing due to those errors missing. I haven't had time to debug why PHPStan doesn't report them, although I do believe they should be:

-94: Template type K is declared as contravariant, but occurs in invariant position in parameter l of method MethodSignatureVariance\B::a().
-127: Template type K is declared as contravariant, but occurs in invariant position in return type of method MethodSignatureVariance\B::l().
-130: Template type K is declared as contravariant, but occurs in invariant position in return type of method MethodSignatureVariance\B::m().

If somebody can help with those that'd be greatly appreciated :)

edit: Solved by adding the if($this->invariant()) return invariant(); check. Need to verify this is ok

}
if ($other->covariant()) {
return self::createCovariant();
}
return self::createInvariant();
}

if ($this->invariant()) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change has broken some things. But is this change wrong?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is in fact correct, this has also been a bug in PHPStan since 2019. Given the example from the test:

class Base {}
class Extended extends Base {}

/**
 * @template-contravariant K
 */
class B {
	/**
	 * @param Invariant<Out<In<K>>> $l
	 */
	function a($l) {}
}

/**
 * @param B<Extended> $b
 */
function f1($b) {}

/**
 * @param B<Base> $b
 */
function f2($b) {
    f1($b);
}

Without this change, PHPStan would effectively allow changing an invariant type parameter from Out<In<Extended>> to Out<In<Base>>, which is a bug.

@ondrejmirtes Can you verify I'm not wrong so I can fix the tests this has affected?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this has also been a bug in PHPStan since 2019

Can you please show the bug on an existing code on phpstan.org/try? Your example uses @template-contravariant which is a new feature (so it couldn't be a bug in 2019).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing. Here's a similar example with @template-covariant: https://phpstan.org/r/144953ee-3dfd-4606-a558-b373309ef9c5

It should have given the following error, but it currently passes: Template type K is declared as covariant, but occurs in invariant position in parameter a of method C::a().

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any updates on this @ondrejmirtes? I'd love to finish this PR and get it merged

@autaut03
Copy link
Author

autaut03 commented Jul 2, 2022

All the newly reported errors are technically all correct. It doesn't make sense that changing of variance for an extended class is allowed. It is currently covered by other PHPStan rules, but is there a point in doing that?

https://phpstan.org/r/fa55f2f8-8798-47fd-99d7-06c007e44be2

@ondrejmirtes
Copy link
Member

Sorry, I can't review or merge this PR, the build is pretty broken. Please make it green first.

@autaut03
Copy link
Author

Sorry, I can't review or merge this PR, the build is pretty broken. Please make it green first.

Sure. I was just waiting for a response in a thread above. I'll make it green.

@ondrejmirtes
Copy link
Member

Yeah, at the same time I'm not sure about the failures, I need to see how the fixes look like. Is the code that causes the errors the added if ($this->invariant()) {? Does the @template-contravariant feature need that addition or not?

Maybe we could decouple that fix from the rest of the feature, it looks pretty blocking to me.

So maybe the build would be come green by removing the if ($this->invariant()) { and you could send another PR with that to have a discussion about that?

@autaut03
Copy link
Author

Yeah, at the same time I'm not sure about the failures, I need to see how the fixes look like. Is the code that causes the errors the added if ($this->invariant()) {? Does the @template-contravariant feature need that addition or not?

Maybe we could decouple that fix from the rest of the feature, it looks pretty blocking to me.

So maybe the build would be come green by removing the if ($this->invariant()) { and you could send another PR with that to have a discussion about that?

Yeah, it's all caused by that change. Decoupling it sounds good, I'll do that.

@ondrejmirtes
Copy link
Member

Awesome 👍

@ondrejmirtes
Copy link
Member

Hi, I'm cleaning up old and stale PRs. Please send a new PR if you're still interested, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants