diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 6c3ff7e153..bf785355b9 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1437,6 +1437,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 @@ -1767,6 +1779,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/ExprHandler/BooleanAndHandler.php b/src/Analyser/ExprHandler/BooleanAndHandler.php index 5b672a2db5..4bc2f002ed 100644 --- a/src/Analyser/ExprHandler/BooleanAndHandler.php +++ b/src/Analyser/ExprHandler/BooleanAndHandler.php @@ -19,7 +19,6 @@ use PHPStan\Node\BooleanAndNode; use PHPStan\Type\BooleanType; use PHPStan\Type\Constant\ConstantBooleanType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use function array_merge; @@ -91,7 +90,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex $leftTruthyScope = $leftResult->getTruthyScope(); $rightResult = $nodeScopeResolver->processExprNode($stmt, $expr->right, $leftTruthyScope, $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()); diff --git a/src/Analyser/ExprHandler/BooleanOrHandler.php b/src/Analyser/ExprHandler/BooleanOrHandler.php index 9c828edb94..ed63207c68 100644 --- a/src/Analyser/ExprHandler/BooleanOrHandler.php +++ b/src/Analyser/ExprHandler/BooleanOrHandler.php @@ -17,7 +17,6 @@ use PHPStan\Node\BooleanOrNode; use PHPStan\Type\BooleanType; use PHPStan\Type\Constant\ConstantBooleanType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use function array_merge; @@ -75,7 +74,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex $leftFalseyScope = $leftResult->getFalseyScope(); $rightResult = $nodeScopeResolver->processExprNode($stmt, $expr->right, $leftFalseyScope, $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()); diff --git a/src/Analyser/ExprHandler/CoalesceHandler.php b/src/Analyser/ExprHandler/CoalesceHandler.php index 4c9d01d194..e83f233ea0 100644 --- a/src/Analyser/ExprHandler/CoalesceHandler.php +++ b/src/Analyser/ExprHandler/CoalesceHandler.php @@ -13,7 +13,6 @@ use PHPStan\Analyser\MutatingScope; use PHPStan\Analyser\NodeScopeResolver; use PHPStan\DependencyInjection\AutowiredService; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use function array_merge; @@ -76,7 +75,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex $rightScope = $scope->filterByFalseyValue($expr); $rightResult = $nodeScopeResolver->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()); diff --git a/src/Analyser/ExprHandler/FuncCallHandler.php b/src/Analyser/ExprHandler/FuncCallHandler.php index 96cf7fa0f1..984a04769f 100644 --- a/src/Analyser/ExprHandler/FuncCallHandler.php +++ b/src/Analyser/ExprHandler/FuncCallHandler.php @@ -52,7 +52,6 @@ use PHPStan\Type\IntegerType; use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\NullType; use PHPStan\Type\ObjectType; use PHPStan\Type\StringType; @@ -160,7 +159,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex 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 ( @@ -511,7 +510,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); } } diff --git a/src/Analyser/ExprHandler/InstanceofHandler.php b/src/Analyser/ExprHandler/InstanceofHandler.php index 59d09b1c9a..cd33e0cffd 100644 --- a/src/Analyser/ExprHandler/InstanceofHandler.php +++ b/src/Analyser/ExprHandler/InstanceofHandler.php @@ -17,7 +17,6 @@ use PHPStan\Type\BooleanType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\StaticType; use PHPStan\Type\Type; @@ -75,7 +74,7 @@ public function resolveType(MutatingScope $scope, Expr $expr): Type ) { return new BooleanType(); } - if ($expressionType instanceof NeverType) { + if ($expressionType->isNever()->yes()) { return new ConstantBooleanType(false); } diff --git a/src/Analyser/ExprHandler/MatchHandler.php b/src/Analyser/ExprHandler/MatchHandler.php index 626e6fc717..77351e476c 100644 --- a/src/Analyser/ExprHandler/MatchHandler.php +++ b/src/Analyser/ExprHandler/MatchHandler.php @@ -442,7 +442,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex $isExhaustive = $hasDefaultCond || $hasAlwaysTrueCond; if (!$isExhaustive) { $remainingType = $matchScope->getType($expr->cond); - if ($remainingType instanceof NeverType) { + if ($remainingType->isNever()->yes()) { $isExhaustive = true; } } @@ -548,7 +548,7 @@ private function scopeHasNeverVariable(MutatingScope $scope, array $varNames): b { foreach ($varNames as $varName) { $type = $scope->getVariableType($varName); - if ($type instanceof NeverType) { + if ($type->isNever()->yes()) { return true; } } diff --git a/src/Analyser/ExprHandler/MethodCallHandler.php b/src/Analyser/ExprHandler/MethodCallHandler.php index bf40faf546..eb3888b317 100644 --- a/src/Analyser/ExprHandler/MethodCallHandler.php +++ b/src/Analyser/ExprHandler/MethodCallHandler.php @@ -34,7 +34,6 @@ use PHPStan\Type\Generic\TemplateTypeVariance; use PHPStan\Type\Generic\TemplateTypeVarianceMap; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -140,7 +139,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex if ($parametersAcceptor !== null) { $normalizedExpr = ArgumentsNormalizer::reorderMethodArguments($parametersAcceptor, $expr) ?? $expr; $returnType = $parametersAcceptor->getReturnType(); - $isAlwaysTerminating = $returnType instanceof NeverType && $returnType->isExplicit(); + $isAlwaysTerminating = $returnType->isExplicitNever()->yes(); } $argsResult = $nodeScopeResolver->processArgs( @@ -262,7 +261,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); } } diff --git a/src/Analyser/ExprHandler/NewHandler.php b/src/Analyser/ExprHandler/NewHandler.php index 4179b5259d..e501d849c6 100644 --- a/src/Analyser/ExprHandler/NewHandler.php +++ b/src/Analyser/ExprHandler/NewHandler.php @@ -41,7 +41,6 @@ use PHPStan\Type\Generic\GenericStaticType; use PHPStan\Type\Generic\TemplateType; use PHPStan\Type\Generic\TemplateTypeMap; -use PHPStan\Type\NeverType; use PHPStan\Type\NonexistentParentClassType; use PHPStan\Type\ObjectType; use PHPStan\Type\StaticType; @@ -394,7 +393,7 @@ private function exactInstantiation(MutatingScope $scope, New_ $node, Name $clas } $methodResult = $scope->getType($methodCall); - if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { + if ($methodResult->isExplicitNever()->yes()) { return $methodResult; } diff --git a/src/Analyser/ExprHandler/StaticCallHandler.php b/src/Analyser/ExprHandler/StaticCallHandler.php index 1438af86fa..a45436a894 100644 --- a/src/Analyser/ExprHandler/StaticCallHandler.php +++ b/src/Analyser/ExprHandler/StaticCallHandler.php @@ -33,7 +33,6 @@ use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\Type\ErrorType; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\StaticType; use PHPStan\Type\Type; @@ -197,7 +196,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex if ($parametersAcceptor !== null) { $normalizedExpr = ArgumentsNormalizer::reorderStaticCallArguments($parametersAcceptor, $expr) ?? $expr; $returnType = $parametersAcceptor->getReturnType(); - $isAlwaysTerminating = $returnType instanceof NeverType && $returnType->isExplicit(); + $isAlwaysTerminating = $returnType->isExplicitNever()->yes(); } $argsResult = $nodeScopeResolver->processArgs($stmt, $methodReflection, null, $parametersAcceptor, $normalizedExpr, $scope, $storage, $nodeCallback, $context, $closureBindScope); $scope = $argsResult->getScope(); diff --git a/src/Analyser/ExprHandler/TernaryHandler.php b/src/Analyser/ExprHandler/TernaryHandler.php index 81b58b16c8..90e2ef3066 100644 --- a/src/Analyser/ExprHandler/TernaryHandler.php +++ b/src/Analyser/ExprHandler/TernaryHandler.php @@ -13,7 +13,6 @@ use PHPStan\Analyser\NodeScopeResolver; use PHPStan\Analyser\NoopNodeCallback; use PHPStan\DependencyInjection\AutowiredService; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use function array_merge; @@ -104,12 +103,12 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex } 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); diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index e60242af43..ef1d0d000e 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -84,7 +84,6 @@ use PHPStan\Type\IntegerType; use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\NullType; use PHPStan\Type\ObjectType; use PHPStan\Type\StaticType; @@ -3023,12 +3022,12 @@ public function addTypeToExpression(Expr $expr, Type $type): self public function removeTypeFromExpression(Expr $expr, Type $typeToRemove): self { - if ($typeToRemove instanceof NeverType) { + if ($typeToRemove->isNever()->yes()) { return $this; } $exprType = $this->getType($expr); - if ($exprType instanceof NeverType) { + if ($exprType->isNever()->yes()) { return $this; } @@ -4532,7 +4531,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; } } @@ -4544,7 +4543,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 79b05cd0f8..555abcbfa9 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -1799,7 +1799,7 @@ public function processStmtNode( } } - $exhaustive = $scopeForBranches->getType($stmt->cond) instanceof NeverType; + $exhaustive = $scopeForBranches->getType($stmt->cond)->isNever()->yes(); if (!$hasDefaultCase && !$exhaustive) { $alwaysTerminating = false; @@ -1949,7 +1949,7 @@ public function processStmtNode( foreach ($throwPoints as $throwPoint) { $newThrowPoint = $throwPoint->subtractCatchType($originalCatchType); - if ($newThrowPoint->getType() instanceof NeverType) { + if (!$newThrowPoint->getType()->isNever()->no()) { continue; } @@ -2460,7 +2460,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; } @@ -2723,7 +2723,7 @@ public function processClosureNode( } $returnType = $closureType->getReturnType(); - $isAlwaysTerminating = ($returnType instanceof NeverType && $returnType->isExplicit()); + $isAlwaysTerminating = ($returnType->isExplicitNever()->yes()); $this->callNodeCallback($nodeCallback, new InClosureNode($closureType, $expr), $closureScope, $storage); @@ -3416,7 +3416,7 @@ public 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()); } } } @@ -4088,7 +4088,7 @@ public function processCalledMethod(MethodReflection $methodReflection): ?Mutati $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/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 0aafa3956b..e40dee13cd 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -1628,7 +1628,7 @@ private function getConditionalSpecifiedTypes( ( $argumentExpr instanceof Node\Scalar || ($argumentExpr instanceof ConstFetch && in_array(strtolower($argumentExpr->name->toString()), ['true', 'false', 'null'], true)) - ) && ($ifType instanceof NeverType || $elseType instanceof NeverType) + ) && ($ifType->isNever()->yes() || $elseType->isNever()->yes()) ) { return null; } 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 6c48e4b010..4a0d81106e 100644 --- a/src/Reflection/Callables/FunctionCallableVariant.php +++ b/src/Reflection/Callables/FunctionCallableVariant.php @@ -10,7 +10,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; @@ -98,7 +97,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 0891f487b7..31ebf901df 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -933,7 +933,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); } } @@ -991,7 +991,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); } @@ -1049,7 +1049,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); } @@ -1157,7 +1157,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); } @@ -1205,7 +1205,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); } @@ -1302,7 +1302,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); } @@ -1416,7 +1416,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); } @@ -1761,7 +1761,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); } @@ -1825,7 +1825,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); } @@ -1908,7 +1908,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), []); } @@ -2090,7 +2090,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); } @@ -2725,10 +2725,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/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/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 127cae01cd..c7be6d254f 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; @@ -150,7 +149,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 665b7af1e3..e5b07a2efd 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; @@ -135,7 +134,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/Comparison/WhileLoopAlwaysTrueConditionRule.php b/src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php index bfc50e3e48..772a19d5b9 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 @@ -75,7 +74,7 @@ public function processNode( $ref = $scope->getFunction() ?? $scope->getAnonymousFunctionReflection(); - if ($ref !== null && $ref->getReturnType() instanceof NeverType) { + if ($ref !== null && $ref->getReturnType()->isNever()->yes()) { return []; } 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 16c0938b06..835bd69f67 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -22,7 +22,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; @@ -517,8 +516,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 6ef8f74b15..ec7d2b2ae1 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; @@ -524,7 +523,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..ac1c94a967 100644 --- a/src/Rules/PhpDoc/UnresolvableTypeHelper.php +++ b/src/Rules/PhpDoc/UnresolvableTypeHelper.php @@ -4,7 +4,7 @@ use PHPStan\DependencyInjection\AutowiredService; use PHPStan\Type\ErrorType; -use PHPStan\Type\NeverType; +use PHPStan\Type\LateResolvableType; use PHPStan\Type\Type; use PHPStan\Type\TypeTraverser; @@ -19,7 +19,7 @@ public function containsUnresolvableType(Type $type): bool if ($type instanceof ErrorType) { $containsUnresolvable = true; } - if ($type instanceof NeverType && !$type->isExplicit()) { + if (!$type instanceof LateResolvableType && $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 9c05539935..7b00908bd5 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/Accessory/AccessoryArrayListType.php b/src/Type/Accessory/AccessoryArrayListType.php index ff3536f473..22d86d5852 100644 --- a/src/Type/Accessory/AccessoryArrayListType.php +++ b/src/Type/Accessory/AccessoryArrayListType.php @@ -435,6 +435,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 da1abf5e37..dd2120f581 100644 --- a/src/Type/Accessory/AccessoryLiteralStringType.php +++ b/src/Type/Accessory/AccessoryLiteralStringType.php @@ -345,6 +345,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 2e5ca83146..3642d6fbfc 100644 --- a/src/Type/Accessory/AccessoryLowercaseStringType.php +++ b/src/Type/Accessory/AccessoryLowercaseStringType.php @@ -342,6 +342,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 2499084ba4..9bc218b433 100644 --- a/src/Type/Accessory/AccessoryNonEmptyStringType.php +++ b/src/Type/Accessory/AccessoryNonEmptyStringType.php @@ -337,6 +337,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 9f2eebdbd2..f0e545b9de 100644 --- a/src/Type/Accessory/AccessoryNonFalsyStringType.php +++ b/src/Type/Accessory/AccessoryNonFalsyStringType.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 { $falseyTypes = StaticTypeFactory::falsey(); diff --git a/src/Type/Accessory/AccessoryNumericStringType.php b/src/Type/Accessory/AccessoryNumericStringType.php index bece8e04ec..bb9fcaaa5c 100644 --- a/src/Type/Accessory/AccessoryNumericStringType.php +++ b/src/Type/Accessory/AccessoryNumericStringType.php @@ -345,6 +345,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 a85c74745b..dce06b0667 100644 --- a/src/Type/Accessory/AccessoryUppercaseStringType.php +++ b/src/Type/Accessory/AccessoryUppercaseStringType.php @@ -342,6 +342,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 b6757fefb6..841f9b07c4 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 e3b06be521..e6eef03cf5 100644 --- a/src/Type/Accessory/HasOffsetValueType.php +++ b/src/Type/Accessory/HasOffsetValueType.php @@ -431,6 +431,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 688da67695..7aedb13dbf 100644 --- a/src/Type/Accessory/NonEmptyArrayType.php +++ b/src/Type/Accessory/NonEmptyArrayType.php @@ -422,6 +422,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 4956e87992..3b96087d61 100644 --- a/src/Type/Accessory/OversizedArrayType.php +++ b/src/Type/Accessory/OversizedArrayType.php @@ -399,6 +399,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/ArrayType.php b/src/Type/ArrayType.php index 288caefdc6..bf7efd87f7 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([], []); } @@ -617,7 +617,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([], []); } @@ -660,7 +660,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/CallableType.php b/src/Type/CallableType.php index 380c87982a..7859cd6320 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -738,6 +738,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 0a380dff93..835bad18f9 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -840,6 +840,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/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 47d57f8b09..5a97a7de96 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -595,7 +595,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/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/Generic/GenericClassStringType.php b/src/Type/Generic/GenericClassStringType.php index b4ac3eff88..4641925764 100644 --- a/src/Type/Generic/GenericClassStringType.php +++ b/src/Type/Generic/GenericClassStringType.php @@ -226,7 +226,7 @@ public function tryRemove(Type $typeToRemove): ?Type $classReflection = $reflectionProvider->getClass($typeToRemove->getValue()); if ($classReflection->isFinal()) { $remainingType = TypeCombinator::remove($generic, $objectTypeToRemove); - if ($remainingType instanceof NeverType) { + if ($remainingType->isNever()->yes()) { 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 d823f9b20d..0c40abf549 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; @@ -221,7 +220,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 cca7052f5f..02b7e885e1 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -254,7 +254,7 @@ public function isSuperTypeOf(Type $otherType): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - if ($otherType instanceof NeverType) { + if (!$otherType->isNever()->no()) { return IsSuperTypeOfResult::createYes(); } @@ -853,6 +853,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 2cf46b754e..a9082ad851 100644 --- a/src/Type/IterableType.php +++ b/src/Type/IterableType.php @@ -417,6 +417,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 0c1892e01e..e4a5e0b939 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(); } @@ -1076,6 +1076,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 2da6f5e9fa..d70924b4f9 100644 --- a/src/Type/NeverType.php +++ b/src/Type/NeverType.php @@ -554,6 +554,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/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/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/ObjectShapeType.php b/src/Type/ObjectShapeType.php index 9dedcfa148..fa437aba71 100644 --- a/src/Type/ObjectShapeType.php +++ b/src/Type/ObjectShapeType.php @@ -527,7 +527,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 f90a09d690..3c3a11693d 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -129,7 +129,7 @@ public function __construct( private ?ClassReflection $classReflection = null, ) { - if ($subtractedType instanceof NeverType) { + if ($subtractedType !== null && !$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -1353,6 +1353,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()) { @@ -1891,7 +1901,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 48f6b1e07b..1753930477 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; } @@ -199,7 +199,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/ArrayCountValuesDynamicReturnTypeExtension.php b/src/Type/Php/ArrayCountValuesDynamicReturnTypeExtension.php index e04b66a84e..191818dff3 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; @@ -51,7 +50,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/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 682bc77d30..28b25aec54 100644 --- a/src/Type/StaticType.php +++ b/src/Type/StaticType.php @@ -50,7 +50,7 @@ public function __construct( ?Type $subtractedType = null, ) { - if ($subtractedType instanceof NeverType) { + if ($subtractedType !== null && !$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -703,6 +703,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(); @@ -806,7 +816,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/StrictMixedType.php b/src/Type/StrictMixedType.php index af20367941..5a4ccc4f13 100644 --- a/src/Type/StrictMixedType.php +++ b/src/Type/StrictMixedType.php @@ -336,6 +336,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 4b0dacddd7..83c40b8bb2 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(); } @@ -544,6 +543,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 9af6fcf203..4523bacc2a 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -416,6 +416,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/TypeCombinator.php b/src/Type/TypeCombinator.php index 3f0e8877bc..20916f15df 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -167,7 +167,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; @@ -611,7 +611,7 @@ private static function unionWithSubtractedType( $type->getTypeWithoutSubtractedType(), $subtractedType, ); - if ($subtractedType instanceof NeverType) { + if (!$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -630,7 +630,7 @@ private static function intersectWithSubtractedType( Type $b, ): Type { - if ($a->getSubtractedType() === null || $b instanceof NeverType) { + if ($a->getSubtractedType() === null || !$b->isNever()->no()) { return $a; } @@ -672,7 +672,7 @@ private static function intersectWithSubtractedType( $subtractedType = self::remove($a->getSubtractedType(), $b); if ( - $subtractedType instanceof NeverType + !$subtractedType->isNever()->no() || !$subtractedType->isSuperTypeOf($b)->no() ) { $subtractedType = null; @@ -697,7 +697,7 @@ private static function intersectWithSubtractedType( $a->getSubtractedType(), $subtractedType, ); - if ($subtractedType instanceof NeverType) { + if (!$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -1137,7 +1137,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; } } @@ -1184,7 +1184,7 @@ public static function intersect(Type ...$types): Type } $union = self::union(...$topLevelUnionSubTypes); - if ($union instanceof NeverType) { + if (!$union->isNever()->no()) { return $union; } @@ -1375,7 +1375,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); @@ -1388,7 +1388,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; } @@ -1487,7 +1487,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/TypeUtils.php b/src/Type/TypeUtils.php index 2b0c7635de..629217fbf8 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -157,7 +157,7 @@ public static function flattenTypes(Type $type): array static fn (array $types): Type => TypeCombinator::intersect(...$types), iterator_to_array(CombinationsHelper::combinations($newTypes)), ), - static fn (Type $type): bool => !$type instanceof NeverType, + static fn (Type $type): bool => $type->isNever()->no(), ); } diff --git a/src/Type/TypehintHelper.php b/src/Type/TypehintHelper.php index 076fedcacc..34460e68a9 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 instanceof LateResolvableType || $phpDocType->isNever()->no() || ($type instanceof MixedType && !$type->isExplicitMixed())) && $type->isSuperTypeOf(TemplateTypeHelper::resolveToBounds($phpDocType))->yes() ) ) { diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index 1348e27dc5..fcf8242f3d 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -243,7 +243,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 ) { @@ -751,6 +751,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(); 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 508768ca6d..d9b929ea86 100644 --- a/tests/PHPStan/Type/TypeCombinatorTest.php +++ b/tests/PHPStan/Type/TypeCombinatorTest.php @@ -4875,8 +4875,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'; @@ -4918,8 +4918,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'; @@ -5457,8 +5457,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';