@@ -150,6 +150,8 @@ class MutatingScope implements Scope
150
150
151
151
private ?self $ scopeOutOfFirstLevelStatement = null ;
152
152
153
+ private ?self $ scopeWithPromotedNativeTypes = null ;
154
+
153
155
/**
154
156
* @param array<string, ExpressionTypeHolder> $expressionTypes
155
157
* @param array<string, ConditionalExpressionHolder[]> $conditionalExpressions
@@ -183,7 +185,6 @@ public function __construct(
183
185
private array $ currentlyAssignedExpressions = [],
184
186
private array $ currentlyAllowedUndefinedExpressions = [],
185
187
private array $ inFunctionCallsStack = [],
186
- private bool $ treatPhpDocTypesAsCertain = true ,
187
188
private bool $ afterExtractCall = false ,
188
189
private ?Scope $ parentScope = null ,
189
190
private bool $ nativeTypesPromoted = false ,
@@ -739,11 +740,7 @@ private function resolveType(string $exprString, Expr $node): Type
739
740
}
740
741
741
742
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 ();
747
744
if ($ exprBooleanType instanceof ConstantBooleanType) {
748
745
return new ConstantBooleanType (!$ exprBooleanType ->getValue ());
749
746
}
@@ -759,23 +756,14 @@ private function resolveType(string $exprString, Expr $node): Type
759
756
$ node instanceof Node \Expr \BinaryOp \BooleanAnd
760
757
|| $ node instanceof Node \Expr \BinaryOp \LogicalAnd
761
758
) {
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 ();
768
760
if (
769
761
$ leftBooleanType ->isFalse ()->yes ()
770
762
) {
771
763
return new ConstantBooleanType (false );
772
764
}
773
765
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 ();
779
767
780
768
if (
781
769
$ rightBooleanType ->isFalse ()->yes ()
@@ -797,22 +785,14 @@ private function resolveType(string $exprString, Expr $node): Type
797
785
$ node instanceof Node \Expr \BinaryOp \BooleanOr
798
786
|| $ node instanceof Node \Expr \BinaryOp \LogicalOr
799
787
) {
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 ();
805
789
if (
806
790
$ leftBooleanType ->isTrue ()->yes ()
807
791
) {
808
792
return new ConstantBooleanType (true );
809
793
}
810
794
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 ();
816
796
817
797
if (
818
798
$ rightBooleanType ->isTrue ()->yes ()
@@ -831,13 +811,8 @@ private function resolveType(string $exprString, Expr $node): Type
831
811
}
832
812
833
813
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 ();
841
816
842
817
if (
843
818
$ leftBooleanType instanceof ConstantBooleanType
@@ -862,13 +837,8 @@ private function resolveType(string $exprString, Expr $node): Type
862
837
return new ConstantBooleanType (true );
863
838
}
864
839
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 );
872
842
873
843
if (
874
844
(
@@ -900,11 +870,7 @@ private function resolveType(string $exprString, Expr $node): Type
900
870
}
901
871
902
872
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 );
908
874
if (
909
875
$ this ->isInTrait ()
910
876
&& TypeUtils::findThisType ($ expressionType ) !== null
@@ -1681,6 +1647,22 @@ private function resolveType(string $exprString, Expr $node): Type
1681
1647
}
1682
1648
1683
1649
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
+
1684
1666
$ typeCallback = function () use ($ node ): Type {
1685
1667
$ returnType = $ this ->methodCallReturnType (
1686
1668
$ this ->getType ($ node ->var ),
@@ -1920,12 +1902,8 @@ public function issetCheck(Expr $expr, callable $typeCallback, ?bool $result = n
1920
1902
1921
1903
return $ result ;
1922
1904
} 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 );
1929
1907
$ hasOffsetValue = $ type ->hasOffsetValueType ($ dimType );
1930
1908
if (!$ type ->isOffsetAccessible ()->yes ()) {
1931
1909
return $ result ?? $ this ->issetCheckUndefined ($ expr ->var );
@@ -2076,65 +2054,16 @@ private function createFirstClassCallable(array $variants): Type
2076
2054
/** @api */
2077
2055
public function getNativeType (Expr $ expr ): Type
2078
2056
{
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 );
2097
2058
}
2098
2059
2099
- /** @api */
2060
+ /**
2061
+ * @api
2062
+ * @deprecated Use getNativeType()
2063
+ */
2100
2064
public function doNotTreatPhpDocTypesAsCertain (): Scope
2101
2065
{
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 ();
2138
2067
}
2139
2068
2140
2069
private function promoteNativeTypes (): self
@@ -2143,24 +2072,18 @@ private function promoteNativeTypes(): self
2143
2072
return $ this ;
2144
2073
}
2145
2074
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 ;
2154
2077
}
2155
2078
2156
- return $ this ->scopeFactory ->create (
2079
+ return $ this ->scopeWithPromotedNativeTypes = $ this -> scopeFactory ->create (
2157
2080
$ this ->context ,
2158
2081
$ this ->declareStrictTypes ,
2159
2082
$ this ->function ,
2160
2083
$ this ->namespace ,
2161
- $ expressionTypes ,
2162
2084
$ this ->nativeExpressionTypes ,
2163
- $ this ->conditionalExpressions ,
2085
+ [],
2086
+ [],
2164
2087
$ this ->inClosureBindScopeClass ,
2165
2088
$ this ->anonymousFunctionReflection ,
2166
2089
$ this ->inFirstLevelStatement ,
0 commit comments