this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

internal/core/adt: handle nested pending arcs

When a comprehension had multiple nested fixed
fields, the type of the node was not properly updated
if a node had only fixed arcs (so no dynamic fields
and no embeddings).

With this change we explicitly track these cases,
and whether this may result in an error.

Fixes #3729

Signed-off-by: Marcel van Lohuizen <mpvl@gmail.com>
Change-Id: I9bacc04c53da6bc0923bdaedba359d9823b73309
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1211617
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Reviewed-by: Matthew Sackman <matthew@cue.works>
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>

+160 -161
+2 -2
cue/testdata/comprehensions/closed.txtar
··· 111 111 } 112 112 } 113 113 -- out/eval/stats -- 114 - Leaks: 2 115 - Freed: 80 114 + Leaks: 4 115 + Freed: 78 116 116 Reused: 74 117 117 Allocs: 8 118 118 Retain: 3
+2 -2
cue/testdata/comprehensions/issue287.txtar
··· 8 8 #E: [_]: bool 9 9 #E: x: true 10 10 -- out/eval/stats -- 11 - Leaks: 0 12 - Freed: 5 11 + Leaks: 1 12 + Freed: 4 13 13 Reused: 1 14 14 Allocs: 4 15 15 Retain: 2
+90 -119
cue/testdata/comprehensions/pushdown.txtar
··· 934 934 ./in.cue:87:4 935 935 issue3535.regular.foo.regular: field not allowed: 936 936 ./issue3535.cue:22:4 937 + issue3729.withoutDisjunction.root.#sub1.#sub2: conflicting values null and {#sub1?:{#sub2:true}} (mismatched types null and struct): 938 + ./issue3729.cue:9:9 939 + ./issue3729.cue:11:9 937 940 noStackOverflowStructCycle.#list.tail: structural cycle 938 941 noStackOverflowStructCycle.list.tail: structural cycle 939 942 structShare.err1.x.d.e: field not allowed: ··· 1652 1655 } 1653 1656 } 1654 1657 } 1655 - issue3729: (struct){ 1658 + issue3729: (_|_){ 1659 + // [eval] 1656 1660 withDisjunction: (struct){ 1657 1661 #Root: (#struct){ 1658 1662 sub1?: (#struct){ 1659 1663 #sub2?: (bool){ bool } 1660 1664 } 1661 1665 } 1662 - root: ((null|struct)){ |((null){ null }, (#struct){ 1663 - sub1?: (#struct){ 1664 - #sub2: (bool){ true } 1665 - } 1666 - }) } 1666 + root: (#struct){ 1667 + sub1?: (#struct){ 1668 + #sub2: (bool){ true } 1669 + } 1670 + } 1667 1671 } 1668 - withoutDisjunction: (struct){ 1669 - root: (null){ 1670 - null 1672 + withoutDisjunction: (_|_){ 1673 + // [eval] 1674 + root: (_|_){ 1675 + // [eval] issue3729.withoutDisjunction.root.#sub1.#sub2: conflicting values null and {#sub1?:{#sub2:true}} (mismatched types null and struct): 1676 + // ./issue3729.cue:9:9 1677 + // ./issue3729.cue:11:9 1671 1678 #sub1?: (#struct){ 1672 1679 #sub2: (bool){ true } 1673 1680 } ··· 1687 1694 #sub2?: (bool){ bool } 1688 1695 } 1689 1696 } 1690 - root: ((null|struct)){ |((null){ null }, (#struct){ 1691 - #sub1?: (#struct){ 1692 - #sub2: (bool){ true } 1693 - } 1694 - }) } 1697 + root: (#struct){ 1698 + #sub1?: (#struct){ 1699 + #sub2: (bool){ true } 1700 + } 1701 + } 1695 1702 } 1696 1703 withEmbed: (struct){ 1697 1704 incomplete: (struct){ ··· 1731 1738 } 1732 1739 argoApp: (#struct){ 1733 1740 spec: (#struct){ 1734 - syncPolicy: ((null|struct)){ |((null){ null }, (#struct){ 1735 - automated: (#struct){ 1736 - prune: (bool){ true } 1737 - selfHeal: (bool){ true } 1738 - } 1739 - }) } 1741 + syncPolicy: (#struct){ 1742 + automated: (#struct){ 1743 + prune: (bool){ true } 1744 + selfHeal: (bool){ true } 1745 + } 1746 + } 1740 1747 _syncpolicy: (string){ "selfhealprune" } 1741 1748 } 1742 1749 } ··· 1766 1773 diff old new 1767 1774 --- old 1768 1775 +++ new 1769 - @@ -1,35 +1,14 @@ 1776 + @@ -1,39 +1,17 @@ 1770 1777 Errors: 1771 1778 embed.fail1.p: field not allowed: 1772 1779 - ./in.cue:37:9 ··· 1788 1795 - ./issue3535.cue:21:3 1789 1796 ./issue3535.cue:22:4 1790 1797 - ./issue3535.cue:25:7 1798 + issue3729.withoutDisjunction.root.#sub1.#sub2: conflicting values null and {#sub1?:{#sub2:true}} (mismatched types null and struct): 1799 + ./issue3729.cue:9:9 1800 + - ./issue3729.cue:10:2 1801 + ./issue3729.cue:11:9 1791 1802 noStackOverflowStructCycle.#list.tail: structural cycle 1792 1803 noStackOverflowStructCycle.list.tail: structural cycle 1793 1804 -provideIncompleteSuccess.t2.a.c.d: field not allowed: ··· 1802 1813 ./in.cue:591:9 1803 1814 fieldMismatch.a: cannot combine regular field "x" with 2: 1804 1815 ./in.cue:152:7 1805 - @@ -75,8 +54,8 @@ 1816 + @@ -79,8 +57,8 @@ 1806 1817 } 1807 1818 fail: (struct){ 1808 1819 a: (_|_){ ··· 1813 1824 } 1814 1825 } 1815 1826 embed: (_|_){ 1816 - @@ -85,10 +64,6 @@ 1827 + @@ -89,10 +67,6 @@ 1817 1828 // [eval] 1818 1829 p: (_|_){ 1819 1830 // [eval] embed.fail1.p: field not allowed: ··· 1824 1835 // ./in.cue:46:4 1825 1836 // ./in.cue:49:9 1826 1837 } 1827 - @@ -117,12 +92,11 @@ 1838 + @@ -121,12 +95,11 @@ 1828 1839 // [eval] 1829 1840 p: (_|_){ 1830 1841 // [eval] embed.fail4.p: field not allowed: ··· 1841 1852 } 1842 1853 } 1843 1854 #C4: (#struct){ 1844 - @@ -194,8 +168,7 @@ 1855 + @@ -198,8 +171,7 @@ 1845 1856 // [structural cycle] noStackOverflowStructCycle.list.tail: structural cycle 1846 1857 } 1847 1858 } ··· 1851 1862 t1: (struct){ 1852 1863 #a: (_|_){ 1853 1864 // [incomplete] provideIncompleteSuccess.t1.#a: incomplete bool: bool: 1854 - @@ -203,16 +176,12 @@ 1865 + @@ -207,16 +179,12 @@ 1855 1866 b: (bool){ bool } 1856 1867 } 1857 1868 x: (#struct){ ··· 1874 1885 #a: (#struct){ 1875 1886 c: (int){ 4 } 1876 1887 b: (bool){ true } 1877 - @@ -219,17 +188,8 @@ 1888 + @@ -223,17 +191,8 @@ 1878 1889 } 1879 1890 #c: (#struct){ 1880 1891 } ··· 1894 1905 } 1895 1906 b: (bool){ true } 1896 1907 } 1897 - @@ -259,9 +219,22 @@ 1908 + @@ -263,9 +222,22 @@ 1898 1909 } 1899 1910 cyclicError: (struct){ 1900 1911 a: (_|_){ ··· 1920 1931 } 1921 1932 } 1922 1933 midwayReferences: (struct){ 1923 - @@ -275,24 +248,9 @@ 1934 + @@ -279,24 +251,9 @@ 1924 1935 } 1925 1936 } 1926 1937 } ··· 1948 1959 } 1949 1960 closedCheck: (struct){ 1950 1961 success1: (struct){ 1951 - @@ -395,13 +353,7 @@ 1962 + @@ -399,13 +356,7 @@ 1952 1963 } 1953 1964 } 1954 1965 } ··· 1963 1974 #F: (#struct){ 1964 1975 e: (bool){ bool } 1965 1976 f: (_|_){ 1966 - @@ -418,17 +370,11 @@ 1977 + @@ -422,17 +373,11 @@ 1967 1978 } 1968 1979 } 1969 1980 E: (_|_){ ··· 1982 1993 } 1983 1994 } 1984 1995 derefDisj2: (struct){ 1985 - @@ -439,17 +385,11 @@ 1996 + @@ -443,17 +388,11 @@ 1986 1997 } 1987 1998 } 1988 1999 E: (_|_){ ··· 2001 2012 } 2002 2013 } 2003 2014 bulk1: (struct){ 2004 - @@ -572,9 +512,6 @@ 2015 + @@ -576,9 +515,6 @@ 2005 2016 // [eval] 2006 2017 e: (_|_){ 2007 2018 // [eval] structShare.err1.x.d.e: field not allowed: ··· 2011 2022 // ./in.cue:591:9 2012 2023 } 2013 2024 } 2014 - @@ -598,13 +535,13 @@ 2025 + @@ -602,13 +538,13 @@ 2015 2026 } 2016 2027 envs: (struct){ 2017 2028 e1: (#struct){ ··· 2029 2040 } 2030 2041 } 2031 2042 } 2032 - @@ -641,9 +578,8 @@ 2043 + @@ -645,9 +581,8 @@ 2033 2044 _c: (struct){ 2034 2045 y: (int){ 1 } 2035 2046 } ··· 2041 2052 } 2042 2053 } 2043 2054 errorPropagation: (_|_){ 2044 - @@ -701,10 +637,10 @@ 2055 + @@ -705,10 +640,10 @@ 2045 2056 } 2046 2057 foo: (#struct){ 2047 2058 kind: (string){ "foo" } ··· 2054 2065 } 2055 2066 } 2056 2067 regular: (_|_){ 2057 - @@ -717,16 +653,11 @@ 2068 + @@ -721,16 +656,11 @@ 2058 2069 foo: (_|_){ 2059 2070 // [eval] 2060 2071 kind: (string){ "foo" } ··· 2073 2084 } 2074 2085 } 2075 2086 } 2076 - @@ -738,10 +669,10 @@ 2087 + @@ -742,10 +672,10 @@ 2077 2088 } 2078 2089 foo: (#struct){ 2079 2090 kind: (string){ "foo" } ··· 2086 2097 } 2087 2098 } 2088 2099 } 2089 - @@ -800,12 +731,7 @@ 2090 - #sub2?: (bool){ bool } 2091 - } 2092 - } 2093 - - root: ((null|struct)){ |((null){ 2094 - - null 2095 - - sub1?: (struct){ 2096 - - #sub2: (bool){ true } 2097 - - } 2098 - - }, (#struct){ 2099 - + root: ((null|struct)){ |((null){ null }, (#struct){ 2100 - sub1?: (#struct){ 2101 - #sub2: (bool){ true } 2102 - } 2103 - @@ -833,12 +759,7 @@ 2104 - #sub2?: (bool){ bool } 2105 - } 2106 - } 2107 - - root: ((null|struct)){ |((null){ 2108 - - null 2109 - - #sub1?: (#struct){ 2110 - - #sub2: (bool){ true } 2111 - - } 2112 - - }, (#struct){ 2113 - + root: ((null|struct)){ |((null){ null }, (#struct){ 2114 - #sub1?: (#struct){ 2115 - #sub2: (bool){ true } 2116 - } 2117 - @@ -851,12 +772,7 @@ 2100 + @@ -816,7 +746,6 @@ 2101 + root: (_|_){ 2102 + // [eval] issue3729.withoutDisjunction.root.#sub1.#sub2: conflicting values null and {#sub1?:{#sub2:true}} (mismatched types null and struct): 2103 + // ./issue3729.cue:9:9 2104 + - // ./issue3729.cue:10:2 2105 + // ./issue3729.cue:11:9 2106 + #sub1?: (#struct){ 2107 + #sub2: (bool){ true } 2108 + @@ -850,12 +779,7 @@ 2118 2109 #sub2?: (bool){ bool } 2119 2110 } 2120 2111 } ··· 2128 2119 #sub1?: (#struct){ 2129 2120 #sub2: (bool){ true } 2130 2121 } 2131 - @@ -865,14 +781,7 @@ 2122 + @@ -864,14 +788,7 @@ 2132 2123 } 2133 2124 full: (struct){ 2134 2125 #Application: (#struct){ ··· 2144 2135 } 2145 2136 #ApplicationSpec: (#struct){ 2146 2137 syncPolicy?: ((null|struct)){ |((null){ null }, (#struct){ 2147 - @@ -894,12 +803,12 @@ 2148 - } 2149 - argoApp: (#struct){ 2150 - spec: (#struct){ 2151 - - syncPolicy: (#struct){ 2152 - - automated: (#struct){ 2153 - - prune: (bool){ true } 2154 - - selfHeal: (bool){ true } 2155 - - } 2156 - - } 2157 - + syncPolicy: ((null|struct)){ |((null){ null }, (#struct){ 2158 - + automated: (#struct){ 2159 - + prune: (bool){ true } 2160 - + selfHeal: (bool){ true } 2161 - + } 2162 - + }) } 2163 - _syncpolicy: (string){ "selfhealprune" } 2164 - } 2165 - } 2166 2138 -- out/evalalpha/stats -- 2167 2139 Leaks: 620 2168 2140 Freed: 0 ··· 2178 2150 --- old 2179 2151 +++ new 2180 2152 @@ -1,9 +1,9 @@ 2181 - -Leaks: 17 2182 - -Freed: 564 2183 - -Reused: 551 2184 - -Allocs: 30 2153 + -Leaks: 63 2154 + -Freed: 518 2155 + -Reused: 510 2156 + -Allocs: 71 2185 2157 -Retain: 107 2186 2158 +Leaks: 620 2187 2159 +Freed: 0 ··· 2196 2168 +Conjuncts: 943 2197 2169 +Disjuncts: 28 2198 2170 -- out/eval/stats -- 2199 - Leaks: 17 2200 - Freed: 564 2201 - Reused: 551 2202 - Allocs: 30 2171 + Leaks: 63 2172 + Freed: 518 2173 + Reused: 510 2174 + Allocs: 71 2203 2175 Retain: 107 2204 2176 2205 2177 Unifications: 545 ··· 2233 2205 ./issue3535.cue:21:3 2234 2206 ./issue3535.cue:22:4 2235 2207 ./issue3535.cue:25:7 2208 + issue3729.withoutDisjunction.root.#sub1.#sub2: conflicting values null and {#sub1?:{#sub2:true}} (mismatched types null and struct): 2209 + ./issue3729.cue:9:9 2210 + ./issue3729.cue:10:2 2211 + ./issue3729.cue:11:9 2236 2212 noStackOverflowStructCycle.#list.tail: structural cycle 2237 2213 noStackOverflowStructCycle.list.tail: structural cycle 2238 2214 provideIncompleteSuccess.t2.a.c.d: field not allowed: ··· 3007 2983 } 3008 2984 } 3009 2985 } 3010 - issue3729: (struct){ 2986 + issue3729: (_|_){ 2987 + // [eval] 3011 2988 withDisjunction: (struct){ 3012 2989 #Root: (#struct){ 3013 2990 sub1?: (#struct){ 3014 2991 #sub2?: (bool){ bool } 3015 2992 } 3016 2993 } 3017 - root: ((null|struct)){ |((null){ 3018 - null 3019 - sub1?: (struct){ 3020 - #sub2: (bool){ true } 3021 - } 3022 - }, (#struct){ 3023 - sub1?: (#struct){ 3024 - #sub2: (bool){ true } 3025 - } 3026 - }) } 2994 + root: (#struct){ 2995 + sub1?: (#struct){ 2996 + #sub2: (bool){ true } 2997 + } 2998 + } 3027 2999 } 3028 - withoutDisjunction: (struct){ 3029 - root: (null){ 3030 - null 3000 + withoutDisjunction: (_|_){ 3001 + // [eval] 3002 + root: (_|_){ 3003 + // [eval] issue3729.withoutDisjunction.root.#sub1.#sub2: conflicting values null and {#sub1?:{#sub2:true}} (mismatched types null and struct): 3004 + // ./issue3729.cue:9:9 3005 + // ./issue3729.cue:10:2 3006 + // ./issue3729.cue:11:9 3031 3007 #sub1?: (#struct){ 3032 3008 #sub2: (bool){ true } 3033 3009 } ··· 3047 3023 #sub2?: (bool){ bool } 3048 3024 } 3049 3025 } 3050 - root: ((null|struct)){ |((null){ 3051 - null 3052 - #sub1?: (#struct){ 3053 - #sub2: (bool){ true } 3054 - } 3055 - }, (#struct){ 3056 - #sub1?: (#struct){ 3057 - #sub2: (bool){ true } 3058 - } 3059 - }) } 3026 + root: (#struct){ 3027 + #sub1?: (#struct){ 3028 + #sub2: (bool){ true } 3029 + } 3030 + } 3060 3031 } 3061 3032 withEmbed: (struct){ 3062 3033 incomplete: (struct){
+4 -4
cue/testdata/cycle/compbottom2.txtar
··· 281 281 } 282 282 } 283 283 -- out/eval/stats -- 284 - Leaks: 1 285 - Freed: 158 286 - Reused: 149 287 - Allocs: 10 284 + Leaks: 15 285 + Freed: 144 286 + Reused: 138 287 + Allocs: 21 288 288 Retain: 67 289 289 290 290 Unifications: 159
+4 -4
cue/testdata/cycle/freeze.txtar
··· 141 141 } 142 142 } 143 143 -- out/eval/stats -- 144 - Leaks: 0 145 - Freed: 72 146 - Reused: 64 147 - Allocs: 8 144 + Leaks: 14 145 + Freed: 58 146 + Reused: 51 147 + Allocs: 21 148 148 Retain: 15 149 149 150 150 Unifications: 72
+4 -4
cue/testdata/eval/comprehensions.txtar
··· 119 119 } 120 120 } 121 121 -- out/eval/stats -- 122 - Leaks: 4 123 - Freed: 77 124 - Reused: 69 125 - Allocs: 12 122 + Leaks: 9 123 + Freed: 72 124 + Reused: 66 125 + Allocs: 15 126 126 Retain: 19 127 127 128 128 Unifications: 81
+5 -5
cue/testdata/eval/issue2235.txtar
··· 100 100 101 101 clusters: foo: {} 102 102 -- out/eval/stats -- 103 - Leaks: 3 104 - Freed: 101 105 - Reused: 84 106 - Allocs: 20 107 - Retain: 72 103 + Leaks: 20 104 + Freed: 84 105 + Reused: 79 106 + Allocs: 25 107 + Retain: 68 108 108 109 109 Unifications: 104 110 110 Conjuncts: 271
+8 -8
cue/testdata/eval/letjoin.txtar
··· 146 146 --- old 147 147 +++ new 148 148 @@ -1,9 +1,9 @@ 149 - -Leaks: 24 150 - -Freed: 219 151 - -Reused: 207 152 - -Allocs: 36 149 + -Leaks: 28 150 + -Freed: 215 151 + -Reused: 203 152 + -Allocs: 40 153 153 -Retain: 160 154 154 +Leaks: 212 155 155 +Freed: 0 ··· 164 164 +Conjuncts: 353 165 165 +Disjuncts: 36 166 166 -- out/eval/stats -- 167 - Leaks: 24 168 - Freed: 219 169 - Reused: 207 170 - Allocs: 36 167 + Leaks: 28 168 + Freed: 215 169 + Reused: 203 170 + Allocs: 40 171 171 Retain: 160 172 172 173 173 Unifications: 167
+2 -2
cue/testdata/resolve/047_struct_comprehensions.txtar
··· 76 76 } 77 77 } 78 78 -- out/eval/stats -- 79 - Leaks: 2 80 - Freed: 12 79 + Leaks: 3 80 + Freed: 11 81 81 Reused: 7 82 82 Allocs: 7 83 83 Retain: 2
+28 -3
internal/core/adt/comprehension.go
··· 157 157 ci.closeInfo.span |= ComprehensionSpan 158 158 } 159 159 160 + node := n.node.DerefDisjunct() 161 + 160 162 var decls []Decl 161 163 switch v := ToExpr(x).(type) { 162 164 case *StructLit: 165 + kind := TopKind 163 166 numFixed := 0 164 167 var fields []Decl 165 168 for _, d := range v.Decls { ··· 167 170 case *Field: 168 171 numFixed++ 169 172 173 + if f.Label.IsInt() { 174 + kind &= ListKind 175 + } else if f.Label.IsString() { 176 + kind &= StructKind 177 + } 178 + 170 179 // Create partial comprehension 171 180 c := &Comprehension{ 172 181 Syntax: c.Syntax, ··· 176 185 177 186 comp: ec, 178 187 parent: c, 179 - arc: n.node, 188 + arc: node, 180 189 } 181 190 182 191 conjunct := MakeConjunct(env, c, ci) ··· 203 212 204 213 comp: ec, 205 214 parent: c, 206 - arc: n.node, 215 + arc: node, 207 216 } 208 217 209 218 conjunct := MakeConjunct(env, c, ci) ··· 236 245 Decls: fields, 237 246 } 238 247 } 239 - n.node.AddStruct(st, env, ci) 248 + node.AddStruct(st, env, ci) 240 249 switch { 241 250 case !ec.done: 242 251 ec.structs = append(ec.structs, st) 243 252 case len(ec.envs) > 0: 244 253 st.Init(n.ctx) 254 + if kind == StructKind || kind == ListKind { 255 + n.updateNodeType(kind, st, ci) 256 + } 245 257 } 246 258 } 247 259 260 + c.kind = kind 261 + 248 262 switch numFixed { 249 263 case 0: 250 264 // Add comprehension as is. 251 265 252 266 case len(v.Decls): 253 267 // No comprehension to add at this level. 268 + // The should be considered a struct if it has only non-regular 269 + // fields (like definitions), and no embeddings. 270 + if kind == TopKind { 271 + c.kind = StructKind 272 + } 254 273 return 255 274 256 275 default: ··· 460 479 ctx.current().err = b 461 480 ctx.current().state = taskFAILED 462 481 return nil 482 + } 483 + if k := c.kind; k == StructKind || k == ListKind { 484 + v := v.DerefDisjunct() 485 + if s := v.getBareState(n.ctx); s != nil { 486 + s.updateNodeType(k, ToExpr(c.Value), d.id) 487 + } 463 488 } 464 489 v = c.arc 465 490 }
+3
internal/core/adt/expr.go
··· 2000 2000 // The type of field as which the comprehension is added. 2001 2001 arcType ArcType 2002 2002 2003 + // Kind indicates the possible kind of Value. 2004 + kind Kind 2005 + 2003 2006 // The node into which the comprehension is added. Upon a successful 2004 2007 // completion of the comprehension, the arcType should be updated in this 2005 2008 // node.
+8 -8
tools/flow/testdata/issue2559.txtar
··· 59 59 text: "5" 60 60 } 61 61 -- out/run/t1/stats -- 62 - Leaks: 0 63 - Freed: 25574 64 - Reused: 25554 65 - Allocs: 20 62 + Leaks: 35 63 + Freed: 25539 64 + Reused: 25523 65 + Allocs: 51 66 66 Retain: 337 67 67 68 68 Unifications: 18344 69 69 Conjuncts: 76391 70 70 Disjuncts: 25823 71 71 -- out/run/stats/totals -- 72 - Leaks: 0 73 - Freed: 25574 74 - Reused: 25554 75 - Allocs: 20 72 + Leaks: 35 73 + Freed: 25539 74 + Reused: 25523 75 + Allocs: 51 76 76 Retain: 337 77 77 78 78 Unifications: 18344