diff --git a/config.xsd b/config.xsd
index 875d1e5be..53918684e 100644
--- a/config.xsd
+++ b/config.xsd
@@ -310,6 +310,8 @@
+
+
diff --git a/docs/running_psalm/issues.md b/docs/running_psalm/issues.md
index edbae2e6a..6f7903fa6 100644
--- a/docs/running_psalm/issues.md
+++ b/docs/running_psalm/issues.md
@@ -1951,6 +1951,32 @@ echo $arr["b"];
```
+### PossiblyUndefinedIntArrayOffset
+
+Emitted when the config flag `ensureArrayIntOffsetsExist` is set to `true` and an integer-keyed offset is not checked for existence
+
+```php
+/**
+ * @param array $arr
+ */
+function foo(array $arr) : void {
+ echo $arr[0];
+}
+```
+
+### PossiblyUndefinedStringArrayOffset
+
+Emitted when the config flag `ensureArrayStringOffsetsExist` is set to `true` and an integer-keyed offset is not checked for existence
+
+```php
+/**
+ * @param array $arr
+ */
+function foo(array $arr) : void {
+ echo $arr["hello"];
+}
+```
+
### PossiblyUndefinedGlobalVariable
Emitted when trying to access a variable in the global scope that may not be defined
diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php
index 7cb836b6c..3812410b4 100644
--- a/src/Psalm/Config.php
+++ b/src/Psalm/Config.php
@@ -1272,6 +1272,12 @@ class Config
*/
public static function getParentIssueType($issue_type)
{
+ if ($issue_type === 'PossiblyUndefinedIntArrayOffset'
+ || $issue_type === 'PossiblyUndefinedStringArrayOffset'
+ ) {
+ return 'PossiblyUndefinedArrayOffset';
+ }
+
if (strpos($issue_type, 'Possibly') === 0) {
$stripped_issue_type = preg_replace('/^Possibly(False|Null)?/', '', $issue_type);
diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php
index 8ee531967..55fed3362 100644
--- a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php
+++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php
@@ -25,6 +25,8 @@ use Psalm\Issue\PossiblyNullArrayAccess;
use Psalm\Issue\PossiblyNullArrayAssignment;
use Psalm\Issue\PossiblyNullArrayOffset;
use Psalm\Issue\PossiblyUndefinedArrayOffset;
+use Psalm\Issue\PossiblyUndefinedIntArrayOffset;
+use Psalm\Issue\PossiblyUndefinedStringArrayOffset;
use Psalm\IssueBuffer;
use Psalm\Type;
use Psalm\Type\Atomic\ObjectLike;
@@ -1263,7 +1265,7 @@ class ArrayFetchAnalyzer
if (!$found_match) {
if (IssueBuffer::accepts(
- new PossiblyUndefinedArrayOffset(
+ new PossiblyUndefinedIntArrayOffset(
'Possibly undefined array offset \''
. $offset_type->getId() . '\' '
. 'is risky given expected type \''
@@ -1312,7 +1314,7 @@ class ArrayFetchAnalyzer
if (!$found_match) {
if (IssueBuffer::accepts(
- new PossiblyUndefinedArrayOffset(
+ new PossiblyUndefinedStringArrayOffset(
'Possibly undefined array offset \''
. $offset_type->getId() . '\' '
. 'is risky given expected type \''
diff --git a/src/Psalm/Issue/PossiblyUndefinedIntArrayOffset.php b/src/Psalm/Issue/PossiblyUndefinedIntArrayOffset.php
new file mode 100644
index 000000000..91116dd93
--- /dev/null
+++ b/src/Psalm/Issue/PossiblyUndefinedIntArrayOffset.php
@@ -0,0 +1,6 @@
+project_analyzer->trackUnusedSuppressions();
}
+ $is_array_offset_test = strpos($error_message, 'ArrayOffset') && strpos($error_message, 'PossiblyUndefined') !== false;
+
+ $this->project_analyzer->getConfig()->ensure_array_string_offsets_exist = $is_array_offset_test;
+ $this->project_analyzer->getConfig()->ensure_array_int_offsets_exist = $is_array_offset_test;
+
+ if (strpos($error_message, 'ArrayOffset')) {
+
+ }
+
foreach ($error_levels as $error_level) {
$this->project_analyzer->getCodebase()->config->setCustomErrorLevel($error_level, Config::REPORT_SUPPRESS);
}