From 2d415ca12b7f4511c6634b833ed1a6dcdf9f76fc Mon Sep 17 00:00:00 2001 From: Ratmir Karabut Date: Thu, 23 Jan 2025 22:10:44 +0300 Subject: [PATCH] feat(ssa): Expand feature set of the Brillig constraint check (#7060) Co-authored-by: Michael J Klein Co-authored-by: rkarabut Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- Cargo.lock | 499 +++++++------ .../check_for_underconstrained_values.rs | 688 ++++++++++++++---- .../src/main.nr | 2 + 3 files changed, 779 insertions(+), 410 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e82d47d690a..f72a458d5ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -240,19 +240,20 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "ark-bls12-381" @@ -318,7 +319,7 @@ dependencies = [ "ark-std 0.5.0", "educe", "fnv", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "itertools 0.13.0", "num-bigint", "num-integer", @@ -383,7 +384,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -409,7 +410,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -449,7 +450,7 @@ dependencies = [ "ark-std 0.5.0", "educe", "fnv", - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -496,7 +497,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -541,7 +542,7 @@ dependencies = [ "bstr", "doc-comment", "libc", - "predicates 3.1.2", + "predicates 3.1.3", "predicates-core", "predicates-tree", "wait-timeout", @@ -556,7 +557,7 @@ dependencies = [ "anstyle", "doc-comment", "globwalk", - "predicates 3.1.2", + "predicates 3.1.3", "predicates-core", "predicates-tree", "tempfile", @@ -584,13 +585,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.83" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -682,9 +683,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" [[package]] name = "bitmaps" @@ -729,9 +730,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" +checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e" dependencies = [ "arrayref", "arrayvec", @@ -801,12 +802,12 @@ dependencies = [ [[package]] name = "bstr" -version = "1.10.0" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" dependencies = [ "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "serde", ] @@ -829,9 +830,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" @@ -841,9 +842,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cast" @@ -853,9 +854,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.36" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "shlex", ] @@ -874,9 +875,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -916,9 +917,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", "clap_derive", @@ -934,9 +935,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstream", "anstyle", @@ -946,30 +947,30 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.37" +version = "4.5.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11611dca53440593f38e6b25ec629de50b14cdfa63adc0fb856115a2c6d97595" +checksum = "33a7e468e750fa4b6be660e8b5651ad47372e8fb114030b594c2d75d48c5ffd0" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clipboard-win" @@ -1065,14 +1066,14 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "console" -version = "0.15.8" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" dependencies = [ - "encode_unicode 0.3.6", - "lazy_static", + "encode_unicode", "libc", - "windows-sys 0.52.0", + "once_cell", + "windows-sys 0.59.0", ] [[package]] @@ -1099,18 +1100,18 @@ checksum = "3618cccc083bb987a415d85c02ca6c9994ea5b44731ec28b9ecf09658655fba9" [[package]] name = "const_format" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" +checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" dependencies = [ "proc-macro2", "quote", @@ -1159,9 +1160,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -1213,18 +1214,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -1241,9 +1242,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -1275,9 +1276,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ "csv-core", "itoa", @@ -1326,7 +1327,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -1337,7 +1338,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -1460,7 +1461,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -1505,7 +1506,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -1534,12 +1535,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - [[package]] name = "encode_unicode" version = "1.0.0" @@ -1569,23 +1564,23 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "env_filter" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", ] [[package]] name = "env_logger" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" dependencies = [ "env_filter", "log", @@ -1608,7 +1603,7 @@ checksum = "3bf679796c0322556351f287a51b49e48f7c4986e727b5dd78c972d30e2e16cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -1619,12 +1614,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1649,9 +1644,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fd-lock" @@ -1736,12 +1731,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide 0.8.3", ] [[package]] @@ -1852,7 +1847,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -1925,9 +1920,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "globset" @@ -1938,7 +1933,7 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -1948,7 +1943,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "ignore", "walkdir", ] @@ -2001,7 +1996,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.6.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -2064,9 +2059,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", @@ -2094,12 +2089,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hermit-abi" version = "0.4.0" @@ -2190,9 +2179,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.3" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", "http", @@ -2369,7 +2358,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -2409,7 +2398,7 @@ dependencies = [ "globset", "log", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "same-file", "walkdir", "winapi-util", @@ -2473,12 +2462,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "serde", ] @@ -2494,7 +2483,7 @@ dependencies = [ "crossbeam-utils", "dashmap", "env_logger", - "indexmap 2.6.0", + "indexmap 2.7.0", "is-terminal", "itoa", "log", @@ -2540,7 +2529,7 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi", "libc", "windows-sys 0.52.0", ] @@ -2575,9 +2564,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jni" @@ -2681,7 +2670,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -2795,9 +2784,9 @@ checksum = "82903360c009b816f5ab72a9b68158c27c301ee2c3f20655b55c5e589e7d3bb7" [[package]] name = "libc" -version = "0.2.162" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libredox" @@ -2805,7 +2794,7 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "libc", "redox_syscall 0.4.1", ] @@ -2816,9 +2805,9 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.8", ] [[package]] @@ -2835,15 +2824,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" @@ -2857,9 +2846,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "louds-rs" @@ -2876,7 +2865,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -2955,9 +2944,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", ] @@ -2976,11 +2965,10 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", @@ -3436,7 +3424,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "crossbeam-channel", "filetime", "fsevent-sys", @@ -3628,7 +3616,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.8", "smallvec", "windows-targets 0.52.6", ] @@ -3682,7 +3670,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.6.0", + "indexmap 2.7.0", ] [[package]] @@ -3731,29 +3719,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -3859,9 +3847,9 @@ dependencies = [ [[package]] name = "predicates" -version = "3.1.2" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" dependencies = [ "anstyle", "difflib", @@ -3870,15 +3858,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" [[package]] name = "predicates-tree" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" dependencies = [ "predicates-core", "termtree", @@ -3891,7 +3879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" dependencies = [ "csv", - "encode_unicode 1.0.0", + "encode_unicode", "is-terminal", "lazy_static", "term", @@ -3915,9 +3903,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -3930,7 +3918,7 @@ checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.6.0", + "bitflags 2.7.0", "lazy_static", "num-traits", "rand", @@ -3944,13 +3932,13 @@ dependencies = [ [[package]] name = "proptest-derive" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77" +checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -3970,9 +3958,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -4078,11 +4066,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", ] [[package]] @@ -4110,7 +4098,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -4125,9 +4113,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -4220,7 +4208,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.87", + "syn 2.0.96", "walkdir", ] @@ -4263,22 +4251,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.39" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "rustls" -version = "0.23.20" +version = "0.23.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" +checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" dependencies = [ "log", "once_cell", @@ -4357,9 +4345,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "rusty-fork" @@ -4516,7 +4504,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "core-foundation", "core-foundation-sys", "libc", @@ -4526,9 +4514,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -4536,15 +4524,15 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] @@ -4585,20 +4573,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", @@ -4614,7 +4602,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -4628,15 +4616,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.11.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_derive", "serde_json", @@ -4646,14 +4634,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.11.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -4799,9 +4787,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -4902,9 +4890,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "symbolic-common" -version = "12.12.1" +version = "12.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d4d73159efebfb389d819fd479afb2dbd57dcb3e3f4b7fcfa0e675f5a46c1cb" +checksum = "8150eae9699e3c73a3e6431dc1f80d87748797c0457336af23e94c1de619ed24" dependencies = [ "debugid", "memmap2", @@ -4914,9 +4902,9 @@ dependencies = [ [[package]] name = "symbolic-demangle" -version = "12.12.1" +version = "12.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a767859f6549c665011970874c3f541838b4835d5aaaa493d3ee383918be9f10" +checksum = "95f4a9846f7a8933b6d198c022faa2c9bd89e1a970bed9d9a98d25708bf8de17" dependencies = [ "cpp_demangle", "rustc-demangle", @@ -4936,9 +4924,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -4953,7 +4941,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -4964,12 +4952,13 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", "fastrand", + "getrandom", "once_cell", "rustix", "windows-sys 0.59.0", @@ -5009,9 +4998,9 @@ dependencies = [ [[package]] name = "termtree" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "test-case" @@ -5031,7 +5020,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -5042,7 +5031,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", "test-case-core", ] @@ -5069,22 +5058,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -5099,9 +5088,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -5120,9 +5109,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -5150,14 +5139,14 @@ dependencies = [ [[package]] name = "tokio" -version = "1.42.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", "libc", - "mio 1.0.2", + "mio 1.0.3", "pin-project-lite", "socket2", "tokio-macros", @@ -5166,13 +5155,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -5199,9 +5188,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -5238,7 +5227,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -5251,9 +5240,9 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "toml_datetime", - "winnow 0.6.20", + "winnow 0.6.24", ] [[package]] @@ -5285,9 +5274,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -5309,20 +5298,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -5330,9 +5319,9 @@ dependencies = [ [[package]] name = "tracing-error" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", "tracing-subscriber", @@ -5351,9 +5340,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ "serde", "tracing-core", @@ -5361,9 +5350,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -5398,7 +5387,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -5443,9 +5432,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-linebreak" @@ -5509,9 +5498,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" [[package]] name = "valuable" @@ -5607,7 +5596,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", "wasm-bindgen-shared", ] @@ -5641,7 +5630,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5894,9 +5883,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.20" +version = "0.6.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" dependencies = [ "memchr", ] @@ -5924,9 +5913,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -5936,13 +5925,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", "synstructure", ] @@ -5964,27 +5953,27 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", "synstructure", ] @@ -6005,7 +5994,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -6027,7 +6016,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] diff --git a/compiler/noirc_evaluator/src/ssa/checks/check_for_underconstrained_values.rs b/compiler/noirc_evaluator/src/ssa/checks/check_for_underconstrained_values.rs index f44f726bfc7..24ad67c3b69 100644 --- a/compiler/noirc_evaluator/src/ssa/checks/check_for_underconstrained_values.rs +++ b/compiler/noirc_evaluator/src/ssa/checks/check_for_underconstrained_values.rs @@ -13,6 +13,10 @@ use rayon::prelude::*; use std::collections::{BTreeMap, BTreeSet, HashSet}; use tracing::trace; +/// The number of instructions that have to be passed to stop +/// following a Brillig call, with assumption it wouldn't get constrained +const BRILLIG_CONSTRAINT_SEARCH_DEPTH: usize = 1000; + impl Ssa { /// This function provides an SSA pass that detects if the final function has any subgraphs independent from inputs and outputs. /// If this is the case, then part of the final circuit can be completely replaced by any other passing circuit, since there are no constraints ensuring connections. @@ -79,7 +83,7 @@ fn check_for_underconstrained_values_within_function( let connected_sets_indices = context.find_sets_connected_to_function_inputs_or_outputs(function); - // Go through each disconnected set, find brillig calls that caused it and form warnings + // Go through each disconnected set, find Brillig calls that caused it and form warnings for set_index in BTreeSet::from_iter(0..(context.value_sets.len())).difference(&connected_sets_indices) { @@ -99,12 +103,20 @@ struct DependencyContext { block_queue: Vec, // Map keeping track of values stored at memory locations memory_slots: HashMap, - // Map of values resulting from array get instructions - // to the actual array values - array_elements: HashMap, - // Map of brillig call ids to sets of the value ids descending + // Value currently affecting every instruction (i.e. being + // considered a parent of every value id met) because + // of its involvement in an EnableSideEffectsIf condition + side_effects_condition: Option, + // Map of Brillig call ids to sets of the value ids descending // from their arguments and results tainted: BTreeMap, + // Map of argument value ids to the Brillig call ids employing them + call_arguments: HashMap>, + // Maintains count of calls being tracked + tracking_count: usize, + // Map of block indices to Brillig call ids that should not be + // followed after meeting them + search_limits: HashMap, } /// Structure keeping track of value ids descending from Brillig calls' @@ -116,8 +128,12 @@ struct BrilligTaintedIds { arguments: HashSet, // Results status results: Vec, - // Initial result value ids + // Indices of the array elements in the results vector + array_elements: HashMap>, + // Initial result value ids, along with element ids for arrays root_results: HashSet, + // The flag signaling that the call should be now tracked + tracking: bool, } #[derive(Clone, Debug)] @@ -128,17 +144,60 @@ enum ResultStatus { } impl BrilligTaintedIds { - fn new(arguments: &[ValueId], results: &[ValueId]) -> Self { + fn new(function: &Function, arguments: &[ValueId], results: &[ValueId]) -> Self { + // Exclude numeric constants + let arguments: Vec = arguments + .iter() + .filter(|value| function.dfg.get_numeric_constant(**value).is_none()) + .copied() + .map(|value| function.dfg.resolve(value)) + .collect(); + let results: Vec = results + .iter() + .filter(|value| function.dfg.get_numeric_constant(**value).is_none()) + .copied() + .map(|value| function.dfg.resolve(value)) + .collect(); + + let mut results_status: Vec = vec![]; + let mut array_elements: HashMap> = HashMap::new(); + + for result in &results { + match function.dfg.try_get_array_length(*result) { + // If the result value is an array, create an empty descendant set for + // every element to be accessed further on and record the indices + // of the resulting sets for future reference + Some(length) => { + array_elements.insert(*result, vec![]); + for _ in 0..length { + array_elements[result].push(results_status.len()); + results_status + .push(ResultStatus::Unconstrained { descendants: HashSet::new() }); + } + } + // Otherwise initialize a descendant set with the current value + None => { + results_status.push(ResultStatus::Unconstrained { + descendants: HashSet::from([*result]), + }); + } + } + } + BrilligTaintedIds { arguments: HashSet::from_iter(arguments.iter().copied()), - results: results - .iter() - .map(|result| ResultStatus::Unconstrained { descendants: HashSet::from([*result]) }) - .collect(), + results: results_status, + array_elements, root_results: HashSet::from_iter(results.iter().copied()), + tracking: false, } } + /// Check if the call being tracked is a simple wrapper of another call + fn is_wrapper(&self, other: &BrilligTaintedIds) -> bool { + other.root_results == self.arguments + } + /// Add children of a given parent to the tainted value set /// (for arguments one set is enough, for results we keep them /// separate as the forthcoming check considers the call covered @@ -147,12 +206,11 @@ impl BrilligTaintedIds { if self.arguments.intersection(parents).next().is_some() { self.arguments.extend(children); } - for result_status in &mut self.results.iter_mut() { - match result_status { + + for result in &mut self.results.iter_mut() { + match result { // Skip updating results already found covered - ResultStatus::Constrained => { - continue; - } + ResultStatus::Constrained => {} ResultStatus::Unconstrained { descendants } => { if descendants.intersection(parents).next().is_some() { descendants.extend(children); @@ -162,6 +220,20 @@ impl BrilligTaintedIds { } } + /// Update children of all the results (helper function for + /// chained Brillig call handling) + fn update_results_children(&mut self, children: &[ValueId]) { + for result in &mut self.results.iter_mut() { + match result { + // Skip updating results already found covered + ResultStatus::Constrained => {} + ResultStatus::Unconstrained { descendants } => { + descendants.extend(children); + } + } + } + } + /// If Brillig call is properly constrained by the given ids, return true fn check_constrained(&self) -> bool { // If every result has now been constrained, @@ -181,9 +253,7 @@ impl BrilligTaintedIds { for (i, result_status) in self.results.iter().enumerate() { match result_status { // Skip checking already covered results - ResultStatus::Constrained => { - continue; - } + ResultStatus::Constrained => {} ResultStatus::Unconstrained { descendants } => { if descendants.intersection(constrained_values).next().is_some() { results_involved.push(i); @@ -205,6 +275,21 @@ impl BrilligTaintedIds { results_involved.iter().for_each(|i| self.results[*i] = ResultStatus::Constrained); } } + + /// When an ArrayGet instruction occurs, place the resulting ValueId into + /// the corresponding sets of the call's array element result values + fn process_array_get(&mut self, array: ValueId, index: usize, element_results: &[ValueId]) { + if let Some(element_indices) = self.array_elements.get(&array) { + if let Some(result_index) = element_indices.get(index) { + if let Some(ResultStatus::Unconstrained { descendants }) = + self.results.get_mut(*result_index) + { + descendants.extend(element_results); + self.root_results.extend(element_results); + } + } + } + } } impl DependencyContext { @@ -231,9 +316,57 @@ impl DependencyContext { ) { trace!("processing instructions of block {} of function {}", block, function.id()); - for instruction in function.dfg[block].instructions() { + // First, gather information on all Brillig calls in the block + // to be able to follow their arguments first appearing in the + // flow graph before the calls themselves + function.dfg[block].instructions().iter().enumerate().for_each( + |(block_index, instruction)| { + if let Instruction::Call { func, arguments } = &function.dfg[*instruction] { + if let Value::Function(callee) = &function.dfg[*func] { + if all_functions[&callee].runtime().is_brillig() { + let results = function.dfg.instruction_results(*instruction); + let current_tainted = + BrilligTaintedIds::new(function, arguments, results); + + // Record arguments/results for each Brillig call for the check. + // + // Do not track Brillig calls acting as simple wrappers over + // another registered Brillig call, update the tainted sets of + // the wrapped call instead + let mut wrapped_call_found = false; + for (_, tainted_call) in self.tainted.iter_mut() { + if current_tainted.is_wrapper(tainted_call) { + tainted_call.update_results_children(results); + wrapped_call_found = true; + break; + } + } + + if !wrapped_call_found { + // Record the current call, remember the argument values involved + self.tainted.insert(*instruction, current_tainted); + arguments.iter().for_each(|value| { + self.call_arguments + .entry(*value) + .or_default() + .push(*instruction); + }); + + // Set the constraint search limit for the call + self.search_limits.insert( + block_index + BRILLIG_CONSTRAINT_SEARCH_DEPTH, + *instruction, + ); + } + } + } + } + }, + ); + + //Then, go over the instructions + for (block_index, instruction) in function.dfg[block].instructions().iter().enumerate() { let mut arguments = Vec::new(); - let mut results = Vec::new(); // Collect non-constant instruction arguments function.dfg[*instruction].for_each_value(|value_id| { @@ -242,137 +375,172 @@ impl DependencyContext { } }); - // Collect non-constant instruction results - for value_id in function.dfg.instruction_results(*instruction).iter() { - if function.dfg.get_numeric_constant(*value_id).is_none() { - results.push(function.dfg.resolve(*value_id)); + // Start tracking calls when their argument value ids first appear, + // or when their instruction id comes up (in case there were + // no non-constant arguments) + for argument in &arguments { + if let Some(calls) = self.call_arguments.get(argument) { + for call in calls { + if let Some(tainted_ids) = self.tainted.get_mut(call) { + tainted_ids.tracking = true; + self.tracking_count += 1; + } + } } } + if let Some(tainted_ids) = self.tainted.get_mut(instruction) { + tainted_ids.tracking = true; + self.tracking_count += 1; + } - // Process instructions - match &function.dfg[*instruction] { - // For memory operations, we have to link up the stored value as a parent - // of one loaded from the same memory slot - Instruction::Store { address, value } => { - self.memory_slots.insert(*address, function.dfg.resolve(*value)); + // Stop tracking calls when their search limit is hit + if let Some(call) = self.search_limits.get(&block_index) { + if let Some(tainted_ids) = self.tainted.get_mut(call) { + tainted_ids.tracking = false; + self.tracking_count -= 1; } - Instruction::Load { address } => { - // Recall the value stored at address as parent for the results - if let Some(value_id) = self.memory_slots.get(address) { - self.update_children(&[*value_id], &results); - } else { - panic!("load instruction {} has attempted to access previously unused memory location", - instruction); + } + + // We can skip over instructions while nothing is being tracked + if self.tracking_count > 0 { + let mut results = Vec::new(); + + // Collect non-constant instruction results + for value_id in function.dfg.instruction_results(*instruction).iter() { + if function.dfg.get_numeric_constant(*value_id).is_none() { + results.push(function.dfg.resolve(*value_id)); } } - // Check the constrain instruction arguments against those - // involved in Brillig calls, remove covered calls - Instruction::Constrain(value_id1, value_id2, _) - | Instruction::ConstrainNotEqual(value_id1, value_id2, _) => { - self.clear_constrained( - &[function.dfg.resolve(*value_id1), function.dfg.resolve(*value_id2)], - function, - ); - } - // Consider range check to also be constraining - Instruction::RangeCheck { value, .. } => { - self.clear_constrained(&[function.dfg.resolve(*value)], function); - } - Instruction::Call { func: func_id, .. } => { - // For functions, we remove the first element of arguments, - // as .for_each_value() used previously also includes func_id - arguments.remove(0); - match &function.dfg[*func_id] { - Value::Intrinsic(intrinsic) => match intrinsic { - Intrinsic::ApplyRangeConstraint | Intrinsic::AssertConstant => { - // Consider these intrinsic arguments constrained - self.clear_constrained(&arguments, function); - } - Intrinsic::AsWitness | Intrinsic::IsUnconstrained => { - // These intrinsics won't affect the dependency graph + match &function.dfg[*instruction] { + // For memory operations, we have to link up the stored value as a parent + // of one loaded from the same memory slot + Instruction::Store { address, value } => { + self.memory_slots.insert(*address, function.dfg.resolve(*value)); + } + Instruction::Load { address } => { + // Recall the value stored at address as parent for the results + if let Some(value_id) = self.memory_slots.get(address) { + self.update_children(&[*value_id], &results); + } else { + panic!("load instruction {} has attempted to access previously unused memory location", + instruction); + } + } + // Record the condition to set as future parent for the following values + Instruction::EnableSideEffectsIf { condition: value } => { + self.side_effects_condition = + match function.dfg.get_numeric_constant(*value) { + None => Some(function.dfg.resolve(*value)), + Some(_) => None, } - Intrinsic::ArrayLen - | Intrinsic::ArrayRefCount - | Intrinsic::ArrayAsStrUnchecked - | Intrinsic::AsSlice - | Intrinsic::BlackBox(..) - | Intrinsic::DerivePedersenGenerators - | Intrinsic::Hint(..) - | Intrinsic::SlicePushBack - | Intrinsic::SlicePushFront - | Intrinsic::SlicePopBack - | Intrinsic::SlicePopFront - | Intrinsic::SliceRefCount - | Intrinsic::SliceInsert - | Intrinsic::SliceRemove - | Intrinsic::StaticAssert - | Intrinsic::StrAsBytes - | Intrinsic::ToBits(..) - | Intrinsic::ToRadix(..) - | Intrinsic::FieldLessThan => { - // Record all the function arguments as parents of the results - self.update_children(&arguments, &results); + } + // Check the constrain instruction arguments against those + // involved in Brillig calls, remove covered calls + Instruction::Constrain(value_id1, value_id2, _) + | Instruction::ConstrainNotEqual(value_id1, value_id2, _) => { + self.clear_constrained( + &[function.dfg.resolve(*value_id1), function.dfg.resolve(*value_id2)], + function, + ); + } + // Consider range check to also be constraining + Instruction::RangeCheck { value, .. } => { + self.clear_constrained(&[function.dfg.resolve(*value)], function); + } + Instruction::Call { func: func_id, .. } => { + // For functions, we remove the first element of arguments, + // as .for_each_value() used previously also includes func_id + arguments.remove(0); + + match &function.dfg[*func_id] { + Value::Intrinsic(intrinsic) => match intrinsic { + Intrinsic::ApplyRangeConstraint | Intrinsic::AssertConstant => { + // Consider these intrinsic arguments constrained + self.clear_constrained(&arguments, function); + } + Intrinsic::AsWitness | Intrinsic::IsUnconstrained => { + // These intrinsics won't affect the dependency graph + } + Intrinsic::ArrayLen + | Intrinsic::ArrayRefCount + | Intrinsic::ArrayAsStrUnchecked + | Intrinsic::AsSlice + | Intrinsic::BlackBox(..) + | Intrinsic::DerivePedersenGenerators + | Intrinsic::Hint(..) + | Intrinsic::SlicePushBack + | Intrinsic::SlicePushFront + | Intrinsic::SlicePopBack + | Intrinsic::SlicePopFront + | Intrinsic::SliceRefCount + | Intrinsic::SliceInsert + | Intrinsic::SliceRemove + | Intrinsic::StaticAssert + | Intrinsic::StrAsBytes + | Intrinsic::ToBits(..) + | Intrinsic::ToRadix(..) + | Intrinsic::FieldLessThan => { + // Record all the function arguments as parents of the results + self.update_children(&arguments, &results); + } + }, + Value::Function(callee) => match all_functions[&callee].runtime() { + // Only update tainted sets for non-Brillig calls, as + // the chained Brillig case should already be covered + RuntimeType::Acir(..) => { + self.update_children(&arguments, &results); + } + RuntimeType::Brillig(..) => {} + }, + Value::ForeignFunction(..) => { + panic!("should not be able to reach foreign function from non-Brillig functions, {func_id} in function {}", function.name()); } - }, - Value::Function(callee) => match all_functions[callee].runtime() { - RuntimeType::Brillig(_) => { - // Record arguments/results for each Brillig call for the check - self.tainted.insert( - *instruction, - BrilligTaintedIds::new(&arguments, &results), + Value::Instruction { .. } + | Value::NumericConstant { .. } + | Value::Param { .. } + | Value::Global(_) => { + panic!( + "calling non-function value with ID {func_id} in function {}", + function.name() ); } - RuntimeType::Acir(..) => { - // Record all the function arguments as parents of the results - self.update_children(&arguments, &results); - } - }, - Value::ForeignFunction(..) => { - panic!("should not be able to reach foreign function from non-Brillig functions, {func_id} in function {}", function.name()); - } - Value::Instruction { .. } - | Value::NumericConstant { .. } - | Value::Param { .. } - | Value::Global(_) => { - panic!( - "calling non-function value with ID {func_id} in function {}", - function.name() - ); } } - } - // For array get operations, we link the resulting values to - // the corresponding array value ids - // (this is required later because for now we consider array elements - // being constrained as valid as the whole arrays being constrained) - Instruction::ArrayGet { array, .. } => { - for result in &results { - self.array_elements.insert(*result, function.dfg.resolve(*array)); + // For array get operations, we check the Brillig calls for + // results involving the array in question, to properly + // populate the array element tainted sets + Instruction::ArrayGet { array, index } => { + self.process_array_get(function, *array, *index, &results); + // Record all the used arguments as parents of the results + self.update_children(&arguments, &results); } - // Record all the used arguments as parents of the results - self.update_children(&arguments, &results); - } - Instruction::ArraySet { .. } - | Instruction::Binary(..) - | Instruction::Cast(..) - | Instruction::IfElse { .. } - | Instruction::Not(..) - | Instruction::Truncate { .. } => { - // Record all the used arguments as parents of the results - self.update_children(&arguments, &results); + Instruction::ArraySet { .. } + | Instruction::Binary(..) + | Instruction::Cast(..) + | Instruction::IfElse { .. } + | Instruction::Not(..) + | Instruction::Truncate { .. } => { + // Record all the used arguments as parents of the results + self.update_children(&arguments, &results); + } + // These instructions won't affect the dependency graph + Instruction::Allocate { .. } + | Instruction::DecrementRc { .. } + | Instruction::IncrementRc { .. } + | Instruction::MakeArray { .. } + | Instruction::Noop => {} } - // These instructions won't affect the dependency graph - Instruction::Allocate { .. } - | Instruction::DecrementRc { .. } - | Instruction::EnableSideEffectsIf { .. } - | Instruction::IncrementRc { .. } - | Instruction::Noop - | Instruction::MakeArray { .. } => {} } } - trace!("Number tainted Brillig calls: {}", self.tainted.len()); + if !self.tainted.is_empty() { + trace!( + "number of Brillig calls in function {} left unchecked: {}", + function, + self.tainted.len() + ); + } } /// Every Brillig call not properly constrained should remain in the tainted set @@ -382,6 +550,7 @@ impl DependencyContext { .tainted .keys() .map(|brillig_call| { + trace!("tainted structure for {}: {:?}", brillig_call, self.tainted[brillig_call]); SsaReport::Bug(InternalBug::UncheckedBrilligCall { call_stack: function.dfg.get_instruction_call_stack(*brillig_call), }) @@ -389,7 +558,7 @@ impl DependencyContext { .collect(); trace!( - "making {} under constrained reports for function {}", + "making {} reports on underconstrained Brillig calls for function {}", warnings.len(), function.name() ); @@ -398,9 +567,17 @@ impl DependencyContext { /// Update sets of value ids that can be traced back to the Brillig calls being tracked fn update_children(&mut self, parents: &[ValueId], children: &[ValueId]) { - let parents: HashSet<_> = HashSet::from_iter(parents.iter().copied()); + let mut parents: HashSet<_> = HashSet::from_iter(parents.iter().copied()); + + // Also include the current EnableSideEffectsIf condition in parents + // (as it would affect every following statement) + self.side_effects_condition.map(|v| parents.insert(v)); + + // Don't update sets for the calls not yet being tracked for (_, tainted_ids) in self.tainted.iter_mut() { - tainted_ids.update_children(&parents, children); + if tainted_ids.tracking { + tainted_ids.update_children(&parents, children); + } } } @@ -408,28 +585,44 @@ impl DependencyContext { /// by given values after recording partial constraints, if so stop tracking them fn clear_constrained(&mut self, constrained_values: &[ValueId], function: &Function) { // Remove numeric constants - let constrained_values = - constrained_values.iter().filter(|v| function.dfg.get_numeric_constant(**v).is_none()); - - // For now, consider array element constraints to be array constraints - // TODO(https://github.com/noir-lang/noir/issues/6698): - // This probably has to be further looked into, to ensure _every_ element - // of an array result of a Brillig call has been constrained let constrained_values: HashSet<_> = constrained_values - .map(|v| { - if let Some(parent_array) = self.array_elements.get(v) { - *parent_array - } else { - *v - } - }) + .iter() + .filter(|v| function.dfg.get_numeric_constant(**v).is_none()) + .copied() .collect(); - self.tainted.iter_mut().for_each(|(_, tainted_ids)| { - tainted_ids.store_partial_constraints(&constrained_values); - }); + // Skip untracked calls + for (_, tainted_ids) in self.tainted.iter_mut() { + if tainted_ids.tracking { + tainted_ids.store_partial_constraints(&constrained_values); + } + } + self.tainted.retain(|_, tainted_ids| !tainted_ids.check_constrained()); } + + /// Process ArrayGet instruction for tracked Brillig calls + fn process_array_get( + &mut self, + function: &Function, + array: ValueId, + index: ValueId, + element_results: &[ValueId], + ) { + use acvm::acir::AcirField; + + // Only allow numeric constant indices + if let Some(value) = function.dfg.get_numeric_constant(index) { + if let Some(index) = value.try_to_u32() { + // Skip untracked calls + for (_, tainted_ids) in self.tainted.iter_mut() { + if tainted_ids.tracking { + tainted_ids.process_array_get(array, index as usize, element_results); + } + } + } + } + } } #[derive(Default)] @@ -499,7 +692,7 @@ impl Context { function: &Function, ) -> Vec { let mut warnings = Vec::new(); - // Find brillig-generated values in the set + // Find Brillig-generated values in the set let intersection = all_brillig_generated_values.intersection(current_set).copied(); // Go through all Brillig outputs in the set @@ -1018,4 +1211,189 @@ mod test { let ssa_level_warnings = ssa.check_for_missing_brillig_constraints(); assert_eq!(ssa_level_warnings.len(), 2); } + + #[test] + #[traced_test] + /// Test EnableSideEffectsIf conditions affecting the dependency graph + /// (SSA a bit convoluted to work around simplification breaking the flow + /// of the parsed test code) + fn test_enable_side_effects_if_affecting_following_statements() { + let program = r#" + acir(inline) fn main f0 { + b0(v0: Field, v1: Field): + v3 = call f1(v0, v1) -> Field + v5 = add v0, v1 + v6 = eq v3, v5 + v7 = add u1 1, u1 0 + enable_side_effects v6 + v8 = add v7, u1 1 + enable_side_effects u1 1 + constrain v8 == u1 2 + return v3 + } + + brillig(inline) fn foo f1 { + b0(v0: Field, v1: Field): + v2 = add v0, v1 + return v2 + } + "#; + + let mut ssa = Ssa::from_str(program).unwrap(); + let ssa_level_warnings = ssa.check_for_missing_brillig_constraints(); + assert_eq!(ssa_level_warnings.len(), 0); + } + + #[test] + #[traced_test] + /// Test call result array elements being underconstrained + fn test_brillig_result_array_missing_element_constraint() { + let program = r#" + acir(inline) fn main f0 { + b0(v0: u32): + v16 = call f1(v0) -> [u32; 3] + v17 = array_get v16, index u32 0 -> u32 + constrain v17 == v0 + v19 = array_get v16, index u32 2 -> u32 + constrain v19 == v0 + return v17 + } + + brillig(inline) fn into_array f1 { + b0(v0: u32): + v4 = make_array [v0, v0, v0] : [u32; 3] + return v4 + } + "#; + + let mut ssa = Ssa::from_str(program).unwrap(); + let ssa_level_warnings = ssa.check_for_missing_brillig_constraints(); + assert_eq!(ssa_level_warnings.len(), 1); + } + + #[test] + #[traced_test] + /// Test call result array elements being constrained properly + fn test_brillig_result_array_all_elements_constrained() { + let program = r#" + acir(inline) fn main f0 { + b0(v0: u32): + v16 = call f1(v0) -> [u32; 3] + v17 = array_get v16, index u32 0 -> u32 + constrain v17 == v0 + v20 = array_get v16, index u32 1 -> u32 + constrain v20 == v0 + v19 = array_get v16, index u32 2 -> u32 + constrain v19 == v0 + return v17 + } + + brillig(inline) fn into_array f1 { + b0(v0: u32): + v4 = make_array [v0, v0, v0] : [u32; 3] + return v4 + } + "#; + + let mut ssa = Ssa::from_str(program).unwrap(); + let ssa_level_warnings = ssa.check_for_missing_brillig_constraints(); + assert_eq!(ssa_level_warnings.len(), 0); + } + + #[test] + #[traced_test] + /// Test chained (wrapper) Brillig calls not producing a false positive + fn test_chained_brillig_calls_constrained() { + /* + struct Animal { + legs: Field, + eyes: u8, + tag: Tag, + } + + struct Tag { + no: Field, + } + + unconstrained fn foo(x: Field) -> Animal { + Animal { + legs: 4, + eyes: 2, + tag: Tag { no: x } + } + } + + unconstrained fn bar(x: Animal) -> Animal { + Animal { + legs: x.legs, + eyes: x.eyes, + tag: Tag { no: x.tag.no + 1 } + } + } + + fn main(x: Field) -> pub Animal { + let dog = bar(foo(x)); + assert(dog.legs == 4); + assert(dog.eyes == 2); + assert(dog.tag.no == x + 1); + + dog + } + */ + + let program = r#" + acir(inline) fn main f0 { + b0(v0: Field): + v27, v28, v29 = call f2(v0) -> (Field, u8, Field) + v30, v31, v32 = call f1(v27, v28, v29) -> (Field, u8, Field) + constrain v30 == Field 4 + constrain v31 == u8 2 + v35 = add v0, Field 1 + constrain v32 == v35 + return v30, v31, v32 + } + + brillig(inline) fn foo f2 { + b0(v0: Field): + return Field 4, u8 2, v0 + } + + brillig(inline) fn bar f1 { + b0(v0: Field, v1: u8, v2: Field): + v7 = add v2, Field 1 + return v0, v1, v7 + } + + "#; + + let mut ssa = Ssa::from_str(program).unwrap(); + let ssa_level_warnings = ssa.check_for_missing_brillig_constraints(); + assert_eq!(ssa_level_warnings.len(), 0); + } + + #[test] + #[traced_test] + /// Test for the argument descendants coming before Brillig calls themselves being + /// registered as such + fn test_brillig_argument_descendants_preceding_call() { + let program = r#" + acir(inline) fn main f0 { + b0(v0: Field, v1: Field): + v3 = add v0, v1 + v5 = call f1(v0, v1) -> Field + constrain v3 == v5 + return v3 + } + + brillig(inline) fn foo f1 { + b0(v0: Field, v1: Field): + v2 = add v0, v1 + return v2 + } + "#; + + let mut ssa = Ssa::from_str(program).unwrap(); + let ssa_level_warnings = ssa.check_for_missing_brillig_constraints(); + assert_eq!(ssa_level_warnings.len(), 0); + } } diff --git a/test_programs/compile_success_no_bug/check_unconstrained_regression/src/main.nr b/test_programs/compile_success_no_bug/check_unconstrained_regression/src/main.nr index 174b68fd162..e4cb15f099d 100644 --- a/test_programs/compile_success_no_bug/check_unconstrained_regression/src/main.nr +++ b/test_programs/compile_success_no_bug/check_unconstrained_regression/src/main.nr @@ -23,7 +23,9 @@ impl Trigger { let result = unsafe { convert(self) }; assert(result.a == self.x + 1); assert(result.b == self.y - 1 + self.z[2]); + assert(result.c[0] == self.z[0]); assert(result.c[1] == 0); + assert(result.c[2] == self.z[1]); result } }