Skip to content

Conversation

@canvural
Copy link
Contributor

@canvural canvural commented Nov 6, 2025

This one does not add too much value, but I just didn't want to do instanceof ErrorType in my extensions 😄

Copy link
Member

@ondrejmirtes ondrejmirtes left a comment

Choose a reason for hiding this comment

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

ApiInstanceofTypeRule should be made aware of this 😊

@ondrejmirtes
Copy link
Member

Do you also feel like doing isNever() + isExplicitNever()? :)

@canvural
Copy link
Contributor Author

canvural commented Nov 7, 2025

Do you also feel like doing isNever() + isExplicitNever()? :)

Didn't ever need that I guess, but sure I can. In a separate PR?

@canvural
Copy link
Contributor Author

canvural commented Nov 10, 2025

The mutations look valid, but I don't know how I can change them in bulk.

Edit: I guess $type instanceof ErrorType could be !$type->isError()->no() and !$type instanceof ErrorType can be $type->isError()->no() ?

@ondrejmirtes
Copy link
Member

I'm not sure how to cover the mutations with tests here. i'm more concerned about the things the issue bot found https://github.com/phpstan/phpstan-src/actions/runs/19215786400, I'm not sure why that's happening.

if ($this->default !== null) {
$recursionGuard = RecursionGuard::runOnObjectIdentity($this->default, fn () => $this->default->describe($level));
if (!$recursionGuard instanceof ErrorType) {
if (is_string($recursionGuard)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this looks fishy

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, definitely weird

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why? It can only be string or ErrorType here. So I thought is_string is ok instead of instanceof


$classHasProperty = RecursionGuard::run($this, static fn (): bool => $classReflection->hasProperty($propertyName));
if ($classHasProperty === true || $classHasProperty instanceof ErrorType) {
if ($classHasProperty !== false) {
Copy link
Contributor

Choose a reason for hiding this comment

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

are we sure this does not change existing logic?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, definitely weird

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, doesn't change it. It can only be bool or ErrorType.

@staabm
Copy link
Contributor

staabm commented Nov 11, 2025

just a gut feeling in case the 2 above comments regarding behaviour changes are not valid:

another source of problems could be

  • class ErrorType extends MixedType
  • class TemplateMixedType extends MixedType

because MixedType - because of substraction logic - might lead to a Maybe.

$containsUnresolvable = false;
TypeTraverser::map($type, static function (Type $type, callable $traverse) use (&$containsUnresolvable): Type {
if ($type instanceof ErrorType) {
if ($type->isError()->yes()) {
Copy link
Contributor Author

@canvural canvural Nov 11, 2025

Choose a reason for hiding this comment

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

@staabm @ondrejmirtes

I debugged a bit and I think the issue bot errors might be valid. It's always an issue with ValueOfType and it comes down to this line. When we do $type->isError() here ValueOfType resolves the underlying value and it resolves to ErrorType. We do not get the issue with instanceof check because that's always ValueOfType vs ErrorType

Does it make sense?

Copy link
Contributor

Choose a reason for hiding this comment

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

#4548 Might help on this.

Copy link
Contributor

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

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

In #4547

$expressionType instanceof NeverType

by

!$expressionType->isNever()->no()

But here you're replacing

$type instanceof ErrorType

by

$type->isError()->yes()

How did you choose ? I feel like we should have consistency...

return TrinaryLogic::createMaybe();
}

public function isError(): TrinaryLogic
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't it just simpler to always return no ?

Cause currently MixedType instanceof ErrorType is just false.

And anyway, I don't think there is a isError()->maybe() used somewhere...

ErrorType extends MixedType for simplicity, but a "real" MixedType is never an error.
And Mixed~Error is not a Type I often saw...


$classHasProperty = RecursionGuard::run($this, static fn (): bool => $classReflection->hasProperty($propertyName));
if ($classHasProperty === true || $classHasProperty instanceof ErrorType) {
if ($classHasProperty !== false) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be easier to understand

if ($classHasProperty === true || $classHasProperty->isError()->yes())

$containsUnresolvable = false;
TypeTraverser::map($type, static function (Type $type, callable $traverse) use (&$containsUnresolvable): Type {
if ($type instanceof ErrorType) {
if ($type->isError()->yes()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

#4548 Might help on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants