Skip to content

Commit ce24c83

Browse files
committed
Native types
2 parents 34dabdd + c4f1eb7 commit ce24c83

File tree

57 files changed

+612
-368
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+612
-368
lines changed

.github/workflows/lint.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ jobs:
6666
uses: actions/cache@v3
6767
with:
6868
path: ./tmp/rectorCache.php
69-
key: "rector-v2-lint-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-${{ steps.rector-cache-key.outputs.sha }}"
69+
key: "rector-v3-lint-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-${{ steps.rector-cache-key.outputs.sha }}"
7070
restore-keys: |
71-
rector-v2-lint-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-
71+
rector-v3-lint-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-
7272
7373
- name: "Transform source code"
7474
if: matrix.php-version != '8.1' && matrix.php-version != '8.2'

.github/workflows/phar.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ jobs:
5959
uses: actions/cache@v3
6060
with:
6161
path: ./tmp/rectorCache.php
62-
key: "rector-v2-phar-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ steps.rector-cache-key.outputs.sha }}"
62+
key: "rector-v3-phar-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ steps.rector-cache-key.outputs.sha }}"
6363
restore-keys: |
64-
rector-v2-phar-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-
64+
rector-v3-phar-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-
6565
6666
- name: "Prepare for PHAR compilation"
6767
working-directory: "compiler"

.github/workflows/static-analysis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ jobs:
7272
uses: actions/cache@v3
7373
with:
7474
path: ./tmp/rectorCache.php
75-
key: "rector-v2-sa-${{ matrix.script }}-${{ matrix.operating-system }}-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-${{ steps.rector-cache-key.outputs.sha }}"
75+
key: "rector-v3-sa-${{ matrix.script }}-${{ matrix.operating-system }}-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-${{ steps.rector-cache-key.outputs.sha }}"
7676
restore-keys: |
77-
rector-v2-sa-${{ matrix.script }}-${{ matrix.operating-system }}-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-
77+
rector-v3-sa-${{ matrix.script }}-${{ matrix.operating-system }}-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-
7878
7979
- name: "Transform source code"
8080
if: matrix.php-version != '8.1' && matrix.php-version != '8.2'

.github/workflows/tests.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ jobs:
7777
uses: actions/cache@v3
7878
with:
7979
path: ./tmp/rectorCache.php
80-
key: "rector-v2-tests-${{ matrix.script }}-${{ matrix.operating-system }}-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-${{ steps.rector-cache-key.outputs.sha }}"
80+
key: "rector-v3-tests-${{ matrix.script }}-${{ matrix.operating-system }}-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-${{ steps.rector-cache-key.outputs.sha }}"
8181
restore-keys: |
82-
rector-v2-tests-${{ matrix.script }}-${{ matrix.operating-system }}-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-
82+
rector-v3-tests-${{ matrix.script }}-${{ matrix.operating-system }}-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-
8383
8484
- name: "Transform source code"
8585
if: matrix.php-version != '8.1' && matrix.php-version != '8.2'
@@ -200,9 +200,9 @@ jobs:
200200
uses: actions/cache@v3
201201
with:
202202
path: ./tmp/rectorCache.php
203-
key: "rector-v2-tests-old-${{ matrix.script }}-${{ matrix.operating-system }}-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-${{ steps.rector-cache-key.outputs.sha }}"
203+
key: "rector-v3-tests-old-${{ matrix.script }}-${{ matrix.operating-system }}-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-${{ steps.rector-cache-key.outputs.sha }}"
204204
restore-keys: |
205-
rector-v2-tests-old-${{ matrix.script }}-${{ matrix.operating-system }}-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-
205+
rector-v3-tests-old-${{ matrix.script }}-${{ matrix.operating-system }}-${{ hashFiles('composer.lock', 'build/rector-downgrade.php') }}-${{ matrix.php-version }}-
206206
207207
- name: "Transform source code"
208208
shell: bash

conf/config.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ services:
629629
earlyTerminatingMethodCalls: %earlyTerminatingMethodCalls%
630630
earlyTerminatingFunctionCalls: %earlyTerminatingFunctionCalls%
631631
implicitThrows: %exceptions.implicitThrows%
632+
treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain%
632633

633634
-
634635
class: PHPStan\Analyser\ConstantResolver

phpstan-baseline.neon

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,14 @@ parameters:
340340
count: 1
341341
path: src/Reflection/SignatureMap/Php8SignatureMapProvider.php
342342

343+
-
344+
message: """
345+
#^Call to deprecated method doNotTreatPhpDocTypesAsCertain\\(\\) of class PHPStan\\\\Analyser\\\\Scope\\:
346+
Use getNativeType\\(\\)$#
347+
"""
348+
count: 1
349+
path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php
350+
343351
-
344352
message: "#^Function class_implements\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#"
345353
count: 1

src/Analyser/DirectInternalScopeFactory.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ public function __construct(
3131
private PropertyReflectionFinder $propertyReflectionFinder,
3232
private Parser $parser,
3333
private NodeScopeResolver $nodeScopeResolver,
34-
private bool $treatPhpDocTypesAsCertain,
3534
private PhpVersion $phpVersion,
3635
private bool $explicitMixedInUnknownGenericNew,
3736
private bool $explicitMixedForGlobalVariables,
@@ -97,7 +96,6 @@ public function create(
9796
$currentlyAssignedExpressions,
9897
$currentlyAllowedUndefinedExpressions,
9998
$inFunctionCallsStack,
100-
$this->treatPhpDocTypesAsCertain,
10199
$afterExtractCall,
102100
$parentScope,
103101
$nativeTypesPromoted,

src/Analyser/LazyInternalScopeFactory.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
class LazyInternalScopeFactory implements InternalScopeFactory
1919
{
2020

21-
private bool $treatPhpDocTypesAsCertain;
22-
2321
private bool $explicitMixedInUnknownGenericNew;
2422

2523
private bool $explicitMixedForGlobalVariables;
@@ -32,7 +30,6 @@ public function __construct(
3230
private Container $container,
3331
)
3432
{
35-
$this->treatPhpDocTypesAsCertain = $container->getParameter('treatPhpDocTypesAsCertain');
3633
$this->explicitMixedInUnknownGenericNew = $this->container->getParameter('featureToggles')['explicitMixedInUnknownGenericNew'];
3734
$this->explicitMixedForGlobalVariables = $this->container->getParameter('featureToggles')['explicitMixedForGlobalVariables'];
3835
}
@@ -95,7 +92,6 @@ public function create(
9592
$currentlyAssignedExpressions,
9693
$currentlyAllowedUndefinedExpressions,
9794
$inFunctionCallsStack,
98-
$this->treatPhpDocTypesAsCertain,
9995
$afterExtractCall,
10096
$parentScope,
10197
$nativeTypesPromoted,

src/Analyser/MutatingScope.php

Lines changed: 41 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ class MutatingScope implements Scope
150150

151151
private ?self $scopeOutOfFirstLevelStatement = null;
152152

153+
private ?self $scopeWithPromotedNativeTypes = null;
154+
153155
/**
154156
* @param array<string, ExpressionTypeHolder> $expressionTypes
155157
* @param array<string, ConditionalExpressionHolder[]> $conditionalExpressions
@@ -183,7 +185,6 @@ public function __construct(
183185
private array $currentlyAssignedExpressions = [],
184186
private array $currentlyAllowedUndefinedExpressions = [],
185187
private array $inFunctionCallsStack = [],
186-
private bool $treatPhpDocTypesAsCertain = true,
187188
private bool $afterExtractCall = false,
188189
private ?Scope $parentScope = null,
189190
private bool $nativeTypesPromoted = false,
@@ -739,11 +740,7 @@ private function resolveType(string $exprString, Expr $node): Type
739740
}
740741

741742
if ($node instanceof Node\Expr\BooleanNot) {
742-
if ($this->treatPhpDocTypesAsCertain) {
743-
$exprBooleanType = $this->getType($node->expr)->toBoolean();
744-
} else {
745-
$exprBooleanType = $this->getNativeType($node->expr)->toBoolean();
746-
}
743+
$exprBooleanType = $this->getType($node->expr)->toBoolean();
747744
if ($exprBooleanType instanceof ConstantBooleanType) {
748745
return new ConstantBooleanType(!$exprBooleanType->getValue());
749746
}
@@ -759,23 +756,14 @@ private function resolveType(string $exprString, Expr $node): Type
759756
$node instanceof Node\Expr\BinaryOp\BooleanAnd
760757
|| $node instanceof Node\Expr\BinaryOp\LogicalAnd
761758
) {
762-
if ($this->treatPhpDocTypesAsCertain) {
763-
$leftBooleanType = $this->getType($node->left)->toBoolean();
764-
} else {
765-
$leftBooleanType = $this->getNativeType($node->left)->toBoolean();
766-
}
767-
759+
$leftBooleanType = $this->getType($node->left)->toBoolean();
768760
if (
769761
$leftBooleanType->isFalse()->yes()
770762
) {
771763
return new ConstantBooleanType(false);
772764
}
773765

774-
if ($this->treatPhpDocTypesAsCertain) {
775-
$rightBooleanType = $this->filterByTruthyValue($node->left)->getType($node->right)->toBoolean();
776-
} else {
777-
$rightBooleanType = $this->promoteNativeTypes()->filterByTruthyValue($node->left)->getType($node->right)->toBoolean();
778-
}
766+
$rightBooleanType = $this->filterByTruthyValue($node->left)->getType($node->right)->toBoolean();
779767

780768
if (
781769
$rightBooleanType->isFalse()->yes()
@@ -797,22 +785,14 @@ private function resolveType(string $exprString, Expr $node): Type
797785
$node instanceof Node\Expr\BinaryOp\BooleanOr
798786
|| $node instanceof Node\Expr\BinaryOp\LogicalOr
799787
) {
800-
if ($this->treatPhpDocTypesAsCertain) {
801-
$leftBooleanType = $this->getType($node->left)->toBoolean();
802-
} else {
803-
$leftBooleanType = $this->getNativeType($node->left)->toBoolean();
804-
}
788+
$leftBooleanType = $this->getType($node->left)->toBoolean();
805789
if (
806790
$leftBooleanType->isTrue()->yes()
807791
) {
808792
return new ConstantBooleanType(true);
809793
}
810794

811-
if ($this->treatPhpDocTypesAsCertain) {
812-
$rightBooleanType = $this->filterByFalseyValue($node->left)->getType($node->right)->toBoolean();
813-
} else {
814-
$rightBooleanType = $this->promoteNativeTypes()->filterByFalseyValue($node->left)->getType($node->right)->toBoolean();
815-
}
795+
$rightBooleanType = $this->filterByFalseyValue($node->left)->getType($node->right)->toBoolean();
816796

817797
if (
818798
$rightBooleanType->isTrue()->yes()
@@ -831,13 +811,8 @@ private function resolveType(string $exprString, Expr $node): Type
831811
}
832812

833813
if ($node instanceof Node\Expr\BinaryOp\LogicalXor) {
834-
if ($this->treatPhpDocTypesAsCertain) {
835-
$leftBooleanType = $this->getType($node->left)->toBoolean();
836-
$rightBooleanType = $this->getType($node->right)->toBoolean();
837-
} else {
838-
$leftBooleanType = $this->getNativeType($node->left)->toBoolean();
839-
$rightBooleanType = $this->getNativeType($node->right)->toBoolean();
840-
}
814+
$leftBooleanType = $this->getType($node->left)->toBoolean();
815+
$rightBooleanType = $this->getType($node->right)->toBoolean();
841816

842817
if (
843818
$leftBooleanType instanceof ConstantBooleanType
@@ -862,13 +837,8 @@ private function resolveType(string $exprString, Expr $node): Type
862837
return new ConstantBooleanType(true);
863838
}
864839

865-
if ($this->treatPhpDocTypesAsCertain) {
866-
$leftType = $this->getType($node->left);
867-
$rightType = $this->getType($node->right);
868-
} else {
869-
$leftType = $this->getNativeType($node->left);
870-
$rightType = $this->getNativeType($node->right);
871-
}
840+
$leftType = $this->getType($node->left);
841+
$rightType = $this->getType($node->right);
872842

873843
if (
874844
(
@@ -900,11 +870,7 @@ private function resolveType(string $exprString, Expr $node): Type
900870
}
901871

902872
if ($node instanceof Expr\Instanceof_) {
903-
if ($this->treatPhpDocTypesAsCertain) {
904-
$expressionType = $this->getType($node->expr);
905-
} else {
906-
$expressionType = $this->getNativeType($node->expr);
907-
}
873+
$expressionType = $this->getType($node->expr);
908874
if (
909875
$this->isInTrait()
910876
&& TypeUtils::findThisType($expressionType) !== null
@@ -1681,6 +1647,22 @@ private function resolveType(string $exprString, Expr $node): Type
16811647
}
16821648

16831649
if ($node instanceof MethodCall && $node->name instanceof Node\Identifier) {
1650+
if ($this->nativeTypesPromoted) {
1651+
$typeCallback = function () use ($node): Type {
1652+
$methodReflection = $this->getMethodReflection(
1653+
$this->getNativeType($node->var),
1654+
$node->name->name,
1655+
);
1656+
if ($methodReflection === null) {
1657+
return new ErrorType();
1658+
}
1659+
1660+
return ParametersAcceptorSelector::combineAcceptors($methodReflection->getVariants())->getNativeReturnType();
1661+
};
1662+
1663+
return $this->getNullsafeShortCircuitingType($node->var, $typeCallback());
1664+
}
1665+
16841666
$typeCallback = function () use ($node): Type {
16851667
$returnType = $this->methodCallReturnType(
16861668
$this->getType($node->var),
@@ -1920,12 +1902,8 @@ public function issetCheck(Expr $expr, callable $typeCallback, ?bool $result = n
19201902

19211903
return $result;
19221904
} elseif ($expr instanceof Node\Expr\ArrayDimFetch && $expr->dim !== null) {
1923-
$type = $this->treatPhpDocTypesAsCertain
1924-
? $this->getType($expr->var)
1925-
: $this->getNativeType($expr->var);
1926-
$dimType = $this->treatPhpDocTypesAsCertain
1927-
? $this->getType($expr->dim)
1928-
: $this->getNativeType($expr->dim);
1905+
$type = $this->getType($expr->var);
1906+
$dimType = $this->getType($expr->dim);
19291907
$hasOffsetValue = $type->hasOffsetValueType($dimType);
19301908
if (!$type->isOffsetAccessible()->yes()) {
19311909
return $result ?? $this->issetCheckUndefined($expr->var);
@@ -2076,65 +2054,16 @@ private function createFirstClassCallable(array $variants): Type
20762054
/** @api */
20772055
public function getNativeType(Expr $expr): Type
20782056
{
2079-
$key = $this->getNodeKey($expr);
2080-
2081-
if (array_key_exists($key, $this->nativeExpressionTypes) && $this->nativeExpressionTypes[$key]->getCertainty()->yes()) {
2082-
return $this->nativeExpressionTypes[$key]->getType();
2083-
}
2084-
2085-
if ($expr instanceof Expr\ArrayDimFetch && $expr->dim !== null) {
2086-
return $this->getNullsafeShortCircuitingType(
2087-
$expr->var,
2088-
$this->getTypeFromArrayDimFetch(
2089-
$expr,
2090-
$this->getNativeType($expr->dim),
2091-
$this->getNativeType($expr->var),
2092-
),
2093-
);
2094-
}
2095-
2096-
return $this->getType($expr);
2057+
return $this->promoteNativeTypes()->getType($expr);
20972058
}
20982059

2099-
/** @api */
2060+
/**
2061+
* @api
2062+
* @deprecated Use getNativeType()
2063+
*/
21002064
public function doNotTreatPhpDocTypesAsCertain(): Scope
21012065
{
2102-
if (!$this->treatPhpDocTypesAsCertain) {
2103-
return $this;
2104-
}
2105-
2106-
return new self(
2107-
$this->scopeFactory,
2108-
$this->reflectionProvider,
2109-
$this->initializerExprTypeResolver,
2110-
$this->dynamicReturnTypeExtensionRegistry,
2111-
$this->exprPrinter,
2112-
$this->typeSpecifier,
2113-
$this->propertyReflectionFinder,
2114-
$this->parser,
2115-
$this->nodeScopeResolver,
2116-
$this->constantResolver,
2117-
$this->context,
2118-
$this->phpVersion,
2119-
$this->declareStrictTypes,
2120-
$this->function,
2121-
$this->namespace,
2122-
$this->expressionTypes,
2123-
$this->nativeExpressionTypes,
2124-
$this->conditionalExpressions,
2125-
$this->inClosureBindScopeClass,
2126-
$this->anonymousFunctionReflection,
2127-
$this->inFirstLevelStatement,
2128-
$this->currentlyAssignedExpressions,
2129-
$this->currentlyAllowedUndefinedExpressions,
2130-
$this->inFunctionCallsStack,
2131-
false,
2132-
$this->afterExtractCall,
2133-
$this->parentScope,
2134-
false,
2135-
$this->explicitMixedInUnknownGenericNew,
2136-
$this->explicitMixedForGlobalVariables,
2137-
);
2066+
return $this->promoteNativeTypes();
21382067
}
21392068

21402069
private function promoteNativeTypes(): self
@@ -2143,24 +2072,18 @@ private function promoteNativeTypes(): self
21432072
return $this;
21442073
}
21452074

2146-
$expressionTypes = $this->expressionTypes;
2147-
foreach ($this->nativeExpressionTypes as $exprString => $typeHolder) {
2148-
$has = $this->hasVariableType(substr($exprString, 1));
2149-
if ($has->no()) {
2150-
continue;
2151-
}
2152-
2153-
$expressionTypes[$exprString] = $typeHolder;
2075+
if ($this->scopeWithPromotedNativeTypes !== null) {
2076+
return $this->scopeWithPromotedNativeTypes;
21542077
}
21552078

2156-
return $this->scopeFactory->create(
2079+
return $this->scopeWithPromotedNativeTypes = $this->scopeFactory->create(
21572080
$this->context,
21582081
$this->declareStrictTypes,
21592082
$this->function,
21602083
$this->namespace,
2161-
$expressionTypes,
21622084
$this->nativeExpressionTypes,
2163-
$this->conditionalExpressions,
2085+
[],
2086+
[],
21642087
$this->inClosureBindScopeClass,
21652088
$this->anonymousFunctionReflection,
21662089
$this->inFirstLevelStatement,

0 commit comments

Comments
 (0)