@@ -39,14 +39,10 @@ public function getReturnValueType(Type $arrayType, Type $columnType, Scope $sco
39
39
}
40
40
41
41
$ iterableValueType = $ arrayType ->getIterableValueType ();
42
- $ returnValueType = $ this ->getOffsetOrProperty ($ iterableValueType , $ columnType , $ scope, false );
42
+ [ $ returnValueType, $ certainty ] = $ this ->getOffsetOrProperty ($ iterableValueType , $ columnType , $ scope );
43
43
44
- if ($ returnValueType === null ) {
45
- $ returnValueType = $ this ->getOffsetOrProperty ($ iterableValueType , $ columnType , $ scope , true );
44
+ if (!$ certainty ->yes ()) {
46
45
$ iterableAtLeastOnce = TrinaryLogic::createMaybe ();
47
- if ($ returnValueType === null ) {
48
- throw new ShouldNotHappenException ();
49
- }
50
46
}
51
47
52
48
return [$ returnValueType , $ iterableAtLeastOnce ];
@@ -57,15 +53,12 @@ public function getReturnIndexType(Type $arrayType, Type $indexType, Scope $scop
57
53
if (!$ indexType ->isNull ()->yes ()) {
58
54
$ iterableValueType = $ arrayType ->getIterableValueType ();
59
55
60
- $ type = $ this ->getOffsetOrProperty ($ iterableValueType , $ indexType , $ scope, false );
61
- if ($ type !== null ) {
56
+ [ $ type, $ certainty ] = $ this ->getOffsetOrProperty ($ iterableValueType , $ indexType , $ scope );
57
+ if ($ certainty -> yes () ) {
62
58
return $ type ;
63
59
}
64
60
65
- $ type = $ this ->getOffsetOrProperty ($ iterableValueType , $ indexType , $ scope , true );
66
- if ($ type !== null ) {
67
- return TypeCombinator::union ($ type , new IntegerType ());
68
- }
61
+ return TypeCombinator::union ($ type , new IntegerType ());
69
62
}
70
63
71
64
return new IntegerType ();
@@ -96,25 +89,20 @@ public function handleConstantArray(ConstantArrayType $arrayType, Type $columnTy
96
89
$ builder = ConstantArrayTypeBuilder::createEmpty ();
97
90
98
91
foreach ($ arrayType ->getValueTypes () as $ i => $ iterableValueType ) {
99
- $ valueType = $ this ->getOffsetOrProperty ($ iterableValueType , $ columnType , $ scope, false );
100
- if ($ valueType === null ) {
92
+ [ $ valueType, $ certainty ] = $ this ->getOffsetOrProperty ($ iterableValueType , $ columnType , $ scope );
93
+ if (! $ certainty -> yes () ) {
101
94
return null ;
102
95
}
103
96
if ($ valueType instanceof NeverType) {
104
97
continue ;
105
98
}
106
99
107
100
if (!$ indexType ->isNull ()->yes ()) {
108
- $ type = $ this ->getOffsetOrProperty ($ iterableValueType , $ indexType , $ scope, false );
109
- if ($ type !== null ) {
101
+ [ $ type, $ certainty ] = $ this ->getOffsetOrProperty ($ iterableValueType , $ indexType , $ scope );
102
+ if ($ certainty -> yes () ) {
110
103
$ keyType = $ type ;
111
104
} else {
112
- $ type = $ this ->getOffsetOrProperty ($ iterableValueType , $ indexType , $ scope , true );
113
- if ($ type !== null ) {
114
- $ keyType = TypeCombinator::union ($ type , new IntegerType ());
115
- } else {
116
- $ keyType = null ;
117
- }
105
+ $ keyType = TypeCombinator::union ($ type , new IntegerType ());
118
106
}
119
107
} else {
120
108
$ keyType = null ;
@@ -129,11 +117,14 @@ public function handleConstantArray(ConstantArrayType $arrayType, Type $columnTy
129
117
return $ builder ->getArray ();
130
118
}
131
119
132
- private function getOffsetOrProperty (Type $ type , Type $ offsetOrProperty , Scope $ scope , bool $ allowMaybe ): ?Type
120
+ /**
121
+ * @return array{Type, TrinaryLogic}
122
+ */
123
+ private function getOffsetOrProperty (Type $ type , Type $ offsetOrProperty , Scope $ scope ): array
133
124
{
134
125
$ offsetIsNull = $ offsetOrProperty ->isNull ();
135
126
if ($ offsetIsNull ->yes ()) {
136
- return $ type ;
127
+ return [ $ type, TrinaryLogic:: createYes ()] ;
137
128
}
138
129
139
130
$ returnTypes = [];
@@ -145,13 +136,13 @@ private function getOffsetOrProperty(Type $type, Type $offsetOrProperty, Scope $
145
136
if (!$ type ->canAccessProperties ()->no ()) {
146
137
$ propertyTypes = $ offsetOrProperty ->getConstantStrings ();
147
138
if ($ propertyTypes === []) {
148
- return $ allowMaybe ? new MixedType () : null ;
139
+ return [ new MixedType (), TrinaryLogic:: createMaybe ()] ;
149
140
}
150
141
foreach ($ propertyTypes as $ propertyType ) {
151
142
$ propertyName = $ propertyType ->getValue ();
152
143
$ hasProperty = $ type ->hasProperty ($ propertyName );
153
144
if ($ hasProperty ->maybe ()) {
154
- return $ allowMaybe ? new MixedType () : null ;
145
+ return [ new MixedType (), TrinaryLogic:: createMaybe ()] ;
155
146
}
156
147
if (!$ hasProperty ->yes ()) {
157
148
continue ;
@@ -161,21 +152,22 @@ private function getOffsetOrProperty(Type $type, Type $offsetOrProperty, Scope $
161
152
}
162
153
}
163
154
155
+ $ certainty = TrinaryLogic::createYes ();
164
156
if ($ type ->isOffsetAccessible ()->yes ()) {
165
157
$ hasOffset = $ type ->hasOffsetValueType ($ offsetOrProperty );
166
- if (! $ allowMaybe && $ hasOffset ->maybe ()) {
167
- return null ;
158
+ if ($ hasOffset ->maybe ()) {
159
+ $ certainty = TrinaryLogic:: createMaybe () ;
168
160
}
169
161
if (!$ hasOffset ->no ()) {
170
162
$ returnTypes [] = $ type ->getOffsetValueType ($ offsetOrProperty );
171
163
}
172
164
}
173
165
174
166
if ($ returnTypes === []) {
175
- return new NeverType ();
167
+ return [ new NeverType (), TrinaryLogic:: createYes ()] ;
176
168
}
177
169
178
- return TypeCombinator::union (...$ returnTypes );
170
+ return [ TypeCombinator::union (...$ returnTypes ), $ certainty ] ;
179
171
}
180
172
181
173
private function castToArrayKeyType (Type $ type ): Type
0 commit comments