From 8e9401e7ae79e357819fa620297a25db73907fd0 Mon Sep 17 00:00:00 2001 From: Can Vural Date: Mon, 10 Nov 2025 11:21:52 +0100 Subject: [PATCH 1/3] add Type::isNever and Type::isExplicitNever methods --- src/Rules/Api/ApiInstanceofTypeRule.php | 2 ++ src/Type/Accessory/AccessoryArrayListType.php | 10 ++++++++++ src/Type/Accessory/AccessoryLiteralStringType.php | 10 ++++++++++ src/Type/Accessory/AccessoryLowercaseStringType.php | 10 ++++++++++ src/Type/Accessory/AccessoryNonEmptyStringType.php | 10 ++++++++++ src/Type/Accessory/AccessoryNonFalsyStringType.php | 10 ++++++++++ src/Type/Accessory/AccessoryNumericStringType.php | 10 ++++++++++ src/Type/Accessory/AccessoryUppercaseStringType.php | 10 ++++++++++ src/Type/Accessory/HasOffsetType.php | 10 ++++++++++ src/Type/Accessory/HasOffsetValueType.php | 10 ++++++++++ src/Type/Accessory/NonEmptyArrayType.php | 10 ++++++++++ src/Type/Accessory/OversizedArrayType.php | 10 ++++++++++ src/Type/CallableType.php | 10 ++++++++++ src/Type/ClosureType.php | 10 ++++++++++ src/Type/FloatType.php | 10 ++++++++++ src/Type/IntersectionType.php | 10 ++++++++++ src/Type/IterableType.php | 10 ++++++++++ src/Type/JustNullableTypeTrait.php | 10 ++++++++++ src/Type/MixedType.php | 10 ++++++++++ src/Type/NeverType.php | 10 ++++++++++ src/Type/NullType.php | 10 ++++++++++ src/Type/ObjectType.php | 10 ++++++++++ src/Type/StaticType.php | 10 ++++++++++ src/Type/StrictMixedType.php | 10 ++++++++++ src/Type/Traits/ArrayTypeTrait.php | 10 ++++++++++ src/Type/Traits/LateResolvableTypeTrait.php | 10 ++++++++++ src/Type/Traits/ObjectTypeTrait.php | 10 ++++++++++ src/Type/Type.php | 4 ++++ src/Type/UnionType.php | 10 ++++++++++ src/Type/VoidType.php | 10 ++++++++++ 30 files changed, 286 insertions(+) diff --git a/src/Rules/Api/ApiInstanceofTypeRule.php b/src/Rules/Api/ApiInstanceofTypeRule.php index 7949b4e51d..c920cb8326 100644 --- a/src/Rules/Api/ApiInstanceofTypeRule.php +++ b/src/Rules/Api/ApiInstanceofTypeRule.php @@ -38,6 +38,7 @@ use PHPStan\Type\IntegerType; use PHPStan\Type\IntersectionType; use PHPStan\Type\IterableType; +use PHPStan\Type\NeverType; use PHPStan\Type\NullType; use PHPStan\Type\ObjectShapeType; use PHPStan\Type\ObjectType; @@ -80,6 +81,7 @@ final class ApiInstanceofTypeRule implements Rule IntersectionType::class => null, ConstantScalarType::class => 'Type::isConstantScalarValue() or Type::getConstantScalarTypes() or Type::getConstantScalarValues()', ObjectShapeType::class => 'Type::isObject() and Type::hasProperty()', + NeverType::class => 'Type::isNever() or Type::isExplicitNever()', // accessory types NonEmptyArrayType::class => 'Type::isIterableAtLeastOnce()', diff --git a/src/Type/Accessory/AccessoryArrayListType.php b/src/Type/Accessory/AccessoryArrayListType.php index d6624108f2..497aa58ff9 100644 --- a/src/Type/Accessory/AccessoryArrayListType.php +++ b/src/Type/Accessory/AccessoryArrayListType.php @@ -433,6 +433,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createNo(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/Accessory/AccessoryLiteralStringType.php b/src/Type/Accessory/AccessoryLiteralStringType.php index abf0b2cbc4..d93d352053 100644 --- a/src/Type/Accessory/AccessoryLiteralStringType.php +++ b/src/Type/Accessory/AccessoryLiteralStringType.php @@ -343,6 +343,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createYes(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/Accessory/AccessoryLowercaseStringType.php b/src/Type/Accessory/AccessoryLowercaseStringType.php index 13ce997f52..553f38533e 100644 --- a/src/Type/Accessory/AccessoryLowercaseStringType.php +++ b/src/Type/Accessory/AccessoryLowercaseStringType.php @@ -340,6 +340,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createYes(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { if ( diff --git a/src/Type/Accessory/AccessoryNonEmptyStringType.php b/src/Type/Accessory/AccessoryNonEmptyStringType.php index a635ea8618..db364bf699 100644 --- a/src/Type/Accessory/AccessoryNonEmptyStringType.php +++ b/src/Type/Accessory/AccessoryNonEmptyStringType.php @@ -335,6 +335,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createYes(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { if ($type->isNull()->yes()) { diff --git a/src/Type/Accessory/AccessoryNonFalsyStringType.php b/src/Type/Accessory/AccessoryNonFalsyStringType.php index dc5548789a..c359b4fba9 100644 --- a/src/Type/Accessory/AccessoryNonFalsyStringType.php +++ b/src/Type/Accessory/AccessoryNonFalsyStringType.php @@ -338,6 +338,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createYes(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { $falseyTypes = StaticTypeFactory::falsey(); diff --git a/src/Type/Accessory/AccessoryNumericStringType.php b/src/Type/Accessory/AccessoryNumericStringType.php index 625c82675d..d3480b9d19 100644 --- a/src/Type/Accessory/AccessoryNumericStringType.php +++ b/src/Type/Accessory/AccessoryNumericStringType.php @@ -343,6 +343,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createYes(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { if ($type->isNull()->yes()) { diff --git a/src/Type/Accessory/AccessoryUppercaseStringType.php b/src/Type/Accessory/AccessoryUppercaseStringType.php index f4f63666fe..bcb209f6a3 100644 --- a/src/Type/Accessory/AccessoryUppercaseStringType.php +++ b/src/Type/Accessory/AccessoryUppercaseStringType.php @@ -340,6 +340,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createYes(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { if ( diff --git a/src/Type/Accessory/HasOffsetType.php b/src/Type/Accessory/HasOffsetType.php index 004c4b8cb8..be47fd1e1d 100644 --- a/src/Type/Accessory/HasOffsetType.php +++ b/src/Type/Accessory/HasOffsetType.php @@ -345,6 +345,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createMaybe(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/Accessory/HasOffsetValueType.php b/src/Type/Accessory/HasOffsetValueType.php index 60a4478a06..3f510d3325 100644 --- a/src/Type/Accessory/HasOffsetValueType.php +++ b/src/Type/Accessory/HasOffsetValueType.php @@ -427,6 +427,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createMaybe(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/Accessory/NonEmptyArrayType.php b/src/Type/Accessory/NonEmptyArrayType.php index d06699b90d..0c05e78cf0 100644 --- a/src/Type/Accessory/NonEmptyArrayType.php +++ b/src/Type/Accessory/NonEmptyArrayType.php @@ -420,6 +420,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createNo(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { if ($type->isArray()->yes() && $type->isIterableAtLeastOnce()->no()) { diff --git a/src/Type/Accessory/OversizedArrayType.php b/src/Type/Accessory/OversizedArrayType.php index d624455997..334afdf791 100644 --- a/src/Type/Accessory/OversizedArrayType.php +++ b/src/Type/Accessory/OversizedArrayType.php @@ -397,6 +397,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createNo(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/CallableType.php b/src/Type/CallableType.php index 6e2c98b88c..0b0af0e106 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -730,6 +730,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createMaybe(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/ClosureType.php b/src/Type/ClosureType.php index 69bc2752f0..287a69ede3 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -823,6 +823,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createNo(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/FloatType.php b/src/Type/FloatType.php index 5df57fe795..867892983c 100644 --- a/src/Type/FloatType.php +++ b/src/Type/FloatType.php @@ -266,6 +266,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createYes(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index 60090bdfaa..bca26d4f70 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -834,6 +834,16 @@ public function isScalar(): TrinaryLogic return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isScalar()); } + public function isNever(): TrinaryLogic + { + return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isNever()); + } + + public function isExplicitNever(): TrinaryLogic + { + return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isExplicitNever()); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return $this->intersectResults( diff --git a/src/Type/IterableType.php b/src/Type/IterableType.php index 46e004ae23..7963e7aa1b 100644 --- a/src/Type/IterableType.php +++ b/src/Type/IterableType.php @@ -412,6 +412,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createNo(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/JustNullableTypeTrait.php b/src/Type/JustNullableTypeTrait.php index 5435c540ff..1b747e470e 100644 --- a/src/Type/JustNullableTypeTrait.php +++ b/src/Type/JustNullableTypeTrait.php @@ -164,6 +164,16 @@ public function getObjectTypeOrClassStringObjectType(): Type return new ErrorType(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function isVoid(): TrinaryLogic { return TrinaryLogic::createNo(); diff --git a/src/Type/MixedType.php b/src/Type/MixedType.php index 80a0bc2f0b..4dfc27e456 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -1071,6 +1071,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createMaybe(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/NeverType.php b/src/Type/NeverType.php index c762202f0b..b5f3e9e750 100644 --- a/src/Type/NeverType.php +++ b/src/Type/NeverType.php @@ -549,6 +549,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createNo(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createYes(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createFromBoolean($this->isExplicit); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/NullType.php b/src/Type/NullType.php index 5c7730ee9f..ca306fbf03 100644 --- a/src/Type/NullType.php +++ b/src/Type/NullType.php @@ -335,6 +335,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createNo(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { if ($type instanceof ConstantScalarType) { diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 85fcc4bf05..091f444606 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -1334,6 +1334,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createNo(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { if ($type->isTrue()->yes()) { diff --git a/src/Type/StaticType.php b/src/Type/StaticType.php index 2876bfb15e..36ae462099 100644 --- a/src/Type/StaticType.php +++ b/src/Type/StaticType.php @@ -682,6 +682,16 @@ public function isScalar(): TrinaryLogic return $this->getStaticObjectType()->isScalar(); } + public function isNever(): TrinaryLogic + { + return $this->getStaticObjectType()->isNever(); + } + + public function isExplicitNever(): TrinaryLogic + { + return $this->getStaticObjectType()->isExplicitNever(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/StrictMixedType.php b/src/Type/StrictMixedType.php index 953cb19054..74a90510f2 100644 --- a/src/Type/StrictMixedType.php +++ b/src/Type/StrictMixedType.php @@ -331,6 +331,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createNo(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/Traits/ArrayTypeTrait.php b/src/Type/Traits/ArrayTypeTrait.php index a019125c3f..a9f5c03ff8 100644 --- a/src/Type/Traits/ArrayTypeTrait.php +++ b/src/Type/Traits/ArrayTypeTrait.php @@ -190,6 +190,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createNo(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function exponentiate(Type $exponent): Type { return new ErrorType(); diff --git a/src/Type/Traits/LateResolvableTypeTrait.php b/src/Type/Traits/LateResolvableTypeTrait.php index 4a5dd1e0b9..98d142af51 100644 --- a/src/Type/Traits/LateResolvableTypeTrait.php +++ b/src/Type/Traits/LateResolvableTypeTrait.php @@ -539,6 +539,16 @@ public function isScalar(): TrinaryLogic return $this->resolve()->isScalar(); } + public function isNever(): TrinaryLogic + { + return $this->resolve()->isNever(); + } + + public function isExplicitNever(): TrinaryLogic + { + return $this->resolve()->isExplicitNever(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/Traits/ObjectTypeTrait.php b/src/Type/Traits/ObjectTypeTrait.php index 51a4922f43..a2d58ae3ad 100644 --- a/src/Type/Traits/ObjectTypeTrait.php +++ b/src/Type/Traits/ObjectTypeTrait.php @@ -275,6 +275,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createNo(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); diff --git a/src/Type/Type.php b/src/Type/Type.php index b5de81b99c..cdb0316dea 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -411,6 +411,10 @@ public function isVoid(): TrinaryLogic; public function isScalar(): TrinaryLogic; + public function isNever(): TrinaryLogic; + + public function isExplicitNever(): TrinaryLogic; + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType; /** diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index c5c9f65415..a1907e6525 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -742,6 +742,16 @@ public function isScalar(): TrinaryLogic return $this->unionResults(static fn (Type $type): TrinaryLogic => $type->isScalar()); } + public function isNever(): TrinaryLogic + { + return $this->unionResults(static fn (Type $type): TrinaryLogic => $type->isNever()); + } + + public function isExplicitNever(): TrinaryLogic + { + return $this->unionResults(static fn (Type $type): TrinaryLogic => $type->isExplicitNever()); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return $this->notBenevolentUnionResults( diff --git a/src/Type/VoidType.php b/src/Type/VoidType.php index ca864245e6..4e72b565b5 100644 --- a/src/Type/VoidType.php +++ b/src/Type/VoidType.php @@ -239,6 +239,16 @@ public function isScalar(): TrinaryLogic return TrinaryLogic::createNo(); } + public function isNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isExplicitNever(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); From 487eb4f21e637031f2fbe7b8e54457255cebb712 Mon Sep 17 00:00:00 2001 From: Can Vural Date: Tue, 11 Nov 2025 00:44:05 +0000 Subject: [PATCH 2/3] replace instanceof NeverType with isNever method --- phpstan-baseline.neon | 18 ++++++++++ src/Analyser/MutatingScope.php | 10 +++--- src/Analyser/NodeScopeResolver.php | 34 +++++++++---------- src/Node/ClassPropertiesNode.php | 3 +- .../Callables/FunctionCallableVariant.php | 3 +- .../InitializerExprTypeResolver.php | 24 ++++++------- .../Php/PhpClassReflectionExtension.php | 3 +- src/Reflection/Php/PhpPropertyReflection.php | 3 +- .../NonexistentOffsetInArrayDimFetchCheck.php | 3 +- .../Comparison/ImpossibleCheckTypeHelper.php | 3 +- src/Rules/Comparison/MatchExpressionRule.php | 3 +- .../CatchWithUnthrownExceptionRule.php | 3 +- .../Exceptions/TooWideThrowTypeCheck.php | 2 +- src/Rules/FunctionCallParametersCheck.php | 5 ++- src/Rules/FunctionDefinitionCheck.php | 3 +- src/Rules/FunctionReturnTypeCheck.php | 3 +- .../Functions/ArrowFunctionReturnTypeRule.php | 7 ++-- ...unctionStatementWithoutSideEffectsRule.php | 3 +- src/Rules/Generators/YieldInGeneratorRule.php | 3 +- src/Rules/IssetCheck.php | 3 +- ...tructorStatementWithoutSideEffectsRule.php | 3 +- ...oMethodStatementWithoutSideEffectsRule.php | 3 +- ...cMethodStatementWithoutSideEffectsRule.php | 3 +- src/Rules/Missing/MissingReturnRule.php | 3 +- src/Rules/PhpDoc/UnresolvableTypeHelper.php | 3 +- src/Rules/Playground/NeverRuleHelper.php | 3 +- .../SetNonVirtualPropertyHookAssignRule.php | 3 +- src/Rules/RuleLevelHelper.php | 3 +- .../ParameterOutExecutionEndTypeRule.php | 3 +- src/Type/ArrayType.php | 12 +++---- src/Type/Constant/ConstantArrayType.php | 2 +- src/Type/ExponentiateHelper.php | 2 +- src/Type/Generic/GenericStaticType.php | 3 +- src/Type/Generic/TemplateTypeMap.php | 7 ++-- src/Type/Generic/TemplateTypeTrait.php | 3 +- src/Type/Generic/TemplateTypeVariance.php | 3 +- src/Type/IntersectionType.php | 2 +- src/Type/MixedType.php | 4 +-- src/Type/NonAcceptingNeverType.php | 2 +- src/Type/ObjectShapeType.php | 2 +- src/Type/ObjectType.php | 4 +-- src/Type/ObjectWithoutClassType.php | 4 +-- src/Type/Php/ArrayColumnHelper.php | 4 +-- .../ArrayFilterFunctionReturnTypeHelper.php | 8 ++--- ...ergeFunctionDynamicReturnTypeExtension.php | 3 +- ...rrayReplaceFunctionReturnTypeExtension.php | 3 +- ...hNumberOperatorTypeSpecifyingExtension.php | 3 +- ...eIntervalConstructorThrowTypeExtension.php | 3 +- .../DateTimeConstructorThrowTypeExtension.php | 3 +- ...DateTimeModifyMethodThrowTypeExtension.php | 3 +- .../Php/DateTimeModifyReturnTypeExtension.php | 2 +- ...eTimeZoneConstructorThrowTypeExtension.php | 3 +- ...ertEncodingFunctionReturnTypeExtension.php | 3 +- ...nFunctionConstructorThrowTypeExtension.php | 3 +- ...ionMethodConstructorThrowTypeExtension.php | 5 ++- ...nPropertyConstructorThrowTypeExtension.php | 5 ++- ...MLElementConstructorThrowTypeExtension.php | 3 +- ...LElementXpathMethodReturnTypeExtension.php | 3 +- src/Type/StaticType.php | 4 +-- src/Type/Traits/LateResolvableTypeTrait.php | 3 +- src/Type/TypeCombinator.php | 16 ++++----- src/Type/TypehintHelper.php | 4 +-- src/Type/UnionType.php | 2 +- .../InitializerExprTypeResolverTest.php | 4 +-- tests/PHPStan/Type/TypeCombinatorTest.php | 12 +++---- 65 files changed, 146 insertions(+), 172 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 23b4baa7a4..d6d2bdc5d7 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1431,6 +1431,18 @@ parameters: count: 1 path: src/Type/IterableType.php + - + rawMessage: 'Doing instanceof PHPStan\Type\NeverType is error-prone and deprecated. Use Type::isNever() or Type::isExplicitNever() instead.' + identifier: phpstanApi.instanceofType + count: 2 + path: src/Type/NeverType.php + + - + rawMessage: 'Doing instanceof PHPStan\Type\NeverType is error-prone and deprecated. Use Type::isNever() or Type::isExplicitNever() instead.' + identifier: phpstanApi.instanceofType + count: 1 + path: src/Type/NonAcceptingNeverType.php + - rawMessage: 'Doing instanceof PHPStan\Type\ConstantScalarType is error-prone and deprecated. Use Type::isConstantScalarValue() or Type::getConstantScalarTypes() or Type::getConstantScalarValues() instead.' identifier: phpstanApi.instanceofType @@ -1773,6 +1785,12 @@ parameters: count: 1 path: src/Type/TypehintHelper.php + - + rawMessage: 'Call to an undefined method PHPStan\Type\Type::isSubTypeOf().' + identifier: method.notFound + count: 1 + path: src/Type/UnionType.php + - rawMessage: 'Doing instanceof PHPStan\Type\CallableType is error-prone and deprecated. Use Type::isCallable() and Type::getCallableParametersAcceptors() instead.' identifier: phpstanApi.instanceofType diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 6be5088a39..a97ea5d8af 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -3643,8 +3643,8 @@ public function removeTypeFromExpression(Expr $expr, Type $typeToRemove): self { $exprType = $this->getType($expr); if ( - $exprType instanceof NeverType || - $typeToRemove instanceof NeverType + !$exprType->isNever()->no() || + !$typeToRemove->isNever()->no() ) { return $this; } @@ -5029,7 +5029,7 @@ private function exactInstantiation(New_ $node, Name $className): Type } $methodResult = $this->getType($methodCall); - if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { + if ($methodResult->isExplicitNever()->yes()) { return $methodResult; } @@ -5468,7 +5468,7 @@ public function getIterableKeyType(Type $iteratee): Type { if ($iteratee instanceof UnionType) { $filtered = $iteratee->filterTypes(static fn (Type $innerType) => $innerType->isIterable()->yes()); - if (!$filtered instanceof NeverType) { + if ($filtered->isNever()->no()) { $iteratee = $filtered; } } @@ -5480,7 +5480,7 @@ public function getIterableValueType(Type $iteratee): Type { if ($iteratee instanceof UnionType) { $filtered = $iteratee->filterTypes(static fn (Type $innerType) => $innerType->isIterable()->yes()); - if (!$filtered instanceof NeverType) { + if ($filtered->isNever()->no()) { $iteratee = $filtered; } } diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index fee23f509e..4e2d88ee09 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -1833,7 +1833,7 @@ private function processStmtNode( } } - $exhaustive = $scopeForBranches->getType($stmt->cond) instanceof NeverType; + $exhaustive = $scopeForBranches->getType($stmt->cond)->isNever()->yes(); if (!$hasDefaultCase && !$exhaustive) { $alwaysTerminating = false; @@ -1978,7 +1978,7 @@ private function processStmtNode( foreach ($throwPoints as $throwPoint) { $newThrowPoint = $throwPoint->subtractCatchType($originalCatchType); - if ($newThrowPoint->getType() instanceof NeverType) { + if (!$newThrowPoint->getType()->isNever()->no()) { continue; } @@ -2553,7 +2553,7 @@ private function findEarlyTerminatingExpr(Expr $expr, Scope $scope): ?Expr } $exprType = $scope->getType($expr); - if ($exprType instanceof NeverType && $exprType->isExplicit()) { + if ($exprType->isExplicitNever()->yes()) { return $expr; } @@ -2803,7 +2803,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto if ($parametersAcceptor !== null) { $normalizedExpr = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $expr) ?? $expr; $returnType = $parametersAcceptor->getReturnType(); - $isAlwaysTerminating = $isAlwaysTerminating || $returnType instanceof NeverType && $returnType->isExplicit(); + $isAlwaysTerminating = $isAlwaysTerminating || $returnType->isExplicitNever()->yes(); } if ( @@ -3156,7 +3156,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto if ($parametersAcceptor !== null) { $normalizedExpr = ArgumentsNormalizer::reorderMethodArguments($parametersAcceptor, $expr) ?? $expr; $returnType = $parametersAcceptor->getReturnType(); - $isAlwaysTerminating = $returnType instanceof NeverType && $returnType->isExplicit(); + $isAlwaysTerminating = $returnType->isExplicitNever()->yes(); } $result = $this->processArgs( @@ -3367,7 +3367,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto if ($parametersAcceptor !== null) { $normalizedExpr = ArgumentsNormalizer::reorderStaticCallArguments($parametersAcceptor, $expr) ?? $expr; $returnType = $parametersAcceptor->getReturnType(); - $isAlwaysTerminating = $returnType instanceof NeverType && $returnType->isExplicit(); + $isAlwaysTerminating = $returnType->isExplicitNever()->yes(); } $result = $this->processArgs($stmt, $methodReflection, null, $parametersAcceptor, $normalizedExpr, $scope, $storage, $nodeCallback, $context, $closureBindScope ?? null); $scope = $result->getScope(); @@ -3600,7 +3600,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto $leftResult = $this->processExprNode($stmt, $expr->left, $scope, $storage, $nodeCallback, $context->enterDeep()); $rightResult = $this->processExprNode($stmt, $expr->right, $leftResult->getTruthyScope(), $storage, $nodeCallback, $context); $rightExprType = $rightResult->getScope()->getType($expr->right); - if ($rightExprType instanceof NeverType && $rightExprType->isExplicit()) { + if ($rightExprType->isExplicitNever()->yes()) { $leftMergedWithRightScope = $leftResult->getFalseyScope(); } else { $leftMergedWithRightScope = $leftResult->getScope()->mergeWith($rightResult->getScope()); @@ -3622,7 +3622,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto $leftResult = $this->processExprNode($stmt, $expr->left, $scope, $storage, $nodeCallback, $context->enterDeep()); $rightResult = $this->processExprNode($stmt, $expr->right, $leftResult->getFalseyScope(), $storage, $nodeCallback, $context); $rightExprType = $rightResult->getScope()->getType($expr->right); - if ($rightExprType instanceof NeverType && $rightExprType->isExplicit()) { + if ($rightExprType->isExplicitNever()->yes()) { $leftMergedWithRightScope = $leftResult->getTruthyScope(); } else { $leftMergedWithRightScope = $leftResult->getScope()->mergeWith($rightResult->getScope()); @@ -3649,7 +3649,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto $rightScope = $scope->filterByFalseyValue($expr); $rightResult = $this->processExprNode($stmt, $expr->right, $rightScope, $storage, $nodeCallback, $context->enterDeep()); $rightExprType = $scope->getType($expr->right); - if ($rightExprType instanceof NeverType && $rightExprType->isExplicit()) { + if ($rightExprType->isExplicitNever()->yes()) { $scope = $scope->filterByTruthyValue(new Expr\Isset_([$expr->left])); } else { $scope = $scope->filterByTruthyValue(new Expr\Isset_([$expr->left]))->mergeWith($rightResult->getScope()); @@ -4090,12 +4090,12 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto } elseif ($condType->isFalse()->yes()) { $finalScope = $ifFalseScope; } else { - if ($ifTrueType instanceof NeverType && $ifTrueType->isExplicit()) { + if ($ifTrueType !== null && $ifTrueType->isExplicitNever()->yes()) { $finalScope = $ifFalseScope; } else { $ifFalseType = $ifFalseScope->getType($expr->else); - if ($ifFalseType instanceof NeverType && $ifFalseType->isExplicit()) { + if ($ifFalseType->isExplicitNever()->yes()) { $finalScope = $ifTrueScope; } else { $finalScope = $ifTrueScope->mergeWith($ifFalseScope); @@ -4355,7 +4355,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto if (!$hasDefaultCond && !$hasAlwaysTrueCond) { $remainingType = $matchScope->getType($expr->cond); - if (!$remainingType instanceof NeverType) { + if ($remainingType->isNever()->no()) { $throwPoints[] = InternalThrowPoint::createExplicit($scope, new ObjectType(UnhandledMatchError::class), $expr, false); } } @@ -4668,7 +4668,7 @@ private function getFunctionThrowPoint( $throwType = $functionReflection->getThrowType(); if ($throwType === null && $parametersAcceptor !== null) { $returnType = $parametersAcceptor->getReturnType(); - if ($returnType instanceof NeverType && $returnType->isExplicit()) { + if ($returnType->isExplicitNever()->yes()) { $throwType = new ObjectType(Throwable::class); } } @@ -4726,7 +4726,7 @@ private function getMethodThrowPoint(MethodReflection $methodReflection, Paramet $throwType = $methodReflection->getThrowType(); if ($throwType === null) { $returnType = $parametersAcceptor->getReturnType(); - if ($returnType instanceof NeverType && $returnType->isExplicit()) { + if ($returnType->isExplicitNever()->yes()) { $throwType = new ObjectType(Throwable::class); } } @@ -5038,7 +5038,7 @@ private function processClosureNode( } $returnType = $closureType->getReturnType(); - $isAlwaysTerminating = ($returnType instanceof NeverType && $returnType->isExplicit()); + $isAlwaysTerminating = ($returnType->isExplicitNever()->yes()); $this->callNodeCallback($nodeCallback, new InClosureNode($closureType, $expr), $closureScope, $storage); @@ -5731,7 +5731,7 @@ private function processArgs( $throwPoints = array_merge($throwPoints, $callableThrowPoints); $impurePoints = array_merge($impurePoints, array_map(static fn (SimpleImpurePoint $impurePoint) => new ImpurePoint($scope, $arg->value, $impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()), $acceptors[0]->getImpurePoints())); $returnType = $acceptors[0]->getReturnType(); - $isAlwaysTerminating = $isAlwaysTerminating || ($returnType instanceof NeverType && $returnType->isExplicit()); + $isAlwaysTerminating = $isAlwaysTerminating || ($returnType->isExplicitNever()->yes()); } } } @@ -7196,7 +7196,7 @@ private function processCalledMethod(MethodReflection $methodReflection): ?Mutat $endNode = $executionEnd->getNode(); if ($endNode instanceof Node\Stmt\Expression) { $exprType = $statementResult->getScope()->getType($endNode->expr); - if ($exprType instanceof NeverType && $exprType->isExplicit()) { + if ($exprType->isExplicitNever()->yes()) { continue; } } diff --git a/src/Node/ClassPropertiesNode.php b/src/Node/ClassPropertiesNode.php index 5f47c928b5..637797d1f6 100644 --- a/src/Node/ClassPropertiesNode.php +++ b/src/Node/ClassPropertiesNode.php @@ -21,7 +21,6 @@ use PHPStan\Reflection\MethodReflection; use PHPStan\Rules\Properties\ReadWritePropertiesExtensionProvider; use PHPStan\TrinaryLogic; -use PHPStan\Type\NeverType; use PHPStan\Type\TypeUtils; use function array_diff_key; use function array_key_exists; @@ -276,7 +275,7 @@ private function collectUninitializedProperties(array $constructors, array $unin if ($statementResult->isAlwaysTerminating()) { if ($endNode instanceof Node\Stmt\Expression) { $exprType = $statementResult->getScope()->getType($endNode->expr); - if ($exprType instanceof NeverType && $exprType->isExplicit()) { + if ($exprType->isExplicitNever()->yes()) { continue; } } diff --git a/src/Reflection/Callables/FunctionCallableVariant.php b/src/Reflection/Callables/FunctionCallableVariant.php index ca45e92e3c..f96fe4a994 100644 --- a/src/Reflection/Callables/FunctionCallableVariant.php +++ b/src/Reflection/Callables/FunctionCallableVariant.php @@ -9,7 +9,6 @@ use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\Generic\TemplateTypeVarianceMap; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use Throwable; @@ -97,7 +96,7 @@ public function getThrowPoints(): array $returnType = $this->variant->getReturnType(); $throwType = $this->function->getThrowType(); if ($throwType === null) { - if ($returnType instanceof NeverType && $returnType->isExplicit()) { + if ($returnType->isExplicitNever()->yes()) { $throwType = new ObjectType(Throwable::class); } } diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index 499f504a7a..6681fb265e 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -916,7 +916,7 @@ public function createFirstClassCallable( $returnTypeForThrow = $variant->getReturnType(); $throwType = $function->getThrowType(); if ($throwType === null) { - if ($returnTypeForThrow instanceof NeverType && $returnTypeForThrow->isExplicit()) { + if ($returnTypeForThrow->isExplicitNever()->yes()) { $throwType = new ObjectType(Throwable::class); } } @@ -972,7 +972,7 @@ public function getBitwiseAndType(Expr $left, Expr $right, callable $getTypeCall public function getBitwiseAndTypeFromTypes(Type $leftType, Type $rightType): Type { - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1030,7 +1030,7 @@ public function getBitwiseOrType(Expr $left, Expr $right, callable $getTypeCallb public function getBitwiseOrTypeFromTypes(Type $leftType, Type $rightType): Type { - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1186,7 +1186,7 @@ public function getSpaceshipType(Expr $left, Expr $right, callable $getTypeCallb public function getSpaceshipTypeFromTypes(Type $leftTypes, Type $rightTypes): Type { - if ($leftTypes instanceof NeverType || $rightTypes instanceof NeverType) { + if ($leftTypes->isNever()->or($rightTypes->isNever())->yes()) { return $this->getNeverType($leftTypes, $rightTypes); } @@ -1283,7 +1283,7 @@ public function getModType(Expr $left, Expr $right, callable $getTypeCallback): public function getModTypeFromTypes(Expr $left, Expr $right, Type $leftType, Type $rightType): Type { - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1397,7 +1397,7 @@ public function getPlusType(Expr $left, Expr $right, callable $getTypeCallback): public function getPlusTypeFromTypes(Expr $left, Expr $right, Type $leftType, Type $rightType): Type { - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1725,7 +1725,7 @@ public function getShiftLeftType(Expr $left, Expr $right, callable $getTypeCallb public function getShiftLeftTypeFromTypes(Expr $left, Expr $right, Type $leftType, Type $rightType): Type { - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1789,7 +1789,7 @@ public function getShiftRightType(Expr $left, Expr $right, callable $getTypeCall public function getShiftRightTypeFromTypes(Expr $left, Expr $right, Type $leftType, Type $rightType): Type { - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1872,7 +1872,7 @@ private function optimizeScalarType(Type $type): Type */ public function resolveIdenticalType(Type $leftType, Type $rightType): TypeResult { - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return new TypeResult(new ConstantBooleanType(false), []); } @@ -2054,7 +2054,7 @@ private function resolveCommonMath(Expr\BinaryOp $expr, Type $leftType, Type $ri if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } - if ($leftNumberType instanceof NeverType || $rightNumberType instanceof NeverType) { + if ($leftNumberType->isNever()->yes() || $rightNumberType->isNever()->yes()) { return $this->getNeverType($leftNumberType, $rightNumberType); } @@ -2689,10 +2689,10 @@ private function getReflectionProvider(): ReflectionProvider private function getNeverType(Type $leftType, Type $rightType): Type { // make sure we don't lose the explicit flag in the process - if ($leftType instanceof NeverType && $leftType->isExplicit()) { + if ($leftType->isExplicitNever()->yes()) { return $leftType; } - if ($rightType instanceof NeverType && $rightType->isExplicit()) { + if ($rightType->isExplicitNever()->yes()) { return $rightType; } return new NeverType(); diff --git a/src/Reflection/Php/PhpClassReflectionExtension.php b/src/Reflection/Php/PhpClassReflectionExtension.php index e471943e87..83f4157628 100644 --- a/src/Reflection/Php/PhpClassReflectionExtension.php +++ b/src/Reflection/Php/PhpClassReflectionExtension.php @@ -49,7 +49,6 @@ use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\Generic\TemplateTypeVariance; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypehintHelper; @@ -1178,7 +1177,7 @@ private function inferAndCachePropertyTypes( } $propertyType = $methodScope->getType($expr->expr); - if ($propertyType instanceof ErrorType || $propertyType instanceof NeverType) { + if ($propertyType instanceof ErrorType || !$propertyType->isNever()->no()) { continue; } diff --git a/src/Reflection/Php/PhpPropertyReflection.php b/src/Reflection/Php/PhpPropertyReflection.php index 8b30efb00b..eabc7ebdc0 100644 --- a/src/Reflection/Php/PhpPropertyReflection.php +++ b/src/Reflection/Php/PhpPropertyReflection.php @@ -11,7 +11,6 @@ use PHPStan\Reflection\MissingMethodFromReflectionException; use PHPStan\TrinaryLogic; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypehintHelper; use function sprintf; @@ -126,7 +125,7 @@ public function getWritableType(): Type return $this->writableType; } - if ($this->writablePhpDocType === null || $this->writablePhpDocType instanceof NeverType) { + if ($this->writablePhpDocType === null || !$this->writablePhpDocType->isNever()->no()) { return $this->writableType = TypehintHelper::decideType( $this->nativeType, $this->readablePhpDocType, diff --git a/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php b/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php index 3e4b1e7b3f..f43f89efb2 100644 --- a/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php +++ b/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php @@ -13,7 +13,6 @@ use PHPStan\Type\BenevolentUnionType; use PHPStan\Type\ErrorType; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypeUtils; @@ -65,7 +64,7 @@ public function check( if ($type->hasOffsetValueType($dimType)->no()) { if ($type->isArray()->yes()) { $validArrayDimType = TypeCombinator::intersect(AllowedArrayKeysTypes::getType(), $dimType); - if ($validArrayDimType instanceof NeverType) { + if (!$validArrayDimType->isNever()->no()) { // Already reported by InvalidKeyInArrayDimFetchRule return []; } diff --git a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php index 1ebe569289..74ebf6d637 100644 --- a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php +++ b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php @@ -24,7 +24,6 @@ use PHPStan\Type\Generic\GenericClassStringType; use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use PHPStan\Type\TypeTraverser; @@ -145,7 +144,7 @@ public function findSpecifiedType( if (!$haystackType instanceof ConstantArrayType || count($haystackType->getValueTypes()) > 0) { $haystackArrayTypes = $haystackType->getArrays(); - if (count($haystackArrayTypes) === 1 && $haystackArrayTypes[0]->getIterableValueType() instanceof NeverType) { + if (count($haystackArrayTypes) === 1 && !$haystackArrayTypes[0]->getIterableValueType()->isNever()->no()) { return null; } diff --git a/src/Rules/Comparison/MatchExpressionRule.php b/src/Rules/Comparison/MatchExpressionRule.php index 8c31b92242..8547815bf1 100644 --- a/src/Rules/Comparison/MatchExpressionRule.php +++ b/src/Rules/Comparison/MatchExpressionRule.php @@ -11,7 +11,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\Constant\ConstantBooleanType; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\TypeCombinator; use PHPStan\Type\UnionType; @@ -131,7 +130,7 @@ public function processNode(Node $node, Scope $scope): array $remainingType = $cases[0]; } if ( - !$remainingType instanceof NeverType + $remainingType->isNever()->no() && !$this->isUnhandledMatchErrorCaught($node) && !$this->hasUnhandledMatchErrorThrowsTag($scope) ) { diff --git a/src/Rules/Exceptions/CatchWithUnthrownExceptionRule.php b/src/Rules/Exceptions/CatchWithUnthrownExceptionRule.php index f4e2479a2a..118376b8f1 100644 --- a/src/Rules/Exceptions/CatchWithUnthrownExceptionRule.php +++ b/src/Rules/Exceptions/CatchWithUnthrownExceptionRule.php @@ -9,7 +9,6 @@ use PHPStan\Node\CatchWithUnthrownExceptionNode; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\Type\NeverType; use PHPStan\Type\VerbosityLevel; use function sprintf; @@ -36,7 +35,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - if ($node->getCaughtType() instanceof NeverType) { + if ($node->getCaughtType()->isNever()->yes()) { return [ RuleErrorBuilder::message( sprintf('Dead catch - %s is already caught above.', $node->getOriginalCaughtType()->describe(VerbosityLevel::typeOnly())), diff --git a/src/Rules/Exceptions/TooWideThrowTypeCheck.php b/src/Rules/Exceptions/TooWideThrowTypeCheck.php index 1eb978a73f..a246e99bc0 100644 --- a/src/Rules/Exceptions/TooWideThrowTypeCheck.php +++ b/src/Rules/Exceptions/TooWideThrowTypeCheck.php @@ -43,7 +43,7 @@ public function check(Type $throwType, array $throwPoints): array $throwClasses = []; foreach (TypeUtils::flattenTypes($throwType) as $type) { - if (!$throwPointType instanceof NeverType && !$type->isSuperTypeOf($throwPointType)->no()) { + if ($throwPointType->isNever()->no() && !$type->isSuperTypeOf($throwPointType)->no()) { continue; } diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index a41177bc1e..ff14581c19 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -21,7 +21,6 @@ use PHPStan\Type\ErrorType; use PHPStan\Type\Generic\TemplateType; use PHPStan\Type\IntegerRangeType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypeTraverser; @@ -505,8 +504,8 @@ static function (Type $type, callable $traverse) use (&$returnTemplateTypes): Ty if ( !($type instanceof ErrorType) && ( - !$type instanceof NeverType - || $type->isExplicit() + $type->isNever()->no() + || $type->isExplicitNever()->yes() ) ) { continue; diff --git a/src/Rules/FunctionDefinitionCheck.php b/src/Rules/FunctionDefinitionCheck.php index 3e7cf63770..0a39ba82aa 100644 --- a/src/Rules/FunctionDefinitionCheck.php +++ b/src/Rules/FunctionDefinitionCheck.php @@ -31,7 +31,6 @@ use PHPStan\ShouldNotHappenException; use PHPStan\Type\ConditionalTypeForParameter; use PHPStan\Type\Generic\TemplateType; -use PHPStan\Type\NeverType; use PHPStan\Type\NonexistentParentClassType; use PHPStan\Type\ParserNodeTypeToPHPStanType; use PHPStan\Type\Type; @@ -502,7 +501,7 @@ private function checkParametersAcceptor( $returnType = $parametersAcceptor->getReturnType(); if ( $returnType->isVoid()->yes() - || ($returnType instanceof NeverType && $returnType->isExplicit()) + || ($returnType->isExplicitNever()->yes()) ) { $errors[] = RuleErrorBuilder::message(sprintf($noDiscardReturnTypeMessage, $returnType->describe(VerbosityLevel::typeOnly()))) ->line($returnTypeNode->getStartLine()) diff --git a/src/Rules/FunctionReturnTypeCheck.php b/src/Rules/FunctionReturnTypeCheck.php index e61965ca3a..4da1628b78 100644 --- a/src/Rules/FunctionReturnTypeCheck.php +++ b/src/Rules/FunctionReturnTypeCheck.php @@ -8,7 +8,6 @@ use PHPStan\Analyser\Scope; use PHPStan\DependencyInjection\AutowiredService; use PHPStan\Type\ErrorType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeUtils; use PHPStan\Type\VerbosityLevel; @@ -39,7 +38,7 @@ public function checkReturnType( { $returnType = TypeUtils::resolveLateResolvableTypes($returnType); - if ($returnType instanceof NeverType && $returnType->isExplicit()) { + if ($returnType->isExplicitNever()->yes()) { return [ RuleErrorBuilder::message($neverMessage) ->line($returnNode->getStartLine()) diff --git a/src/Rules/Functions/ArrowFunctionReturnTypeRule.php b/src/Rules/Functions/ArrowFunctionReturnTypeRule.php index ab1fecfe73..37e308e083 100644 --- a/src/Rules/Functions/ArrowFunctionReturnTypeRule.php +++ b/src/Rules/Functions/ArrowFunctionReturnTypeRule.php @@ -10,7 +10,6 @@ use PHPStan\Rules\FunctionReturnTypeCheck; use PHPStan\Rules\Rule; use PHPStan\ShouldNotHappenException; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; /** @@ -46,10 +45,8 @@ public function processNode(Node $node, Scope $scope): array $exprType = $scope->getType($originalNode->expr); if ( - $returnType instanceof NeverType - && $returnType->isExplicit() - && $exprType instanceof NeverType - && $exprType->isExplicit() + $returnType->isExplicitNever()->yes() + && $exprType->isExplicitNever()->yes() ) { return []; } diff --git a/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php b/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php index 361c9377aa..9cf03560bd 100644 --- a/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php +++ b/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php @@ -9,7 +9,6 @@ use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\Type\NeverType; use function count; use function in_array; use function sprintf; @@ -71,7 +70,7 @@ public function processNode(Node $node, Scope $scope): array } $functionResult = $scope->getType($funcCall); - if ($functionResult instanceof NeverType && $functionResult->isExplicit()) { + if ($functionResult->isExplicitNever()->yes()) { return []; } diff --git a/src/Rules/Generators/YieldInGeneratorRule.php b/src/Rules/Generators/YieldInGeneratorRule.php index 601c8f43a4..b91fd89fcc 100644 --- a/src/Rules/Generators/YieldInGeneratorRule.php +++ b/src/Rules/Generators/YieldInGeneratorRule.php @@ -10,7 +10,6 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\TrinaryLogic; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use function sprintf; /** @@ -57,7 +56,7 @@ public function processNode(Node $node, Scope $scope): array return []; } - if ($returnType instanceof NeverType && $returnType->isExplicit()) { + if ($returnType->isExplicitNever()->yes()) { $isSuperType = TrinaryLogic::createNo(); } else { $isSuperType = $returnType->isIterable()->and(TrinaryLogic::createFromBoolean( diff --git a/src/Rules/IssetCheck.php b/src/Rules/IssetCheck.php index 2e1adcf1c6..e0af04ae2b 100644 --- a/src/Rules/IssetCheck.php +++ b/src/Rules/IssetCheck.php @@ -10,7 +10,6 @@ use PHPStan\Node\Expr\PropertyInitializationExpr; use PHPStan\Rules\Properties\PropertyDescriptor; use PHPStan\Rules\Properties\PropertyReflectionFinder; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\VerbosityLevel; use function is_string; @@ -55,7 +54,7 @@ public function check(Expr $expr, Scope $scope, string $operatorDescription, str } $type = $this->treatPhpDocTypesAsCertain ? $scope->getScopeType($expr) : $scope->getScopeNativeType($expr); - if (!$type instanceof NeverType) { + if ($type->isNever()->no()) { return $this->generateError( $type, sprintf('Variable $%s %s always exists and', $expr->name, $operatorDescription), diff --git a/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php index 8377d4cfcd..44a1652639 100644 --- a/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php @@ -9,7 +9,6 @@ use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\Type\NeverType; use function count; use function sprintf; @@ -63,7 +62,7 @@ public function processNode(Node $node, Scope $scope): array } $methodResult = $scope->getType($instantiation); - if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { + if ($methodResult->isExplicitNever()->yes()) { return []; } diff --git a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php index 22ce22ec39..0955bde225 100644 --- a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php @@ -11,7 +11,6 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Type\ErrorType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use function count; use function sprintf; @@ -72,7 +71,7 @@ public function processNode(Node $node, Scope $scope): array } $methodResult = $scope->getType($methodCall); - if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { + if ($methodResult->isExplicitNever()->yes()) { return []; } diff --git a/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php index a6fde544ca..00f571c0cf 100644 --- a/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php @@ -12,7 +12,6 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Type\ErrorType; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use function count; @@ -96,7 +95,7 @@ public function processNode(Node $node, Scope $scope): array } $methodResult = $scope->getType($staticCall); - if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { + if ($methodResult->isExplicitNever()->yes()) { return []; } diff --git a/src/Rules/Missing/MissingReturnRule.php b/src/Rules/Missing/MissingReturnRule.php index 5bc9d3d40e..46d9400cd8 100644 --- a/src/Rules/Missing/MissingReturnRule.php +++ b/src/Rules/Missing/MissingReturnRule.php @@ -15,7 +15,6 @@ use PHPStan\Type\ErrorType; use PHPStan\Type\Generic\TemplateMixedType; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypeUtils; use PHPStan\Type\VerbosityLevel; @@ -112,7 +111,7 @@ public function processNode(Node $node, Scope $scope): array return []; } - if ($returnType instanceof NeverType && $returnType->isExplicit()) { + if ($returnType->isExplicitNever()->yes()) { $errorBuilder = RuleErrorBuilder::message(sprintf('%s should always throw an exception or terminate script execution but doesn\'t do that.', $description))->line($node->getNode()->getStartLine()); if ($node->hasNativeReturnTypehint()) { diff --git a/src/Rules/PhpDoc/UnresolvableTypeHelper.php b/src/Rules/PhpDoc/UnresolvableTypeHelper.php index 29167a7f18..b60005c52d 100644 --- a/src/Rules/PhpDoc/UnresolvableTypeHelper.php +++ b/src/Rules/PhpDoc/UnresolvableTypeHelper.php @@ -4,7 +4,6 @@ use PHPStan\DependencyInjection\AutowiredService; use PHPStan\Type\ErrorType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeTraverser; @@ -19,7 +18,7 @@ public function containsUnresolvableType(Type $type): bool if ($type instanceof ErrorType) { $containsUnresolvable = true; } - if ($type instanceof NeverType && !$type->isExplicit()) { + if ($type->isNever()->yes() && $type->isExplicitNever()->no()) { $containsUnresolvable = true; } diff --git a/src/Rules/Playground/NeverRuleHelper.php b/src/Rules/Playground/NeverRuleHelper.php index a0870f7ce3..c54f99162a 100644 --- a/src/Rules/Playground/NeverRuleHelper.php +++ b/src/Rules/Playground/NeverRuleHelper.php @@ -5,7 +5,6 @@ use PhpParser\Node; use PHPStan\DependencyInjection\AutowiredService; use PHPStan\Node\ReturnStatementsNode; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; #[AutowiredService] @@ -17,7 +16,7 @@ final class NeverRuleHelper */ public function shouldReturnNever(ReturnStatementsNode $node, Type $returnType): array|false { - if ($returnType instanceof NeverType && $returnType->isExplicit()) { + if ($returnType->isExplicitNever()->yes()) { return false; } diff --git a/src/Rules/Properties/SetNonVirtualPropertyHookAssignRule.php b/src/Rules/Properties/SetNonVirtualPropertyHookAssignRule.php index e7a4ac5d88..9fd38c9517 100644 --- a/src/Rules/Properties/SetNonVirtualPropertyHookAssignRule.php +++ b/src/Rules/Properties/SetNonVirtualPropertyHookAssignRule.php @@ -10,7 +10,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\ShouldNotHappenException; -use PHPStan\Type\NeverType; use function sprintf; /** @@ -51,7 +50,7 @@ public function processNode(Node $node, Scope $scope): array if ($statementResult->isAlwaysTerminating()) { if ($endNode instanceof Node\Stmt\Expression) { $exprType = $statementResult->getScope()->getType($endNode->expr); - if ($exprType instanceof NeverType && $exprType->isExplicit()) { + if ($exprType->isExplicitNever()->yes()) { continue; } } diff --git a/src/Rules/RuleLevelHelper.php b/src/Rules/RuleLevelHelper.php index 1b46ccfbe7..a2e5b5621a 100644 --- a/src/Rules/RuleLevelHelper.php +++ b/src/Rules/RuleLevelHelper.php @@ -14,7 +14,6 @@ use PHPStan\Type\Generic\TemplateMixedType; use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\NullType; use PHPStan\Type\StrictMixedType; use PHPStan\Type\Type; @@ -214,7 +213,7 @@ private function findTypeToCheckImplementation( ); } - if ($type instanceof MixedType || $type instanceof NeverType) { + if ($type instanceof MixedType || !$type->isNever()->no()) { return new FoundTypeResult(new ErrorType(), [], [], null); } diff --git a/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php b/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php index edddff8a91..09787cd41c 100644 --- a/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php +++ b/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php @@ -15,7 +15,6 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Type\ErrorType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeUtils; use PHPStan\Type\VerbosityLevel; @@ -54,7 +53,7 @@ public function processNode(Node $node, Scope $scope): array if ($endNode instanceof Node\Stmt\Expression) { $endNodeExpr = $endNode->expr; $endNodeExprType = $scope->getType($endNodeExpr); - if ($endNodeExprType instanceof NeverType && $endNodeExprType->isExplicit()) { + if ($endNodeExprType->isExplicitNever()->yes()) { return []; } } diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index f6550a5845..2f320b9a17 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -138,8 +138,8 @@ public function describe(VerbosityLevel $level): string $isMixedItemType = $this->itemType instanceof MixedType && $this->itemType->describe(VerbosityLevel::precise()) === 'mixed' && !$this->itemType->isExplicitMixed(); $valueHandler = function () use ($level, $isMixedKeyType, $isMixedItemType): string { - if ($isMixedKeyType || $this->keyType instanceof NeverType) { - if ($isMixedItemType || $this->itemType instanceof NeverType) { + if ($isMixedKeyType || !$this->keyType->isNever()->no()) { + if ($isMixedItemType || !$this->itemType->isNever()->no()) { return 'array'; } @@ -272,7 +272,7 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic if ($offsetArrayKeyType instanceof ErrorType) { $allowedArrayKeys = AllowedArrayKeysTypes::getType(); $offsetArrayKeyType = TypeCombinator::intersect($allowedArrayKeys, $offsetType)->toArrayKey(); - if ($offsetArrayKeyType instanceof NeverType) { + if (!$offsetArrayKeyType->isNever()->no()) { return TrinaryLogic::createNo(); } } @@ -425,7 +425,7 @@ public function unsetOffset(Type $offsetType): Type && !$this->keyType->isSuperTypeOf($offsetType)->no() ) { $keyType = TypeCombinator::remove($this->keyType, $offsetType); - if ($keyType instanceof NeverType) { + if (!$keyType->isNever()->no()) { return new ConstantArrayType([], []); } @@ -595,7 +595,7 @@ public function traverse(callable $cb): Type $itemType = $cb($this->itemType); if ($keyType !== $this->keyType || $itemType !== $this->itemType) { - if ($keyType instanceof NeverType && $itemType instanceof NeverType) { + if (!$keyType->isNever()->no() && !$itemType->isNever()->no()) { return new ConstantArrayType([], []); } @@ -638,7 +638,7 @@ public function traverseSimultaneously(Type $right, callable $cb): Type $itemType = $cb($this->itemType, $right->getIterableValueType()); if ($keyType !== $this->keyType || $itemType !== $this->itemType) { - if ($keyType instanceof NeverType && $itemType instanceof NeverType) { + if (!$keyType->isNever()->no() && !$itemType->isNever()->no()) { return new ConstantArrayType([], []); } diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 6cff7ef3af..03db8a9e15 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -592,7 +592,7 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic if ($offsetArrayKeyType instanceof ErrorType) { $allowedArrayKeys = AllowedArrayKeysTypes::getType(); $offsetArrayKeyType = TypeCombinator::intersect($allowedArrayKeys, $offsetType)->toArrayKey(); - if ($offsetArrayKeyType instanceof NeverType) { + if (!$offsetArrayKeyType->isNever()->no()) { return TrinaryLogic::createNo(); } } diff --git a/src/Type/ExponentiateHelper.php b/src/Type/ExponentiateHelper.php index fd65dc9e51..73ec4ad91a 100644 --- a/src/Type/ExponentiateHelper.php +++ b/src/Type/ExponentiateHelper.php @@ -23,7 +23,7 @@ public static function exponentiate(Type $base, Type $exponent): Type return TypeCombinator::union(...$results); } - if ($exponent instanceof NeverType) { + if (!$exponent->isNever()->no()) { return new NeverType(); } diff --git a/src/Type/Generic/GenericStaticType.php b/src/Type/Generic/GenericStaticType.php index 99fc517dae..e69b6073c7 100644 --- a/src/Type/Generic/GenericStaticType.php +++ b/src/Type/Generic/GenericStaticType.php @@ -9,7 +9,6 @@ use PHPStan\ShouldNotHappenException; use PHPStan\Type\CompoundType; use PHPStan\Type\IsSuperTypeOfResult; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\StaticType; use PHPStan\Type\Type; @@ -229,7 +228,7 @@ public function changeSubtractedType(?Type $subtractedType): Type $classReflection = $this->getClassReflection(); if ($classReflection->getAllowedSubTypes() !== null) { $objectType = $this->getStaticObjectType()->changeSubtractedType($subtractedType); - if ($objectType instanceof NeverType) { + if (!$objectType->isNever()->no()) { return $objectType; } diff --git a/src/Type/Generic/TemplateTypeMap.php b/src/Type/Generic/TemplateTypeMap.php index 356772085a..0a00088b68 100644 --- a/src/Type/Generic/TemplateTypeMap.php +++ b/src/Type/Generic/TemplateTypeMap.php @@ -2,7 +2,6 @@ namespace PHPStan\Type\Generic; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypeTraverser; @@ -55,7 +54,7 @@ public function convertToLowerBoundTypes(): self foreach ($this->lowerBoundTypes as $name => $type) { if (isset($lowerBoundTypes[$name])) { $intersection = TypeCombinator::intersect($lowerBoundTypes[$name], $type); - if ($intersection instanceof NeverType) { + if (!$intersection->isNever()->no()) { continue; } $lowerBoundTypes[$name] = $intersection; @@ -151,7 +150,7 @@ public function union(self $other): self foreach ($other->lowerBoundTypes as $name => $type) { if (isset($resultLowerBoundTypes[$name])) { $intersection = TypeCombinator::intersect($resultLowerBoundTypes[$name], $type); - if ($intersection instanceof NeverType) { + if (!$intersection->isNever()->no()) { continue; } $resultLowerBoundTypes[$name] = $intersection; @@ -179,7 +178,7 @@ public function benevolentUnion(self $other): self foreach ($other->lowerBoundTypes as $name => $type) { if (isset($resultLowerBoundTypes[$name])) { $intersection = TypeCombinator::intersect($resultLowerBoundTypes[$name], $type); - if ($intersection instanceof NeverType) { + if (!$intersection->isNever()->no()) { continue; } $resultLowerBoundTypes[$name] = $intersection; diff --git a/src/Type/Generic/TemplateTypeTrait.php b/src/Type/Generic/TemplateTypeTrait.php index a1f381e6f5..ab2c5aacd5 100644 --- a/src/Type/Generic/TemplateTypeTrait.php +++ b/src/Type/Generic/TemplateTypeTrait.php @@ -10,7 +10,6 @@ use PHPStan\Type\IntersectionType; use PHPStan\Type\IsSuperTypeOfResult; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\RecursionGuard; use PHPStan\Type\SubtractableType; use PHPStan\Type\Type; @@ -220,7 +219,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return $type->isSubTypeOf($this); } - if ($type instanceof NeverType) { + if (!$type->isNever()->no()) { return IsSuperTypeOfResult::createYes(); } diff --git a/src/Type/Generic/TemplateTypeVariance.php b/src/Type/Generic/TemplateTypeVariance.php index 35536317dd..308113a4ae 100644 --- a/src/Type/Generic/TemplateTypeVariance.php +++ b/src/Type/Generic/TemplateTypeVariance.php @@ -8,7 +8,6 @@ use PHPStan\Type\BenevolentUnionType; use PHPStan\Type\IsSuperTypeOfResult; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use function sprintf; @@ -151,7 +150,7 @@ public function compose(self $other): self public function isValidVariance(TemplateType $templateType, Type $a, Type $b): IsSuperTypeOfResult { - if ($b instanceof NeverType) { + if (!$b->isNever()->no()) { return IsSuperTypeOfResult::createYes(); } diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index bca26d4f70..c37584f514 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -253,7 +253,7 @@ public function isSuperTypeOf(Type $otherType): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - if ($otherType instanceof NeverType) { + if (!$otherType->isNever()->no()) { return IsSuperTypeOfResult::createYes(); } diff --git a/src/Type/MixedType.php b/src/Type/MixedType.php index 4dfc27e456..07529d9551 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -59,7 +59,7 @@ public function __construct( ?Type $subtractedType = null, ) { - if ($subtractedType instanceof NeverType) { + if ($subtractedType !== null && !$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -135,7 +135,7 @@ public function isSuperTypeOfMixed(MixedType $type): IsSuperTypeOfResult public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { - if ($this->subtractedType === null || $type instanceof NeverType) { + if ($this->subtractedType === null || !$type->isNever()->no()) { return IsSuperTypeOfResult::createYes(); } diff --git a/src/Type/NonAcceptingNeverType.php b/src/Type/NonAcceptingNeverType.php index dd14d3f9d2..deaf11ab10 100644 --- a/src/Type/NonAcceptingNeverType.php +++ b/src/Type/NonAcceptingNeverType.php @@ -26,7 +26,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult public function accepts(Type $type, bool $strictTypes): AcceptsResult { - if ($type instanceof NeverType) { + if (!$type->isNever()->no()) { return AcceptsResult::createYes(); } diff --git a/src/Type/ObjectShapeType.php b/src/Type/ObjectShapeType.php index 57d48a0d0d..d9dd70a134 100644 --- a/src/Type/ObjectShapeType.php +++ b/src/Type/ObjectShapeType.php @@ -521,7 +521,7 @@ public function traverseSimultaneously(Type $right, callable $cb): Type public function exponentiate(Type $exponent): Type { - if (!$exponent instanceof NeverType && !$this->isSuperTypeOf($exponent)->no()) { + if ($exponent->isNever()->no() && !$this->isSuperTypeOf($exponent)->no()) { return TypeCombinator::union($this, $exponent); } diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 091f444606..c7369c486b 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -128,7 +128,7 @@ public function __construct( private ?ClassReflection $classReflection = null, ) { - if ($subtractedType instanceof NeverType) { + if ($subtractedType !== null && !$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -1882,7 +1882,7 @@ public function getFiniteTypes(): array public function exponentiate(Type $exponent): Type { $object = new ObjectWithoutClassType(); - if (!$exponent instanceof NeverType && !$object->isSuperTypeOf($this)->no() && !$object->isSuperTypeOf($exponent)->no()) { + if ($exponent->isNever()->no() && !$object->isSuperTypeOf($this)->no() && !$object->isSuperTypeOf($exponent)->no()) { return TypeCombinator::union($this, $exponent); } return new ErrorType(); diff --git a/src/Type/ObjectWithoutClassType.php b/src/Type/ObjectWithoutClassType.php index c1417f24d6..073edf8886 100644 --- a/src/Type/ObjectWithoutClassType.php +++ b/src/Type/ObjectWithoutClassType.php @@ -28,7 +28,7 @@ public function __construct( ?Type $subtractedType = null, ) { - if ($subtractedType instanceof NeverType) { + if ($subtractedType !== null && !$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -194,7 +194,7 @@ public function tryRemove(Type $typeToRemove): ?Type public function exponentiate(Type $exponent): Type { - if (!$exponent instanceof NeverType && !$this->isSuperTypeOf($exponent)->no()) { + if ($exponent->isNever()->no() && !$this->isSuperTypeOf($exponent)->no()) { return TypeCombinator::union($this, $exponent); } diff --git a/src/Type/Php/ArrayColumnHelper.php b/src/Type/Php/ArrayColumnHelper.php index 179d85bc04..0601df4868 100644 --- a/src/Type/Php/ArrayColumnHelper.php +++ b/src/Type/Php/ArrayColumnHelper.php @@ -66,7 +66,7 @@ public function getReturnIndexType(Type $arrayType, Type $indexType, Scope $scop public function handleAnyArray(Type $arrayType, Type $columnType, Type $indexType, Scope $scope): Type { [$returnValueType, $iterableAtLeastOnce] = $this->getReturnValueType($arrayType, $columnType, $scope); - if ($returnValueType instanceof NeverType) { + if (!$returnValueType->isNever()->no()) { return new ConstantArrayType([], []); } @@ -92,7 +92,7 @@ public function handleConstantArray(ConstantArrayType $arrayType, Type $columnTy if (!$certainty->yes()) { return null; } - if ($valueType instanceof NeverType) { + if (!$valueType->isNever()->no()) { continue; } diff --git a/src/Type/Php/ArrayFilterFunctionReturnTypeHelper.php b/src/Type/Php/ArrayFilterFunctionReturnTypeHelper.php index 04ef90fef5..384f810998 100644 --- a/src/Type/Php/ArrayFilterFunctionReturnTypeHelper.php +++ b/src/Type/Php/ArrayFilterFunctionReturnTypeHelper.php @@ -66,7 +66,7 @@ public function getType(Scope $scope, ?Expr $arrayArg, ?Expr $callbackArg, ?Expr $keyType = $arrayArgType->getIterableKeyType(); $itemType = $arrayArgType->getIterableValueType(); - if ($itemType instanceof NeverType || $keyType instanceof NeverType) { + if (!$itemType->isNever()->no() || !$keyType->isNever()->no()) { return new ConstantArrayType([], []); } @@ -183,7 +183,7 @@ private function removeFalsey(Type $type): Type $valueType = TypeCombinator::remove($valueType, $falseyTypes); - if ($valueType instanceof NeverType) { + if (!$valueType->isNever()->no()) { return new ConstantArrayType([], []); } @@ -206,7 +206,7 @@ private function filterByTruthyValue(Scope $scope, Error|Variable|null $itemVar, $itemType = $constantArray->getValueTypes()[$i]; [$newKeyType, $newItemType, $optional] = $this->processKeyAndItemType($scope, $keyType, $itemType, $itemVar, $keyVar, $expr); $optional = $optional || in_array($i, $optionalKeys, true); - if ($newKeyType instanceof NeverType || $newItemType instanceof NeverType) { + if (!$newKeyType->isNever()->no() || !$newItemType->isNever()->no()) { continue; } if ($itemType->equals($newItemType) && $keyType->equals($newKeyType)) { @@ -225,7 +225,7 @@ private function filterByTruthyValue(Scope $scope, Error|Variable|null $itemVar, [$newKeyType, $newItemType] = $this->processKeyAndItemType($scope, $arrayType->getIterableKeyType(), $arrayType->getIterableValueType(), $itemVar, $keyVar, $expr); - if ($newItemType instanceof NeverType || $newKeyType instanceof NeverType) { + if (!$newItemType->isNever()->no() || !$newKeyType->isNever()->no()) { return new ConstantArrayType([], []); } diff --git a/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php b/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php index 1283fa610a..53881c1c55 100644 --- a/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php @@ -19,7 +19,6 @@ use PHPStan\Type\DynamicFunctionReturnTypeExtension; use PHPStan\Type\IntegerType; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypeUtils; @@ -162,7 +161,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, } $keyType = TypeCombinator::union(...$keyTypes); - if ($keyType instanceof NeverType) { + if (!$keyType->isNever()->no()) { return new ConstantArrayType([], []); } diff --git a/src/Type/Php/ArrayReplaceFunctionReturnTypeExtension.php b/src/Type/Php/ArrayReplaceFunctionReturnTypeExtension.php index 422aa9e2d7..e16c281a56 100644 --- a/src/Type/Php/ArrayReplaceFunctionReturnTypeExtension.php +++ b/src/Type/Php/ArrayReplaceFunctionReturnTypeExtension.php @@ -18,7 +18,6 @@ use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypeUtils; @@ -163,7 +162,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, } $keyType = TypeCombinator::union(...$keyTypes); - if ($keyType instanceof NeverType) { + if (!$keyType->isNever()->no()) { return new ConstantArrayType([], []); } diff --git a/src/Type/Php/BcMathNumberOperatorTypeSpecifyingExtension.php b/src/Type/Php/BcMathNumberOperatorTypeSpecifyingExtension.php index 8539349a15..a379a99906 100644 --- a/src/Type/Php/BcMathNumberOperatorTypeSpecifyingExtension.php +++ b/src/Type/Php/BcMathNumberOperatorTypeSpecifyingExtension.php @@ -7,7 +7,6 @@ use PHPStan\Type\BooleanType; use PHPStan\Type\ErrorType; use PHPStan\Type\IntegerRangeType; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\OperatorTypeSpecifyingExtension; use PHPStan\Type\Type; @@ -23,7 +22,7 @@ public function __construct(private PhpVersion $phpVersion) public function isOperatorSupported(string $operatorSigil, Type $leftSide, Type $rightSide): bool { - if (!$this->phpVersion->supportsBcMathNumberOperatorOverloading() || $leftSide instanceof NeverType || $rightSide instanceof NeverType) { + if (!$this->phpVersion->supportsBcMathNumberOperatorOverloading() || !$leftSide->isNever()->no() || !$rightSide->isNever()->no()) { return false; } diff --git a/src/Type/Php/DateIntervalConstructorThrowTypeExtension.php b/src/Type/Php/DateIntervalConstructorThrowTypeExtension.php index 971f593bfc..fcc93237dd 100644 --- a/src/Type/Php/DateIntervalConstructorThrowTypeExtension.php +++ b/src/Type/Php/DateIntervalConstructorThrowTypeExtension.php @@ -9,7 +9,6 @@ use PHPStan\Php\PhpVersion; use PHPStan\Reflection\MethodReflection; use PHPStan\Type\DynamicStaticMethodThrowTypeExtension; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -47,7 +46,7 @@ public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflect $valueType = TypeCombinator::remove($valueType, $constantString); } - if (!$valueType instanceof NeverType) { + if ($valueType->isNever()->no()) { return $this->exceptionType(); } diff --git a/src/Type/Php/DateTimeConstructorThrowTypeExtension.php b/src/Type/Php/DateTimeConstructorThrowTypeExtension.php index 2facd03945..1b50ccbae3 100644 --- a/src/Type/Php/DateTimeConstructorThrowTypeExtension.php +++ b/src/Type/Php/DateTimeConstructorThrowTypeExtension.php @@ -10,7 +10,6 @@ use PHPStan\Php\PhpVersion; use PHPStan\Reflection\MethodReflection; use PHPStan\Type\DynamicStaticMethodThrowTypeExtension; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -49,7 +48,7 @@ public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflect $valueType = TypeCombinator::remove($valueType, $constantString); } - if (!$valueType instanceof NeverType) { + if ($valueType->isNever()->no()) { return $this->exceptionType(); } diff --git a/src/Type/Php/DateTimeModifyMethodThrowTypeExtension.php b/src/Type/Php/DateTimeModifyMethodThrowTypeExtension.php index 02c0099c4e..1fe65bded4 100644 --- a/src/Type/Php/DateTimeModifyMethodThrowTypeExtension.php +++ b/src/Type/Php/DateTimeModifyMethodThrowTypeExtension.php @@ -10,7 +10,6 @@ use PHPStan\Php\PhpVersion; use PHPStan\Reflection\MethodReflection; use PHPStan\Type\DynamicMethodThrowTypeExtension; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -54,7 +53,7 @@ public function getThrowTypeFromMethodCall(MethodReflection $methodReflection, M $valueType = TypeCombinator::remove($valueType, $constantString); } - if (!$valueType instanceof NeverType) { + if ($valueType->isNever()->no()) { return $this->exceptionType(); } diff --git a/src/Type/Php/DateTimeModifyReturnTypeExtension.php b/src/Type/Php/DateTimeModifyReturnTypeExtension.php index 0ed2933856..e89056e550 100644 --- a/src/Type/Php/DateTimeModifyReturnTypeExtension.php +++ b/src/Type/Php/DateTimeModifyReturnTypeExtension.php @@ -66,7 +66,7 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method $valueType = TypeCombinator::remove($valueType, $constantString); } - if (!$valueType instanceof NeverType) { + if ($valueType->isNever()->no()) { return null; } diff --git a/src/Type/Php/DateTimeZoneConstructorThrowTypeExtension.php b/src/Type/Php/DateTimeZoneConstructorThrowTypeExtension.php index 0c4c0bd9dd..eb034e1041 100644 --- a/src/Type/Php/DateTimeZoneConstructorThrowTypeExtension.php +++ b/src/Type/Php/DateTimeZoneConstructorThrowTypeExtension.php @@ -9,7 +9,6 @@ use PHPStan\Php\PhpVersion; use PHPStan\Reflection\MethodReflection; use PHPStan\Type\DynamicStaticMethodThrowTypeExtension; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -47,7 +46,7 @@ public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflect $valueType = TypeCombinator::remove($valueType, $constantString); } - if (!$valueType instanceof NeverType) { + if ($valueType->isNever()->no()) { return $this->exceptionType(); } diff --git a/src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php b/src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php index 310045be6e..589f8b40cf 100644 --- a/src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php +++ b/src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php @@ -13,7 +13,6 @@ use PHPStan\Type\ArrayType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; -use PHPStan\Type\NeverType; use PHPStan\Type\StringType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -56,7 +55,7 @@ public function getTypeFromFunctionCall( )->getReturnType(); $result = TypeCombinator::intersect($initialReturnType, $this->generalizeStringType($argType)); - if ($result instanceof NeverType) { + if (!$result->isNever()->no()) { $result = $initialReturnType; } diff --git a/src/Type/Php/ReflectionFunctionConstructorThrowTypeExtension.php b/src/Type/Php/ReflectionFunctionConstructorThrowTypeExtension.php index 01fe08f354..ec417571bf 100644 --- a/src/Type/Php/ReflectionFunctionConstructorThrowTypeExtension.php +++ b/src/Type/Php/ReflectionFunctionConstructorThrowTypeExtension.php @@ -9,7 +9,6 @@ use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\DynamicStaticMethodThrowTypeExtension; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use ReflectionFunction; @@ -47,7 +46,7 @@ public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflect $valueType = TypeCombinator::remove($valueType, $constantString); } - if (!$valueType instanceof NeverType) { + if ($valueType->isNever()->no()) { return $methodReflection->getThrowType(); } diff --git a/src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php b/src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php index a2371b6434..1f14a4ef06 100644 --- a/src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php +++ b/src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php @@ -10,7 +10,6 @@ use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\DynamicStaticMethodThrowTypeExtension; use PHPStan\Type\Generic\GenericClassStringType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypeUtils; @@ -62,7 +61,7 @@ public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflect $valueType = TypeCombinator::remove($valueType, $type); } - if (!$valueType instanceof NeverType) { + if ($valueType->isNever()->no()) { return $methodReflection->getThrowType(); } @@ -71,7 +70,7 @@ public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflect $propertyType = TypeCombinator::remove($propertyType, $constantPropertyString); } - if (!$propertyType instanceof NeverType) { + if ($propertyType->isNever()->no()) { return $methodReflection->getThrowType(); } diff --git a/src/Type/Php/ReflectionPropertyConstructorThrowTypeExtension.php b/src/Type/Php/ReflectionPropertyConstructorThrowTypeExtension.php index 64392e86a1..ece8e3ddbe 100644 --- a/src/Type/Php/ReflectionPropertyConstructorThrowTypeExtension.php +++ b/src/Type/Php/ReflectionPropertyConstructorThrowTypeExtension.php @@ -8,7 +8,6 @@ use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\DynamicStaticMethodThrowTypeExtension; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use ReflectionProperty; @@ -50,7 +49,7 @@ public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflect $valueType = TypeCombinator::remove($valueType, $constantString); } - if (!$valueType instanceof NeverType) { + if ($valueType->isNever()->no()) { return $methodReflection->getThrowType(); } @@ -59,7 +58,7 @@ public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflect $propertyType = TypeCombinator::remove($propertyType, $constantPropertyString); } - if (!$propertyType instanceof NeverType) { + if ($propertyType->isNever()->no()) { return $methodReflection->getThrowType(); } diff --git a/src/Type/Php/SimpleXMLElementConstructorThrowTypeExtension.php b/src/Type/Php/SimpleXMLElementConstructorThrowTypeExtension.php index 78faf2d1d3..ef334ef5e4 100644 --- a/src/Type/Php/SimpleXMLElementConstructorThrowTypeExtension.php +++ b/src/Type/Php/SimpleXMLElementConstructorThrowTypeExtension.php @@ -7,7 +7,6 @@ use PHPStan\DependencyInjection\AutowiredService; use PHPStan\Reflection\MethodReflection; use PHPStan\Type\DynamicStaticMethodThrowTypeExtension; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use SimpleXMLElement; @@ -51,7 +50,7 @@ public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflect libxml_use_internal_errors($internalErrorsOld); } - if (!$valueType instanceof NeverType) { + if ($valueType->isNever()->no()) { return $methodReflection->getThrowType(); } diff --git a/src/Type/Php/SimpleXMLElementXpathMethodReturnTypeExtension.php b/src/Type/Php/SimpleXMLElementXpathMethodReturnTypeExtension.php index 45715f21be..07313936db 100644 --- a/src/Type/Php/SimpleXMLElementXpathMethodReturnTypeExtension.php +++ b/src/Type/Php/SimpleXMLElementXpathMethodReturnTypeExtension.php @@ -9,7 +9,6 @@ use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\DynamicMethodReturnTypeExtension; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use SimpleXMLElement; @@ -50,7 +49,7 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method $argType = TypeCombinator::remove($argType, $constantString); } - if (!$argType instanceof NeverType) { + if ($argType->isNever()->no()) { return null; } diff --git a/src/Type/StaticType.php b/src/Type/StaticType.php index 36ae462099..cee4b85dfc 100644 --- a/src/Type/StaticType.php +++ b/src/Type/StaticType.php @@ -49,7 +49,7 @@ public function __construct( ?Type $subtractedType = null, ) { - if ($subtractedType instanceof NeverType) { + if ($subtractedType !== null && !$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -795,7 +795,7 @@ public function changeSubtractedType(?Type $subtractedType): Type $classReflection = $this->getClassReflection(); if ($classReflection->getAllowedSubTypes() !== null) { $objectType = $this->getStaticObjectType()->changeSubtractedType($subtractedType); - if ($objectType instanceof NeverType) { + if (!$objectType->isNever()->no()) { return $objectType; } diff --git a/src/Type/Traits/LateResolvableTypeTrait.php b/src/Type/Traits/LateResolvableTypeTrait.php index 98d142af51..89eef3c665 100644 --- a/src/Type/Traits/LateResolvableTypeTrait.php +++ b/src/Type/Traits/LateResolvableTypeTrait.php @@ -17,7 +17,6 @@ use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\IsSuperTypeOfResult; use PHPStan\Type\LateResolvableType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; trait LateResolvableTypeTrait @@ -62,7 +61,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult private function isSuperTypeOfDefault(Type $type): IsSuperTypeOfResult { - if ($type instanceof NeverType) { + if (!$type->isNever()->no()) { return IsSuperTypeOfResult::createYes(); } diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index aa5f933532..ad679cae4d 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -609,7 +609,7 @@ private static function unionWithSubtractedType( $type->getTypeWithoutSubtractedType(), $subtractedType, ); - if ($subtractedType instanceof NeverType) { + if (!$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -628,7 +628,7 @@ private static function intersectWithSubtractedType( Type $b, ): Type { - if ($a->getSubtractedType() === null || $b instanceof NeverType) { + if ($a->getSubtractedType() === null || !$b->isNever()->no()) { return $a; } @@ -670,7 +670,7 @@ private static function intersectWithSubtractedType( $subtractedType = self::remove($a->getSubtractedType(), $b); if ( - $subtractedType instanceof NeverType + !$subtractedType->isNever()->no() || !$subtractedType->isSuperTypeOf($b)->no() ) { $subtractedType = null; @@ -695,7 +695,7 @@ private static function intersectWithSubtractedType( $a->getSubtractedType(), $subtractedType, ); - if ($subtractedType instanceof NeverType) { + if (!$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -1182,7 +1182,7 @@ public static function intersect(Type ...$types): Type } $union = self::union(...$topLevelUnionSubTypes); - if ($union instanceof NeverType) { + if (!$union->isNever()->no()) { return $union; } @@ -1359,7 +1359,7 @@ public static function intersect(Type ...$types): Type $offsetType = $types[$j]->getOffsetType(); $valueType = $types[$j]->getValueType(); $newValueType = self::intersect($types[$i]->getOffsetValueType($offsetType), $valueType); - if ($newValueType instanceof NeverType) { + if (!$newValueType->isNever()->no()) { return $newValueType; } $types[$i] = $types[$i]->setOffsetValueType($offsetType, $newValueType); @@ -1372,7 +1372,7 @@ public static function intersect(Type ...$types): Type $offsetType = $types[$i]->getOffsetType(); $valueType = $types[$i]->getValueType(); $newValueType = self::intersect($types[$j]->getOffsetValueType($offsetType), $valueType); - if ($newValueType instanceof NeverType) { + if (!$newValueType->isNever()->no()) { return $newValueType; } @@ -1471,7 +1471,7 @@ public static function intersect(Type ...$types): Type && !$types[$j]->getIterableKeyType()->isSuperTypeOf($types[$i]->getIterableKeyType())->yes() ) { $keyType = self::intersect($types[$i]->getIterableKeyType(), $types[$j]->getIterableKeyType()); - if ($keyType instanceof NeverType) { + if (!$keyType->isNever()->no()) { return $keyType; } $types[$i] = new ArrayType($keyType, $types[$i]->getItemType()); diff --git a/src/Type/TypehintHelper.php b/src/Type/TypehintHelper.php index 076fedcacc..cf2156a3d2 100644 --- a/src/Type/TypehintHelper.php +++ b/src/Type/TypehintHelper.php @@ -86,7 +86,7 @@ public static function decideType( } if ($phpDocType !== null && !$phpDocType instanceof ErrorType) { - if ($phpDocType instanceof NeverType && $phpDocType->isExplicit()) { + if ($phpDocType->isExplicitNever()->yes()) { return $phpDocType; } if ( @@ -122,7 +122,7 @@ public static function decideType( if ( ($type->isCallable()->yes() && $phpDocType->isCallable()->yes()) || ( - (!$phpDocType instanceof NeverType || ($type instanceof MixedType && !$type->isExplicitMixed())) + (!$phpDocType->isNever()->yes() || ($type instanceof MixedType && !$type->isExplicitMixed())) && $type->isSuperTypeOf(TemplateTypeHelper::resolveToBounds($phpDocType))->yes() ) ) { diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index a1907e6525..0afcf9d661 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -239,7 +239,7 @@ public function isSuperTypeOf(Type $otherType): IsSuperTypeOfResult if ( ($otherType instanceof self && !$otherType instanceof TemplateUnionType) || ($otherType instanceof IterableType && !$otherType instanceof TemplateIterableType) - || $otherType instanceof NeverType + || $otherType->isNever()->yes() || ($otherType instanceof LateResolvableType && $otherType instanceof CompoundType && !$otherType instanceof TemplateType) || $otherType instanceof IntegerRangeType ) { diff --git a/tests/PHPStan/Reflection/InitializerExprTypeResolverTest.php b/tests/PHPStan/Reflection/InitializerExprTypeResolverTest.php index 6c3ba79cfb..09013cb38a 100644 --- a/tests/PHPStan/Reflection/InitializerExprTypeResolverTest.php +++ b/tests/PHPStan/Reflection/InitializerExprTypeResolverTest.php @@ -117,14 +117,14 @@ public function testExplicitNever(Expr $left, Expr $right, callable $callback, s ); $this->assertInstanceOf($resultClass, $result); - if (!($result instanceof NeverType)) { + if (!$result->isNever()->yes()) { return; } if ($resultIsExplicit === null) { throw new ShouldNotHappenException(); } - $this->assertSame($resultIsExplicit, $result->isExplicit()); + $this->assertSame($resultIsExplicit, $result->isExplicitNever()->yes()); } } diff --git a/tests/PHPStan/Type/TypeCombinatorTest.php b/tests/PHPStan/Type/TypeCombinatorTest.php index 136e43c51e..59837fc860 100644 --- a/tests/PHPStan/Type/TypeCombinatorTest.php +++ b/tests/PHPStan/Type/TypeCombinatorTest.php @@ -4836,8 +4836,8 @@ public function testIntersect( $actualTypeDescription .= '=implicit'; } } - if ($actualType instanceof NeverType) { - if ($actualType->isExplicit()) { + if (!$actualType->isNever()->no()) { + if ($actualType->isExplicitNever()->yes()) { $actualTypeDescription .= '=explicit'; } else { $actualTypeDescription .= '=implicit'; @@ -4879,8 +4879,8 @@ public function testIntersectInversed( $actualTypeDescription .= '=implicit'; } } - if ($actualType instanceof NeverType) { - if ($actualType->isExplicit()) { + if (!$actualType->isNever()->no()) { + if ($actualType->isExplicitNever()->yes()) { $actualTypeDescription .= '=explicit'; } else { $actualTypeDescription .= '=implicit'; @@ -5418,8 +5418,8 @@ public function testRemove( { $result = TypeCombinator::remove($fromType, $type); $actualTypeDescription = $result->describe(VerbosityLevel::precise()); - if ($result instanceof NeverType) { - if ($result->isExplicit()) { + if (!$result->isNever()->no()) { + if ($result->isExplicitNever()->yes()) { $actualTypeDescription .= '=explicit'; } else { $actualTypeDescription .= '=implicit'; From 398377fad10c16404bc1c000651e19ff47338b94 Mon Sep 17 00:00:00 2001 From: Can Vural Date: Wed, 11 Feb 2026 14:31:26 +0100 Subject: [PATCH 3/3] refactor new usages to methods --- src/Analyser/MutatingScope.php | 2 +- src/Reflection/InitializerExprTypeResolver.php | 2 +- src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php | 3 +-- src/Type/Php/ArrayCountValuesDynamicReturnTypeExtension.php | 3 +-- src/Type/TypeCombinator.php | 4 ++-- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index a97ea5d8af..66a970dad4 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -5530,7 +5530,7 @@ private function getInstanceOfType(Expr\Instanceof_ $node): Type ) { return new BooleanType(); } - if ($expressionType instanceof NeverType) { + if ($expressionType->isNever()->yes()) { return new ConstantBooleanType(false); } diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index 6681fb265e..a46b610c3f 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -1138,7 +1138,7 @@ private function getFiniteOrConstantScalarTypes(Type $leftType, Type $rightType, public function getBitwiseXorTypeFromTypes(Type $leftType, Type $rightType): Type { - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->or($rightType->isNever())->yes()) { return $this->getNeverType($leftType, $rightType); } diff --git a/src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php b/src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php index 3f251f8366..406326a4f7 100644 --- a/src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php +++ b/src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php @@ -13,7 +13,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\Constant\ConstantBooleanType; -use PHPStan\Type\NeverType; /** * @implements Rule @@ -70,7 +69,7 @@ public function processNode( if ($exprType->isTrue()->yes()) { $ref = $scope->getFunction() ?? $scope->getAnonymousFunctionReflection(); - if ($ref !== null && $ref->getReturnType() instanceof NeverType) { + if ($ref !== null && $ref->getReturnType()->isNever()->yes()) { return []; } diff --git a/src/Type/Php/ArrayCountValuesDynamicReturnTypeExtension.php b/src/Type/Php/ArrayCountValuesDynamicReturnTypeExtension.php index 986f299cd8..dff929ad7b 100644 --- a/src/Type/Php/ArrayCountValuesDynamicReturnTypeExtension.php +++ b/src/Type/Php/ArrayCountValuesDynamicReturnTypeExtension.php @@ -13,7 +13,6 @@ use PHPStan\Type\IntegerRangeType; use PHPStan\Type\IntegerType; use PHPStan\Type\IntersectionType; -use PHPStan\Type\NeverType; use PHPStan\Type\StringType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -50,7 +49,7 @@ public function getTypeFromFunctionCall( foreach ($arrayTypes as $arrayType) { $itemType = TypeCombinator::intersect($arrayType->getItemType(), $allowedValues); - if ($itemType instanceof NeverType) { + if ($itemType->isNever()->yes()) { continue; } diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index ad679cae4d..56a5f74314 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -165,7 +165,7 @@ public static function union(Type ...$types): Type ) { return $types[$i]; } - if ($types[$i] instanceof NeverType && !$types[$i]->isExplicit()) { + if ($types[$i]->isNever()->yes() && $types[$i]->isExplicitNever()->no()) { array_splice($types, $i--, 1); $typesCount--; continue; @@ -1135,7 +1135,7 @@ public static function intersect(Type ...$types): Type } foreach ($types as $type) { - if ($type instanceof NeverType && !$type->isExplicit()) { + if ($type->isNever()->yes() && $type->isExplicitNever()->no()) { return $type; } }