psalm icon indicating copy to clipboard operation
psalm copied to clipboard

False Flag for InvalidArrayOffset

Open MelechMizrachi opened this issue 1 year ago • 1 comments

When working on https://github.com/vimeo/psalm/pull/10738 I was able to notice this issue with string array keys being misrepresented as ints.

Fails: https://psalm.dev/r/e0a6a199fd (Note how all the keys are strings, but they are numberic) Works: https://psalm.dev/r/4753dde5a9 (Note the 00 for the first key)

ERROR: [InvalidArrayOffset](https://psalm.dev/115) - 112:37 - Cannot access value on variable MyTest::LOOKUP using a string offset, expecting

Please close if this is expected, but this seems incorrect to me.

MelechMizrachi avatar Feb 23 '24 18:02 MelechMizrachi

I found these snippets:

https://psalm.dev/r/e0a6a199fd
<?php
                    class MyTest {
                        const LOOKUP = [
                            "0" => null,
                            "1" => null,
                            "2" => null,
                            "3" => null,
                            "4" => null,
                            "5" => null,
                            "6" => null,
                            "7" => null,
                            "8" => null,
                            "9" => null,
                            "10" => null,
                            "11" => null,
                            "12" => null,
                            "13" => null,
                            "14" => null,
                            "15" => null,
                            "16" => null,
                            "17" => null,
                            "18" => null,
                            "19" => null,
                            "20" => null,
                            "21" => null,
                            "22" => null,
                            "23" => null,
                            "24" => null,
                            "25" => null,
                            "26" => null,
                            "27" => null,
                            "28" => null,
                            "29" => null,
                            "30" => null,
                            "31" => null,
                            "32" => null,
                            "33" => null,
                            "34" => null,
                            "35" => null,
                            "36" => null,
                            "37" => null,
                            "38" => null,
                            "39" => null,
                            "40" => null,
                            "41" => null,
                            "42" => null,
                            "43" => null,
                            "44" => null,
                            "45" => null,
                            "46" => null,
                            "47" => null,
                            "48" => null,
                            "49" => null,
                            "50" => null,
                            "51" => null,
                            "52" => null,
                            "53" => null,
                            "54" => null,
                            "55" => null,
                            "56" => null,
                            "57" => null,
                            "58" => null,
                            "59" => null,
                            "60" => null,
                            "61" => null,
                            "62" => null,
                            "63" => null,
                            "64" => null,
                            "65" => null,
                            "66" => null,
                            "67" => null,
                            "68" => null,
                            "69" => null,
                            "70" => self::SUCCEED,
                            "71" => self::FAIL,
                            "72" => null,
                            "73" => null,
                            "74" => null,
                            "75" => null,
                            "76" => null,
                            "77" => null,
                            "78" => null,
                            "79" => null,
                            "80" => null,
                            "81" => null,
                            "82" => null,
                            "83" => null,
                            "84" => null,
                            "85" => null,
                            "86" => null,
                            "87" => null,
                            "88" => null,
                            "89" => null,
                            "90" => null,
                            "91" => null,
                            "92" => null,
                            "93" => null,
                            "94" => null,
                            "95" => null,
                            "96" => null,
                            "97" => null,
                            "98" => null,
                            "99" => null,
                            "100" => null,
                            "101" => null,
                        ];

                        const SUCCEED = "SUCCEED";
                        const FAIL = "FAIL";

                        public static function will_succeed(string $code) : bool {
                            return (self::LOOKUP[$code] ?? null) === self::SUCCEED;
                        }
                    }
Psalm output (using commit c488d40):

ERROR: InvalidArrayOffset - 112:37 - Cannot access value on variable MyTest::LOOKUP using a string offset, expecting 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101

ERROR: InvalidConstantAssignmentValue - 3:31 - MyTest::LOOKUP with declared type array{0: null, 100: null, 101: null, 10: null, 11: null, 12: null, 13: null, 14: null, 15: null, 16: null, 17: null, 18: null, 19: null, 1: null, 20: null, 21: null, 22: null, 23: null, 24: null, 25: null, 26: null, 27: null, 28: null, 29: null, 2: null, 30: null, 31: null, 32: null, 33: null, 34: null, 35: null, 36: null, 37: null, 38: null, 39: null, 3: null, 40: null, 41: null, 42: null, 43: null, 44: null, 45: null, 46: null, 47: null, 48: null, 49: null, 4: null, 50: null, 51: null, 52: null, 53: null, 54: null, 55: null, 56: null, 57: null, 58: null, 59: null, 5: null, 60: null, 61: null, 62: null, 63: null, 64: null, 65: null, 66: null, 67: null, 68: null, 69: null, 6: null, 70: 'SUCCEED', 71: 'FAIL', 72: null, 73: null, 74: null, 75: null, 76: null, 77: null, 78: null, 79: null, 7: null, 80: null, 81: null, 82: null, 83: null, 84: null, 85: null, 86: null, 87: null, 88: null, 89: null, 8: null, 90: null, 91: null, 92: null, 93: null, 94: null, 95: null, 96: null, 97: null, 98: null, 99: null, 9: null} cannot be assigned type list{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 'SUCCEED', 'FAIL', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ...<null>}
https://psalm.dev/r/4753dde5a9
<?php
                    class MyTest {
                        const LOOKUP = [
                            "00" => null,
                            "1" => null,
                            "2" => null,
                            "3" => null,
                            "4" => null,
                            "5" => null,
                            "6" => null,
                            "7" => null,
                            "8" => null,
                            "9" => null,
                            "10" => null,
                            "11" => null,
                            "12" => null,
                            "13" => null,
                            "14" => null,
                            "15" => null,
                            "16" => null,
                            "17" => null,
                            "18" => null,
                            "19" => null,
                            "20" => null,
                            "21" => null,
                            "22" => null,
                            "23" => null,
                            "24" => null,
                            "25" => null,
                            "26" => null,
                            "27" => null,
                            "28" => null,
                            "29" => null,
                            "30" => null,
                            "31" => null,
                            "32" => null,
                            "33" => null,
                            "34" => null,
                            "35" => null,
                            "36" => null,
                            "37" => null,
                            "38" => null,
                            "39" => null,
                            "40" => null,
                            "41" => null,
                            "42" => null,
                            "43" => null,
                            "44" => null,
                            "45" => null,
                            "46" => null,
                            "47" => null,
                            "48" => null,
                            "49" => null,
                            "50" => null,
                            "51" => null,
                            "52" => null,
                            "53" => null,
                            "54" => null,
                            "55" => null,
                            "56" => null,
                            "57" => null,
                            "58" => null,
                            "59" => null,
                            "60" => null,
                            "61" => null,
                            "62" => null,
                            "63" => null,
                            "64" => null,
                            "65" => null,
                            "66" => null,
                            "67" => null,
                            "68" => null,
                            "69" => null,
                            "70" => self::SUCCEED,
                            "71" => self::FAIL,
                            "72" => null,
                            "73" => null,
                            "74" => null,
                            "75" => null,
                            "76" => null,
                            "77" => null,
                            "78" => null,
                            "79" => null,
                            "80" => null,
                            "81" => null,
                            "82" => null,
                            "83" => null,
                            "84" => null,
                            "85" => null,
                            "86" => null,
                            "87" => null,
                            "88" => null,
                            "89" => null,
                            "90" => null,
                            "91" => null,
                            "92" => null,
                            "93" => null,
                            "94" => null,
                            "95" => null,
                            "96" => null,
                            "97" => null,
                            "98" => null,
                            "99" => null,
                            "100" => null,
                            "101" => null,
                        ];

                        const SUCCEED = "SUCCEED";
                        const FAIL = "FAIL";

                        public static function will_succeed(string $code) : bool {
                            return (self::LOOKUP[$code] ?? null) === self::SUCCEED;
                        }
                    }
Psalm output (using commit c488d40):

ERROR: InvalidConstantAssignmentValue - 3:31 - MyTest::LOOKUP with declared type array{00: null, 100: null, 101: null, 10: null, 11: null, 12: null, 13: null, 14: null, 15: null, 16: null, 17: null, 18: null, 19: null, 1: null, 20: null, 21: null, 22: null, 23: null, 24: null, 25: null, 26: null, 27: null, 28: null, 29: null, 2: null, 30: null, 31: null, 32: null, 33: null, 34: null, 35: null, 36: null, 37: null, 38: null, 39: null, 3: null, 40: null, 41: null, 42: null, 43: null, 44: null, 45: null, 46: null, 47: null, 48: null, 49: null, 4: null, 50: null, 51: null, 52: null, 53: null, 54: null, 55: null, 56: null, 57: null, 58: null, 59: null, 5: null, 60: null, 61: null, 62: null, 63: null, 64: null, 65: null, 66: null, 67: null, 68: null, 69: null, 6: null, 70: 'SUCCEED', 71: 'FAIL', 72: null, 73: null, 74: null, 75: null, 76: null, 77: null, 78: null, 79: null, 7: null, 80: null, 81: null, 82: null, 83: null, 84: null, 85: null, 86: null, 87: null, 88: null, 89: null, 8: null, 90: null, 91: null, 92: null, 93: null, 94: null, 95: null, 96: null, 97: null, 98: null, 99: null, 9: null} cannot be assigned type array{00: null, 100: null, 10: null, 11: null, 12: null, 13: null, 14: null, 15: null, 16: null, 17: null, 18: null, 19: null, 1: null, 20: null, 21: null, 22: null, 23: null, 24: null, 25: null, 26: null, 27: null, 28: null, 29: null, 2: null, 30: null, 31: null, 32: null, 33: null, 34: null, 35: null, 36: null, 37: null, 38: null, 39: null, 3: null, 40: null, 41: null, 42: null, 43: null, 44: null, 45: null, 46: null, 47: null, 48: null, 49: null, 4: null, 50: null, 51: null, 52: null, 53: null, 54: null, 55: null, 56: null, 57: null, 58: null, 59: null, 5: null, 60: null, 61: null, 62: null, 63: null, 64: null, 65: null, 66: null, 67: null, 68: null, 69: null, 6: null, 70: 'SUCCEED', 71: 'FAIL', 72: null, 73: null, 74: null, 75: null, 76: null, 77: null, 78: null, 79: null, 7: null, 80: null, 81: null, 82: null, 83: null, 84: null, 85: null, 86: null, 87: null, 88: null, 89: null, 8: null, 90: null, 91: null, 92: null, 93: null, 94: null, 95: null, 96: null, 97: null, 98: null, 99: null, 9: null, ...<101, null>}

psalm-github-bot[bot] avatar Feb 23 '24 18:02 psalm-github-bot[bot]