diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 4b4096c92c..de14e50b0b 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1443,6 +1443,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 @@ -1785,6 +1797,12 @@ parameters: count: 1 path: src/Type/TypehintHelper.php + - + rawMessage: 'Call to an undefined method PHPStan\Type\Type::isSubTypeOf().' + identifier: method.notFound + count: 1 + path: src/Type/UnionType.php + - rawMessage: 'Doing instanceof PHPStan\Type\CallableType is error-prone and deprecated. Use Type::isCallable() and Type::getCallableParametersAcceptors() instead.' identifier: phpstanApi.instanceofType diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 6b4aa7ffb0..eff888980c 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -1068,7 +1068,7 @@ private function resolveType(string $exprString, Expr $node): Type ) { return new BooleanType(); } - if ($expressionType instanceof NeverType) { + if (!$expressionType->isNever()->no()) { return new ConstantBooleanType(false); } @@ -4578,8 +4578,8 @@ public function removeTypeFromExpression(Expr $expr, Type $typeToRemove): self { $exprType = $this->getType($expr); if ( - $exprType instanceof NeverType || - $typeToRemove instanceof NeverType + !$exprType->isNever()->no() || + !$typeToRemove->isNever()->no() ) { return $this; } @@ -5891,7 +5891,7 @@ private function exactInstantiation(New_ $node, string $className): ?Type } $methodResult = $this->getType($methodCall); - if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { + if ($methodResult->isExplicitNever()->yes()) { return $methodResult; } @@ -6347,7 +6347,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; } } @@ -6359,7 +6359,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 11bd88f402..c69c16f44d 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -1748,7 +1748,7 @@ private function processStmtNode( } } - $exhaustive = $scopeForBranches->getType($stmt->cond) instanceof NeverType; + $exhaustive = $scopeForBranches->getType($stmt->cond)->isNever()->yes(); if (!$hasDefaultCase && !$exhaustive) { $alwaysTerminating = false; @@ -1893,7 +1893,7 @@ private function processStmtNode( foreach ($throwPoints as $throwPoint) { $newThrowPoint = $throwPoint->subtractCatchType($originalCatchType); - if ($newThrowPoint->getType() instanceof NeverType) { + if (!$newThrowPoint->getType()->isNever()->no()) { continue; } @@ -2489,7 +2489,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; } @@ -2709,7 +2709,7 @@ static function (): void { if ($parametersAcceptor !== null) { $expr = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $expr) ?? $expr; $returnType = $parametersAcceptor->getReturnType(); - $isAlwaysTerminating = $isAlwaysTerminating || $returnType instanceof NeverType && $returnType->isExplicit(); + $isAlwaysTerminating = $isAlwaysTerminating || $returnType->isExplicitNever()->yes(); } if ( @@ -3032,7 +3032,7 @@ static function (): void { if ($parametersAcceptor !== null) { $expr = ArgumentsNormalizer::reorderMethodArguments($parametersAcceptor, $expr) ?? $expr; $returnType = $parametersAcceptor->getReturnType(); - $isAlwaysTerminating = $returnType instanceof NeverType && $returnType->isExplicit(); + $isAlwaysTerminating = $returnType->isExplicitNever()->yes(); } $result = $this->processArgs( @@ -3224,7 +3224,7 @@ static function (): void { if ($parametersAcceptor !== null) { $expr = ArgumentsNormalizer::reorderStaticCallArguments($parametersAcceptor, $expr) ?? $expr; $returnType = $parametersAcceptor->getReturnType(); - $isAlwaysTerminating = $returnType instanceof NeverType && $returnType->isExplicit(); + $isAlwaysTerminating = $returnType->isExplicitNever()->yes(); } $result = $this->processArgs($stmt, $methodReflection, null, $parametersAcceptor, $expr, $scope, $nodeCallback, $context, $closureBindScope ?? null); $scope = $result->getScope(); @@ -3450,7 +3450,7 @@ static function (): void { $leftResult = $this->processExprNode($stmt, $expr->left, $scope, $nodeCallback, $context->enterDeep()); $rightResult = $this->processExprNode($stmt, $expr->right, $leftResult->getTruthyScope(), $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()); @@ -3471,7 +3471,7 @@ static function (): void { $leftResult = $this->processExprNode($stmt, $expr->left, $scope, $nodeCallback, $context->enterDeep()); $rightResult = $this->processExprNode($stmt, $expr->right, $leftResult->getFalseyScope(), $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()); @@ -3498,7 +3498,7 @@ static function (): void { $rightScope = $scope->filterByFalseyValue($expr); $rightResult = $this->processExprNode($stmt, $expr->right, $rightScope, $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()); @@ -3936,12 +3936,12 @@ static function (): void { } 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); @@ -4196,7 +4196,7 @@ static function (): void { } $remainingType = $matchScope->getType($expr->cond); - if (!$hasDefaultCond && !$hasAlwaysTrueCond && !$remainingType instanceof NeverType) { + if (!$hasDefaultCond && !$hasAlwaysTrueCond && $remainingType->isNever()->no()) { $throwPoints[] = ThrowPoint::createExplicit($scope, new ObjectType(UnhandledMatchError::class), $expr, false); } @@ -4502,7 +4502,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); } } @@ -4560,7 +4560,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); } } @@ -4857,7 +4857,7 @@ private function processClosureNode( } $returnType = $closureType->getReturnType(); - $isAlwaysTerminating = ($returnType instanceof NeverType && $returnType->isExplicit()); + $isAlwaysTerminating = ($returnType->isExplicitNever()->yes()); $nodeCallback(new InClosureNode($closureType, $expr), $closureScope); @@ -5545,7 +5545,7 @@ private function processArgs( $throwPoints = array_merge($throwPoints, $callableThrowPoints); $impurePoints = array_merge($impurePoints, array_map(static fn (SimpleImpurePoint $impurePoint) => new ImpurePoint($scope, $arg->value, $impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()), $acceptors[0]->getImpurePoints())); $returnType = $acceptors[0]->getReturnType(); - $isAlwaysTerminating = $isAlwaysTerminating || ($returnType instanceof NeverType && $returnType->isExplicit()); + $isAlwaysTerminating = $isAlwaysTerminating || ($returnType->isExplicitNever()->yes()); } } } @@ -6961,7 +6961,7 @@ private function processCalledMethod(MethodReflection $methodReflection): ?Mutat $endNode = $executionEnd->getNode(); if ($endNode instanceof Node\Stmt\Expression) { $exprType = $statementResult->getScope()->getType($endNode->expr); - if ($exprType instanceof NeverType && $exprType->isExplicit()) { + if ($exprType->isExplicitNever()->yes()) { continue; } } diff --git a/src/Node/ClassPropertiesNode.php b/src/Node/ClassPropertiesNode.php index 5f47c928b5..637797d1f6 100644 --- a/src/Node/ClassPropertiesNode.php +++ b/src/Node/ClassPropertiesNode.php @@ -21,7 +21,6 @@ use PHPStan\Reflection\MethodReflection; use PHPStan\Rules\Properties\ReadWritePropertiesExtensionProvider; use PHPStan\TrinaryLogic; -use PHPStan\Type\NeverType; use PHPStan\Type\TypeUtils; use function array_diff_key; use function array_key_exists; @@ -276,7 +275,7 @@ private function collectUninitializedProperties(array $constructors, array $unin if ($statementResult->isAlwaysTerminating()) { if ($endNode instanceof Node\Stmt\Expression) { $exprType = $statementResult->getScope()->getType($endNode->expr); - if ($exprType instanceof NeverType && $exprType->isExplicit()) { + if ($exprType->isExplicitNever()->yes()) { continue; } } diff --git a/src/Reflection/Callables/FunctionCallableVariant.php b/src/Reflection/Callables/FunctionCallableVariant.php index 5e385e4480..b036dede14 100644 --- a/src/Reflection/Callables/FunctionCallableVariant.php +++ b/src/Reflection/Callables/FunctionCallableVariant.php @@ -9,7 +9,6 @@ use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\Generic\TemplateTypeVarianceMap; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use Throwable; @@ -97,7 +96,7 @@ public function getThrowPoints(): array $returnType = $this->variant->getReturnType(); $throwType = $this->function->getThrowType(); if ($throwType === null) { - if ($returnType instanceof NeverType && $returnType->isExplicit()) { + if ($returnType->isExplicitNever()->yes()) { $throwType = new ObjectType(Throwable::class); } } diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index 47157cf01a..d96be65612 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -903,7 +903,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); } } @@ -954,7 +954,7 @@ public function getBitwiseAndType(Expr $left, Expr $right, callable $getTypeCall $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1023,7 +1023,7 @@ public function getBitwiseOrType(Expr $left, Expr $right, callable $getTypeCallb $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1082,7 +1082,7 @@ public function getBitwiseXorType(Expr $left, Expr $right, callable $getTypeCall $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1141,7 +1141,7 @@ public function getSpaceshipType(Expr $left, Expr $right, callable $getTypeCallb $callbackLeftType = $getTypeCallback($left); $callbackRightType = $getTypeCallback($right); - if ($callbackLeftType instanceof NeverType || $callbackRightType instanceof NeverType) { + if ($callbackLeftType->isNever()->yes() || $callbackRightType->isNever()->yes()) { return $this->getNeverType($callbackLeftType, $callbackRightType); } @@ -1228,7 +1228,7 @@ public function getModType(Expr $left, Expr $right, callable $getTypeCallback): $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1337,7 +1337,7 @@ public function getPlusType(Expr $left, Expr $right, callable $getTypeCallback): $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1645,7 +1645,7 @@ public function getShiftLeftType(Expr $left, Expr $right, callable $getTypeCallb $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1704,7 +1704,7 @@ public function getShiftRightType(Expr $left, Expr $right, callable $getTypeCall $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); - if ($leftType instanceof NeverType || $rightType instanceof NeverType) { + if ($leftType->isNever()->yes() || $rightType->isNever()->yes()) { return $this->getNeverType($leftType, $rightType); } @@ -1787,7 +1787,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), []); } @@ -1969,7 +1969,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); } @@ -2587,10 +2587,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 37959a7a64..6920771626 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; @@ -1161,7 +1160,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 ce6f8a2e37..f162f3a2cf 100644 --- a/src/Reflection/Php/PhpPropertyReflection.php +++ b/src/Reflection/Php/PhpPropertyReflection.php @@ -10,7 +10,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; @@ -124,7 +123,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 c88c5114bf..3682fe9c45 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; @@ -79,6 +80,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 b353e7f60d..5b3caeeb94 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; @@ -146,7 +145,7 @@ public function findSpecifiedType( if (!$haystackType instanceof ConstantArrayType || count($haystackType->getValueTypes()) > 0) { $haystackArrayTypes = $haystackType->getArrays(); - if (count($haystackArrayTypes) === 1 && $haystackArrayTypes[0]->getIterableValueType() instanceof NeverType) { + if (count($haystackArrayTypes) === 1 && !$haystackArrayTypes[0]->getIterableValueType()->isNever()->no()) { return null; } diff --git a/src/Rules/Comparison/MatchExpressionRule.php b/src/Rules/Comparison/MatchExpressionRule.php index 8c31b92242..8547815bf1 100644 --- a/src/Rules/Comparison/MatchExpressionRule.php +++ b/src/Rules/Comparison/MatchExpressionRule.php @@ -11,7 +11,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\Constant\ConstantBooleanType; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\TypeCombinator; use PHPStan\Type\UnionType; @@ -131,7 +130,7 @@ public function processNode(Node $node, Scope $scope): array $remainingType = $cases[0]; } if ( - !$remainingType instanceof NeverType + $remainingType->isNever()->no() && !$this->isUnhandledMatchErrorCaught($node) && !$this->hasUnhandledMatchErrorThrowsTag($scope) ) { diff --git a/src/Rules/Exceptions/CatchWithUnthrownExceptionRule.php b/src/Rules/Exceptions/CatchWithUnthrownExceptionRule.php index f4e2479a2a..118376b8f1 100644 --- a/src/Rules/Exceptions/CatchWithUnthrownExceptionRule.php +++ b/src/Rules/Exceptions/CatchWithUnthrownExceptionRule.php @@ -9,7 +9,6 @@ use PHPStan\Node\CatchWithUnthrownExceptionNode; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\Type\NeverType; use PHPStan\Type\VerbosityLevel; use function sprintf; @@ -36,7 +35,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - if ($node->getCaughtType() instanceof NeverType) { + if ($node->getCaughtType()->isNever()->yes()) { return [ RuleErrorBuilder::message( sprintf('Dead catch - %s is already caught above.', $node->getOriginalCaughtType()->describe(VerbosityLevel::typeOnly())), diff --git a/src/Rules/Exceptions/TooWideThrowTypeCheck.php b/src/Rules/Exceptions/TooWideThrowTypeCheck.php index 1eb978a73f..a246e99bc0 100644 --- a/src/Rules/Exceptions/TooWideThrowTypeCheck.php +++ b/src/Rules/Exceptions/TooWideThrowTypeCheck.php @@ -43,7 +43,7 @@ public function check(Type $throwType, array $throwPoints): array $throwClasses = []; foreach (TypeUtils::flattenTypes($throwType) as $type) { - if (!$throwPointType instanceof NeverType && !$type->isSuperTypeOf($throwPointType)->no()) { + if ($throwPointType->isNever()->no() && !$type->isSuperTypeOf($throwPointType)->no()) { continue; } diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index 5cb8b48761..5bb5c2f4f7 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -21,7 +21,6 @@ use PHPStan\Type\ErrorType; use PHPStan\Type\Generic\TemplateType; use PHPStan\Type\IntegerRangeType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypeTraverser; @@ -503,8 +502,8 @@ static function (Type $type, callable $traverse) use (&$returnTemplateTypes): Ty if ( !($type instanceof ErrorType) && ( - !$type instanceof NeverType - || $type->isExplicit() + $type->isNever()->no() + || $type->isExplicitNever()->yes() ) ) { continue; diff --git a/src/Rules/FunctionDefinitionCheck.php b/src/Rules/FunctionDefinitionCheck.php index 3e7cf63770..0a39ba82aa 100644 --- a/src/Rules/FunctionDefinitionCheck.php +++ b/src/Rules/FunctionDefinitionCheck.php @@ -31,7 +31,6 @@ use PHPStan\ShouldNotHappenException; use PHPStan\Type\ConditionalTypeForParameter; use PHPStan\Type\Generic\TemplateType; -use PHPStan\Type\NeverType; use PHPStan\Type\NonexistentParentClassType; use PHPStan\Type\ParserNodeTypeToPHPStanType; use PHPStan\Type\Type; @@ -502,7 +501,7 @@ private function checkParametersAcceptor( $returnType = $parametersAcceptor->getReturnType(); if ( $returnType->isVoid()->yes() - || ($returnType instanceof NeverType && $returnType->isExplicit()) + || ($returnType->isExplicitNever()->yes()) ) { $errors[] = RuleErrorBuilder::message(sprintf($noDiscardReturnTypeMessage, $returnType->describe(VerbosityLevel::typeOnly()))) ->line($returnTypeNode->getStartLine()) diff --git a/src/Rules/FunctionReturnTypeCheck.php b/src/Rules/FunctionReturnTypeCheck.php index e61965ca3a..4da1628b78 100644 --- a/src/Rules/FunctionReturnTypeCheck.php +++ b/src/Rules/FunctionReturnTypeCheck.php @@ -8,7 +8,6 @@ use PHPStan\Analyser\Scope; use PHPStan\DependencyInjection\AutowiredService; use PHPStan\Type\ErrorType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeUtils; use PHPStan\Type\VerbosityLevel; @@ -39,7 +38,7 @@ public function checkReturnType( { $returnType = TypeUtils::resolveLateResolvableTypes($returnType); - if ($returnType instanceof NeverType && $returnType->isExplicit()) { + if ($returnType->isExplicitNever()->yes()) { return [ RuleErrorBuilder::message($neverMessage) ->line($returnNode->getStartLine()) diff --git a/src/Rules/Functions/ArrowFunctionReturnTypeRule.php b/src/Rules/Functions/ArrowFunctionReturnTypeRule.php index ab1fecfe73..37e308e083 100644 --- a/src/Rules/Functions/ArrowFunctionReturnTypeRule.php +++ b/src/Rules/Functions/ArrowFunctionReturnTypeRule.php @@ -10,7 +10,6 @@ use PHPStan\Rules\FunctionReturnTypeCheck; use PHPStan\Rules\Rule; use PHPStan\ShouldNotHappenException; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; /** @@ -46,10 +45,8 @@ public function processNode(Node $node, Scope $scope): array $exprType = $scope->getType($originalNode->expr); if ( - $returnType instanceof NeverType - && $returnType->isExplicit() - && $exprType instanceof NeverType - && $exprType->isExplicit() + $returnType->isExplicitNever()->yes() + && $exprType->isExplicitNever()->yes() ) { return []; } diff --git a/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php b/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php index 361c9377aa..9cf03560bd 100644 --- a/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php +++ b/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php @@ -9,7 +9,6 @@ use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\Type\NeverType; use function count; use function in_array; use function sprintf; @@ -71,7 +70,7 @@ public function processNode(Node $node, Scope $scope): array } $functionResult = $scope->getType($funcCall); - if ($functionResult instanceof NeverType && $functionResult->isExplicit()) { + if ($functionResult->isExplicitNever()->yes()) { return []; } diff --git a/src/Rules/Generators/YieldInGeneratorRule.php b/src/Rules/Generators/YieldInGeneratorRule.php index 601c8f43a4..b91fd89fcc 100644 --- a/src/Rules/Generators/YieldInGeneratorRule.php +++ b/src/Rules/Generators/YieldInGeneratorRule.php @@ -10,7 +10,6 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\TrinaryLogic; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use function sprintf; /** @@ -57,7 +56,7 @@ public function processNode(Node $node, Scope $scope): array return []; } - if ($returnType instanceof NeverType && $returnType->isExplicit()) { + if ($returnType->isExplicitNever()->yes()) { $isSuperType = TrinaryLogic::createNo(); } else { $isSuperType = $returnType->isIterable()->and(TrinaryLogic::createFromBoolean( diff --git a/src/Rules/IssetCheck.php b/src/Rules/IssetCheck.php index 28b7780543..513be5ff2a 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->getType($expr) : $scope->getNativeType($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 3a064dc646..b038435185 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; @@ -68,7 +67,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 69f539f373..73a98ca05a 100644 --- a/src/Rules/PhpDoc/UnresolvableTypeHelper.php +++ b/src/Rules/PhpDoc/UnresolvableTypeHelper.php @@ -4,7 +4,6 @@ use PHPStan\DependencyInjection\AutowiredService; use PHPStan\Type\ErrorType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeTraverser; @@ -20,7 +19,7 @@ public function containsUnresolvableType(Type $type): bool $containsUnresolvable = true; return $type; } - if ($type instanceof NeverType && !$type->isExplicit()) { + if ($type->isNever()->yes() && $type->isExplicitNever()->no()) { $containsUnresolvable = true; return $type; } diff --git a/src/Rules/Playground/NeverRuleHelper.php b/src/Rules/Playground/NeverRuleHelper.php index a0870f7ce3..c54f99162a 100644 --- a/src/Rules/Playground/NeverRuleHelper.php +++ b/src/Rules/Playground/NeverRuleHelper.php @@ -5,7 +5,6 @@ use PhpParser\Node; use PHPStan\DependencyInjection\AutowiredService; use PHPStan\Node\ReturnStatementsNode; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; #[AutowiredService] @@ -17,7 +16,7 @@ final class NeverRuleHelper */ public function shouldReturnNever(ReturnStatementsNode $node, Type $returnType): array|false { - if ($returnType instanceof NeverType && $returnType->isExplicit()) { + if ($returnType->isExplicitNever()->yes()) { return false; } diff --git a/src/Rules/Properties/SetNonVirtualPropertyHookAssignRule.php b/src/Rules/Properties/SetNonVirtualPropertyHookAssignRule.php index e7a4ac5d88..9fd38c9517 100644 --- a/src/Rules/Properties/SetNonVirtualPropertyHookAssignRule.php +++ b/src/Rules/Properties/SetNonVirtualPropertyHookAssignRule.php @@ -10,7 +10,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\ShouldNotHappenException; -use PHPStan\Type\NeverType; use function sprintf; /** @@ -51,7 +50,7 @@ public function processNode(Node $node, Scope $scope): array if ($statementResult->isAlwaysTerminating()) { if ($endNode instanceof Node\Stmt\Expression) { $exprType = $statementResult->getScope()->getType($endNode->expr); - if ($exprType instanceof NeverType && $exprType->isExplicit()) { + if ($exprType->isExplicitNever()->yes()) { continue; } } diff --git a/src/Rules/RuleLevelHelper.php b/src/Rules/RuleLevelHelper.php index 1b46ccfbe7..a2e5b5621a 100644 --- a/src/Rules/RuleLevelHelper.php +++ b/src/Rules/RuleLevelHelper.php @@ -14,7 +14,6 @@ use PHPStan\Type\Generic\TemplateMixedType; use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\NullType; use PHPStan\Type\StrictMixedType; use PHPStan\Type\Type; @@ -214,7 +213,7 @@ private function findTypeToCheckImplementation( ); } - if ($type instanceof MixedType || $type instanceof NeverType) { + if ($type instanceof MixedType || !$type->isNever()->no()) { return new FoundTypeResult(new ErrorType(), [], [], null); } diff --git a/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php b/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php index edddff8a91..09787cd41c 100644 --- a/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php +++ b/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php @@ -15,7 +15,6 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Type\ErrorType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeUtils; use PHPStan\Type\VerbosityLevel; @@ -54,7 +53,7 @@ public function processNode(Node $node, Scope $scope): array if ($endNode instanceof Node\Stmt\Expression) { $endNodeExpr = $endNode->expr; $endNodeExprType = $scope->getType($endNodeExpr); - if ($endNodeExprType instanceof NeverType && $endNodeExprType->isExplicit()) { + if ($endNodeExprType->isExplicitNever()->yes()) { return []; } } diff --git a/src/Type/Accessory/AccessoryArrayListType.php b/src/Type/Accessory/AccessoryArrayListType.php index 6ed6baeced..a18be711f3 100644 --- a/src/Type/Accessory/AccessoryArrayListType.php +++ b/src/Type/Accessory/AccessoryArrayListType.php @@ -429,6 +429,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 d8a02005d6..57e505ce00 100644 --- a/src/Type/Accessory/AccessoryLiteralStringType.php +++ b/src/Type/Accessory/AccessoryLiteralStringType.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 { return new BooleanType(); diff --git a/src/Type/Accessory/AccessoryLowercaseStringType.php b/src/Type/Accessory/AccessoryLowercaseStringType.php index 3e1383bdb4..6f32d80aed 100644 --- a/src/Type/Accessory/AccessoryLowercaseStringType.php +++ b/src/Type/Accessory/AccessoryLowercaseStringType.php @@ -334,6 +334,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 a8b573809a..0d39f4a374 100644 --- a/src/Type/Accessory/AccessoryNonEmptyStringType.php +++ b/src/Type/Accessory/AccessoryNonEmptyStringType.php @@ -332,6 +332,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 f32d613154..c64ce5d633 100644 --- a/src/Type/Accessory/AccessoryNonFalsyStringType.php +++ b/src/Type/Accessory/AccessoryNonFalsyStringType.php @@ -332,6 +332,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 c10dd28082..af145af96a 100644 --- a/src/Type/Accessory/AccessoryNumericStringType.php +++ b/src/Type/Accessory/AccessoryNumericStringType.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/AccessoryUppercaseStringType.php b/src/Type/Accessory/AccessoryUppercaseStringType.php index 5688e62df7..4a1d980292 100644 --- a/src/Type/Accessory/AccessoryUppercaseStringType.php +++ b/src/Type/Accessory/AccessoryUppercaseStringType.php @@ -334,6 +334,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 da6c176655..be1deef9b0 100644 --- a/src/Type/Accessory/HasOffsetType.php +++ b/src/Type/Accessory/HasOffsetType.php @@ -347,6 +347,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 5e7c834942..2b600c5fc2 100644 --- a/src/Type/Accessory/HasOffsetValueType.php +++ b/src/Type/Accessory/HasOffsetValueType.php @@ -426,6 +426,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 a58f87cb86..5ad67b8cd9 100644 --- a/src/Type/Accessory/NonEmptyArrayType.php +++ b/src/Type/Accessory/NonEmptyArrayType.php @@ -415,6 +415,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 77fdec48fb..eff31d2204 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 f97ac2a014..383e36682e 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -138,8 +138,8 @@ public function describe(VerbosityLevel $level): string $isMixedItemType = $this->itemType instanceof MixedType && $this->itemType->describe(VerbosityLevel::precise()) === 'mixed' && !$this->itemType->isExplicitMixed(); $valueHandler = function () use ($level, $isMixedKeyType, $isMixedItemType): string { - if ($isMixedKeyType || $this->keyType instanceof NeverType) { - if ($isMixedItemType || $this->itemType instanceof NeverType) { + if ($isMixedKeyType || !$this->keyType->isNever()->no()) { + if ($isMixedItemType || !$this->itemType->isNever()->no()) { return 'array'; } @@ -272,7 +272,7 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic if ($offsetArrayKeyType instanceof ErrorType) { $allowedArrayKeys = AllowedArrayKeysTypes::getType(); $offsetArrayKeyType = TypeCombinator::intersect($allowedArrayKeys, $offsetType)->toArrayKey(); - if ($offsetArrayKeyType instanceof NeverType) { + if (!$offsetArrayKeyType->isNever()->no()) { return TrinaryLogic::createNo(); } } @@ -425,7 +425,7 @@ public function unsetOffset(Type $offsetType): Type && !$this->keyType->isSuperTypeOf($offsetType)->no() ) { $keyType = TypeCombinator::remove($this->keyType, $offsetType); - if ($keyType instanceof NeverType) { + if (!$keyType->isNever()->no()) { return new ConstantArrayType([], []); } @@ -595,7 +595,7 @@ public function traverse(callable $cb): Type $itemType = $cb($this->itemType); if ($keyType !== $this->keyType || $itemType !== $this->itemType) { - if ($keyType instanceof NeverType && $itemType instanceof NeverType) { + if (!$keyType->isNever()->no() && !$itemType->isNever()->no()) { return new ConstantArrayType([], []); } @@ -638,7 +638,7 @@ public function traverseSimultaneously(Type $right, callable $cb): Type $itemType = $cb($this->itemType, $right->getIterableValueType()); if ($keyType !== $this->keyType || $itemType !== $this->itemType) { - if ($keyType instanceof NeverType && $itemType instanceof NeverType) { + if (!$keyType->isNever()->no() && !$itemType->isNever()->no()) { return new ConstantArrayType([], []); } diff --git a/src/Type/CallableType.php b/src/Type/CallableType.php index 079afc8c1e..9778dae49d 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -634,6 +634,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 49bbfe8c1b..cdd4420d96 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -806,6 +806,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 4cec2bf409..8ed27f064b 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -586,7 +586,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 92ebb92cf1..7612c1387b 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/GenericStaticType.php b/src/Type/Generic/GenericStaticType.php index f677142e20..c86272f145 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 49f3a08496..36d6e747c6 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; @@ -35,7 +34,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; @@ -131,7 +130,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; @@ -159,7 +158,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 584439c12d..d2af72c830 100644 --- a/src/Type/Generic/TemplateTypeTrait.php +++ b/src/Type/Generic/TemplateTypeTrait.php @@ -10,7 +10,6 @@ use PHPStan\Type\IntersectionType; use PHPStan\Type\IsSuperTypeOfResult; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\RecursionGuard; use PHPStan\Type\SubtractableType; use PHPStan\Type\Type; @@ -220,7 +219,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return $type->isSubTypeOf($this); } - if ($type instanceof NeverType) { + if (!$type->isNever()->no()) { return IsSuperTypeOfResult::createYes(); } diff --git a/src/Type/Generic/TemplateTypeVariance.php b/src/Type/Generic/TemplateTypeVariance.php index a630895bed..cbde028530 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; @@ -128,7 +127,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 16cb33d2dd..205e0398be 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -233,7 +233,7 @@ public function isSuperTypeOf(Type $otherType): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - if ($otherType instanceof NeverType) { + if (!$otherType->isNever()->no()) { return IsSuperTypeOfResult::createYes(); } @@ -796,6 +796,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 c2b44b809b..b5270e9c89 100644 --- a/src/Type/IterableType.php +++ b/src/Type/IterableType.php @@ -411,6 +411,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 ad8d4fbfb1..f14b8f9d7e 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -58,7 +58,7 @@ public function __construct( ?Type $subtractedType = null, ) { - if ($subtractedType instanceof NeverType) { + if ($subtractedType !== null && !$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -134,7 +134,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(); } @@ -1065,6 +1065,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 5fc9a05280..6760310bf9 100644 --- a/src/Type/NeverType.php +++ b/src/Type/NeverType.php @@ -548,6 +548,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 ef2408e713..cedc42c4a1 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 361190316b..3b02fafd5b 100644 --- a/src/Type/ObjectShapeType.php +++ b/src/Type/ObjectShapeType.php @@ -515,7 +515,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 3b7a72baaa..0feea98eba 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -125,7 +125,7 @@ public function __construct( private ?ClassReflection $classReflection = null, ) { - if ($subtractedType instanceof NeverType) { + if ($subtractedType !== null && !$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -1327,6 +1327,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()) { @@ -1855,7 +1865,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 9823dcaf80..354b9472cb 100644 --- a/src/Type/ObjectWithoutClassType.php +++ b/src/Type/ObjectWithoutClassType.php @@ -27,7 +27,7 @@ public function __construct( ?Type $subtractedType = null, ) { - if ($subtractedType instanceof NeverType) { + if ($subtractedType !== null && !$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -188,7 +188,7 @@ public function tryRemove(Type $typeToRemove): ?Type public function exponentiate(Type $exponent): Type { - if (!$exponent instanceof NeverType && !$this->isSuperTypeOf($exponent)->no()) { + if ($exponent->isNever()->no() && !$this->isSuperTypeOf($exponent)->no()) { return TypeCombinator::union($this, $exponent); } diff --git a/src/Type/Php/ArrayColumnHelper.php b/src/Type/Php/ArrayColumnHelper.php index 179d85bc04..0601df4868 100644 --- a/src/Type/Php/ArrayColumnHelper.php +++ b/src/Type/Php/ArrayColumnHelper.php @@ -66,7 +66,7 @@ public function getReturnIndexType(Type $arrayType, Type $indexType, Scope $scop public function handleAnyArray(Type $arrayType, Type $columnType, Type $indexType, Scope $scope): Type { [$returnValueType, $iterableAtLeastOnce] = $this->getReturnValueType($arrayType, $columnType, $scope); - if ($returnValueType instanceof NeverType) { + if (!$returnValueType->isNever()->no()) { return new ConstantArrayType([], []); } @@ -92,7 +92,7 @@ public function handleConstantArray(ConstantArrayType $arrayType, Type $columnTy if (!$certainty->yes()) { return null; } - if ($valueType instanceof NeverType) { + if (!$valueType->isNever()->no()) { continue; } diff --git a/src/Type/Php/ArrayFilterFunctionReturnTypeHelper.php b/src/Type/Php/ArrayFilterFunctionReturnTypeHelper.php index 04ef90fef5..384f810998 100644 --- a/src/Type/Php/ArrayFilterFunctionReturnTypeHelper.php +++ b/src/Type/Php/ArrayFilterFunctionReturnTypeHelper.php @@ -66,7 +66,7 @@ public function getType(Scope $scope, ?Expr $arrayArg, ?Expr $callbackArg, ?Expr $keyType = $arrayArgType->getIterableKeyType(); $itemType = $arrayArgType->getIterableValueType(); - if ($itemType instanceof NeverType || $keyType instanceof NeverType) { + if (!$itemType->isNever()->no() || !$keyType->isNever()->no()) { return new ConstantArrayType([], []); } @@ -183,7 +183,7 @@ private function removeFalsey(Type $type): Type $valueType = TypeCombinator::remove($valueType, $falseyTypes); - if ($valueType instanceof NeverType) { + if (!$valueType->isNever()->no()) { return new ConstantArrayType([], []); } @@ -206,7 +206,7 @@ private function filterByTruthyValue(Scope $scope, Error|Variable|null $itemVar, $itemType = $constantArray->getValueTypes()[$i]; [$newKeyType, $newItemType, $optional] = $this->processKeyAndItemType($scope, $keyType, $itemType, $itemVar, $keyVar, $expr); $optional = $optional || in_array($i, $optionalKeys, true); - if ($newKeyType instanceof NeverType || $newItemType instanceof NeverType) { + if (!$newKeyType->isNever()->no() || !$newItemType->isNever()->no()) { continue; } if ($itemType->equals($newItemType) && $keyType->equals($newKeyType)) { @@ -225,7 +225,7 @@ private function filterByTruthyValue(Scope $scope, Error|Variable|null $itemVar, [$newKeyType, $newItemType] = $this->processKeyAndItemType($scope, $arrayType->getIterableKeyType(), $arrayType->getIterableValueType(), $itemVar, $keyVar, $expr); - if ($newItemType instanceof NeverType || $newKeyType instanceof NeverType) { + if (!$newItemType->isNever()->no() || !$newKeyType->isNever()->no()) { return new ConstantArrayType([], []); } diff --git a/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php b/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php index 1d4f7a1122..2b1495f364 100644 --- a/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php @@ -16,7 +16,6 @@ use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; use PHPStan\Type\IntegerType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use function array_keys; @@ -117,7 +116,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 fdb8066f60..0b35bd94e6 100644 --- a/src/Type/Php/ArrayReplaceFunctionReturnTypeExtension.php +++ b/src/Type/Php/ArrayReplaceFunctionReturnTypeExtension.php @@ -15,7 +15,6 @@ use PHPStan\Type\Constant\ConstantIntegerType; use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use function array_keys; @@ -118,7 +117,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 f12efd095c..6d9387e5c0 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; @@ -55,7 +54,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 21622b5b93..78d39987c3 100644 --- a/src/Type/StaticType.php +++ b/src/Type/StaticType.php @@ -45,7 +45,7 @@ public function __construct( ?Type $subtractedType = null, ) { - if ($subtractedType instanceof NeverType) { + if ($subtractedType !== null && !$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -669,6 +669,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(); @@ -772,7 +782,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 71678b77a4..140321824f 100644 --- a/src/Type/StrictMixedType.php +++ b/src/Type/StrictMixedType.php @@ -330,6 +330,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 813b0136d9..21f5d86421 100644 --- a/src/Type/Traits/ArrayTypeTrait.php +++ b/src/Type/Traits/ArrayTypeTrait.php @@ -189,6 +189,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 d35ee72461..39dae96b29 100644 --- a/src/Type/Traits/LateResolvableTypeTrait.php +++ b/src/Type/Traits/LateResolvableTypeTrait.php @@ -16,7 +16,6 @@ use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\IsSuperTypeOfResult; use PHPStan\Type\LateResolvableType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; trait LateResolvableTypeTrait @@ -61,7 +60,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult private function isSuperTypeOfDefault(Type $type): IsSuperTypeOfResult { - if ($type instanceof NeverType) { + if (!$type->isNever()->no()) { return IsSuperTypeOfResult::createYes(); } @@ -533,6 +532,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 e9cbca0b7a..a0de040ed9 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -292,6 +292,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; public function getSmallerType(PhpVersion $phpVersion): Type; diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index 4ac858b067..b46ef01c82 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -561,7 +561,7 @@ private static function unionWithSubtractedType( $type->getTypeWithoutSubtractedType(), $subtractedType, ); - if ($subtractedType instanceof NeverType) { + if (!$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -580,7 +580,7 @@ private static function intersectWithSubtractedType( Type $b, ): Type { - if ($a->getSubtractedType() === null || $b instanceof NeverType) { + if ($a->getSubtractedType() === null || !$b->isNever()->no()) { return $a; } @@ -622,7 +622,7 @@ private static function intersectWithSubtractedType( $subtractedType = self::remove($a->getSubtractedType(), $b); if ( - $subtractedType instanceof NeverType + !$subtractedType->isNever()->no() || !$subtractedType->isSuperTypeOf($b)->no() ) { $subtractedType = null; @@ -647,7 +647,7 @@ private static function intersectWithSubtractedType( $a->getSubtractedType(), $subtractedType, ); - if ($subtractedType instanceof NeverType) { + if (!$subtractedType->isNever()->no()) { $subtractedType = null; } @@ -1126,7 +1126,7 @@ public static function intersect(Type ...$types): Type } $union = self::union(...$topLevelUnionSubTypes); - if ($union instanceof NeverType) { + if (!$union->isNever()->no()) { return $union; } @@ -1310,7 +1310,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); @@ -1323,7 +1323,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; } @@ -1422,7 +1422,7 @@ public static function intersect(Type ...$types): Type && !$types[$j]->getIterableKeyType()->isSuperTypeOf($types[$i]->getIterableKeyType())->yes() ) { $keyType = self::intersect($types[$i]->getIterableKeyType(), $types[$j]->getIterableKeyType()); - if ($keyType instanceof NeverType) { + if (!$keyType->isNever()->no()) { return $keyType; } $types[$i] = new ArrayType($keyType, $types[$i]->getItemType()); diff --git a/src/Type/TypehintHelper.php b/src/Type/TypehintHelper.php index 076fedcacc..cf2156a3d2 100644 --- a/src/Type/TypehintHelper.php +++ b/src/Type/TypehintHelper.php @@ -86,7 +86,7 @@ public static function decideType( } if ($phpDocType !== null && !$phpDocType instanceof ErrorType) { - if ($phpDocType instanceof NeverType && $phpDocType->isExplicit()) { + if ($phpDocType->isExplicitNever()->yes()) { return $phpDocType; } if ( @@ -122,7 +122,7 @@ public static function decideType( if ( ($type->isCallable()->yes() && $phpDocType->isCallable()->yes()) || ( - (!$phpDocType instanceof NeverType || ($type instanceof MixedType && !$type->isExplicitMixed())) + (!$phpDocType->isNever()->yes() || ($type instanceof MixedType && !$type->isExplicitMixed())) && $type->isSuperTypeOf(TemplateTypeHelper::resolveToBounds($phpDocType))->yes() ) ) { diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index 178e72eeb9..e00c816b92 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -239,7 +239,7 @@ public function isSuperTypeOf(Type $otherType): IsSuperTypeOfResult if ( ($otherType instanceof self && !$otherType instanceof TemplateUnionType) || ($otherType instanceof IterableType && !$otherType instanceof TemplateIterableType) - || $otherType instanceof NeverType + || $otherType->isNever()->yes() || ($otherType instanceof LateResolvableType && $otherType instanceof CompoundType && !$otherType instanceof TemplateType) || $otherType instanceof IntegerRangeType ) { @@ -742,6 +742,16 @@ public function isScalar(): TrinaryLogic return $this->unionResults(static fn (Type $type): TrinaryLogic => $type->isScalar()); } + public function isNever(): TrinaryLogic + { + return $this->unionResults(static fn (Type $type): TrinaryLogic => $type->isNever()); + } + + public function isExplicitNever(): TrinaryLogic + { + return $this->unionResults(static fn (Type $type): TrinaryLogic => $type->isExplicitNever()); + } + public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return $this->notBenevolentUnionResults( diff --git a/src/Type/VoidType.php b/src/Type/VoidType.php index 83c5a05726..4b2b82afe2 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 95edb13b3d..cc6aaefa75 100644 --- a/tests/PHPStan/Type/TypeCombinatorTest.php +++ b/tests/PHPStan/Type/TypeCombinatorTest.php @@ -4779,8 +4779,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'; @@ -4822,8 +4822,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'; @@ -5361,8 +5361,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';