Skip to content
Open
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
146 changes: 140 additions & 6 deletions src/Type/Accessory/HasMethodType.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace PHPStan\Type\Accessory;

use Closure;
use PHPStan\Php\PhpVersion;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Reflection\ClassMemberAccessAnswerer;
Expand All @@ -13,20 +14,29 @@
use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection;
use PHPStan\TrinaryLogic;
use PHPStan\Type\AcceptsResult;
use PHPStan\Type\BooleanType;
use PHPStan\Type\CompoundType;
use PHPStan\Type\Enum\EnumCaseObjectType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\Generic\GenericClassStringType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\IsSuperTypeOfResult;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\Traits\MaybeCallableTypeTrait;
use PHPStan\Type\Traits\MaybeIterableTypeTrait;
use PHPStan\Type\Traits\MaybeObjectTypeTrait;
use PHPStan\Type\Traits\MaybeOffsetAccessibleTypeTrait;
use PHPStan\Type\Traits\MaybeStringTypeTrait;
use PHPStan\Type\Traits\NonArrayTypeTrait;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\ObjectTypeTrait;
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\UnionType;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
Expand All @@ -35,7 +45,13 @@
class HasMethodType implements AccessoryType, CompoundType
{

use ObjectTypeTrait;
use MaybeCallableTypeTrait;
use MaybeIterableTypeTrait;
use MaybeObjectTypeTrait;
use MaybeOffsetAccessibleTypeTrait;
use MaybeStringTypeTrait;
use NonArrayTypeTrait;
use TruthyBooleanTypeTrait;
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;
Expand All @@ -61,6 +77,11 @@ public function getObjectClassReflections(): array
return [];
}

public function getConstantStrings(): array
{
return [];
}

public function getClassStringType(): Type
{
return new GenericClassStringType($this);
Expand All @@ -82,6 +103,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult

public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
{
if ($type instanceof CompoundType) {
return $type->isSubTypeOf($this);
}
Comment on lines +106 to +108
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As a proof this works, the implementation should now be

if ($type instanceof CompoundType) {
			return $type->isSubTypeOf($this);
		}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done. Simplified the isSuperTypeOf() CompoundType delegation in both HasMethodType and HasPropertyType to unconditionally return $type->isSubTypeOf($this) — the fallback-on-No guard is no longer needed since the string/scalar Maybe overrides now ensure correct results through the delegation path. All 11,997 tests pass and make phpstan reports no errors.


return new IsSuperTypeOfResult($type->hasMethod($this->methodName), []);
}

Expand Down Expand Up @@ -158,6 +183,93 @@ public function isCallable(): TrinaryLogic
return TrinaryLogic::createMaybe();
}

public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope): array
{
return [
new TrivialParametersAcceptor(),
];
}

public function isNull(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function isConstantValue(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function isConstantScalarValue(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function getConstantScalarTypes(): array
{
return [];
}

public function getConstantScalarValues(): array
{
return [];
}

public function isTrue(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function isFalse(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function isBoolean(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function isFloat(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function isInteger(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

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

public function getObjectTypeOrClassStringObjectType(): Type
{
return $this;
}

public function isVoid(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
{
return new BooleanType();
}

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

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

public function toString(): Type
{
if ($this->getCanonicalMethodName() === '__tostring') {
Expand All @@ -167,11 +279,33 @@ public function toString(): Type
return new ErrorType();
}

public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope): array
public function toInteger(): Type
{
return [
new TrivialParametersAcceptor(),
];
return new ErrorType();
}

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

public function toArray(): Type
{
return new MixedType();
}

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

public function toCoercedArgumentType(bool $strictTypes): Type
{
if (!$strictTypes) {
return TypeCombinator::union($this, $this->toString());
}

return $this;
}

public function getEnumCases(): array
Expand Down
47 changes: 2 additions & 45 deletions src/Type/Accessory/HasOffsetType.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use PHPStan\Type\Traits\MaybeCallableTypeTrait;
use PHPStan\Type\Traits\MaybeIterableTypeTrait;
use PHPStan\Type\Traits\MaybeObjectTypeTrait;
use PHPStan\Type\Traits\MaybeStringTypeTrait;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
Expand All @@ -40,6 +41,7 @@ class HasOffsetType implements CompoundType, AccessoryType
use MaybeCallableTypeTrait;
use MaybeIterableTypeTrait;
use MaybeObjectTypeTrait;
use MaybeStringTypeTrait;
use TruthyBooleanTypeTrait;
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
Expand Down Expand Up @@ -285,46 +287,6 @@ public function isInteger(): TrinaryLogic
return TrinaryLogic::createNo();
}

public function isString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isNumericString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isNonEmptyString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isNonFalsyString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isLiteralString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isLowercaseString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isClassString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isUppercaseString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function getClassStringObjectType(): Type
{
return new ObjectWithoutClassType();
Expand All @@ -340,11 +302,6 @@ public function isVoid(): TrinaryLogic
return TrinaryLogic::createNo();
}

public function isScalar(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
{
return new BooleanType();
Expand Down
47 changes: 2 additions & 45 deletions src/Type/Accessory/HasOffsetValueType.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use PHPStan\Type\Traits\MaybeCallableTypeTrait;
use PHPStan\Type\Traits\MaybeIterableTypeTrait;
use PHPStan\Type\Traits\MaybeObjectTypeTrait;
use PHPStan\Type\Traits\MaybeStringTypeTrait;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
Expand All @@ -44,6 +45,7 @@ class HasOffsetValueType implements CompoundType, AccessoryType
use MaybeCallableTypeTrait;
use MaybeIterableTypeTrait;
use MaybeObjectTypeTrait;
use MaybeStringTypeTrait;
use TruthyBooleanTypeTrait;
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
Expand Down Expand Up @@ -373,46 +375,6 @@ public function isInteger(): TrinaryLogic
return TrinaryLogic::createNo();
}

public function isString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isNumericString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isNonEmptyString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isNonFalsyString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isLiteralString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isLowercaseString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isUppercaseString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isClassString(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function getClassStringObjectType(): Type
{
return new ObjectWithoutClassType();
Expand All @@ -428,11 +390,6 @@ public function isVoid(): TrinaryLogic
return TrinaryLogic::createNo();
}

public function isScalar(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
{
return new BooleanType();
Expand Down
Loading
Loading