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
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Rector\Tests\Php80\Rector\FunctionLike\MixedTypeRector\Fixture;

/**
* @template T as mixed
*/
class FromTemplate
{
/**
* @param T $param
*/
public function run($param)
{
}
}

?>
-----
<?php

namespace Rector\Tests\Php80\Rector\FunctionLike\MixedTypeRector\Fixture;

/**
* @template T as mixed
*/
class FromTemplate
{
/**
* @param T $param
*/
public function run(mixed $param)
{
}
}

?>

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(ReturnUnionTypeRector::class);
$rectorConfig->phpVersion(PhpVersionFeature::UNION_INTERSECTION_TYPES);
};
};
13 changes: 12 additions & 1 deletion rules/DeadCode/PhpDoc/DeadParamTagValueNodeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
use PhpParser\Node\Param;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\Type\Generic\TemplateType;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\BetterPhpDocParser\ValueObject\Type\BracketsAwareUnionTypeNode;
use Rector\DeadCode\PhpDoc\Guard\StandaloneTypeRemovalGuard;
use Rector\DeadCode\TypeNodeAnalyzer\GenericTypeNodeAnalyzer;
use Rector\DeadCode\TypeNodeAnalyzer\MixedArrayTypeNodeAnalyzer;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\TypeComparator\TypeComparator;
use Rector\StaticTypeMapper\StaticTypeMapper;
use Rector\TypeDeclaration\NodeAnalyzer\ParamAnalyzer;

final readonly class DeadParamTagValueNodeAnalyzer
Expand All @@ -27,7 +29,8 @@ public function __construct(
private MixedArrayTypeNodeAnalyzer $mixedArrayTypeNodeAnalyzer,
private ParamAnalyzer $paramAnalyzer,
private PhpDocTypeChanger $phpDocTypeChanger,
private StandaloneTypeRemovalGuard $standaloneTypeRemovalGuard
private StandaloneTypeRemovalGuard $standaloneTypeRemovalGuard,
private StaticTypeMapper $staticTypeMapper
) {
}

Expand All @@ -46,6 +49,14 @@ public function isDead(ParamTagValueNode $paramTagValueNode, FunctionLike $funct
return false;
}

$docType = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType(
$paramTagValueNode->type,
$functionLike
);
if ($docType instanceof TemplateType) {
return false;
}

if ($param->type instanceof Name && $this->nodeNameResolver->isName($param->type, 'object')) {
return $paramTagValueNode->type instanceof IdentifierTypeNode && (string) $paramTagValueNode->type === 'object';
}
Expand Down
9 changes: 9 additions & 0 deletions rules/DeadCode/PhpDoc/DeadReturnTagValueNodeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\ThisTypeNode;
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\UnionType;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
Expand Down Expand Up @@ -47,6 +48,14 @@ public function isDead(ReturnTagValueNode $returnTagValueNode, ClassMethod|Funct
return false;
}

$docType = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType(
$returnTagValueNode->type,
$functionLike
);
if ($docType instanceof TemplateType) {
return false;
}

$scope = $functionLike->getAttribute(AttributeKey::SCOPE);
if ($scope instanceof Scope && $scope->isInTrait() && $returnTagValueNode->type instanceof ThisTypeNode) {
return false;
Expand Down
5 changes: 5 additions & 0 deletions rules/DeadCode/PhpDoc/DeadVarTagValueNodeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use PhpParser\Node\Stmt\Property;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\TypeCombinator;
Expand Down Expand Up @@ -35,6 +36,10 @@ public function isDead(VarTagValueNode $varTagValueNode, Property $property): bo
$propertyType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($property->type);
$docType = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType($varTagValueNode->type, $property);

if ($docType instanceof TemplateType) {
return false;
}

if ($propertyType instanceof UnionType && ! $docType instanceof UnionType) {
return ! $docType instanceof IntersectionType;
}
Expand Down
5 changes: 0 additions & 5 deletions rules/Php80/Rector/FunctionLike/MixedTypeRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use PhpParser\Node\Stmt\Function_;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\MixedType;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
Expand Down Expand Up @@ -144,10 +143,6 @@ private function refactorParamTypes(
continue;
}

if ($paramType instanceof TemplateType) {
continue;
}

$this->hasChanged = true;
$param->type = new Identifier('mixed');
if ($param->flags !== 0) {
Expand Down
21 changes: 17 additions & 4 deletions src/NodeTypeResolver/TypeComparator/TypeComparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public function __construct(

public function areTypesEqual(Type $firstType, Type $secondType): bool
{
$firstType = $this->normalizeTemplateType($firstType);
$secondType = $this->normalizeTemplateType($secondType);

$firstTypeHash = $this->typeHasher->createTypeHash($firstType);
$secondTypeHash = $this->typeHasher->createTypeHash($secondType);

Expand Down Expand Up @@ -76,10 +79,6 @@ public function arePhpParserAndPhpStanPhpDocTypesEqual(
$node
);

if ($phpStanDocType instanceof TemplateType) {
return false;
}

if (! $this->areTypesEqual($phpParserNodeType, $phpStanDocType) && $this->isSubtype(
$phpStanDocType,
$phpParserNodeType
Expand Down Expand Up @@ -110,6 +109,9 @@ public function arePhpParserAndPhpStanPhpDocTypesEqual(

public function isSubtype(Type $checkedType, Type $mainType): bool
{
$checkedType = $this->normalizeTemplateType($checkedType);
$mainType = $this->normalizeTemplateType($mainType);

if ($mainType instanceof MixedType) {
return false;
}
Expand All @@ -127,6 +129,17 @@ public function isSubtype(Type $checkedType, Type $mainType): bool
return $this->arrayTypeComparator->isSubtype($checkedType, $mainType);
}

/**
* unless it by ref, object param has its own life vs redefined variable
* see https://3v4l.org/dI5Pe vs https://3v4l.org/S8i71
*/
private function normalizeTemplateType(Type $type): Type
{
return $type instanceof TemplateType
? $type->getBound()
: $type;
}

private function areAliasedObjectMatchingFqnObject(Type $firstType, Type $secondType): bool
{
if ($firstType instanceof AliasedObjectType && $secondType instanceof ObjectType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ public function mapToPhpParserNode(Type $type, string $typeKind): ?Node
return current($intersectionedTypeNodes);
}

if ($typeKind === TypeKind::UNION && ! $this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::UNION_INTERSECTION_TYPES)) {
if ($typeKind === TypeKind::UNION && ! $this->phpVersionProvider->isAtLeastPhpVersion(
PhpVersionFeature::UNION_INTERSECTION_TYPES
)) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ public function isCandidate(mixed $value): bool;
/**
* @param T $value
*/
public function map($value): Expr;
public function map(mixed $value): Expr;
}