Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not generalize class-string during template type inference #1038

Merged
merged 1 commit into from Feb 27, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/Type/Accessory/AccessoryLiteralStringType.php
Expand Up @@ -9,6 +9,7 @@
use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\FloatType;
use PHPStan\Type\GeneralizePrecision;
use PHPStan\Type\IntegerType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\MixedType;
Expand Down Expand Up @@ -186,6 +187,11 @@ public function traverse(callable $cb): Type
return $this;
}

public function generalize(GeneralizePrecision $precision): Type
{
return new StringType();
}

public static function __set_state(array $properties): Type
{
return new self();
Expand Down
6 changes: 6 additions & 0 deletions src/Type/Accessory/AccessoryNonEmptyStringType.php
Expand Up @@ -8,6 +8,7 @@
use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\FloatType;
use PHPStan\Type\GeneralizePrecision;
use PHPStan\Type\IntegerType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\StringType;
Expand Down Expand Up @@ -182,6 +183,11 @@ public function traverse(callable $cb): Type
return $this;
}

public function generalize(GeneralizePrecision $precision): Type
{
return new StringType();
}

public static function __set_state(array $properties): Type
{
return new self();
Expand Down
6 changes: 6 additions & 0 deletions src/Type/Accessory/AccessoryNumericStringType.php
Expand Up @@ -8,6 +8,7 @@
use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\FloatType;
use PHPStan\Type\GeneralizePrecision;
use PHPStan\Type\IntegerType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\StringType;
Expand Down Expand Up @@ -181,6 +182,11 @@ public function traverse(callable $cb): Type
return $this;
}

public function generalize(GeneralizePrecision $precision): Type
{
return new StringType();
}

public static function __set_state(array $properties): Type
{
return new self();
Expand Down
2 changes: 2 additions & 0 deletions src/Type/Accessory/HasMethodType.php
Expand Up @@ -11,6 +11,7 @@
use PHPStan\TrinaryLogic;
use PHPStan\Type\CompoundType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\ObjectTypeTrait;
Expand All @@ -28,6 +29,7 @@ class HasMethodType implements AccessoryType, CompoundType
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;
use NonGeneralizableTypeTrait;

/** @api */
public function __construct(private string $methodName)
Expand Down
2 changes: 2 additions & 0 deletions src/Type/Accessory/HasOffsetType.php
Expand Up @@ -11,6 +11,7 @@
use PHPStan\Type\Traits\MaybeCallableTypeTrait;
use PHPStan\Type\Traits\MaybeIterableTypeTrait;
use PHPStan\Type\Traits\MaybeObjectTypeTrait;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
Expand All @@ -30,6 +31,7 @@ class HasOffsetType implements CompoundType, AccessoryType
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;
use NonGeneralizableTypeTrait;

/** @api */
public function __construct(private Type $offsetType)
Expand Down
2 changes: 2 additions & 0 deletions src/Type/Accessory/HasPropertyType.php
Expand Up @@ -7,6 +7,7 @@
use PHPStan\TrinaryLogic;
use PHPStan\Type\CompoundType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\ObjectTypeTrait;
Expand All @@ -23,6 +24,7 @@ class HasPropertyType implements AccessoryType, CompoundType
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;
use NonGeneralizableTypeTrait;

/** @api */
public function __construct(private string $propertyName)
Expand Down
2 changes: 2 additions & 0 deletions src/Type/Accessory/NonEmptyArrayType.php
Expand Up @@ -10,6 +10,7 @@
use PHPStan\Type\IntersectionType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Traits\MaybeCallableTypeTrait;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
Expand All @@ -28,6 +29,7 @@ class NonEmptyArrayType implements CompoundType, AccessoryType
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;
use NonGeneralizableTypeTrait;

/** @api */
public function __construct()
Expand Down
2 changes: 2 additions & 0 deletions src/Type/ArrayType.php
Expand Up @@ -18,6 +18,7 @@
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Generic\TemplateTypeVariance;
use PHPStan\Type\Traits\MaybeCallableTypeTrait;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonTypeTrait;
Expand All @@ -36,6 +37,7 @@ class ArrayType implements Type
use NonObjectTypeTrait;
use UndecidedBooleanTypeTrait;
use UndecidedComparisonTypeTrait;
use NonGeneralizableTypeTrait;

private Type $keyType;

Expand Down
2 changes: 2 additions & 0 deletions src/Type/BooleanType.php
Expand Up @@ -8,6 +8,7 @@
use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\Traits\NonCallableTypeTrait;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonIterableTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
Expand All @@ -27,6 +28,7 @@ class BooleanType implements Type
use UndecidedComparisonTypeTrait;
use NonGenericTypeTrait;
use NonOffsetAccessibleTypeTrait;
use NonGeneralizableTypeTrait;

/** @api */
public function __construct()
Expand Down
2 changes: 2 additions & 0 deletions src/Type/CallableType.php
Expand Up @@ -16,6 +16,7 @@
use PHPStan\Type\Traits\MaybeIterableTypeTrait;
use PHPStan\Type\Traits\MaybeObjectTypeTrait;
use PHPStan\Type\Traits\MaybeOffsetAccessibleTypeTrait;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
Expand All @@ -34,6 +35,7 @@ class CallableType implements CompoundType, ParametersAcceptor
use TruthyBooleanTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;
use NonGeneralizableTypeTrait;

/** @var array<int, ParameterReflection> */
private array $parameters;
Expand Down
2 changes: 2 additions & 0 deletions src/Type/ClosureType.php
Expand Up @@ -22,6 +22,7 @@
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\Generic\TemplateTypeHelper;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonOffsetAccessibleTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
Expand All @@ -39,6 +40,7 @@ class ClosureType implements TypeWithClassName, ParametersAcceptor
use UndecidedComparisonTypeTrait;
use NonOffsetAccessibleTypeTrait;
use NonRemoveableTypeTrait;
use NonGeneralizableTypeTrait;

private ObjectType $objectType;

Expand Down
4 changes: 4 additions & 0 deletions src/Type/Constant/ConstantArrayType.php
Expand Up @@ -625,6 +625,10 @@ public function generalize(GeneralizePrecision $precision): Type
return $this;
}

if ($precision->isTemplateArgument()) {
return $this->traverse(static fn (Type $type) => $type->generalize($precision));
}

$arrayType = new ArrayType(
TypeUtils::generalizeType($this->getKeyType(), $precision),
TypeUtils::generalizeType($this->getItemType(), $precision),
Expand Down
2 changes: 2 additions & 0 deletions src/Type/FloatType.php
Expand Up @@ -7,6 +7,7 @@
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\Traits\NonCallableTypeTrait;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonIterableTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
Expand All @@ -28,6 +29,7 @@ class FloatType implements Type
use NonGenericTypeTrait;
use NonOffsetAccessibleTypeTrait;
use NonRemoveableTypeTrait;
use NonGeneralizableTypeTrait;

/** @api */
public function __construct()
Expand Down
17 changes: 17 additions & 0 deletions src/Type/GeneralizePrecision.php
Expand Up @@ -7,6 +7,7 @@ class GeneralizePrecision

private const LESS_SPECIFIC = 1;
private const MORE_SPECIFIC = 2;
private const TEMPLATE_ARGUMENT = 3;

/** @var self[] */
private static array $registry;
Expand All @@ -33,9 +34,25 @@ public static function moreSpecific(): self
return self::create(self::MORE_SPECIFIC);
}

/** @api */
public static function templateArgument(): self
{
return self::create(self::TEMPLATE_ARGUMENT);
}

public function isLessSpecific(): bool
{
return $this->value === self::LESS_SPECIFIC;
}

public function isMoreSpecific(): bool
{
return $this->value === self::MORE_SPECIFIC;
}

public function isTemplateArgument(): bool
{
return $this->value === self::TEMPLATE_ARGUMENT;
}

}
23 changes: 0 additions & 23 deletions src/Type/Generic/TemplateTypeHelper.php
Expand Up @@ -2,11 +2,7 @@

namespace PHPStan\Type\Generic;

use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\ConstantType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\GeneralizePrecision;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeTraverser;

Expand Down Expand Up @@ -64,23 +60,4 @@ public static function toArgument(Type $type): Type
});
}

public static function generalizeType(Type $type): Type
{
return TypeTraverser::map($type, static function (Type $type, callable $traverse): Type {
if ($type instanceof ConstantType && !$type instanceof ConstantArrayType) {
return $type->generalize(GeneralizePrecision::lessSpecific());
}

if ($type->isNonEmptyString()->yes()) {
return new StringType();
}

if ($type->isLiteralString()->yes()) {
return new StringType();
}

return $traverse($type);
});
}

}
3 changes: 2 additions & 1 deletion src/Type/Generic/TemplateTypeTrait.php
Expand Up @@ -3,6 +3,7 @@
namespace PHPStan\Type\Generic;

use PHPStan\TrinaryLogic;
use PHPStan\Type\GeneralizePrecision;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
Expand Down Expand Up @@ -194,7 +195,7 @@ public function inferTemplateTypes(Type $receivedType): TemplateTypeMap
$resolvedBound = TemplateTypeHelper::resolveTemplateTypes($this->getBound(), $map);
if ($resolvedBound->isSuperTypeOf($receivedType)->yes()) {
return (new TemplateTypeMap([
$this->name => $this->shouldGeneralizeInferredType() ? TemplateTypeHelper::generalizeType($receivedType) : $receivedType,
$this->name => $this->shouldGeneralizeInferredType() ? $receivedType->generalize(GeneralizePrecision::templateArgument()) : $receivedType,
]))->union($map);
}

Expand Down
2 changes: 2 additions & 0 deletions src/Type/IntegerType.php
Expand Up @@ -6,6 +6,7 @@
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\Traits\NonCallableTypeTrait;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonIterableTypeTrait;
use PHPStan\Type\Traits\NonObjectTypeTrait;
Expand All @@ -25,6 +26,7 @@ class IntegerType implements Type
use UndecidedComparisonTypeTrait;
use NonGenericTypeTrait;
use NonOffsetAccessibleTypeTrait;
use NonGeneralizableTypeTrait;

/** @api */
public function __construct()
Expand Down
5 changes: 5 additions & 0 deletions src/Type/IntersectionType.php
Expand Up @@ -22,6 +22,8 @@
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Generic\TemplateTypeVariance;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use function array_map;
use function count;
use function implode;
Expand All @@ -34,6 +36,9 @@
class IntersectionType implements CompoundType
{

use NonRemoveableTypeTrait;
use NonGeneralizableTypeTrait;

/** @var Type[] */
private array $types;

Expand Down
2 changes: 2 additions & 0 deletions src/Type/IterableType.php
Expand Up @@ -12,6 +12,7 @@
use PHPStan\Type\Traits\MaybeCallableTypeTrait;
use PHPStan\Type\Traits\MaybeObjectTypeTrait;
use PHPStan\Type\Traits\MaybeOffsetAccessibleTypeTrait;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
use Traversable;
Expand All @@ -27,6 +28,7 @@ class IterableType implements CompoundType
use MaybeOffsetAccessibleTypeTrait;
use UndecidedBooleanTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonGeneralizableTypeTrait;

/** @api */
public function __construct(
Expand Down
2 changes: 2 additions & 0 deletions src/Type/MixedType.php
Expand Up @@ -19,6 +19,7 @@
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\Generic\TemplateMixedType;
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
use function sprintf;
Expand All @@ -29,6 +30,7 @@ class MixedType implements CompoundType, SubtractableType

use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonGeneralizableTypeTrait;

private ?Type $subtractedType;

Expand Down
2 changes: 2 additions & 0 deletions src/Type/NeverType.php
Expand Up @@ -12,6 +12,7 @@
use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection;
use PHPStan\ShouldNotHappenException;
use PHPStan\TrinaryLogic;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonGenericTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
Expand All @@ -25,6 +26,7 @@ class NeverType implements CompoundType
use NonGenericTypeTrait;
use UndecidedComparisonCompoundTypeTrait;
use NonRemoveableTypeTrait;
use NonGeneralizableTypeTrait;

/** @api */
public function __construct(private bool $isExplicit = false)
Expand Down