Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions src/Analyser/ExprHandler/InstanceofHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use PHPStan\Analyser\ExprHandler;
use PHPStan\Analyser\MutatingScope;
use PHPStan\Analyser\NodeScopeResolver;
use PHPStan\Analyser\Traverser\InstanceOfClassTypeTraverser;
use PHPStan\DependencyInjection\AutowiredService;
use PHPStan\Type\BooleanType;
use PHPStan\Type\Constant\ConstantBooleanType;
Expand All @@ -21,7 +20,6 @@
use PHPStan\Type\ObjectType;
use PHPStan\Type\StaticType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeTraverser;
use PHPStan\Type\TypeUtils;
use function array_merge;
use function strtolower;
Expand Down Expand Up @@ -94,9 +92,9 @@ public function resolveType(MutatingScope $scope, Expr $expr): Type
}
} else {
$classType = $scope->getType($expr->class);
$traverser = new InstanceOfClassTypeTraverser();
$classType = TypeTraverser::map($classType, $traverser);
$uncertainty = $traverser->getUncertainty();
$result = $classType->toObjectTypeForInstanceofCheck();
$classType = $result->type;
$uncertainty = $result->uncertainty;
}

if ($classType->isSuperTypeOf(new MixedType())->yes()) {
Expand Down
47 changes: 0 additions & 47 deletions src/Analyser/Traverser/InstanceOfClassTypeTraverser.php

This file was deleted.

21 changes: 3 additions & 18 deletions src/Analyser/TypeSpecifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,24 +165,9 @@ public function specifyTypesInCondition(
}

$classType = $scope->getType($expr->class);
$uncertainty = false;
$type = TypeTraverser::map($classType, static function (Type $type, callable $traverse) use (&$uncertainty): Type {
if ($type instanceof UnionType || $type instanceof IntersectionType) {
return $traverse($type);
}
if ($type->getObjectClassNames() !== []) {
$uncertainty = true;
return $type;
}
if ($type instanceof GenericClassStringType) {
$uncertainty = true;
return $type->getGenericType();
}
if ($type instanceof ConstantStringType) {
return new ObjectType($type->getValue());
}
return new MixedType();
});
$result = $classType->toObjectTypeForInstanceofCheck();
$type = $result->type;
$uncertainty = $result->uncertainty;

if (!$type->isSuperTypeOf(new MixedType())->yes()) {
if ($context->true()) {
Expand Down
78 changes: 2 additions & 76 deletions src/Reflection/InitializerExprTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypehintHelper;
use PHPStan\Type\TypeResult;
use PHPStan\Type\TypeTraverser;
use PHPStan\Type\TypeUtils;
use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\UnionType;
Expand Down Expand Up @@ -2451,54 +2450,7 @@ public function getClassConstFetchTypeByReflection(Name|Expr $class, string $con
}

if (strtolower($constantName) === 'class') {
return TypeTraverser::map(
$constantClassType,
function (Type $type, callable $traverse): Type {
if ($type instanceof UnionType || $type instanceof IntersectionType) {
return $traverse($type);
}

if ($type instanceof NullType) {
return $type;
}

if ($type instanceof EnumCaseObjectType) {
return new IntersectionType([
new GenericClassStringType(new ObjectType($type->getClassName())),
new AccessoryLiteralStringType(),
]);
}

$objectClassNames = $type->getObjectClassNames();
if (count($objectClassNames) > 1) {
throw new ShouldNotHappenException();
}

if ($type instanceof TemplateType && $objectClassNames === []) {
return new IntersectionType([
new GenericClassStringType($type),
new AccessoryLiteralStringType(),
]);
} elseif ($objectClassNames !== [] && $this->getReflectionProvider()->hasClass($objectClassNames[0])) {
$reflection = $this->getReflectionProvider()->getClass($objectClassNames[0]);
if ($reflection->isFinalByKeyword()) {
return new ConstantStringType($reflection->getName(), true);
}

return new IntersectionType([
new GenericClassStringType($type),
new AccessoryLiteralStringType(),
]);
} elseif ($type->isObject()->yes()) {
return new IntersectionType([
new ClassStringType(),
new AccessoryLiteralStringType(),
]);
}

return new ErrorType();
},
);
return $constantClassType->toClassConstantType($this->getReflectionProvider());
}

if ($constantClassType->isClassString()->yes()) {
Expand Down Expand Up @@ -2699,33 +2651,7 @@ public function getBitwiseNotType(Expr $expr, callable $getTypeCallback): Type

public function getBitwiseNotTypeFromType(Type $exprType): Type
{
return TypeTraverser::map($exprType, static function (Type $type, callable $traverse): Type {
if ($type instanceof UnionType || $type instanceof IntersectionType) {
return $traverse($type);
}
if ($type instanceof ConstantStringType) {
return new ConstantStringType(~$type->getValue());
}
if ($type->isString()->yes()) {
$accessories = [];
if (!$type->isNonEmptyString()->yes()) {
return new StringType();
}

$accessories[] = new AccessoryNonEmptyStringType();
// it is not useful to apply numeric and literal strings here.
// numeric string isn't certainly kept numeric: 3v4l.org/JERDB

return new IntersectionType([new StringType(), ...$accessories]);
}
if ($type instanceof ConstantIntegerType || $type instanceof ConstantFloatType) {
return new ConstantIntegerType(~ (int) $type->getValue());
}
if ($type->isInteger()->yes() || $type->isFloat()->yes()) {
return new IntegerType();
}
return new ErrorType();
});
return $exprType->toBitwiseNotType();
}

private function resolveName(Name $name, ?ClassReflection $classReflection): string
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryArrayListType.php
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,11 @@ public function toNumber(): Type
return new ErrorType();
}

public function toBitwiseNotType(): Type
{
return new ErrorType();
}

public function toAbsoluteNumber(): Type
{
return new ErrorType();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryLiteralStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ public function toNumber(): Type
return new ErrorType();
}

public function toBitwiseNotType(): Type
{
return new StringType();
}

public function toAbsoluteNumber(): Type
{
return new ErrorType();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryLowercaseStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ public function toNumber(): Type
return new ErrorType();
}

public function toBitwiseNotType(): Type
{
return new StringType();
}

public function toAbsoluteNumber(): Type
{
return new ErrorType();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryNonEmptyStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ public function toNumber(): Type
return new ErrorType();
}

public function toBitwiseNotType(): Type
{
return new IntersectionType([new StringType(), new self()]);
}

public function toAbsoluteNumber(): Type
{
return new ErrorType();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryNonFalsyStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,11 @@ public function toNumber(): Type
return new ErrorType();
}

public function toBitwiseNotType(): Type
{
return new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]);
}

public function toAbsoluteNumber(): Type
{
return new ErrorType();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryNumericStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ public function toNumber(): Type
]);
}

public function toBitwiseNotType(): Type
{
return new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]);
}

public function toAbsoluteNumber(): Type
{
return $this->toNumber()->toAbsoluteNumber();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryUppercaseStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ public function toNumber(): Type
return new ErrorType();
}

public function toBitwiseNotType(): Type
{
return new StringType();
}

public function toAbsoluteNumber(): Type
{
return new ErrorType();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/HasOffsetType.php
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,11 @@ public function toNumber(): Type
return new ErrorType();
}

public function toBitwiseNotType(): Type
{
return new ErrorType();
}

public function toAbsoluteNumber(): Type
{
return new ErrorType();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/HasOffsetValueType.php
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,11 @@ public function toNumber(): Type
return new ErrorType();
}

public function toBitwiseNotType(): Type
{
return new ErrorType();
}

public function toAbsoluteNumber(): Type
{
return new ErrorType();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/NonEmptyArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,11 @@ public function toNumber(): Type
return new ErrorType();
}

public function toBitwiseNotType(): Type
{
return new ErrorType();
}

public function toAbsoluteNumber(): Type
{
return new ErrorType();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/OversizedArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,11 @@ public function toNumber(): Type
return new ErrorType();
}

public function toBitwiseNotType(): Type
{
return new ErrorType();
}

public function toAbsoluteNumber(): Type
{
return new ErrorType();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/BooleanType.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ public function toNumber(): Type
return $this->toInteger();
}

public function toBitwiseNotType(): Type
{
return new ErrorType();
}

public function toAbsoluteNumber(): Type
{
return $this->toNumber()->toAbsoluteNumber();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/CallableType.php
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,11 @@ public function toNumber(): Type
return new ErrorType();
}

public function toBitwiseNotType(): Type
{
return new ErrorType();
}

public function toAbsoluteNumber(): Type
{
return new ErrorType();
Expand Down
24 changes: 24 additions & 0 deletions src/Type/ClassNameToObjectTypeResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php declare(strict_types = 1);

namespace PHPStan\Type;

/**
* Result of projecting a "class-name-or-object" `Type` to its corresponding
* `ObjectType` for an `instanceof` / `is_a` check.
*
* `$uncertainty` is `true` when the projection lost information that prevents
* a definite yes/no decision later — e.g. a runtime class string was kept
* symbolically instead of being resolved to a concrete object type. Composite
* types OR-fold the flag across their members.
*/
final class ClassNameToObjectTypeResult
{

public function __construct(
public readonly Type $type,
public readonly bool $uncertainty,
)
{
}

}
Loading
Loading