Skip to content

Commit 60ef734

Browse files
committed
Error on offset assignment to specialized strings
1 parent 4f7beff commit 60ef734

File tree

6 files changed

+89
-0
lines changed

6 files changed

+89
-0
lines changed

src/Type/Accessory/AccessoryLiteralStringType.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ public function getOffsetValueType(Type $offsetType): Type
153153

154154
public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
155155
{
156+
$stringOffset = (new StringType())->setOffsetValueType($offsetType, $valueType, $unionValues);
157+
158+
if ($stringOffset instanceof ErrorType) {
159+
return $stringOffset;
160+
}
161+
156162
if ($valueType->isLiteralString()->yes()) {
157163
return $this;
158164
}

src/Type/Accessory/AccessoryNonEmptyStringType.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ public function getOffsetValueType(Type $offsetType): Type
159159

160160
public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
161161
{
162+
$stringOffset = (new StringType())->setOffsetValueType($offsetType, $valueType, $unionValues);
163+
164+
if ($stringOffset instanceof ErrorType) {
165+
return $stringOffset;
166+
}
167+
162168
return $this;
163169
}
164170

src/Type/Accessory/AccessoryNonFalsyStringType.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ public function getOffsetValueType(Type $offsetType): Type
155155

156156
public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
157157
{
158+
$stringOffset = (new StringType())->setOffsetValueType($offsetType, $valueType, $unionValues);
159+
160+
if ($stringOffset instanceof ErrorType) {
161+
return $stringOffset;
162+
}
163+
158164
if ($valueType->isNonFalsyString()->yes()) {
159165
return $this;
160166
}

src/Type/Accessory/AccessoryNumericStringType.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,12 @@ public function getOffsetValueType(Type $offsetType): Type
158158

159159
public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
160160
{
161+
$stringOffset = (new StringType())->setOffsetValueType($offsetType, $valueType, $unionValues);
162+
163+
if ($stringOffset instanceof ErrorType) {
164+
return $stringOffset;
165+
}
166+
161167
return $this;
162168
}
163169

tests/PHPStan/Rules/Arrays/OffsetAccessAssignmentRuleTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,39 @@ public function testBug8015(): void
156156
$this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-8015.php'], []);
157157
}
158158

159+
public function testBug11572(): void
160+
{
161+
$this->checkUnionTypes = true;
162+
$this->analyse([__DIR__ . '/data/bug-11572.php'], [
163+
[
164+
'Cannot assign new offset to string.',
165+
15,
166+
],
167+
[
168+
'Cannot assign new offset to string.',
169+
16,
170+
],
171+
[
172+
'Cannot assign new offset to string.',
173+
17,
174+
],
175+
[
176+
'Cannot assign new offset to string.',
177+
18,
178+
],
179+
[
180+
'Cannot assign new offset to string.',
181+
19,
182+
],
183+
[
184+
'Cannot assign new offset to string.',
185+
20,
186+
],
187+
[
188+
'Cannot assign new offset to string.',
189+
24,
190+
],
191+
]);
192+
}
193+
159194
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace bug11572;
4+
5+
/**
6+
* @param string $s
7+
* @param numeric-string $numericS
8+
* @param literal-string $literalS
9+
* @param non-empty-string $nonEmptyS
10+
* @param non-falsy-string $nonFalsyS
11+
* @param non-falsy-string&literal-string $intersectedS
12+
*/
13+
function doFoo($s, $numericS, $literalS, $nonEmptyS, $nonFalsyS, $intersectedS): void
14+
{
15+
$s[] = 'foo';
16+
$numericS[] = 'foo';
17+
$literalS[] = 'foo';
18+
$nonEmptyS[] = 'foo';
19+
$nonFalsyS[] = 'foo';
20+
$intersectedS[] = 'foo';
21+
}
22+
23+
$string = returnString() . ' bar';
24+
$string[] = 'foo';
25+
26+
function returnString(): string
27+
{
28+
return 'baz';
29+
}
30+

0 commit comments

Comments
 (0)