Skip to content

Commit e9ea999

Browse files
authored
Merge pull request #10738 from MelechMizrachi/vimeo-fix-long-array-consts-false-flag
2 parents 71707e6 + f553392 commit e9ea999

File tree

2 files changed

+248
-4
lines changed

2 files changed

+248
-4
lines changed

src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -721,19 +721,27 @@ public static function analyzeAssignment(
721721

722722
// Check assigned type matches docblock type
723723
if ($assigned_type = $statements_analyzer->node_data->getType($const->value)) {
724-
if ($const_storage->type !== null
724+
$const_storage_type = $const_storage->type;
725+
726+
if ($const_storage_type !== null
725727
&& $const_storage->stmt_location !== null
726-
&& $assigned_type !== $const_storage->type
728+
&& $assigned_type !== $const_storage_type
729+
// Check if this type was defined via a dockblock or type hint otherwise the inferred type
730+
// should always match the assigned type and we don't even need to do additional checks
731+
// There is an issue with constants over a certain length where additional values
732+
// are added to fallback_params in the assigned_type but not in const_storage_type
733+
// which causes a false flag for this error to appear. Usually happens with arrays
734+
&& ($const_storage_type->from_docblock || $const_storage_type->from_property)
727735
&& !UnionTypeComparator::isContainedBy(
728736
$statements_analyzer->getCodebase(),
729737
$assigned_type,
730-
$const_storage->type,
738+
$const_storage_type,
731739
)
732740
) {
733741
IssueBuffer::maybeAdd(
734742
new InvalidConstantAssignmentValue(
735743
"{$class_storage->name}::{$const->name->name} with declared type "
736-
. "{$const_storage->type->getId()} cannot be assigned type {$assigned_type->getId()}",
744+
. "{$const_storage_type->getId()} cannot be assigned type {$assigned_type->getId()}",
737745
$const_storage->stmt_location,
738746
"{$class_storage->name}::{$const->name->name}",
739747
),

tests/ConstantTest.php

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,242 @@ public static function foo(int $i) : void {}
824824
A::foo(2);
825825
A::foo(3);',
826826
],
827+
'tooLongArrayInvalidConstantAssignmentValueFalsePositiveWithArray' => [
828+
'code' => '<?php
829+
class TestInvalidConstantAssignmentValueFalsePositiveWithArray {
830+
const LOOKUP = [
831+
"00" => null,
832+
"01" => null,
833+
"02" => null,
834+
"03" => null,
835+
"04" => null,
836+
"05" => null,
837+
"06" => null,
838+
"07" => null,
839+
"08" => null,
840+
"09" => null,
841+
"10" => null,
842+
"11" => null,
843+
"12" => null,
844+
"13" => null,
845+
"14" => null,
846+
"15" => null,
847+
"16" => null,
848+
"17" => null,
849+
"18" => null,
850+
"19" => null,
851+
"20" => null,
852+
"21" => null,
853+
"22" => null,
854+
"23" => null,
855+
"24" => null,
856+
"25" => null,
857+
"26" => null,
858+
"27" => null,
859+
"28" => null,
860+
"29" => null,
861+
"30" => null,
862+
"31" => null,
863+
"32" => null,
864+
"33" => null,
865+
"34" => null,
866+
"35" => null,
867+
"36" => null,
868+
"37" => null,
869+
"38" => null,
870+
"39" => null,
871+
"40" => null,
872+
"41" => null,
873+
"42" => null,
874+
"43" => null,
875+
"44" => null,
876+
"45" => null,
877+
"46" => null,
878+
"47" => null,
879+
"48" => null,
880+
"49" => null,
881+
"50" => null,
882+
"51" => null,
883+
"52" => null,
884+
"53" => null,
885+
"54" => null,
886+
"55" => null,
887+
"56" => null,
888+
"57" => null,
889+
"58" => null,
890+
"59" => null,
891+
"60" => null,
892+
"61" => null,
893+
"62" => null,
894+
"63" => null,
895+
"64" => null,
896+
"65" => null,
897+
"66" => null,
898+
"67" => null,
899+
"68" => null,
900+
"69" => null,
901+
"70" => self::SUCCEED,
902+
"71" => self::FAIL,
903+
"72" => null,
904+
"73" => null,
905+
"74" => null,
906+
"75" => null,
907+
"76" => null,
908+
"77" => null,
909+
"78" => null,
910+
"79" => null,
911+
"80" => null,
912+
"81" => null,
913+
"82" => null,
914+
"83" => null,
915+
"84" => null,
916+
"85" => null,
917+
"86" => null,
918+
"87" => null,
919+
"88" => null,
920+
"89" => null,
921+
"90" => null,
922+
"91" => null,
923+
"92" => null,
924+
"93" => null,
925+
"94" => null,
926+
"95" => null,
927+
"96" => null,
928+
"97" => null,
929+
"98" => null,
930+
"99" => null,
931+
"100" => null,
932+
"101" => null,
933+
];
934+
935+
const SUCCEED = "SUCCEED";
936+
const FAIL = "FAIL";
937+
938+
public static function will_succeed(string $code) : bool {
939+
// Seems to fail when the array has over 100+ entries, and at least one value references
940+
// another constant from the same class (even nested)
941+
return (self::LOOKUP[$code] ?? null) === self::SUCCEED;
942+
}
943+
}',
944+
],
945+
'tooLongArrayInvalidConstantAssignmentValueFalsePositiveWithList' => [
946+
'code' => '<?php
947+
class TestInvalidConstantAssignmentValueFalsePositiveWithList {
948+
const LOOKUP = [
949+
null,
950+
null,
951+
null,
952+
null,
953+
null,
954+
null,
955+
null,
956+
null,
957+
null,
958+
null,
959+
null,
960+
null,
961+
null,
962+
null,
963+
null,
964+
null,
965+
null,
966+
null,
967+
null,
968+
null,
969+
null,
970+
null,
971+
null,
972+
null,
973+
null,
974+
null,
975+
null,
976+
null,
977+
null,
978+
null,
979+
null,
980+
null,
981+
null,
982+
null,
983+
null,
984+
null,
985+
null,
986+
null,
987+
null,
988+
null,
989+
null,
990+
null,
991+
null,
992+
null,
993+
null,
994+
null,
995+
null,
996+
null,
997+
null,
998+
null,
999+
null,
1000+
null,
1001+
null,
1002+
null,
1003+
null,
1004+
null,
1005+
null,
1006+
null,
1007+
null,
1008+
null,
1009+
null,
1010+
null,
1011+
null,
1012+
null,
1013+
null,
1014+
null,
1015+
null,
1016+
null,
1017+
null,
1018+
null,
1019+
self::SUCCEED,
1020+
self::FAIL,
1021+
null,
1022+
null,
1023+
null,
1024+
null,
1025+
null,
1026+
null,
1027+
null,
1028+
null,
1029+
null,
1030+
null,
1031+
null,
1032+
null,
1033+
null,
1034+
null,
1035+
null,
1036+
null,
1037+
null,
1038+
null,
1039+
null,
1040+
null,
1041+
null,
1042+
null,
1043+
null,
1044+
null,
1045+
null,
1046+
null,
1047+
null,
1048+
null,
1049+
null,
1050+
null,
1051+
];
1052+
1053+
const SUCCEED = "SUCCEED";
1054+
const FAIL = "FAIL";
1055+
1056+
public static function will_succeed(int $code) : bool {
1057+
// Seems to fail when the array has over 100+ entries, and at least one value references
1058+
// another constant from the same class (even nested)
1059+
return (self::LOOKUP[$code] ?? null) === self::SUCCEED;
1060+
}
1061+
}',
1062+
],
8271063
'valueOf' => [
8281064
'code' => '<?php
8291065
class A {

0 commit comments

Comments
 (0)