Commit 4372b52
Collapse ObjectShapeType against HasPropertyType regardless of member order
An intersection of an object shape carrying an optional key with a
HasPropertyType for that key - as produced by isset()/?? narrowing, e.g.
`stdClass&object{u?:int}` narrowed by `isset($x->u)` - is supposed to resolve
the optional key to its declared type, so that `$x->u ?? null` is `int|null`.
That relied on member order. The collapse
`ObjectShapeType & HasPropertyType -> makePropertyRequired()` sat in the
reduction loop, reached only after the generic supertype dedup. When the
intersection also contains a dynamic-property class such as stdClass, which
reports every property as present, HasPropertyType is a supertype of it and the
dedup splices HasPropertyType out before it is ever paired with the object
shape. Which of the two fires first depends on the order of the members, so the
optional key stayed optional whenever stdClass happened to come first and the
read fell back to the class's mixed. While intersection members were still
sorted in place this was masked - describing the type reordered them so the
shape came first; once that mutation was removed the construction order won.
Move the collapse into its own pass before the reduction loop so member order
no longer decides the result. Guard it with hasInstanceProperty(): when the
shape does not have the key it is left untouched, so a sealed shape intersected
with a HasPropertyType for a key it cannot have still reduces to never in the
loop below, as before.
The array analogue (ConstantArrayType & HasOffsetType) is unaffected: there is
no universal-offset crate reporting every offset as present, so nothing absorbs
the HasOffsetType before the offset is made required.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent c2dbd45 commit 4372b52
2 files changed
Lines changed: 98 additions & 14 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1740 | 1740 | | |
1741 | 1741 | | |
1742 | 1742 | | |
| 1743 | + | |
1743 | 1744 | | |
1744 | 1745 | | |
1745 | 1746 | | |
1746 | 1747 | | |
1747 | 1748 | | |
1748 | 1749 | | |
1749 | 1750 | | |
| 1751 | + | |
| 1752 | + | |
| 1753 | + | |
| 1754 | + | |
1750 | 1755 | | |
1751 | 1756 | | |
1752 | 1757 | | |
| |||
1785 | 1790 | | |
1786 | 1791 | | |
1787 | 1792 | | |
| 1793 | + | |
| 1794 | + | |
| 1795 | + | |
| 1796 | + | |
| 1797 | + | |
| 1798 | + | |
| 1799 | + | |
| 1800 | + | |
| 1801 | + | |
| 1802 | + | |
| 1803 | + | |
| 1804 | + | |
| 1805 | + | |
| 1806 | + | |
| 1807 | + | |
| 1808 | + | |
| 1809 | + | |
| 1810 | + | |
| 1811 | + | |
| 1812 | + | |
| 1813 | + | |
| 1814 | + | |
| 1815 | + | |
| 1816 | + | |
| 1817 | + | |
| 1818 | + | |
| 1819 | + | |
| 1820 | + | |
| 1821 | + | |
| 1822 | + | |
| 1823 | + | |
| 1824 | + | |
| 1825 | + | |
| 1826 | + | |
| 1827 | + | |
1788 | 1828 | | |
1789 | 1829 | | |
1790 | 1830 | | |
| |||
1949 | 1989 | | |
1950 | 1990 | | |
1951 | 1991 | | |
1952 | | - | |
1953 | | - | |
1954 | | - | |
1955 | | - | |
1956 | | - | |
1957 | | - | |
1958 | | - | |
1959 | | - | |
1960 | | - | |
1961 | | - | |
1962 | | - | |
1963 | | - | |
1964 | | - | |
1965 | | - | |
1966 | 1992 | | |
1967 | 1993 | | |
1968 | 1994 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
0 commit comments