git.delta.rocks / jrsonnet / refs/commits / 8a3d104167ad

difftreelog

build merge dependency updates

qwomztulYaroslav Bolyukin2026-02-07parent: #8954130.patch.diff
in: master

49 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,27 +1,21 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-version = 3
+version = 4
 
 [[package]]
-name = "ahash"
-version = "0.8.12"
+name = "aho-corasick"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
+checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
 dependencies = [
- "cfg-if",
- "once_cell",
- "version_check",
- "zerocopy",
+ "memchr",
 ]
 
 [[package]]
-name = "aho-corasick"
-version = "1.1.3"
+name = "aliasable"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
-dependencies = [
- "memchr",
-]
+checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
 
 [[package]]
 name = "allocator-api2"
@@ -31,19 +25,30 @@
 
 [[package]]
 name = "annotate-snippets"
-version = "0.10.2"
+version = "0.12.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d9b665789884a7e8fb06c84b295e923b03ca51edbb7d08f91a6a50322ecbfe6"
+checksum = "16e4850548ff4a25a77ce3bda7241874e17fb702ea551f0cc62a2dbe052f1272"
 dependencies = [
  "anstyle",
  "unicode-width",
 ]
 
 [[package]]
+name = "annotated-string"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "298ed730801db3c02f2edba003c9420a0f57ea48d37fdc5601c536113668c059"
+dependencies = [
+ "hi-doc-jumprope",
+ "itertools",
+ "ouroboros",
+]
+
+[[package]]
 name = "anstream"
-version = "0.6.20"
+version = "0.6.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192"
+checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
 dependencies = [
  "anstyle",
  "anstyle-parse",
@@ -56,9 +61,9 @@
 
 [[package]]
 name = "anstyle"
-version = "1.0.11"
+version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
+checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
 
 [[package]]
 name = "anstyle-parse"
@@ -71,31 +76,40 @@
 
 [[package]]
 name = "anstyle-query"
-version = "1.1.4"
+version = "1.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
+checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
 dependencies = [
- "windows-sys 0.60.2",
+ "windows-sys 0.61.2",
 ]
 
 [[package]]
 name = "anstyle-wincon"
-version = "3.0.10"
+version = "3.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
+checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
 dependencies = [
  "anstyle",
  "once_cell_polyfill",
- "windows-sys 0.60.2",
+ "windows-sys 0.61.2",
 ]
 
 [[package]]
 name = "anyhow"
-version = "1.0.99"
+version = "1.0.101"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
+checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea"
 
 [[package]]
+name = "ar_archive_writer"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b"
+dependencies = [
+ "object",
+]
+
+[[package]]
 name = "autocfg"
 version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -108,16 +122,10 @@
 checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
 
 [[package]]
-name = "beef"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
-
-[[package]]
 name = "bitflags"
-version = "2.9.2"
+version = "2.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29"
+checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
 
 [[package]]
 name = "block-buffer"
@@ -130,30 +138,34 @@
 
 [[package]]
 name = "bumpalo"
-version = "3.19.0"
+version = "3.19.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
+checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
+dependencies = [
+ "allocator-api2",
+]
 
 [[package]]
 name = "cc"
-version = "1.2.33"
+version = "1.2.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f"
+checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29"
 dependencies = [
+ "find-msvc-tools",
  "shlex",
 ]
 
 [[package]]
 name = "cfg-if"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
 
 [[package]]
 name = "clap"
-version = "4.5.45"
+version = "4.5.57"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318"
+checksum = "6899ea499e3fb9305a65d5ebf6e3d2248c5fab291f300ad0a704fbe142eae31a"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -161,9 +173,9 @@
 
 [[package]]
 name = "clap_builder"
-version = "4.5.44"
+version = "4.5.57"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8"
+checksum = "7b12c8b680195a62a8364d16b8447b01b6c2c8f9aaf68bee653be34d4245e238"
 dependencies = [
  "anstream",
  "anstyle",
@@ -173,20 +185,20 @@
 
 [[package]]
 name = "clap_complete"
-version = "4.5.57"
+version = "4.5.65"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d9501bd3f5f09f7bbee01da9a511073ed30a80cd7a509f1214bb74eadea71ad"
+checksum = "430b4dc2b5e3861848de79627b2bedc9f3342c7da5173a14eaa5d0f8dc18ae5d"
 dependencies = [
  "clap",
 ]
 
 [[package]]
 name = "clap_derive"
-version = "4.5.45"
+version = "4.5.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
+checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5"
 dependencies = [
- "heck",
+ "heck 0.5.0",
  "proc-macro2",
  "quote",
  "syn",
@@ -194,9 +206,9 @@
 
 [[package]]
 name = "clap_lex"
-version = "0.7.5"
+version = "0.7.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
+checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32"
 
 [[package]]
 name = "colorchoice"
@@ -233,9 +245,9 @@
 
 [[package]]
 name = "crypto-common"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
 dependencies = [
  "generic-array",
  "typenum",
@@ -259,14 +271,15 @@
 
 [[package]]
 name = "dprint-core"
-version = "0.65.0"
+version = "0.67.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b569f4e3085ae957ecc37588e6b2227791b72745434eae966db29e122ba27f0d"
+checksum = "2c1d827947704a9495f705d6aeed270fa21a67f825f22902c28f38dc3af7a9ae"
 dependencies = [
  "anyhow",
  "bumpalo",
- "indexmap 2.10.0",
- "rustc-hash",
+ "hashbrown 0.15.5",
+ "indexmap",
+ "rustc-hash 2.1.1",
  "serde",
  "unicode-width",
 ]
@@ -297,12 +310,23 @@
 
 [[package]]
 name = "errno"
-version = "0.3.13"
+version = "0.3.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
+checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
 dependencies = [
  "libc",
- "windows-sys 0.60.2",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "extension-trait"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd65f1b59dd22d680c7a626cc4a000c1e03d241c51c3e034d2bc9f1e90734f9b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -312,6 +336,12 @@
 checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
 
 [[package]]
+name = "find-msvc-tools"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
+
+[[package]]
 name = "fnv"
 version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -324,6 +354,12 @@
 checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
 
 [[package]]
+name = "foldhash"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
+
+[[package]]
 name = "generic-array"
 version = "0.14.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -335,131 +371,137 @@
 
 [[package]]
 name = "getrandom"
-version = "0.2.16"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi 0.11.1+wasi-snapshot-preview1",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
 dependencies = [
  "cfg-if",
  "libc",
  "r-efi",
- "wasi 0.14.2+wasi-0.2.4",
+ "wasip2",
 ]
 
 [[package]]
 name = "hashbrown"
-version = "0.12.3"
+version = "0.14.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
 
 [[package]]
 name = "hashbrown"
-version = "0.14.5"
+version = "0.15.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
 dependencies = [
- "ahash",
  "allocator-api2",
+ "equivalent",
+ "foldhash 0.1.5",
 ]
 
 [[package]]
 name = "hashbrown"
-version = "0.15.5"
+version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
+checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
 dependencies = [
  "allocator-api2",
  "equivalent",
- "foldhash",
+ "foldhash 0.2.0",
 ]
 
 [[package]]
 name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "heck"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
 [[package]]
 name = "hi-doc"
-version = "0.1.1"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2390a0c9be1370168ef9557833bad3bfa37e1720df61d7f7034f18c07b4e006"
+checksum = "f70fb920ba34768415fb239d7d607486083bfc38ad35e3f1d558697f9f646f11"
 dependencies = [
+ "annotated-string",
+ "extension-trait",
+ "itertools",
  "num-traits",
  "rand",
  "random_color",
  "range-map",
  "smallvec",
+ "tree-sitter-highlight",
+ "unicode-box-drawing",
 ]
 
 [[package]]
-name = "indexmap"
-version = "1.9.3"
+name = "hi-doc-jumprope"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+checksum = "236c25809a9c0a0249b3488feb57744e12aa64e4f3db851980eab303719c7bdd"
 dependencies = [
- "autocfg",
- "hashbrown 0.12.3",
+ "rand",
+ "str_indices",
 ]
 
 [[package]]
 name = "indexmap"
-version = "2.10.0"
+version = "2.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
+checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
 dependencies = [
  "equivalent",
- "hashbrown 0.15.5",
+ "hashbrown 0.16.1",
  "serde",
+ "serde_core",
 ]
 
 [[package]]
 name = "indoc"
-version = "2.0.6"
+version = "2.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
+checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
+dependencies = [
+ "rustversion",
+]
 
 [[package]]
 name = "insta"
-version = "1.43.1"
+version = "1.46.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "154934ea70c58054b556dd430b99a98c2a7ff5309ac9891597e339b5c28f4371"
+checksum = "e82db8c87c7f1ccecb34ce0c24399b8a73081427f3c7c50a5d597925356115e4"
 dependencies = [
  "console",
  "once_cell",
  "similar",
+ "tempfile",
 ]
 
 [[package]]
 name = "is_terminal_polyfill"
-version = "1.70.1"
+version = "1.70.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
 
 [[package]]
 name = "itertools"
-version = "0.13.0"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
 dependencies = [
  "either",
 ]
 
 [[package]]
 name = "itoa"
-version = "1.0.15"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
 
 [[package]]
 name = "jrsonnet"
@@ -495,7 +537,6 @@
 dependencies = [
  "annotate-snippets",
  "anyhow",
- "hashbrown 0.14.5",
  "hi-doc",
  "jrsonnet-gcmodule",
  "jrsonnet-interner",
@@ -504,7 +545,8 @@
  "jrsonnet-types",
  "num-bigint",
  "pathdiff",
- "rustc-hash",
+ "rustc-hash 2.1.1",
+ "rustversion",
  "serde",
  "stacker",
  "static_assertions",
@@ -528,18 +570,14 @@
 
 [[package]]
 name = "jrsonnet-gcmodule"
-version = "0.3.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87122f4aa9b77c38f96e43d9ba4b7717d63aa87b137090a16ec0107cf17abdac"
+version = "0.4.0"
 dependencies = [
  "jrsonnet-gcmodule-derive",
 ]
 
 [[package]]
 name = "jrsonnet-gcmodule-derive"
-version = "0.3.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17eefaaba135591284e11cda15ed067247bec5fe9ece4fabc2c0df650d7b955a"
+version = "0.4.0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -550,9 +588,9 @@
 name = "jrsonnet-interner"
 version = "0.5.0-pre97"
 dependencies = [
- "hashbrown 0.14.5",
+ "hashbrown 0.16.1",
  "jrsonnet-gcmodule",
- "rustc-hash",
+ "rustc-hash 2.1.1",
 ]
 
 [[package]]
@@ -601,7 +639,7 @@
  "md5",
  "num-bigint",
  "regex",
- "rustc-hash",
+ "rustc-hash 2.1.1",
  "serde",
  "serde_json",
  "serde_yaml_with_quirks",
@@ -620,9 +658,9 @@
 
 [[package]]
 name = "json-structural-diff"
-version = "0.1.0"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25c7940d3c84d2079306c176c7b2b37622b6bc5e43fbd1541b1e4a4e1fd02045"
+checksum = "e878e36a8a44c158505c2c818abdc1350413ad83dcb774a0459f6a7ef2b65cbf"
 dependencies = [
  "difflib",
  "regex",
@@ -637,18 +675,12 @@
 dependencies = [
  "cpufeatures",
 ]
-
-[[package]]
-name = "lazy_static"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "libc"
-version = "0.2.175"
+version = "0.2.180"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
+checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
 
 [[package]]
 name = "libjsonnet"
@@ -662,79 +694,63 @@
 ]
 
 [[package]]
-name = "linked-hash-map"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
-
-[[package]]
 name = "linux-raw-sys"
-version = "0.9.4"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
+checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
 
 [[package]]
 name = "logos"
-version = "0.14.4"
+version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7251356ef8cb7aec833ddf598c6cb24d17b689d20b993f9d11a3d764e34e6458"
+checksum = "eb2c55a318a87600ea870ff8c2012148b44bf18b74fad48d0f835c38c7d07c5f"
 dependencies = [
  "logos-derive",
 ]
 
 [[package]]
 name = "logos-codegen"
-version = "0.14.4"
+version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59f80069600c0d66734f5ff52cc42f2dabd6b29d205f333d61fd7832e9e9963f"
+checksum = "58b3ffaa284e1350d017a57d04ada118c4583cf260c8fb01e0fe28a2e9cf8970"
 dependencies = [
- "beef",
  "fnv",
- "lazy_static",
  "proc-macro2",
  "quote",
+ "regex-automata",
  "regex-syntax",
  "syn",
 ]
 
 [[package]]
 name = "logos-derive"
-version = "0.14.4"
+version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24fb722b06a9dc12adb0963ed585f19fc61dc5413e6a9be9422ef92c091e731d"
+checksum = "52d3a9855747c17eaf4383823f135220716ab49bea5fbea7dd42cc9a92f8aa31"
 dependencies = [
  "logos-codegen",
 ]
 
 [[package]]
 name = "lru"
-version = "0.12.5"
+version = "0.16.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
+checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593"
 dependencies = [
- "hashbrown 0.15.5",
+ "hashbrown 0.16.1",
 ]
 
 [[package]]
 name = "md5"
-version = "0.7.0"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
+checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0"
 
 [[package]]
 name = "memchr"
-version = "2.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
-
-[[package]]
-name = "memoffset"
-version = "0.9.1"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
-dependencies = [
- "autocfg",
-]
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
 
 [[package]]
 name = "mimalloc-sys"
@@ -785,6 +801,15 @@
 ]
 
 [[package]]
+name = "object"
+version = "0.37.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
 name = "once_cell"
 version = "1.21.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -792,11 +817,35 @@
 
 [[package]]
 name = "once_cell_polyfill"
-version = "1.70.1"
+version = "1.70.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
+checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
+
+[[package]]
+name = "ouroboros"
+version = "0.18.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59"
+dependencies = [
+ "aliasable",
+ "ouroboros_macro",
+ "static_assertions",
+]
 
 [[package]]
+name = "ouroboros_macro"
+version = "0.18.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0"
+dependencies = [
+ "heck 0.4.1",
+ "proc-macro2",
+ "proc-macro2-diagnostics",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "pathdiff"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -840,27 +889,41 @@
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.101"
+version = "1.0.106"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
+name = "proc-macro2-diagnostics"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "version_check",
+ "yansi",
+]
+
+[[package]]
 name = "psm"
-version = "0.1.26"
+version = "0.1.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f"
+checksum = "3852766467df634d74f0b2d7819bf8dc483a0eb2e3b0f50f756f9cfe8b0d18d8"
 dependencies = [
+ "ar_archive_writer",
  "cc",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.40"
+version = "1.0.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
 dependencies = [
  "proc-macro2",
 ]
@@ -873,20 +936,19 @@
 
 [[package]]
 name = "rand"
-version = "0.8.5"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
 dependencies = [
- "libc",
  "rand_chacha",
  "rand_core",
 ]
 
 [[package]]
 name = "rand_chacha"
-version = "0.3.1"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
 dependencies = [
  "ppv-lite86",
  "rand_core",
@@ -894,18 +956,18 @@
 
 [[package]]
 name = "rand_core"
-version = "0.6.4"
+version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
 dependencies = [
- "getrandom 0.2.16",
+ "getrandom",
 ]
 
 [[package]]
 name = "random_color"
-version = "0.8.0"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0085421bc527effa7ed6d46bac0a28734663c47abe03d80a5e78e441fad85196"
+checksum = "d635c5e80ae160390ac62ca027d2d06c94c1dc69e5c0a12f1e3a53664dc84966"
 dependencies = [
  "rand",
 ]
@@ -921,9 +983,9 @@
 
 [[package]]
 name = "regex"
-version = "1.11.1"
+version = "1.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -933,9 +995,9 @@
 
 [[package]]
 name = "regex-automata"
-version = "0.4.9"
+version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -944,20 +1006,19 @@
 
 [[package]]
 name = "regex-syntax"
-version = "0.8.5"
+version = "0.8.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c"
 
 [[package]]
 name = "rowan"
-version = "0.15.17"
+version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4f1e4a001f863f41ea8d0e6a0c34b356d5b733db50dadab3efef640bafb779b"
+checksum = "417a3a9f582e349834051b8a10c8d71ca88da4211e4093528e36b9845f6b5f21"
 dependencies = [
  "countme",
  "hashbrown 0.14.5",
- "memoffset",
- "rustc-hash",
+ "rustc-hash 1.1.0",
  "text-size",
 ]
 
@@ -968,38 +1029,60 @@
 checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
 [[package]]
+name = "rustc-hash"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
+
+[[package]]
 name = "rustix"
-version = "1.0.8"
+version = "1.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
+checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
 dependencies = [
  "bitflags",
  "errno",
  "libc",
  "linux-raw-sys",
- "windows-sys 0.60.2",
+ "windows-sys 0.61.2",
 ]
 
 [[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
 name = "ryu"
-version = "1.0.20"
+version = "1.0.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984"
 
 [[package]]
 name = "serde"
-version = "1.0.219"
+version = "1.0.228"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
 dependencies = [
+ "serde_core",
  "serde_derive",
 ]
 
 [[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
 name = "serde_derive"
-version = "1.0.219"
+version = "1.0.228"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1008,26 +1091,29 @@
 
 [[package]]
 name = "serde_json"
-version = "1.0.143"
+version = "1.0.149"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
+checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
 dependencies = [
+ "indexmap",
  "itoa",
  "memchr",
- "ryu",
  "serde",
+ "serde_core",
+ "zmij",
 ]
 
 [[package]]
 name = "serde_yaml_with_quirks"
-version = "0.8.24"
+version = "0.9.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47c5983eba86eae2d0058c35fb1065ccffb23af7f8965871069269088098321a"
+checksum = "d852180e55e824bb347a8e3cdbbca1f02513ea1fa00188f1b2a8a255ac3d6cf9"
 dependencies = [
- "indexmap 1.9.3",
+ "indexmap",
+ "itoa",
  "ryu",
  "serde",
- "yaml-rust",
+ "unsafe-libyaml",
 ]
 
 [[package]]
@@ -1082,9 +1168,9 @@
 
 [[package]]
 name = "stacker"
-version = "0.1.21"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cddb07e32ddb770749da91081d8d0ac3a16f1a569a18b20348cd371f5dead06b"
+checksum = "08d74a23609d509411d10e2176dc2a4346e3b4aea2e7b1869f19fdedbc71c013"
 dependencies = [
  "cc",
  "cfg-if",
@@ -1100,6 +1186,18 @@
 checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 
 [[package]]
+name = "str_indices"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d08889ec5408683408db66ad89e0e1f93dff55c73a4ccc71c427d5b277ee47e6"
+
+[[package]]
+name = "streaming-iterator"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520"
+
+[[package]]
 name = "strsim"
 version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1107,9 +1205,9 @@
 
 [[package]]
 name = "syn"
-version = "2.0.106"
+version = "2.0.114"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
+checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1129,15 +1227,15 @@
 
 [[package]]
 name = "tempfile"
-version = "3.21.0"
+version = "3.24.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e"
+checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c"
 dependencies = [
  "fastrand",
- "getrandom 0.3.3",
+ "getrandom",
  "once_cell",
  "rustix",
- "windows-sys 0.60.2",
+ "windows-sys 0.61.2",
 ]
 
 [[package]]
@@ -1160,18 +1258,18 @@
 
 [[package]]
 name = "thiserror"
-version = "1.0.69"
+version = "2.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.69"
+version = "2.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1179,10 +1277,42 @@
 ]
 
 [[package]]
+name = "tree-sitter"
+version = "0.26.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12987371f54efc9b9306a20dc87ed5aaee9f320c8a8b115e28515c412b2efe39"
+dependencies = [
+ "cc",
+ "regex",
+ "regex-syntax",
+ "serde_json",
+ "streaming-iterator",
+ "tree-sitter-language",
+]
+
+[[package]]
+name = "tree-sitter-highlight"
+version = "0.26.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b688407049ea1b55a7e872f138947d22389118b9c4d09b459cb34ca205e41c0"
+dependencies = [
+ "regex",
+ "streaming-iterator",
+ "thiserror",
+ "tree-sitter",
+]
+
+[[package]]
+name = "tree-sitter-language"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "009994f150cc0cd50ff54917d5bc8bffe8cad10ca10d81c34da2ec421ae61782"
+
+[[package]]
 name = "typenum"
-version = "1.18.0"
+version = "1.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
+checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
 
 [[package]]
 name = "ungrammar"
@@ -1191,16 +1321,28 @@
 checksum = "a3e5df347f0bf3ec1d670aad6ca5c6a1859cd9ea61d2113125794654ccced68f"
 
 [[package]]
+name = "unicode-box-drawing"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a1f97719cf40224391201fc11e7f5b0cc0ba21416367cfc914e2d45af4e42ef"
+
+[[package]]
 name = "unicode-ident"
-version = "1.0.18"
+version = "1.0.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.14"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
+
+[[package]]
+name = "unsafe-libyaml"
+version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
+checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
 
 [[package]]
 name = "utf8parse"
@@ -1215,25 +1357,19 @@
 checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
 
 [[package]]
-name = "wasi"
-version = "0.11.1+wasi-snapshot-preview1"
+name = "wasip2"
+version = "1.0.2+wasi-0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
-
-[[package]]
-name = "wasi"
-version = "0.14.2+wasi-0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
+checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
 dependencies = [
- "wit-bindgen-rt",
+ "wit-bindgen",
 ]
 
 [[package]]
 name = "windows-link"
-version = "0.1.3"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
 
 [[package]]
 name = "windows-sys"
@@ -1241,16 +1377,16 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
 dependencies = [
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
 name = "windows-sys"
-version = "0.60.2"
+version = "0.61.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
+checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
 dependencies = [
- "windows-targets 0.53.3",
+ "windows-link",
 ]
 
 [[package]]
@@ -1259,31 +1395,14 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
 dependencies = [
- "windows_aarch64_gnullvm 0.52.6",
- "windows_aarch64_msvc 0.52.6",
- "windows_i686_gnu 0.52.6",
- "windows_i686_gnullvm 0.52.6",
- "windows_i686_msvc 0.52.6",
- "windows_x86_64_gnu 0.52.6",
- "windows_x86_64_gnullvm 0.52.6",
- "windows_x86_64_msvc 0.52.6",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.53.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
-dependencies = [
- "windows-link",
- "windows_aarch64_gnullvm 0.53.0",
- "windows_aarch64_msvc 0.53.0",
- "windows_i686_gnu 0.53.0",
- "windows_i686_gnullvm 0.53.0",
- "windows_i686_msvc 0.53.0",
- "windows_x86_64_gnu 0.53.0",
- "windows_x86_64_gnullvm 0.53.0",
- "windows_x86_64_msvc 0.53.0",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
 ]
 
 [[package]]
@@ -1293,58 +1412,28 @@
 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
 
 [[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
-
-[[package]]
 name = "windows_aarch64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
 
 [[package]]
-name = "windows_aarch64_msvc"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
-
-[[package]]
 name = "windows_i686_gnu"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
 
 [[package]]
-name = "windows_i686_gnu"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
-
-[[package]]
 name = "windows_i686_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
 
 [[package]]
-name = "windows_i686_gnullvm"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
-
-[[package]]
 name = "windows_i686_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -1353,43 +1442,22 @@
 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
 
 [[package]]
-name = "windows_x86_64_gnu"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
-
-[[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
 
 [[package]]
 name = "windows_x86_64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
 
 [[package]]
-name = "wit-bindgen-rt"
-version = "0.39.0"
+name = "wit-bindgen"
+version = "0.51.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
-dependencies = [
- "bitflags",
-]
+checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
 
 [[package]]
 name = "xshell"
@@ -1412,7 +1480,7 @@
 dependencies = [
  "anyhow",
  "clap",
- "indexmap 2.10.0",
+ "indexmap",
  "itertools",
  "proc-macro2",
  "quote",
@@ -1421,30 +1489,33 @@
 ]
 
 [[package]]
-name = "yaml-rust"
-version = "0.4.5"
+name = "yansi"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
-dependencies = [
- "linked-hash-map",
-]
+checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
 
 [[package]]
 name = "zerocopy"
-version = "0.8.26"
+version = "0.8.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
+checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a"
 dependencies = [
  "zerocopy-derive",
 ]
 
 [[package]]
 name = "zerocopy-derive"
-version = "0.8.26"
+version = "0.8.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
+checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517"
 dependencies = [
  "proc-macro2",
  "quote",
  "syn",
 ]
+
+[[package]]
+name = "zmij"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445"
modifiedCargo.tomldiffbeforeafterboth
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,7 +19,7 @@
 jrsonnet-stdlib = { path = "./crates/jrsonnet-stdlib", version = "0.5.0-pre97" }
 jrsonnet-cli = { path = "./crates/jrsonnet-cli", version = "0.5.0-pre97" }
 jrsonnet-types = { path = "./crates/jrsonnet-types", version = "0.5.0-pre97" }
-jrsonnet-gcmodule = { version = "0.3.7" }
+jrsonnet-gcmodule = { version = "0.4.0", path = "../gcmodule" }
 # Diagnostics.
 # hi-doc is my library, which handles text formatting very well, but isn't polished enough yet
 # Previous implementation was based on annotate-snippets, which I don't like for many reasons.
@@ -27,8 +27,8 @@
 # I'm against using miette, because I want to reuse data between interpreter and annotations, yet miette
 #   and other libraries want to handle spans etc by itself, which is okay for compiler diagnostics, but is
 #   bad for interpreter, where interpreter and parser are paired much closer.
-hi-doc = "0.1.1"
-annotate-snippets = "0.10.1"
+hi-doc = "0.3.0"
+annotate-snippets = "0.12.11"
 
 # CLI
 clap = "4.5"
@@ -37,57 +37,57 @@
 # Parsing, manifestification is implemented manually everywhere
 # Note on serde_yaml_with_quirks: This is a fork of serde-yaml with legacy yaml 1.1 support:
 # https://github.com/dtolnay/serde-yaml/pull/225
-serde = "1.0.197"
-serde_json = "1.0.114"
-serde_yaml_with_quirks = "0.8.24"
+serde = "1.0.228"
+serde_json = "1.0.149"
+serde_yaml_with_quirks = "0.9.34"
 
 # Error handling
-anyhow = "1.0.83"
-thiserror = "1.0.60"
+anyhow = "1.0.101"
+thiserror = "2.0.18"
 
 # Code formatting
-dprint-core = "0.65.0"
+dprint-core = "0.67.4"
 
 # Stdlib hashing functions
-md5 = "0.7.0"
+md5 = "0.8.0"
 sha1 = "0.10.6"
-sha2 = "0.10.8"
+sha2 = "0.10.9"
 sha3 = "0.10.8"
 
 # Source code parsing.
 # Jrsonnet has two parsers for jsonnet - one is for execution, and another is for better parsing diagnostics/lints/LSP.
 # First (and fast one) is based on peg, second is based on rowan.
-peg = "0.8.3"
-logos = "0.14.0"
+peg = "0.8.5"
+logos = "0.16.1"
 ungrammar = "1.16.1"
-rowan = "0.15.15"
+rowan = "0.16.1"
 
 mimallocator = "0.1.3"
 indoc = "2.0"
-insta = "1.39"
-tempfile = "3.10"
-pathdiff = "0.2.1"
-hashbrown = "0.14.5"
+insta = "1.46"
+tempfile = "3.24"
+pathdiff = "0.2.3"
+hashbrown = "0.16.1"
 static_assertions = "1.1"
-rustc-hash = "1.1"
-num-bigint = "0.4.5"
-strsim = "0.11.0"
+rustc-hash = "2.1"
+num-bigint = "0.4.6"
+strsim = "0.11.1"
 proc-macro2 = "1.0"
 quote = "1.0"
 syn = "2.0"
 drop_bomb = "0.1.5"
 base64 = "0.22.1"
-indexmap = "2.2.3"
-itertools = "0.13.0"
-xshell = "0.2.6"
+indexmap = "2.13.0"
+itertools = "0.14.0"
+xshell = "0.2.7"
 
-lsp-server = "0.7.6"
-lsp-types = "0.96.0"
+lsp-server = "0.7.9"
+lsp-types = "0.97.0"
 
-regex = "1.10"
-lru = "0.12.3"
+regex = "1.12"
+lru = "0.16.3"
 
-json-structural-diff = "0.1.0"
+json-structural-diff = "0.2.0"
 syn-dissect-closure = "0.1.0"
 
 [workspace.lints.rust]
modifiedbindings/jsonnet/Cargo.tomldiffbeforeafterboth
--- a/bindings/jsonnet/Cargo.toml
+++ b/bindings/jsonnet/Cargo.toml
@@ -39,5 +39,5 @@
 interop-threading = []
 
 experimental = ["exp-preserve-order", "exp-destruct"]
-exp-preserve-order = ["jrsonnet-evaluator/exp-preserve-order"]
+exp-preserve-order = ["jrsonnet-evaluator/exp-preserve-order", "jrsonnet-stdlib/exp-preserve-order"]
 exp-destruct = ["jrsonnet-evaluator/exp-destruct"]
modifiedbindings/jsonnet/src/import.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/import.rs
+++ b/bindings/jsonnet/src/import.rs
@@ -2,7 +2,6 @@
 
 use std::{
 	alloc::Layout,
-	any::Any,
 	cell::RefCell,
 	collections::HashMap,
 	env::current_dir,
@@ -17,7 +16,7 @@
 	error::{ErrorKind::*, Result},
 	ImportResolver,
 };
-use jrsonnet_gcmodule::Trace;
+use jrsonnet_gcmodule::Acyclic;
 use jrsonnet_parser::{SourceDirectory, SourceFile, SourcePath};
 
 use crate::VM;
@@ -32,11 +31,9 @@
 ) -> c_int;
 
 /// Resolves imports using callback
-#[derive(Trace)]
+#[derive(Acyclic)]
 pub struct CallbackImportResolver {
-	#[trace(skip)]
 	cb: JsonnetImportCallback,
-	#[trace(skip)]
 	ctx: *mut c_void,
 	out: RefCell<HashMap<SourcePath, Vec<u8>>>,
 }
@@ -101,14 +98,6 @@
 	}
 	fn load_file_contents(&self, resolved: &SourcePath) -> Result<Vec<u8>> {
 		Ok(self.out.borrow().get(resolved).unwrap().clone())
-	}
-
-	fn as_any(&self) -> &dyn Any {
-		self
-	}
-
-	fn as_any_mut(&mut self) -> &mut dyn Any {
-		self
 	}
 }
 
modifiedbindings/jsonnet/src/interop.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/interop.rs
+++ b/bindings/jsonnet/src/interop.rs
@@ -60,7 +60,7 @@
 
 #[cfg(feature = "interop-common")]
 mod common {
-	use jrsonnet_evaluator::trace::{CompactFormat, ExplainingFormat, JsFormat, PathResolver};
+	use jrsonnet_evaluator::trace::{CompactFormat, HiDocFormat, JsFormat, PathResolver};
 
 	use crate::VM;
 
@@ -76,7 +76,7 @@
 			}
 			1 => vm.trace_format = Box::new(JsFormat { max_trace: 20 }),
 			2 => {
-				vm.trace_format = Box::new(ExplainingFormat {
+				vm.trace_format = Box::new(HiDocFormat {
 					resolver: PathResolver::new_cwd_fallback(),
 					max_trace: 20,
 				});
modifiedbindings/jsonnet/src/lib.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/lib.rs
+++ b/bindings/jsonnet/src/lib.rs
@@ -17,19 +17,20 @@
 	ffi::{CStr, CString, OsStr},
 	os::raw::{c_char, c_double, c_int, c_uint},
 	path::{Path, PathBuf},
+	rc::Rc,
 };
 
 use jrsonnet_evaluator::{
 	apply_tla, bail,
 	function::TlaArg,
-	gc::{GcHashMap, TraceBox},
+	gc::WithCapacityExt as _,
 	manifest::{JsonFormat, ManifestFormat, ToStringFormat},
+	rustc_hash::FxHashMap,
 	stack::set_stack_depth_limit,
-	tb,
 	trace::{CompactFormat, PathResolver, TraceFormat},
 	FileImportResolver, IStr, ImportResolver, Result, State, Val,
 };
-use jrsonnet_gcmodule::Trace;
+use jrsonnet_gcmodule::Acyclic;
 use jrsonnet_parser::SourcePath;
 use jrsonnet_stdlib::ContextInitializer;
 
@@ -47,7 +48,7 @@
 	b"v0.20.0\0"
 }
 
-unsafe fn parse_path(input: &CStr) -> Cow<Path> {
+unsafe fn parse_path(input: &CStr) -> Cow<'_, Path> {
 	#[cfg(target_family = "unix")]
 	{
 		use std::os::unix::ffi::OsStrExt;
@@ -61,7 +62,7 @@
 	}
 }
 
-unsafe fn unparse_path(input: &Path) -> Cow<CStr> {
+unsafe fn unparse_path(input: &Path) -> Cow<'_, CStr> {
 	#[cfg(target_family = "unix")]
 	{
 		use std::os::unix::ffi::OsStrExt;
@@ -76,15 +77,14 @@
 	}
 }
 
-#[derive(Trace)]
+#[derive(Acyclic)]
 struct VMImportResolver {
-	#[trace(tracking(force))]
-	inner: RefCell<TraceBox<dyn ImportResolver>>,
+	inner: RefCell<Rc<dyn ImportResolver>>,
 }
 impl VMImportResolver {
 	fn new(value: impl ImportResolver) -> Self {
 		Self {
-			inner: RefCell::new(tb!(value)),
+			inner: RefCell::new(Rc::new(value)),
 		}
 	}
 }
@@ -103,13 +103,6 @@
 
 	fn resolve(&self, path: &Path) -> Result<SourcePath> {
 		self.inner.borrow().resolve(path)
-	}
-
-	fn as_any(&self) -> &dyn Any {
-		self
-	}
-	fn as_any_mut(&mut self) -> &mut dyn Any {
-		self
 	}
 }
 
@@ -117,28 +110,23 @@
 	state: State,
 	manifest_format: Box<dyn ManifestFormat>,
 	trace_format: Box<dyn TraceFormat>,
-	tla_args: GcHashMap<IStr, TlaArg>,
+	tla_args: FxHashMap<IStr, TlaArg>,
 }
 impl VM {
 	fn replace_import_resolver(&self, resolver: impl ImportResolver) {
-		*self
-			.state
-			.import_resolver()
-			.as_any()
+		*(self.state.import_resolver() as &dyn Any)
 			.downcast_ref::<VMImportResolver>()
 			.expect("valid resolver ty")
 			.inner
-			.borrow_mut() = tb!(resolver);
+			.borrow_mut() = Rc::new(resolver);
 	}
 	fn add_jpath(&self, path: PathBuf) {
-		self.state
-			.import_resolver()
-			.as_any()
+		let ir = self.state.import_resolver();
+		let vmi = (ir as &dyn Any)
 			.downcast_ref::<VMImportResolver>()
-			.expect("valid resolver ty")
-			.inner
-			.borrow_mut()
-			.as_any_mut()
+			.expect("valid resolver ty");
+		let vmi = &mut *vmi.inner.borrow_mut();
+		(vmi as &mut dyn Any)
 			.downcast_mut::<FileImportResolver>()
 			.expect("jpaths are not compatible with callback imports!")
 			.add_jpath(path);
@@ -158,7 +146,7 @@
 		state,
 		manifest_format: Box::new(JsonFormat::default()),
 		trace_format: Box::new(CompactFormat::default()),
-		tla_args: GcHashMap::new(),
+		tla_args: FxHashMap::new(),
 	}))
 }
 
modifiedcmds/jrsonnet-fmt/src/main.rsdiffbeforeafterboth
--- a/cmds/jrsonnet-fmt/src/main.rs
+++ b/cmds/jrsonnet-fmt/src/main.rs
@@ -46,7 +46,7 @@
 		o
 	}};
 	(@s; $o:ident: str($e:expr $(,)?) $($t:tt)*) => {{
-		$o.push_str($e);
+		$o.push_string($e.to_owned());
 		pi!(@s; $o: $($t)*);
 	}};
 	(@s; $o:ident: string($e:expr $(,)?) $($t:tt)*) => {{
@@ -711,8 +711,8 @@
 		let mut builder = hi_doc::SnippetBuilder::new(input);
 		for error in errors {
 			builder
-				.error(hi_doc::Text::single(
-					format!("{:?}", error.error).chars(),
+				.error(hi_doc::Text::fragment(
+					format!("{:?}", error.error),
 					Formatting::default(),
 				))
 				.range(
modifiedcmds/jrsonnet/Cargo.tomldiffbeforeafterboth
--- a/cmds/jrsonnet/Cargo.toml
+++ b/cmds/jrsonnet/Cargo.toml
@@ -44,8 +44,6 @@
 # --exp-apply
 exp-apply = []
 
-nightly = ["jrsonnet-evaluator/nightly"]
-
 [dependencies]
 jrsonnet-evaluator.workspace = true
 jrsonnet-parser.workspace = true
modifiedcrates/jrsonnet-cli/src/tla.rsdiffbeforeafterboth
--- a/crates/jrsonnet-cli/src/tla.rs
+++ b/crates/jrsonnet-cli/src/tla.rs
@@ -2,7 +2,8 @@
 use jrsonnet_evaluator::{
 	error::{ErrorKind, Result},
 	function::TlaArg,
-	gc::GcHashMap,
+	gc::WithCapacityExt as _,
+	rustc_hash::FxHashMap,
 	IStr,
 };
 use jrsonnet_parser::{ParserSettings, Source};
@@ -32,8 +33,8 @@
 	tla_code_file: Vec<ExtFile>,
 }
 impl TlaOpts {
-	pub fn tla_opts(&self) -> Result<GcHashMap<IStr, TlaArg>> {
-		let mut out = GcHashMap::new();
+	pub fn tla_opts(&self) -> Result<FxHashMap<IStr, TlaArg>> {
+		let mut out = FxHashMap::new();
 		for (name, value) in self
 			.tla_str
 			.iter()
modifiedcrates/jrsonnet-cli/src/trace.rsdiffbeforeafterboth
--- a/crates/jrsonnet-cli/src/trace.rs
+++ b/crates/jrsonnet-cli/src/trace.rs
@@ -1,7 +1,5 @@
 use clap::{Parser, ValueEnum};
-use jrsonnet_evaluator::trace::{
-	CompactFormat, ExplainingFormat, HiDocFormat, PathResolver, TraceFormat,
-};
+use jrsonnet_evaluator::trace::{CompactFormat, HiDocFormat, PathResolver, TraceFormat};
 
 #[derive(PartialEq, Eq, ValueEnum, Clone)]
 pub enum TraceFormatName {
@@ -9,7 +7,7 @@
 	Compact,
 	/// Display source code with attached trace annotations
 	Explaining,
-	/// Experimental trace formatting based on hi-doc library
+	/// Trace formatting based on hi-doc library
 	HiDoc,
 }
 
@@ -38,11 +36,7 @@
 				padding: 4,
 				max_trace,
 			}),
-			TraceFormatName::Explaining => Box::new(ExplainingFormat {
-				resolver,
-				max_trace,
-			}),
-			TraceFormatName::HiDoc => Box::new(HiDocFormat {
+			TraceFormatName::Explaining | TraceFormatName::HiDoc => Box::new(HiDocFormat {
 				resolver,
 				max_trace,
 			}),
modifiedcrates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/Cargo.toml
+++ b/crates/jrsonnet-evaluator/Cargo.toml
@@ -7,6 +7,8 @@
 repository.workspace = true
 version.workspace = true
 
+build = "build.rs"
+
 [lints]
 workspace = true
 
@@ -16,8 +18,6 @@
 explaining-traces = ["annotate-snippets", "hi-doc"]
 # Allows library authors to throw custom errors
 anyhow-error = ["anyhow"]
-# Adds ability to build import closure in async
-async-import = []
 
 # Allows to preserve field order in objects
 exp-preserve-order = []
@@ -29,9 +29,6 @@
 exp-bigint = ["num-bigint", "jrsonnet-types/exp-bigint"]
 # obj?.field, obj?.['field']
 exp-null-coaelse = ["jrsonnet-parser/exp-null-coaelse"]
-
-# Improves performance, and implements some useful things using nightly-only features
-nightly = ["hashbrown/nightly"]
 
 [dependencies]
 jrsonnet-interner.workspace = true
@@ -41,7 +38,6 @@
 jrsonnet-gcmodule.workspace = true
 
 pathdiff.workspace = true
-hashbrown.workspace = true
 static_assertions.workspace = true
 
 rustc-hash.workspace = true
@@ -59,4 +55,8 @@
 hi-doc = { workspace = true, optional = true }
 # Bigint
 num-bigint = { workspace = true, features = ["serde"], optional = true }
-stacker = "0.1.15"
+
+stacker = "0.1.23"
+
+[build-dependencies]
+rustversion = "1.0.22"
addedcrates/jrsonnet-evaluator/build.rsdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-evaluator/build.rs
@@ -0,0 +1,6 @@
+fn main() {
+	println!("cargo:rustc-check-cfg=cfg(nightly)");
+	if rustversion::cfg!(nightly) {
+		println!("cargo:rustc-cfg=nightly");
+	}
+}
modifiedcrates/jrsonnet-evaluator/src/arr/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/arr/mod.rs
+++ b/crates/jrsonnet-evaluator/src/arr/mod.rs
@@ -1,19 +1,30 @@
-use std::{any::Any, num::NonZeroU32};
+use std::{
+	any::Any,
+	fmt::{self},
+	num::NonZeroU32,
+};
 
-use jrsonnet_gcmodule::{Cc, Trace};
+use jrsonnet_gcmodule::{cc_dyn, Cc};
 use jrsonnet_interner::IBytes;
 use jrsonnet_parser::LocExpr;
 
-use crate::{function::FuncVal, gc::TraceBox, tb, Context, Result, Thunk, Val};
+use crate::{function::FuncVal, Context, Result, Thunk, Val};
 
 mod spec;
 pub use spec::{ArrayLike, *};
 
-/// Represents a Jsonnet array value.
-#[derive(Debug, Clone, Trace)]
-// may contain other ArrValue
-#[trace(tracking(force))]
-pub struct ArrValue(Cc<TraceBox<dyn ArrayLike>>);
+cc_dyn!(
+	#[doc = "Represents a Jsonnet array value."]
+	#[derive(Clone)]
+	ArrValue,
+	ArrayLike,
+	pub fn new() {...}
+);
+impl fmt::Debug for ArrValue {
+	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+		self.0.fmt(f)
+	}
+}
 
 pub trait ArrayLikeIter<T>: Iterator<Item = T> + DoubleEndedIterator + ExactSizeIterator {}
 impl<I, T> ArrayLikeIter<T> for I where
@@ -22,9 +33,6 @@
 }
 
 impl ArrValue {
-	pub fn new(v: impl ArrayLike) -> Self {
-		Self(Cc::new(tb!(v)))
-	}
 	pub fn empty() -> Self {
 		Self::new(RangeArray::empty())
 	}
@@ -232,6 +240,3 @@
 		self.0.is_cheap()
 	}
 }
-
-#[cfg(target_pointer_width = "64")]
-static_assertions::assert_eq_size!(ArrValue, [u8; 8]);
modifiedcrates/jrsonnet-evaluator/src/async_import.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/async_import.rs
+++ b/crates/jrsonnet-evaluator/src/async_import.rs
@@ -1,14 +1,15 @@
-use std::{cell::RefCell, future::Future, path::Path};
+use std::{any::Any, cell::RefCell, future::Future, path::Path};
 
-use jrsonnet_gcmodule::Trace;
+use jrsonnet_gcmodule::Acyclic;
 use jrsonnet_interner::IStr;
 use jrsonnet_parser::{
 	ArgsDesc, AssertStmt, BindSpec, CompSpec, Destruct, Expr, FieldMember, FieldName, ForSpecData,
 	IfSpecData, LocExpr, Member, ObjBody, Param, ParamsDesc, ParserSettings, SliceDesc, Source,
 	SourcePath,
 };
+use rustc_hash::FxHashMap;
 
-use crate::{bail, gc::GcHashMap, FileData, ImportResolver, State};
+use crate::{bail, FileData, ImportResolver, State};
 
 pub struct Import {
 	path: IStr,
@@ -132,12 +133,12 @@
 			ObjBody::ObjComp(_) => todo!(),
 		}
 	}
-	match &*expr.0 {
+	match &*expr.expr() {
 		Expr::Import(v) | Expr::ImportStr(v) | Expr::ImportBin(v) => {
-			if let Expr::Str(s) = &*v.0 {
+			if let Expr::Str(s) = &*v.expr() {
 				out.0.push(Import {
 					path: s.clone(),
-					expression: matches!(&*expr.0, Expr::Import(_)),
+					expression: matches!(&*expr.expr(), Expr::Import(_)),
 				});
 			}
 			// Non-string import will fail in runtime
@@ -250,9 +251,9 @@
 	) -> impl Future<Output = Result<Vec<u8>, Self::Error>>;
 }
 
-#[derive(Trace)]
+#[derive(Acyclic)]
 struct ResolvedImportResolver {
-	resolved: RefCell<GcHashMap<(SourcePath, IStr), (SourcePath, bool)>>,
+	resolved: RefCell<FxHashMap<(SourcePath, IStr), (SourcePath, bool)>>,
 }
 impl ImportResolver for ResolvedImportResolver {
 	fn load_file_contents(&self, _resolved: &SourcePath) -> crate::Result<Vec<u8>> {
@@ -278,10 +279,6 @@
 			path.to_owned()
 		))
 	}
-
-	fn as_any(&self) -> &dyn std::any::Any {
-		self
-	}
 }
 
 enum Job {
@@ -295,13 +292,12 @@
 where
 	H: AsyncImportResolver,
 {
-	let mut resolved = s
-		.import_resolver()
-		.as_any()
+	let resolved = (s.import_resolver() as &dyn Any)
 		.downcast_ref::<ResolvedImportResolver>()
-		.map_or_else(GcHashMap::new, |resolver| {
-			std::mem::take(&mut *resolver.resolved.borrow_mut())
-		});
+		.expect("for async imports, import_resolver should be set to ResolvedImportResolver");
+
+	let mut resolved_map = resolved.resolved.borrow_mut();
+
 	let mut queue = vec![Job::LoadFile {
 		path: handler.resolve(path.as_ref()).await?,
 		parse: true,
@@ -344,7 +340,7 @@
 			}
 			Job::ResolveImport { from, import } => {
 				if let Some((resolved, expression)) =
-					resolved.get_mut(&(from.clone(), import.path.clone()))
+					resolved_map.get_mut(&(from.clone(), import.path.clone()))
 				{
 					if import.expression && !*expression {
 						*expression = true;
@@ -360,8 +356,5 @@
 			}
 		}
 	}
-	s.set_import_resolver(ResolvedImportResolver {
-		resolved: RefCell::new(resolved),
-	});
 	Ok(())
 }
modifiedcrates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/ctx.rs
+++ b/crates/jrsonnet-evaluator/src/ctx.rs
@@ -2,10 +2,11 @@
 
 use jrsonnet_gcmodule::{Cc, Trace};
 use jrsonnet_interner::IStr;
+use rustc_hash::FxHashMap;
 
 use crate::{
-	error::ErrorKind::*, gc::GcHashMap, map::LayeredHashMap, ObjValue, Pending, Result, State,
-	Thunk, Val,
+	error::ErrorKind::*, gc::WithCapacityExt as _, map::LayeredHashMap, ObjValue, Pending, Result,
+	State, Thunk, Val,
 };
 
 #[derive(Trace)]
@@ -88,7 +89,7 @@
 
 	#[must_use]
 	pub fn with_var(self, name: impl Into<IStr>, value: Val) -> Self {
-		let mut new_bindings = GcHashMap::with_capacity(1);
+		let mut new_bindings = FxHashMap::with_capacity(1);
 		new_bindings.insert(name.into(), Thunk::evaluated(value));
 		self.extend(new_bindings, None, None, None)
 	}
@@ -96,7 +97,7 @@
 	#[must_use]
 	pub fn extend(
 		self,
-		new_bindings: GcHashMap<IStr, Thunk<Val>>,
+		new_bindings: FxHashMap<IStr, Thunk<Val>>,
 		new_dollar: Option<ObjValue>,
 		new_sup: Option<ObjValue>,
 		new_this: Option<ObjValue>,
@@ -128,7 +129,7 @@
 
 pub struct ContextBuilder {
 	state: Option<State>,
-	bindings: GcHashMap<IStr, Thunk<Val>>,
+	bindings: FxHashMap<IStr, Thunk<Val>>,
 	extend: Option<Context>,
 }
 
@@ -138,7 +139,7 @@
 	pub fn dangerous_empty_state() -> Self {
 		Self {
 			state: None,
-			bindings: GcHashMap::new(),
+			bindings: FxHashMap::new(),
 			extend: None,
 		}
 	}
@@ -148,14 +149,14 @@
 	pub fn with_capacity(state: State, capacity: usize) -> Self {
 		Self {
 			state: Some(state),
-			bindings: GcHashMap::with_capacity(capacity),
+			bindings: FxHashMap::with_capacity(capacity),
 			extend: None,
 		}
 	}
 	pub fn extend(parent: Context) -> Self {
 		Self {
 			state: parent.0.state.clone(),
-			bindings: GcHashMap::new(),
+			bindings: FxHashMap::new(),
 			extend: Some(parent),
 		}
 	}
modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -138,12 +138,12 @@
 	#[error("assert failed: {}", format_empty_str(.0))]
 	AssertionFailed(IStr),
 
-	#[error("local is not defined: {0}{}", format_found(.1, "local"))]
+	#[error("local is not defined: {0}{found}", found = format_found(.1, "local"))]
 	VariableIsNotDefined(IStr, Vec<IStr>),
 	#[error("duplicate local var: {0}")]
 	DuplicateLocalVar(IStr),
 
-	#[error("type mismatch: expected {}, got {2} {0}", .1.iter().map(|e| format!("{e}")).collect::<Vec<_>>().join(", "))]
+	#[error("type mismatch: expected {expected}, got {2} {0}", expected = .1.iter().map(|e| format!("{e}")).collect::<Vec<_>>().join(", "))]
 	TypeMismatch(&'static str, Vec<ValType>, ValType),
 	#[error("no such field: {}{}", format_empty_str(.0), format_found(.1, "field"))]
 	NoSuchField(IStr, Vec<IStr>),
@@ -154,7 +154,7 @@
 	UnknownFunctionParameter(String),
 	#[error("argument {0} is already bound")]
 	BindingParameterASecondTime(IStr),
-	#[error("too many args, function has {0}{}", format_signature(.1))]
+	#[error("too many args, function has {0}{sig}", sig = format_signature(.1))]
 	TooManyArgsFunctionHas(usize, FunctionSignature),
 	#[error("function argument is not passed: {}{}", .0.as_ref().map_or("<unnamed>", IStr::as_str), format_signature(.1))]
 	FunctionParameterNotBoundInCall(Option<IStr>, FunctionSignature),
modifiedcrates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/evaluate/destructure.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/destructure.rs
@@ -1,12 +1,11 @@
 use jrsonnet_interner::IStr;
 use jrsonnet_parser::{BindSpec, Destruct};
+use rustc_hash::FxHashMap;
 
 use crate::{
 	bail,
 	error::{ErrorKind::*, Result},
-	evaluate, evaluate_method, evaluate_named,
-	gc::GcHashMap,
-	Context, Pending, Thunk, Val,
+	evaluate, evaluate_method, evaluate_named, Context, Pending, Thunk, Val,
 };
 
 #[allow(clippy::too_many_lines)]
@@ -15,7 +14,7 @@
 	d: &Destruct,
 	parent: Thunk<Val>,
 	fctx: Pending<Context>,
-	new_bindings: &mut GcHashMap<IStr, Thunk<Val>>,
+	new_bindings: &mut FxHashMap<IStr, Thunk<Val>>,
 ) -> Result<()> {
 	match d {
 		Destruct::Full(v) => {
@@ -163,7 +162,7 @@
 pub fn evaluate_dest(
 	d: &BindSpec,
 	fctx: Pending<Context>,
-	new_bindings: &mut GcHashMap<IStr, Thunk<Val>>,
+	new_bindings: &mut FxHashMap<IStr, Thunk<Val>>,
 ) -> Result<()> {
 	match d {
 		BindSpec::Field { into, value } => {
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -7,6 +7,7 @@
 	ForSpecData, IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc,
 };
 use jrsonnet_types::ValType;
+use rustc_hash::FxHashMap;
 
 use self::destructure::destruct;
 use crate::{
@@ -16,11 +17,12 @@
 	error::{suggest_object_fields, ErrorKind::*},
 	evaluate::operator::{evaluate_add_op, evaluate_binary_op_special, evaluate_unary_op},
 	function::{CallLocation, FuncDesc, FuncVal},
+	gc::WithCapacityExt as _,
 	in_frame,
 	typed::Typed,
 	val::{CachedUnbound, IndexableVal, NumValue, StrValue, Thunk},
-	Context, Error, GcHashMap, ObjValue, ObjValueBuilder, ObjectAssertion, Pending, Result,
-	ResultExt, Unbound, Val,
+	Context, Error, ObjValue, ObjValueBuilder, ObjectAssertion, Pending, Result, ResultExt,
+	Unbound, Val,
 };
 pub mod destructure;
 pub mod operator;
@@ -122,7 +124,7 @@
 			Val::Arr(list) => {
 				for item in list.iter_lazy() {
 					let fctx = Pending::new();
-					let mut new_bindings = GcHashMap::with_capacity(var.capacity_hint());
+					let mut new_bindings = FxHashMap::with_capacity(var.capacity_hint());
 					destruct(var, item, fctx.clone(), &mut new_bindings)?;
 					let ctx = ctx
 						.clone()
@@ -140,7 +142,7 @@
 					false,
 				) {
 					let fctx = Pending::new();
-					let mut new_bindings = GcHashMap::with_capacity(var.capacity_hint());
+					let mut new_bindings = FxHashMap::with_capacity(var.capacity_hint());
 					let obj = obj.clone();
 					let value = Thunk::evaluated(Val::Arr(ArrValue::lazy(vec![
 						Thunk::evaluated(Val::string(field.clone())),
@@ -181,7 +183,7 @@
 		fn bind(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Context> {
 			let fctx = Context::new_future();
 			let mut new_bindings =
-				GcHashMap::with_capacity(self.locals.iter().map(BindSpec::capacity_hint).sum());
+				FxHashMap::with_capacity(self.locals.iter().map(BindSpec::capacity_hint).sum());
 			for b in self.locals.iter() {
 				evaluate_dest(b, fctx.clone(), &mut new_bindings)?;
 			}
@@ -329,7 +331,7 @@
 		}
 	}
 	let this = builder.build();
-	fctx.fill(ctx.extend(GcHashMap::new(), None, None, Some(this.clone())));
+	fctx.fill(ctx.extend(FxHashMap::new(), None, None, Some(this.clone())));
 	Ok(this)
 }
 
@@ -357,7 +359,7 @@
 			let this = builder.build();
 			for (ctx, fctx) in ctxs {
 				let _ctx = ctx
-					.extend(GcHashMap::new(), None, None, Some(this.clone()))
+					.extend(FxHashMap::new(), None, None, Some(this.clone()))
 					.into_future(fctx);
 			}
 			this
@@ -581,8 +583,8 @@
 			Ok(indexable)
 		})?,
 		LocalExpr(bindings, returned) => {
-			let mut new_bindings: GcHashMap<IStr, Thunk<Val>> =
-				GcHashMap::with_capacity(bindings.iter().map(BindSpec::capacity_hint).sum());
+			let mut new_bindings: FxHashMap<IStr, Thunk<Val>> =
+				FxHashMap::with_capacity(bindings.iter().map(BindSpec::capacity_hint).sum());
 			let fctx = Context::new_future();
 			for b in bindings {
 				evaluate_dest(b, fctx.clone(), &mut new_bindings)?;
modifiedcrates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/evaluate/operator.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/operator.rs
@@ -2,11 +2,6 @@
 
 use jrsonnet_parser::{BinaryOpType, LocExpr, UnaryOpType};
 
-#[cfg(feature = "exp-bigint")]
-use num_traits::{FromPrimitive, ToPrimitive};
-
-#[cfg(feature = "exp-bigint")]
-use crate::val::NumValue;
 use crate::{
 	arr::ArrValue,
 	bail,
modifiedcrates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/function/arglike.rs
+++ b/crates/jrsonnet-evaluator/src/function/arglike.rs
@@ -1,9 +1,10 @@
-use hashbrown::HashMap;
+use std::collections::HashMap;
+
 use jrsonnet_gcmodule::Trace;
 use jrsonnet_interner::IStr;
 use jrsonnet_parser::{ArgsDesc, LocExpr};
 
-use crate::{evaluate, gc::GcHashMap, typed::Typed, Context, Result, Thunk, Val};
+use crate::{evaluate, typed::Typed, Context, Result, Thunk, Val};
 
 /// Marker for arguments, which can be evaluated with context set to None
 pub trait OptionalContext {}
@@ -204,38 +205,6 @@
 	}
 }
 impl<V, S> OptionalContext for HashMap<IStr, V, S> where V: ArgLike + OptionalContext {}
-
-impl<A: ArgLike> ArgsLike for GcHashMap<IStr, A> {
-	fn unnamed_len(&self) -> usize {
-		self.0.unnamed_len()
-	}
-
-	fn unnamed_iter(
-		&self,
-		ctx: Context,
-		tailstrict: bool,
-		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,
-	) -> Result<()> {
-		self.0.unnamed_iter(ctx, tailstrict, handler)
-	}
-
-	fn named_iter(
-		&self,
-		ctx: Context,
-		tailstrict: bool,
-		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,
-	) -> Result<()> {
-		self.0.named_iter(ctx, tailstrict, handler)
-	}
-
-	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {
-		self.0.named_names(handler);
-	}
-
-	fn is_empty(&self) -> bool {
-		self.0.is_empty()
-	}
-}
 
 macro_rules! impl_args_like {
 	($count:expr; $($gen:ident)*) => {
modifiedcrates/jrsonnet-evaluator/src/function/builtin.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/function/builtin.rs
+++ b/crates/jrsonnet-evaluator/src/function/builtin.rs
@@ -1,10 +1,10 @@
 use std::{any::Any, borrow::Cow};
 
-use jrsonnet_gcmodule::Trace;
+use jrsonnet_gcmodule::{cc_dyn, Trace, TraceBox};
 use jrsonnet_interner::IStr;
 
 use super::{arglike::ArgsLike, parse::parse_builtin_call, CallLocation};
-use crate::{gc::TraceBox, tb, Context, Result, Val};
+use crate::{Context, Result, Val};
 
 /// Can't have `str` | `IStr`, because constant `BuiltinParam` causes
 /// `E0492: constant functions cannot refer to interior mutable data`
@@ -70,6 +70,30 @@
 	}
 }
 
+cc_dyn!(
+	#[derive(Clone)]
+	BuiltinFunc,
+	Builtin,
+	pub(crate) fn new() {...}
+);
+impl Builtin for BuiltinFunc {
+	fn name(&self) -> &str {
+		self.0.name()
+	}
+
+	fn params(&self) -> &[BuiltinParam] {
+		self.0.params()
+	}
+
+	fn call(&self, ctx: Context, loc: CallLocation<'_>, args: &dyn ArgsLike) -> Result<Val> {
+		self.0.call(ctx, loc, args)
+	}
+
+	fn as_any(&self) -> &dyn Any {
+		self.0.as_any()
+	}
+}
+
 /// Description of function defined by native code
 ///
 /// Prefer to use #[builtin] macro, instead of manual implementation of this trait
@@ -108,7 +132,7 @@
 					default: ParamDefault::None,
 				})
 				.collect(),
-			handler: tb!(handler),
+			handler: TraceBox(Box::new(handler)),
 		}
 	}
 }
modifiedcrates/jrsonnet-evaluator/src/function/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/function/mod.rs
+++ b/crates/jrsonnet-evaluator/src/function/mod.rs
@@ -13,7 +13,7 @@
 	parse::{parse_default_function_call, parse_function_call},
 };
 use crate::{
-	bail, error::ErrorKind::*, evaluate, evaluate_trivial, gc::TraceBox, tb, Context,
+	bail, error::ErrorKind::*, evaluate, evaluate_trivial, function::builtin::BuiltinFunc, Context,
 	ContextBuilder, Result, Thunk, Val,
 };
 
@@ -102,7 +102,7 @@
 	/// Standard library function.
 	StaticBuiltin(#[trace(skip)] &'static dyn StaticBuiltin),
 	/// User-provided function.
-	Builtin(Cc<TraceBox<dyn Builtin>>),
+	Builtin(BuiltinFunc),
 }
 
 impl Debug for FuncVal {
@@ -128,7 +128,7 @@
 
 impl FuncVal {
 	pub fn builtin(builtin: impl Builtin) -> Self {
-		Self::Builtin(Cc::new(tb!(builtin)))
+		Self::Builtin(BuiltinFunc::new(builtin))
 	}
 	pub fn static_builtin(static_builtin: &'static dyn StaticBuiltin) -> Self {
 		Self::StaticBuiltin(static_builtin)
modifiedcrates/jrsonnet-evaluator/src/function/parse.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/function/parse.rs
+++ b/crates/jrsonnet-evaluator/src/function/parse.rs
@@ -2,6 +2,7 @@
 
 use jrsonnet_interner::IStr;
 use jrsonnet_parser::ParamsDesc;
+use rustc_hash::FxHashMap;
 
 use super::{arglike::ArgsLike, builtin::BuiltinParam};
 use crate::{
@@ -10,7 +11,7 @@
 	error::{ErrorKind::*, Result},
 	evaluate_named,
 	function::builtin::ParamDefault,
-	gc::GcHashMap,
+	gc::WithCapacityExt as _,
 	Context, Pending, Thunk, Val,
 };
 
@@ -30,7 +31,7 @@
 	tailstrict: bool,
 ) -> Result<Context> {
 	let mut passed_args =
-		GcHashMap::with_capacity(params.iter().map(|p| p.0.capacity_hint()).sum());
+		FxHashMap::with_capacity(params.iter().map(|p| p.0.capacity_hint()).sum());
 	if args.unnamed_len() > params.len() {
 		bail!(TooManyArgsFunctionHas(
 			params.len(),
@@ -72,7 +73,7 @@
 		// Some args are unset, but maybe we have defaults for them
 		// Default values should be created in newly created context
 		let fctx = Context::new_future();
-		let mut defaults = GcHashMap::with_capacity(
+		let mut defaults = FxHashMap::with_capacity(
 			params.iter().map(|p| p.0.capacity_hint()).sum::<usize>()
 				- filled_named
 				- filled_positionals,
@@ -220,7 +221,7 @@
 pub fn parse_default_function_call(body_ctx: Context, params: &ParamsDesc) -> Result<Context> {
 	let fctx = Context::new_future();
 
-	let mut bindings = GcHashMap::with_capacity(params.iter().map(|p| p.0.capacity_hint()).sum());
+	let mut bindings = FxHashMap::with_capacity(params.iter().map(|p| p.0.capacity_hint()).sum());
 
 	for param in params.iter() {
 		if let Some(v) = &param.1 {
modifiedcrates/jrsonnet-evaluator/src/gc.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/gc.rs
+++ b/crates/jrsonnet-evaluator/src/gc.rs
@@ -1,161 +1,27 @@
 /// Macros to help deal with Gc
-use std::{
-	borrow::{Borrow, BorrowMut},
-	collections::HashSet,
-	hash::BuildHasherDefault,
-	ops::{Deref, DerefMut},
-};
-
-use hashbrown::HashMap;
-use jrsonnet_gcmodule::{Trace, Tracer};
-use rustc_hash::{FxHashSet, FxHasher};
+use jrsonnet_gcmodule::Trace;
+use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
 
-/// Replacement for box, which assumes that the underlying type is [`Trace`]
-/// Used in places, where `Cc<dyn Trait>` should be used instead, but it can't, because `CoerceUnsiced` is not stable
-#[derive(Debug, Clone)]
-pub struct TraceBox<T: ?Sized>(pub Box<T>);
-#[macro_export]
-macro_rules! tb {
-	($v:expr) => {
-		$crate::gc::TraceBox(Box::new($v))
-	};
+pub trait WithCapacityExt {
+	fn new() -> Self;
+	fn with_capacity(capacity: usize) -> Self;
 }
-
-impl<T: ?Sized + Trace> Trace for TraceBox<T> {
-	fn trace(&self, tracer: &mut Tracer<'_>) {
-		self.0.trace(tracer);
+impl<V> WithCapacityExt for FxHashSet<V> {
+	fn with_capacity(capacity: usize) -> Self {
+		Self::with_capacity_and_hasher(capacity, FxBuildHasher::default())
 	}
 
-	fn is_type_tracked() -> bool {
-		true
+	fn new() -> Self {
+		Self::with_hasher(FxBuildHasher::default())
 	}
 }
-
-// TODO: Replace with CoerceUnsized
-impl<T: ?Sized> From<Box<T>> for TraceBox<T> {
-	fn from(inner: Box<T>) -> Self {
-		Self(inner)
+impl<K, V> WithCapacityExt for FxHashMap<K, V> {
+	fn with_capacity(capacity: usize) -> Self {
+		Self::with_capacity_and_hasher(capacity, FxBuildHasher::default())
 	}
-}
-
-impl<T: ?Sized> Deref for TraceBox<T> {
-	type Target = T;
 
-	fn deref(&self) -> &Self::Target {
-		&self.0
-	}
-}
-impl<T: Trace + ?Sized> DerefMut for TraceBox<T> {
-	fn deref_mut(&mut self) -> &mut Self::Target {
-		&mut self.0
-	}
-}
-
-impl<T: ?Sized> Borrow<T> for TraceBox<T> {
-	fn borrow(&self) -> &T {
-		&self.0
-	}
-}
-
-impl<T: ?Sized> BorrowMut<T> for TraceBox<T> {
-	fn borrow_mut(&mut self) -> &mut T {
-		&mut self.0
-	}
-}
-
-impl<T: ?Sized> AsRef<T> for TraceBox<T> {
-	fn as_ref(&self) -> &T {
-		&self.0
-	}
-}
-
-impl<T: ?Sized> AsMut<T> for TraceBox<T> {
-	fn as_mut(&mut self) -> &mut T {
-		&mut self.0
-	}
-}
-
-#[derive(Clone)]
-pub struct GcHashSet<V>(pub FxHashSet<V>);
-impl<V> GcHashSet<V> {
-	pub fn new() -> Self {
-		Self(HashSet::default())
-	}
-	pub fn with_capacity(capacity: usize) -> Self {
-		Self(FxHashSet::with_capacity_and_hasher(
-			capacity,
-			BuildHasherDefault::default(),
-		))
-	}
-}
-impl<V> Trace for GcHashSet<V>
-where
-	V: Trace,
-{
-	fn trace(&self, tracer: &mut Tracer<'_>) {
-		for v in &self.0 {
-			v.trace(tracer);
-		}
-	}
-}
-impl<V> Deref for GcHashSet<V> {
-	type Target = FxHashSet<V>;
-
-	fn deref(&self) -> &Self::Target {
-		&self.0
-	}
-}
-impl<V> DerefMut for GcHashSet<V> {
-	fn deref_mut(&mut self) -> &mut Self::Target {
-		&mut self.0
-	}
-}
-impl<V> Default for GcHashSet<V> {
-	fn default() -> Self {
-		Self::new()
-	}
-}
-
-#[derive(Debug)]
-pub struct GcHashMap<K, V>(pub HashMap<K, V, BuildHasherDefault<FxHasher>>);
-impl<K, V> GcHashMap<K, V> {
-	pub fn new() -> Self {
-		Self(HashMap::default())
-	}
-	pub fn with_capacity(capacity: usize) -> Self {
-		Self(HashMap::with_capacity_and_hasher(
-			capacity,
-			BuildHasherDefault::default(),
-		))
-	}
-}
-impl<K, V> Trace for GcHashMap<K, V>
-where
-	K: Trace,
-	V: Trace,
-{
-	fn trace(&self, tracer: &mut Tracer<'_>) {
-		for (k, v) in &self.0 {
-			k.trace(tracer);
-			v.trace(tracer);
-		}
-	}
-}
-impl<K, V> Deref for GcHashMap<K, V> {
-	type Target = HashMap<K, V, BuildHasherDefault<FxHasher>>;
-
-	fn deref(&self) -> &Self::Target {
-		&self.0
-	}
-}
-impl<K, V> DerefMut for GcHashMap<K, V> {
-	fn deref_mut(&mut self) -> &mut Self::Target {
-		&mut self.0
-	}
-}
-impl<K, V> Default for GcHashMap<K, V> {
-	fn default() -> Self {
-		Self::new()
+	fn new() -> Self {
+		Self::with_hasher(FxBuildHasher::default())
 	}
 }
 
modifiedcrates/jrsonnet-evaluator/src/import.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/import.rs
+++ b/crates/jrsonnet-evaluator/src/import.rs
@@ -7,7 +7,7 @@
 };
 
 use fs::File;
-use jrsonnet_gcmodule::Trace;
+use jrsonnet_gcmodule::Acyclic;
 use jrsonnet_interner::IBytes;
 use jrsonnet_parser::{SourceDirectory, SourceFifo, SourceFile, SourcePath};
 
@@ -17,7 +17,7 @@
 };
 
 /// Implements file resolution logic for `import` and `importStr`
-pub trait ImportResolver: Trace {
+pub trait ImportResolver: Acyclic + Any {
 	/// Resolves file path, e.g. `(/home/user/manifests, b.libjsonnet)` can correspond
 	/// both to `/home/user/manifests/b.libjsonnet` and to `/home/user/${vendor}/b.libjsonnet`
 	/// where `${vendor}` is a library path.
@@ -39,26 +39,14 @@
 	/// This should only be called with value returned from [`ImportResolver::resolve_file`]/[`ImportResolver::resolve`],
 	/// this cannot be resolved using associated type, as evaluator uses object instead of generic for [`ImportResolver`]
 	fn load_file_contents(&self, resolved: &SourcePath) -> Result<Vec<u8>>;
-
-	// For downcasts, will be removed after trait_upcasting_coercion
-	// stabilization.
-	fn as_any(&self) -> &dyn Any;
-	fn as_any_mut(&mut self) -> &mut dyn Any;
 }
 
 /// Dummy resolver, can't resolve/load any file
-#[derive(Trace)]
+#[derive(Acyclic)]
 pub struct DummyImportResolver;
 impl ImportResolver for DummyImportResolver {
 	fn load_file_contents(&self, _resolved: &SourcePath) -> Result<Vec<u8>> {
 		panic!("dummy resolver can't load any file")
-	}
-
-	fn as_any(&self) -> &dyn Any {
-		self
-	}
-	fn as_any_mut(&mut self) -> &mut dyn Any {
-		self
 	}
 }
 #[allow(clippy::use_self)]
@@ -69,7 +57,7 @@
 }
 
 /// File resolver, can load file from both FS and library paths
-#[derive(Default, Trace)]
+#[derive(Default, Acyclic)]
 pub struct FileImportResolver {
 	/// Library directories to search for file.
 	/// Referred to as `jpath` in original jsonnet implementation.
@@ -169,13 +157,5 @@
 
 	fn resolve_from_default(&self, path: &str) -> Result<SourcePath> {
 		self.resolve_from(&SourcePath::default(), path)
-	}
-
-	fn as_any(&self) -> &dyn Any {
-		self
-	}
-
-	fn as_any_mut(&mut self) -> &mut dyn Any {
-		self
 	}
 }
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -1,11 +1,10 @@
 //! jsonnet interpreter implementation
-#![cfg_attr(feature = "nightly", feature(thread_local, type_alias_impl_trait))]
+#![cfg_attr(nightly, feature(thread_local, type_alias_impl_trait))]
 
 // For jrsonnet-macros
 extern crate self as jrsonnet_evaluator;
 
 mod arr;
-#[cfg(feature = "async-import")]
 pub mod async_import;
 mod ctx;
 mod dynamic;
@@ -28,8 +27,10 @@
 use std::{
 	any::Any,
 	cell::{RefCell, RefMut},
+	collections::hash_map::Entry,
 	fmt::{self, Debug},
 	path::Path,
+	rc::Rc,
 };
 
 pub use ctx::*;
@@ -37,20 +38,28 @@
 pub use error::{Error, ErrorKind::*, Result, ResultExt};
 pub use evaluate::*;
 use function::CallLocation;
-use gc::{GcHashMap, TraceBox};
-use hashbrown::hash_map::RawEntryMut;
 pub use import::*;
-use jrsonnet_gcmodule::{Cc, Trace};
+use jrsonnet_gcmodule::{cc_dyn, Cc, Trace};
 pub use jrsonnet_interner::{IBytes, IStr};
 #[doc(hidden)]
 pub use jrsonnet_macros;
 pub use jrsonnet_parser as parser;
 use jrsonnet_parser::{LocExpr, ParserSettings, Source, SourcePath};
 pub use obj::*;
+pub use rustc_hash;
+use rustc_hash::FxHashMap;
 use stack::check_depth;
 pub use tla::apply_tla;
 pub use val::{Thunk, Val};
 
+use crate::gc::WithCapacityExt as _;
+
+cc_dyn!(
+	#[derive(Clone)]
+	CcUnbound<V>,
+	Unbound<Bound = V>
+);
+
 /// Thunk without bound `super`/`this`
 /// object inheritance may be overriden multiple times, and will be fixed only on field read
 pub trait Unbound: Trace {
@@ -65,7 +74,7 @@
 #[derive(Clone, Trace)]
 pub enum MaybeUnbound {
 	/// Value needs to be bound to `this`/`super`
-	Unbound(Cc<TraceBox<dyn Unbound<Bound = Val>>>),
+	Unbound(CcUnbound<Val>),
 	/// Value is object-independent
 	Bound(Thunk<Val>),
 }
@@ -79,12 +88,14 @@
 	/// Attach object context to value, if required
 	pub fn evaluate(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Val> {
 		match self {
-			Self::Unbound(v) => v.bind(sup, this),
+			Self::Unbound(v) => v.0.bind(sup, this),
 			Self::Bound(v) => Ok(v.evaluate()?),
 		}
 	}
 }
 
+cc_dyn!(CcContextInitializer, ContextInitializer);
+
 /// During import, this trait will be called to create initial context for file.
 /// It may initialize global variables, stdlib for example.
 pub trait ContextInitializer: Trace {
@@ -215,12 +226,12 @@
 #[derive(Trace)]
 pub struct EvaluationStateInternals {
 	/// Internal state
-	file_cache: RefCell<GcHashMap<SourcePath, FileData>>,
+	file_cache: RefCell<FxHashMap<SourcePath, FileData>>,
 	/// Context initializer, which will be used for imports and everything
 	/// [`NoopContextInitializer`] is used by default, most likely you want to have `jrsonnet-stdlib`
-	context_initializer: TraceBox<dyn ContextInitializer>,
+	context_initializer: CcContextInitializer,
 	/// Used to resolve file locations/contents
-	import_resolver: TraceBox<dyn ImportResolver>,
+	import_resolver: Rc<dyn ImportResolver>,
 }
 
 /// Maintains stack trace and import resolution
@@ -231,21 +242,17 @@
 	/// Should only be called with path retrieved from [`resolve_path`], may panic otherwise
 	pub fn import_resolved_str(&self, path: SourcePath) -> Result<IStr> {
 		let mut file_cache = self.file_cache();
-		let mut file = file_cache.raw_entry_mut().from_key(&path);
+		let mut file = file_cache.entry(path.clone());
 
 		let file = match file {
-			RawEntryMut::Occupied(ref mut d) => d.get_mut(),
-			RawEntryMut::Vacant(v) => {
+			Entry::Occupied(ref mut d) => d.get_mut(),
+			Entry::Vacant(v) => {
 				let data = self.import_resolver().load_file_contents(&path)?;
-				v.insert(
-					path.clone(),
-					FileData::new_string(
-						std::str::from_utf8(&data)
-							.map_err(|_| ImportBadFileUtf8(path.clone()))?
-							.into(),
-					),
-				)
-				.1
+				v.insert(FileData::new_string(
+					std::str::from_utf8(&data)
+						.map_err(|_| ImportBadFileUtf8(path.clone()))?
+						.into(),
+				))
 			}
 		};
 		Ok(file
@@ -255,14 +262,13 @@
 	/// Should only be called with path retrieved from [`resolve_path`], may panic otherwise
 	pub fn import_resolved_bin(&self, path: SourcePath) -> Result<IBytes> {
 		let mut file_cache = self.file_cache();
-		let mut file = file_cache.raw_entry_mut().from_key(&path);
+		let mut file = file_cache.entry(path.clone());
 
 		let file = match file {
-			RawEntryMut::Occupied(ref mut d) => d.get_mut(),
-			RawEntryMut::Vacant(v) => {
+			Entry::Occupied(ref mut d) => d.get_mut(),
+			Entry::Vacant(v) => {
 				let data = self.import_resolver().load_file_contents(&path)?;
-				v.insert(path.clone(), FileData::new_bytes(data.as_slice().into()))
-					.1
+				v.insert(FileData::new_bytes(data.as_slice().into()))
 			}
 		};
 		if let Some(str) = &file.bytes {
@@ -282,21 +288,17 @@
 	/// Should only be called with path retrieved from [`resolve_path`], may panic otherwise
 	pub fn import_resolved(&self, path: SourcePath) -> Result<Val> {
 		let mut file_cache = self.file_cache();
-		let mut file = file_cache.raw_entry_mut().from_key(&path);
+		let mut file = file_cache.entry(path.clone());
 
 		let file = match file {
-			RawEntryMut::Occupied(ref mut d) => d.get_mut(),
-			RawEntryMut::Vacant(v) => {
+			Entry::Occupied(ref mut d) => d.get_mut(),
+			Entry::Vacant(v) => {
 				let data = self.import_resolver().load_file_contents(&path)?;
-				v.insert(
-					path.clone(),
-					FileData::new_string(
-						std::str::from_utf8(&data)
-							.map_err(|_| ImportBadFileUtf8(path.clone()))?
-							.into(),
-					),
-				)
-				.1
+				v.insert(FileData::new_string(
+					std::str::from_utf8(&data)
+						.map_err(|_| ImportBadFileUtf8(path.clone()))?
+						.into(),
+				))
 			}
 		};
 		if let Some(val) = &file.evaluated {
@@ -330,10 +332,10 @@
 		let res = evaluate(self.create_default_context(file_name), &parsed);
 
 		let mut file_cache = self.file_cache();
-		let mut file = file_cache.raw_entry_mut().from_key(&path);
+		let mut file = file_cache.entry(path.clone());
 
-		let RawEntryMut::Occupied(file) = &mut file else {
-			unreachable!("this file was just here!")
+		let Entry::Occupied(file) = &mut file else {
+			unreachable!("this file was just here")
 		};
 		let file = file.get_mut();
 		file.evaluating = false;
@@ -381,7 +383,7 @@
 
 /// Internals
 impl State {
-	fn file_cache(&self) -> RefMut<'_, GcHashMap<SourcePath, FileData>> {
+	fn file_cache(&self) -> RefMut<'_, FxHashMap<SourcePath, FileData>> {
 		self.0.file_cache.borrow_mut()
 	}
 }
@@ -479,7 +481,7 @@
 		&*self.0.import_resolver
 	}
 	pub fn context_initializer(&self) -> &dyn ContextInitializer {
-		&*self.0.context_initializer
+		&*self.0.context_initializer.0
 	}
 }
 
@@ -497,29 +499,34 @@
 
 #[derive(Default)]
 pub struct StateBuilder {
-	import_resolver: Option<TraceBox<dyn ImportResolver>>,
-	context_initializer: Option<TraceBox<dyn ContextInitializer>>,
+	import_resolver: Option<Rc<dyn ImportResolver>>,
+	context_initializer: Option<CcContextInitializer>,
 }
 impl StateBuilder {
 	pub fn import_resolver(&mut self, import_resolver: impl ImportResolver) -> &mut Self {
-		let _ = self.import_resolver.insert(tb!(import_resolver));
+		let _ = self.import_resolver.insert(Rc::new(import_resolver));
 		self
 	}
 	pub fn context_initializer(
 		&mut self,
 		context_initializer: impl ContextInitializer,
 	) -> &mut Self {
-		let _ = self.context_initializer.insert(tb!(context_initializer));
+		let _ = self
+			.context_initializer
+			.insert(CcContextInitializer::new(context_initializer));
 		self
 	}
 	pub fn build(mut self) -> State {
 		State(Cc::new(EvaluationStateInternals {
-			file_cache: RefCell::new(GcHashMap::new()),
-			context_initializer: self.context_initializer.take().unwrap_or_else(|| tb!(())),
+			file_cache: RefCell::new(FxHashMap::new()),
+			context_initializer: self
+				.context_initializer
+				.take()
+				.unwrap_or_else(|| CcContextInitializer::new(())),
 			import_resolver: self
 				.import_resolver
 				.take()
-				.unwrap_or_else(|| tb!(DummyImportResolver)),
+				.unwrap_or_else(|| Rc::new(DummyImportResolver)),
 		}))
 	}
 }
modifiedcrates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/map.rs
+++ b/crates/jrsonnet-evaluator/src/map.rs
@@ -1,13 +1,14 @@
 use jrsonnet_gcmodule::{Cc, Trace};
 use jrsonnet_interner::IStr;
+use rustc_hash::FxHashMap;
 
-use crate::{GcHashMap, Thunk, Val};
+use crate::{gc::WithCapacityExt as _, Thunk, Val};
 
 #[derive(Trace)]
 #[trace(tracking(force))]
 pub struct LayeredHashMapInternals {
 	parent: Option<LayeredHashMap>,
-	current: GcHashMap<IStr, Thunk<Val>>,
+	current: FxHashMap<IStr, Thunk<Val>>,
 }
 
 #[derive(Trace)]
@@ -15,7 +16,7 @@
 
 impl LayeredHashMap {
 	pub fn iter_keys(self, mut handler: impl FnMut(IStr)) {
-		for (k, _) in &*self.0.current {
+		for (k, _) in &self.0.current {
 			handler(k.clone());
 		}
 		if let Some(parent) = self.0.parent.clone() {
@@ -23,14 +24,14 @@
 		}
 	}
 
-	pub(crate) fn new(layer: GcHashMap<IStr, Thunk<Val>>) -> Self {
+	pub(crate) fn new(layer: FxHashMap<IStr, Thunk<Val>>) -> Self {
 		Self(Cc::new(LayeredHashMapInternals {
 			parent: None,
 			current: layer,
 		}))
 	}
 
-	pub fn extend(self, new_layer: GcHashMap<IStr, Thunk<Val>>) -> Self {
+	pub fn extend(self, new_layer: FxHashMap<IStr, Thunk<Val>>) -> Self {
 		Self(Cc::new(LayeredHashMapInternals {
 			parent: Some(self),
 			current: new_layer,
@@ -64,7 +65,7 @@
 	fn default() -> Self {
 		Self(Cc::new(LayeredHashMapInternals {
 			parent: None,
-			current: GcHashMap::new(),
+			current: FxHashMap::new(),
 		}))
 	}
 }
modifiedcrates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/obj.rs
+++ b/crates/jrsonnet-evaluator/src/obj.rs
@@ -6,22 +6,21 @@
 	ptr::addr_of,
 };
 
-use jrsonnet_gcmodule::{Cc, Trace, Weak};
+use jrsonnet_gcmodule::{cc_dyn, Cc, Trace, Weak};
 use jrsonnet_interner::IStr;
 use jrsonnet_parser::{Span, Visibility};
-use rustc_hash::FxHashMap;
+use rustc_hash::{FxHashMap, FxHashSet};
 
 use crate::{
 	arr::{PickObjectKeyValues, PickObjectValues},
 	bail,
 	error::{suggest_object_fields, Error, ErrorKind::*},
 	function::{CallLocation, FuncVal},
-	gc::{GcHashMap, GcHashSet, TraceBox},
+	gc::WithCapacityExt as _,
 	in_frame,
 	operator::evaluate_add_op,
-	tb,
 	val::ArrValue,
-	MaybeUnbound, Result, Thunk, Unbound, Val,
+	CcUnbound, MaybeUnbound, Result, Thunk, Unbound, Val,
 };
 
 #[cfg(not(feature = "exp-preserve-order"))]
@@ -139,6 +138,7 @@
 	pub location: Option<Span>,
 }
 
+cc_dyn!(CcObjectAssertion, ObjectAssertion);
 pub trait ObjectAssertion: Trace {
 	fn run(&self, super_obj: Option<ObjValue>, this: Option<ObjValue>) -> Result<()>;
 }
@@ -159,10 +159,10 @@
 pub struct OopObject {
 	sup: Option<ObjValue>,
 	// this: Option<ObjValue>,
-	assertions: Cc<Vec<TraceBox<dyn ObjectAssertion>>>,
-	assertions_ran: RefCell<GcHashSet<ObjValue>>,
-	this_entries: Cc<GcHashMap<IStr, ObjMember>>,
-	value_cache: RefCell<GcHashMap<(IStr, Option<WeakObjValue>), CacheValue>>,
+	assertions: Cc<Vec<CcObjectAssertion>>,
+	assertions_ran: RefCell<FxHashSet<ObjValue>>,
+	this_entries: Cc<FxHashMap<IStr, ObjMember>>,
+	value_cache: RefCell<FxHashMap<(IStr, Option<WeakObjValue>), CacheValue>>,
 }
 impl Debug for OopObject {
 	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -203,7 +203,7 @@
 }
 
 #[derive(Clone, Trace)]
-pub struct WeakObjValue(#[trace(skip)] pub(crate) Weak<TraceBox<dyn ObjectLike>>);
+pub struct WeakObjValue(#[trace(skip)] pub(crate) Weak<dyn ObjectLike>);
 
 impl PartialEq for WeakObjValue {
 	fn eq(&self, other: &Self) -> bool {
@@ -220,9 +220,11 @@
 	}
 }
 
-#[allow(clippy::module_name_repetitions)]
-#[derive(Clone, Trace, Debug)]
-pub struct ObjValue(pub(crate) Cc<TraceBox<dyn ObjectLike>>);
+cc_dyn!(
+	#[derive(Clone, Debug)]
+	ObjValue, ObjectLike,
+	pub fn new() {...}
+);
 
 #[derive(Debug, Trace)]
 struct EmptyObject;
@@ -331,9 +333,6 @@
 }
 
 impl ObjValue {
-	pub fn new(v: impl ObjectLike) -> Self {
-		Self(Cc::new(tb!(v)))
-	}
 	pub fn new_empty() -> Self {
 		Self::new(EmptyObject)
 	}
@@ -582,16 +581,16 @@
 impl OopObject {
 	pub fn new(
 		sup: Option<ObjValue>,
-		this_entries: Cc<GcHashMap<IStr, ObjMember>>,
-		assertions: Cc<Vec<TraceBox<dyn ObjectAssertion>>>,
+		this_entries: Cc<FxHashMap<IStr, ObjMember>>,
+		assertions: Cc<Vec<CcObjectAssertion>>,
 	) -> Self {
 		Self {
 			sup,
 			// this: None,
 			assertions,
-			assertions_ran: RefCell::new(GcHashSet::new()),
+			assertions_ran: RefCell::new(FxHashSet::new()),
 			this_entries,
-			value_cache: RefCell::new(GcHashMap::new()),
+			value_cache: RefCell::new(FxHashMap::new()),
 		}
 	}
 
@@ -762,7 +761,7 @@
 		}
 		if self.assertions_ran.borrow_mut().insert(real_this.clone()) {
 			for assertion in self.assertions.iter() {
-				if let Err(e) = assertion.run(self.sup.clone(), Some(real_this.clone())) {
+				if let Err(e) = assertion.0.run(self.sup.clone(), Some(real_this.clone())) {
 					self.assertions_ran.borrow_mut().remove(&real_this);
 					return Err(e);
 				}
@@ -784,15 +783,15 @@
 impl Eq for ObjValue {}
 impl Hash for ObjValue {
 	fn hash<H: Hasher>(&self, hasher: &mut H) {
-		hasher.write_usize(addr_of!(*self.0) as usize);
+		hasher.write_usize(addr_of!(*self.0).expose_provenance() as usize);
 	}
 }
 
 #[allow(clippy::module_name_repetitions)]
 pub struct ObjValueBuilder {
 	sup: Option<ObjValue>,
-	map: GcHashMap<IStr, ObjMember>,
-	assertions: Vec<TraceBox<dyn ObjectAssertion>>,
+	map: FxHashMap<IStr, ObjMember>,
+	assertions: Vec<CcObjectAssertion>,
 	next_field_index: FieldIndex,
 }
 impl ObjValueBuilder {
@@ -802,7 +801,7 @@
 	pub fn with_capacity(capacity: usize) -> Self {
 		Self {
 			sup: None,
-			map: GcHashMap::with_capacity(capacity),
+			map: FxHashMap::with_capacity(capacity),
 			assertions: Vec::new(),
 			next_field_index: FieldIndex::default(),
 		}
@@ -817,7 +816,7 @@
 	}
 
 	pub fn assert(&mut self, assertion: impl ObjectAssertion + 'static) -> &mut Self {
-		self.assertions.push(tb!(assertion));
+		self.assertions.push(CcObjectAssertion::new(assertion));
 		self
 	}
 	pub fn field(&mut self, name: impl Into<IStr>) -> ObjMemberBuilder<ValueBuilder<'_>> {
@@ -922,7 +921,7 @@
 		let (receiver, name, member) =
 			self.build_member(MaybeUnbound::Bound(Thunk::evaluated(value.into())));
 		let entry = receiver.0.map.entry(name);
-		entry.insert(member);
+		entry.insert_entry(member);
 	}
 
 	/// Tries to insert value, returns an error if it was already defined
@@ -933,7 +932,7 @@
 		self.binding(MaybeUnbound::Bound(value.into()))
 	}
 	pub fn bindable(self, bindable: impl Unbound<Bound = Val>) -> Result<()> {
-		self.binding(MaybeUnbound::Unbound(Cc::new(tb!(bindable))))
+		self.binding(MaybeUnbound::Unbound(CcUnbound::new(bindable)))
 	}
 	pub fn binding(self, binding: MaybeUnbound) -> Result<()> {
 		let (receiver, name, member) = self.build_member(binding);
@@ -955,8 +954,8 @@
 	pub fn value(self, value: impl Into<Val>) {
 		self.binding(MaybeUnbound::Bound(Thunk::evaluated(value.into())));
 	}
-	pub fn bindable(self, bindable: TraceBox<dyn Unbound<Bound = Val>>) {
-		self.binding(MaybeUnbound::Unbound(Cc::new(bindable)));
+	pub fn bindable(self, bindable: impl Unbound<Bound = Val>) {
+		self.binding(MaybeUnbound::Unbound(CcUnbound::new(bindable)));
 	}
 	pub fn binding(self, binding: MaybeUnbound) {
 		let (receiver, name, member) = self.build_member(binding);
modifiedcrates/jrsonnet-evaluator/src/stack.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/stack.rs
+++ b/crates/jrsonnet-evaluator/src/stack.rs
@@ -7,23 +7,41 @@
 	current_depth: Cell<usize>,
 }
 
-#[cfg(feature = "nightly")]
-#[allow(clippy::thread_local_initializer_can_be_made_const)]
-#[thread_local]
-static STACK_LIMIT: StackLimit = StackLimit {
-	max_stack_size: Cell::new(200),
-	current_depth: Cell::new(0),
-};
-#[cfg(not(feature = "nightly"))]
-thread_local! {
-	static STACK_LIMIT: StackLimit = const {
-		StackLimit {
-			max_stack_size: Cell::new(200),
-			current_depth: Cell::new(0),
+#[cfg(nightly)]
+struct NightlyLocalKey<T>(pub T);
+#[cfg(nightly)]
+impl<T> NightlyLocalKey<T> {
+	#[inline(always)]
+	fn with<U>(&self, v: impl FnOnce(&T) -> U) -> U {
+		v(&self.0)
+	}
+}
+#[cfg(not(nightly))]
+type NightlyLocalKey<T> = std::thread::LocalKey<T>;
+
+#[cfg(nightly)]
+macro_rules! const_tls {
+	(const $name:ident: $t:ty = $expr:expr;) => {
+		#[thread_local]
+		static $name: NightlyLocalKey<$t> = NightlyLocalKey($expr);
+	};
+}
+#[cfg(not(nightly))]
+macro_rules! const_tls {
+	(const $name:ident: $t:ty = $expr:expr;) => {
+		thread_local! {
+			static $name: $t = const { $expr };
 		}
 	};
 }
 
+const_tls! {
+	const STACK_LIMIT: StackLimit = StackLimit {
+		max_stack_size: Cell::new(200),
+		current_depth: Cell::new(0),
+	};
+}
+
 pub struct StackOverflowError;
 impl From<StackOverflowError> for ErrorKind {
 	fn from(_: StackOverflowError) -> Self {
@@ -39,21 +57,14 @@
 /// Used to implement stack depth limitation
 pub struct StackDepthGuard(PhantomData<()>);
 impl Drop for StackDepthGuard {
-	#[cfg(feature = "nightly")]
 	fn drop(&mut self) {
-		STACK_LIMIT
-			.current_depth
-			.set(STACK_LIMIT.current_depth.get() - 1);
-	}
-	#[cfg(not(feature = "nightly"))]
-	fn drop(&mut self) {
-		STACK_LIMIT.with(|limit| limit.current_depth.set(limit.current_depth.get() - 1));
+		STACK_LIMIT.with(|limit| limit.current_depth.set(limit.current_depth.get() - 1))
 	}
 }
 
 // #[cfg(feature = "nightly")]
 pub fn check_depth() -> Result<StackDepthGuard, StackOverflowError> {
-	fn internal(limit: &StackLimit) -> Result<StackDepthGuard, StackOverflowError> {
+	STACK_LIMIT.with(|limit| {
 		let current = limit.current_depth.get();
 		if current < limit.max_stack_size.get() {
 			limit.current_depth.set(current + 1);
@@ -61,47 +72,26 @@
 		} else {
 			Err(StackOverflowError)
 		}
-	}
-	#[cfg(feature = "nightly")]
-	{
-		internal(&STACK_LIMIT)
-	}
-	#[cfg(not(feature = "nightly"))]
-	{
-		STACK_LIMIT.with(internal)
-	}
+	})
 }
 
 pub struct StackDepthLimitOverrideGuard {
 	old_limit: usize,
 }
 impl Drop for StackDepthLimitOverrideGuard {
-	#[cfg(feature = "nightly")]
-	fn drop(&mut self) {
-		STACK_LIMIT.max_stack_size.set(self.old_limit);
-	}
-	#[cfg(not(feature = "nightly"))]
 	fn drop(&mut self) {
 		STACK_LIMIT.with(|limit| limit.max_stack_size.set(self.old_limit));
 	}
 }
 
 pub fn limit_stack_depth(depth_limit: usize) -> StackDepthLimitOverrideGuard {
-	fn internal(limit: &StackLimit, depth_limit: usize) -> StackDepthLimitOverrideGuard {
+	STACK_LIMIT.with(|limit| {
 		let old_limit = limit.max_stack_size.get();
 		let current_depth = limit.current_depth.get();
 
 		limit.max_stack_size.set(current_depth + depth_limit);
 		StackDepthLimitOverrideGuard { old_limit }
-	}
-	#[cfg(feature = "nightly")]
-	{
-		internal(&STACK_LIMIT, depth_limit)
-	}
-	#[cfg(not(feature = "nightly"))]
-	{
-		STACK_LIMIT.with(|limit| internal(limit, depth_limit))
-	}
+	})
 }
 
 /// Like [`limit_stack_depth`], but set depth is not guarded, and will be kept
modifiedcrates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/trace/mod.rs
+++ b/crates/jrsonnet-evaluator/src/trace/mod.rs
@@ -1,11 +1,14 @@
+#[cfg(feature = "explaining-traces")]
+use std::cell::RefCell;
 use std::{
 	any::Any,
-	cell::RefCell,
 	path::{Path, PathBuf},
 };
 
 use jrsonnet_gcmodule::Trace;
-use jrsonnet_parser::{CodeLocation, Source, Span};
+use jrsonnet_parser::CodeLocation;
+#[cfg(feature = "explaining-traces")]
+use jrsonnet_parser::Span;
 
 use crate::{error::ErrorKind, Error};
 
@@ -225,71 +228,6 @@
 				)?;
 			} else {
 				write!(out, "    during {desc}")?;
-			}
-		}
-		Ok(())
-	}
-
-	fn as_any(&self) -> &dyn Any {
-		self
-	}
-
-	fn as_any_mut(&mut self) -> &mut dyn Any {
-		self
-	}
-}
-
-/// rustc-like trace displaying
-#[cfg(feature = "explaining-traces")]
-#[derive(Trace)]
-pub struct ExplainingFormat {
-	pub resolver: PathResolver,
-	pub max_trace: usize,
-}
-#[cfg(feature = "explaining-traces")]
-impl TraceFormat for ExplainingFormat {
-	fn write_trace(
-		&self,
-		out: &mut dyn std::fmt::Write,
-		error: &Error,
-	) -> Result<(), std::fmt::Error> {
-		write!(out, "{}", error.error())?;
-		if let ErrorKind::ImportSyntaxError { path, error } = error.error() {
-			writeln!(out)?;
-			let offset = error.location.offset;
-			let location = path
-				.map_source_locations(&[offset as u32])
-				.into_iter()
-				.next()
-				.unwrap();
-			let mut end_location = location;
-			end_location.offset += 1;
-
-			self.print_snippet(
-				out,
-				path.code(),
-				path,
-				&location,
-				&end_location,
-				"syntax error",
-			)?;
-		}
-		let trace = &error.trace();
-		for item in &trace.0 {
-			writeln!(out)?;
-			let desc = &item.desc;
-			if let Some(source) = &item.location {
-				let start_end = source.0.map_source_locations(&[source.1, source.2]);
-				self.print_snippet(
-					out,
-					source.0.code(),
-					&source.0,
-					&start_end[0],
-					&start_end[1],
-					desc,
-				)?;
-			} else {
-				write!(out, "{desc}")?;
 			}
 		}
 		Ok(())
@@ -305,68 +243,6 @@
 }
 
 #[cfg(feature = "explaining-traces")]
-impl ExplainingFormat {
-	fn print_snippet(
-		&self,
-		out: &mut dyn std::fmt::Write,
-		source: &str,
-		origin: &Source,
-		start: &CodeLocation,
-		end: &CodeLocation,
-		desc: &str,
-	) -> Result<(), std::fmt::Error> {
-		use annotate_snippets::{
-			// DisplayList, FormatOptions,
-			AnnotationType,
-			Renderer,
-			Slice,
-			Snippet,
-			SourceAnnotation,
-		};
-
-		let source_fragment: String = source
-			.chars()
-			.skip(start.line_start_offset)
-			.take(end.line_end_offset - end.line_start_offset)
-			.collect();
-
-		let origin = origin.source_path().path().map_or_else(
-			|| origin.source_path().to_string(),
-			|r| self.resolver.resolve(r),
-		);
-		let snippet = Snippet {
-			// opt: FormatOptions {
-			// 	color: true,
-			// 	..FormatOptions::default()
-			// },
-			title: None,
-			footer: vec![],
-			slices: vec![Slice {
-				source: &source_fragment,
-				line_start: start.line,
-				origin: Some(&origin),
-				fold: false,
-				annotations: vec![SourceAnnotation {
-					label: desc,
-					annotation_type: AnnotationType::Error,
-					range: (
-						start.offset - start.line_start_offset,
-						(end.offset.saturating_sub(start.line_start_offset))
-							.min(source_fragment.len()),
-					),
-				}],
-			}],
-		};
-
-		let renderer = Renderer::styled();
-		let dl = renderer.render(snippet);
-		write!(out, "{dl}")?;
-
-		Ok(())
-	}
-}
-
-#[cfg(feature = "explaining-traces")]
 #[derive(Trace)]
 pub struct HiDocFormat {
 	pub resolver: PathResolver,
@@ -390,7 +266,7 @@
 			let offset = error.location.offset;
 			let mut builder = SnippetBuilder::new(path.code());
 			builder
-				.error(Text::single("syntax error".chars(), Formatting::default()))
+				.error(Text::fragment("syntax error", Formatting::default()))
 				.range(offset..=offset)
 				.build();
 			let source = builder.build();
@@ -448,7 +324,7 @@
 				let mut builder = snippet_builder.borrow_mut();
 				let builder = builder.as_mut().unwrap();
 				builder
-					.note(Text::single(desc.chars(), Formatting::default()))
+					.note(Text::fragment(desc, Formatting::default()))
 					.range(source.1 as usize..=(source.2 as usize - 1).max(source.1 as usize))
 					.build();
 			} else {
modifiedcrates/jrsonnet-evaluator/src/typed/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/typed/mod.rs
+++ b/crates/jrsonnet-evaluator/src/typed/mod.rs
@@ -20,9 +20,9 @@
 	#[error("every failed from {0}:\n{1}")]
 	UnionFailed(ComplexValType, TypeLocErrorList),
 	#[error(
-		"number out of bounds: {0} not in {}..{}",
-		.1.map(|v|v.to_string()).unwrap_or_default(),
-		.2.map(|v|v.to_string()).unwrap_or_default(),
+		"number out of bounds: {0} not in {start}..{end}",
+		start = .1.map(|v|v.to_string()).unwrap_or_default(),
+		end = .2.map(|v|v.to_string()).unwrap_or_default(),
 	)]
 	BoundsFailed(f64, Option<f64>, Option<f64>),
 }
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -8,10 +8,11 @@
 	rc::Rc,
 };
 
-use jrsonnet_gcmodule::{Cc, Trace};
+use jrsonnet_gcmodule::{Acyclic, Cc, Trace, TraceBox};
 use jrsonnet_interner::IStr;
 pub use jrsonnet_macros::Thunk;
 use jrsonnet_types::ValType;
+use rustc_hash::FxHashMap;
 use thiserror::Error;
 
 pub use crate::arr::{ArrValue, ArrayLike};
@@ -19,9 +20,8 @@
 	bail,
 	error::{Error, ErrorKind::*},
 	function::FuncVal,
-	gc::{GcHashMap, TraceBox},
+	gc::WithCapacityExt as _,
 	manifest::{ManifestFormat, ToStringFormat},
-	tb,
 	typed::BoundedUsize,
 	ObjValue, Result, Unbound, WeakObjValue,
 };
@@ -70,7 +70,9 @@
 		Self(Cc::new(RefCell::new(ThunkInner::Computed(val))))
 	}
 	pub fn new(f: impl ThunkValue<Output = T> + 'static) -> Self {
-		Self(Cc::new(RefCell::new(ThunkInner::Waiting(tb!(f)))))
+		Self(Cc::new(RefCell::new(ThunkInner::Waiting(TraceBox(
+			Box::new(f),
+		)))))
 	}
 	pub fn errored(e: Error) -> Self {
 		Self(Cc::new(RefCell::new(ThunkInner::Errored(e))))
@@ -174,13 +176,13 @@
 	I: Unbound<Bound = T>,
 	T: Trace,
 {
-	cache: Cc<RefCell<GcHashMap<CacheKey, T>>>,
+	cache: Cc<RefCell<FxHashMap<CacheKey, T>>>,
 	value: I,
 }
 impl<I: Unbound<Bound = T>, T: Trace> CachedUnbound<I, T> {
 	pub fn new(value: I) -> Self {
 		Self {
-			cache: Cc::new(RefCell::new(GcHashMap::new())),
+			cache: Cc::new(RefCell::new(FxHashMap::new())),
 			value,
 		}
 	}
@@ -302,7 +304,7 @@
 	}
 }
 
-#[derive(Debug, Clone, Trace)]
+#[derive(Debug, Clone, Acyclic)]
 pub enum StrValue {
 	Flat(IStr),
 	Tree(Rc<(StrValue, StrValue, usize)>),
modifiedcrates/jrsonnet-interner/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-interner/src/lib.rs
+++ b/crates/jrsonnet-interner/src/lib.rs
@@ -9,14 +9,14 @@
 	borrow::Cow,
 	cell::RefCell,
 	fmt::{self, Display},
-	hash::{BuildHasherDefault, Hash, Hasher},
+	hash::{Hash, Hasher},
 	ops::Deref,
 	str,
 };
 
 use hashbrown::{hash_map::RawEntryMut, HashMap};
-use jrsonnet_gcmodule::Trace;
-use rustc_hash::FxHasher;
+use jrsonnet_gcmodule::{Acyclic, Trace};
+use rustc_hash::FxBuildHasher;
 
 mod inner;
 use inner::Inner;
@@ -31,6 +31,7 @@
 		false
 	}
 }
+unsafe impl Acyclic for IStr {}
 
 impl IStr {
 	#[must_use]
@@ -219,10 +220,10 @@
 	}
 }
 
-type PoolMap = HashMap<Inner, (), BuildHasherDefault<FxHasher>>;
+type PoolMap = HashMap<Inner, (), FxBuildHasher>;
 
 thread_local! {
-	static POOL: RefCell<PoolMap> = RefCell::new(HashMap::with_capacity_and_hasher(200, BuildHasherDefault::default()));
+	static POOL: RefCell<PoolMap> = RefCell::new(HashMap::with_capacity_and_hasher(200, FxBuildHasher::default()));
 }
 
 /// Jrsonnet golang bindings require that it is possible to move jsonnet
modifiedcrates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-macros/src/lib.rs
+++ b/crates/jrsonnet-macros/src/lib.rs
@@ -103,13 +103,6 @@
 	syn::custom_keyword!(ok);
 }
 
-struct EmptyAttr;
-impl Parse for EmptyAttr {
-	fn parse(_input: ParseStream) -> Result<Self> {
-		Ok(Self)
-	}
-}
-
 struct BuiltinAttrs {
 	fields: Vec<Field>,
 }
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
--- a/crates/jrsonnet-parser/src/expr.rs
+++ b/crates/jrsonnet-parser/src/expr.rs
@@ -4,12 +4,12 @@
 	rc::Rc,
 };
 
-use jrsonnet_gcmodule::Trace;
+use jrsonnet_gcmodule::Acyclic;
 use jrsonnet_interner::IStr;
 
 use crate::source::Source;
 
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub enum FieldName {
 	/// {fixed: 2}
 	Fixed(IStr),
@@ -17,7 +17,7 @@
 	Dyn(LocExpr),
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]
 #[repr(u8)]
 pub enum Visibility {
 	/// :
@@ -34,10 +34,10 @@
 	}
 }
 
-#[derive(Clone, Debug, PartialEq, Trace)]
+#[derive(Clone, Debug, PartialEq, Acyclic)]
 pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);
 
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub struct FieldMember {
 	pub name: FieldName,
 	pub plus: bool,
@@ -46,14 +46,14 @@
 	pub value: LocExpr,
 }
 
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub enum Member {
 	Field(FieldMember),
 	BindStmt(BindSpec),
 	AssertStmt(AssertStmt),
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]
 pub enum UnaryOpType {
 	Plus,
 	Minus,
@@ -77,7 +77,7 @@
 	}
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]
 pub enum BinaryOpType {
 	Mul,
 	Div,
@@ -146,11 +146,11 @@
 }
 
 /// name, default value
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub struct Param(pub Destruct, pub Option<LocExpr>);
 
 /// Defined function parameters
-#[derive(Debug, Clone, PartialEq, Trace)]
+#[derive(Debug, Clone, PartialEq, Acyclic)]
 pub struct ParamsDesc(pub Rc<Vec<Param>>);
 
 impl Deref for ParamsDesc {
@@ -160,7 +160,7 @@
 	}
 }
 
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub struct ArgsDesc {
 	pub unnamed: Vec<LocExpr>,
 	pub named: Vec<(IStr, LocExpr)>,
@@ -171,7 +171,7 @@
 	}
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Trace)]
+#[derive(Debug, Clone, PartialEq, Eq, Acyclic)]
 pub enum DestructRest {
 	/// ...rest
 	Keep(IStr),
@@ -179,7 +179,7 @@
 	Drop,
 }
 
-#[derive(Debug, Clone, PartialEq, Trace)]
+#[derive(Debug, Clone, PartialEq, Acyclic)]
 pub enum Destruct {
 	Full(IStr),
 	#[cfg(feature = "exp-destruct")]
@@ -240,7 +240,7 @@
 	}
 }
 
-#[derive(Debug, Clone, PartialEq, Trace)]
+#[derive(Debug, Clone, PartialEq, Acyclic)]
 pub enum BindSpec {
 	Field {
 		into: Destruct,
@@ -261,19 +261,19 @@
 	}
 }
 
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub struct IfSpecData(pub LocExpr);
 
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub struct ForSpecData(pub Destruct, pub LocExpr);
 
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub enum CompSpec {
 	IfSpec(IfSpecData),
 	ForSpec(ForSpecData),
 }
 
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub struct ObjComp {
 	pub pre_locals: Vec<BindSpec>,
 	pub field: FieldMember,
@@ -281,13 +281,13 @@
 	pub compspecs: Vec<CompSpec>,
 }
 
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub enum ObjBody {
 	MemberList(Vec<Member>),
 	ObjComp(ObjComp),
 }
 
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Trace)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Acyclic)]
 pub enum LiteralType {
 	This,
 	Super,
@@ -297,7 +297,7 @@
 	False,
 }
 
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub struct SliceDesc {
 	pub start: Option<LocExpr>,
 	pub end: Option<LocExpr>,
@@ -305,7 +305,7 @@
 }
 
 /// Syntax base
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub enum Expr {
 	Literal(LiteralType),
 
@@ -374,7 +374,7 @@
 	Slice(LocExpr, SliceDesc),
 }
 
-#[derive(Debug, PartialEq, Trace)]
+#[derive(Debug, PartialEq, Acyclic)]
 pub struct IndexPart {
 	pub value: LocExpr,
 	#[cfg(feature = "exp-null-coaelse")]
@@ -382,8 +382,7 @@
 }
 
 /// file, begin offset, end offset
-#[derive(Clone, PartialEq, Eq, Trace)]
-#[trace(skip)]
+#[derive(Clone, PartialEq, Eq, Acyclic)]
 #[repr(C)]
 pub struct Span(pub Source, pub u32, pub u32);
 impl Span {
@@ -401,7 +400,7 @@
 }
 
 /// Holds AST expression and its location in source file
-#[derive(Clone, PartialEq, Trace)]
+#[derive(Clone, PartialEq, Acyclic)]
 pub struct LocExpr(Rc<(Expr, Span)>);
 impl LocExpr {
 	pub fn new(expr: Expr, span: Span) -> Self {
modifiedcrates/jrsonnet-parser/src/source.rsdiffbeforeafterboth
--- a/crates/jrsonnet-parser/src/source.rs
+++ b/crates/jrsonnet-parser/src/source.rs
@@ -6,7 +6,7 @@
 	rc::Rc,
 };
 
-use jrsonnet_gcmodule::{Trace, Tracer};
+use jrsonnet_gcmodule::Acyclic;
 use jrsonnet_interner::{IBytes, IStr};
 
 use crate::location::{location_to_offset, offset_to_location, CodeLocation};
@@ -56,7 +56,7 @@
 		impl Eq for dyn $T {}
 	};
 }
-pub trait SourcePathT: Trace + Debug + Display {
+pub trait SourcePathT: Acyclic + Debug + Display {
 	/// This method should be checked by resolver before panicking with bad SourcePath input
 	/// if `true` - then resolver may threat this path as default, and default is usally a CWD
 	fn is_default(&self) -> bool;
@@ -79,7 +79,7 @@
 /// search location is applicable
 ///
 /// Resolver may also return custom implementations of this trait, for example it may return http url in case of remotely loaded files
-#[derive(Eq, Debug, Clone)]
+#[derive(Eq, Debug, Clone, Acyclic)]
 pub struct SourcePath(Rc<dyn SourcePathT>);
 impl SourcePath {
 	pub fn new(inner: impl SourcePathT) -> Self {
@@ -106,18 +106,6 @@
 		&*self.0 == &*other.0
 	}
 }
-impl Trace for SourcePath {
-	fn trace(&self, tracer: &mut Tracer) {
-		(*self.0).trace(tracer)
-	}
-
-	fn is_type_tracked() -> bool
-	where
-		Self: Sized,
-	{
-		true
-	}
-}
 impl Display for SourcePath {
 	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 		write!(f, "{}", self.0)
@@ -129,7 +117,7 @@
 	}
 }
 
-#[derive(Trace, Hash, PartialEq, Eq, Debug)]
+#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]
 struct SourceDefault;
 impl Display for SourceDefault {
 	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -151,7 +139,7 @@
 ///
 /// When `file` is being resolved from `SourceFile(a/b/c)`, it should be resolved to `SourceFile(a/b/file)`,
 /// however if it is being resolved from `SourceDirectory(a/b/c)`, then it should be resolved to `SourceDirectory(a/b/c/file)`
-#[derive(Trace, Hash, PartialEq, Eq, Debug)]
+#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]
 pub struct SourceFile(PathBuf);
 impl SourceFile {
 	pub fn new(path: PathBuf) -> Self {
@@ -179,7 +167,7 @@
 /// Represents path to the directory on the disk
 ///
 /// See also [`SourceFile`]
-#[derive(Trace, Hash, PartialEq, Eq, Debug)]
+#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]
 pub struct SourceDirectory(PathBuf);
 impl SourceDirectory {
 	pub fn new(path: PathBuf) -> Self {
@@ -208,7 +196,7 @@
 ///
 /// It is used for --ext-code=.../--tla-code=.../standard library source code by default,
 /// and user can construct arbitrary values by hand, without asking import resolver
-#[derive(Trace, Hash, PartialEq, Eq, Debug, Clone)]
+#[derive(Acyclic, Hash, PartialEq, Eq, Debug, Clone)]
 pub struct SourceVirtual(pub IStr);
 impl Display for SourceVirtual {
 	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -231,7 +219,7 @@
 /// for better cross-platform support.
 // PartialEq is limited to ptr equality
 #[allow(clippy::derived_hash_with_manual_eq)]
-#[derive(Trace, Debug, Hash)]
+#[derive(Acyclic, Debug, Hash)]
 pub struct SourceFifo(pub String, pub IBytes);
 impl PartialEq for SourceFifo {
 	fn eq(&self, other: &Self) -> bool {
@@ -258,16 +246,8 @@
 
 /// Either real file, or virtual
 /// Hash of FileName always have same value as raw Path, to make it possible to use with raw_entry_mut
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug, Acyclic)]
 pub struct Source(pub Rc<(SourcePath, IStr)>);
-
-impl Trace for Source {
-	fn trace(&self, _tracer: &mut Tracer) {}
-
-	fn is_type_tracked() -> bool {
-		false
-	}
-}
 
 impl Source {
 	pub fn new(path: SourcePath, code: IStr) -> Self {
modifiedcrates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rsdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rs
+++ b/crates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rs
@@ -127,9 +127,9 @@
 	IDENT,
 	#[regex("[ \\t\\n\\r]+")]
 	WHITESPACE,
-	#[regex("//[^\\r\\n]*(\\r\\n|\\n)?")]
+	#[regex("//[^\\r\\n]*?(\\r\\n|\\n)?")]
 	SINGLE_LINE_SLASH_COMMENT,
-	#[regex("#[^\\r\\n]*(\\r\\n|\\n)?")]
+	#[regex("#[^\\r\\n]*?(\\r\\n|\\n)?")]
 	SINGLE_LINE_HASH_COMMENT,
 	#[regex("/\\*([^*]|\\*[^/])*\\*/")]
 	MULTI_LINE_COMMENT,
modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/lib.rs
+++ b/crates/jrsonnet-stdlib/src/lib.rs
@@ -16,7 +16,7 @@
 	trace::PathResolver,
 	ContextBuilder, IStr, ObjValue, ObjValueBuilder, Thunk, Val,
 };
-use jrsonnet_gcmodule::Trace;
+use jrsonnet_gcmodule::{Acyclic, Cc, Trace};
 use jrsonnet_parser::Source;
 pub use manifest::*;
 pub use math::*;
@@ -50,7 +50,7 @@
 mod types;
 
 #[allow(clippy::too_many_lines)]
-pub fn stdlib_uncached(settings: Rc<RefCell<Settings>>) -> ObjValue {
+pub fn stdlib_uncached(settings: Cc<RefCell<Settings>>) -> ObjValue {
 	let mut builder = ObjValueBuilder::new();
 
 	// FIXME: Use PHF
@@ -279,10 +279,11 @@
 	builder.build()
 }
 
-pub trait TracePrinter {
+pub trait TracePrinter: Acyclic {
 	fn print_trace(&self, loc: CallLocation, value: IStr);
 }
 
+#[derive(Acyclic)]
 pub struct StdTracePrinter {
 	resolver: PathResolver,
 }
@@ -309,13 +310,14 @@
 	}
 }
 
+#[derive(Clone, Trace)]
 pub struct Settings {
 	/// Used for `std.extVar`
 	pub ext_vars: HashMap<IStr, TlaArg>,
 	/// Used for `std.native`
 	pub ext_natives: HashMap<IStr, FuncVal>,
 	/// Used for `std.trace`
-	pub trace_printer: Box<dyn TracePrinter>,
+	pub trace_printer: Rc<dyn TracePrinter>,
 	/// Used for `std.thisFile`
 	pub path_resolver: PathResolver,
 }
@@ -329,27 +331,27 @@
 pub struct ContextInitializer {
 	/// std without applied thisFile overlay
 	stdlib_obj: ObjValue,
-	settings: Rc<RefCell<Settings>>,
+	settings: Cc<RefCell<Settings>>,
 }
 impl ContextInitializer {
 	pub fn new(resolver: PathResolver) -> Self {
 		let settings = Settings {
 			ext_vars: HashMap::new(),
 			ext_natives: HashMap::new(),
-			trace_printer: Box::new(StdTracePrinter::new(resolver.clone())),
+			trace_printer: Rc::new(StdTracePrinter::new(resolver.clone())),
 			path_resolver: resolver,
 		};
-		let settings = Rc::new(RefCell::new(settings));
+		let settings = Cc::new(RefCell::new(settings));
 		let stdlib_obj = stdlib_uncached(settings.clone());
 		Self {
 			stdlib_obj,
 			settings,
 		}
 	}
-	pub fn settings(&self) -> Ref<Settings> {
+	pub fn settings(&self) -> Ref<'_, Settings> {
 		self.settings.borrow()
 	}
-	pub fn settings_mut(&self) -> RefMut<Settings> {
+	pub fn settings_mut(&self) -> RefMut<'_, Settings> {
 		self.settings.borrow_mut()
 	}
 	pub fn add_ext_var(&self, name: IStr, value: Val) {
modifiedcrates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/misc.rs
+++ b/crates/jrsonnet-stdlib/src/misc.rs
@@ -1,4 +1,4 @@
-use std::{cell::RefCell, collections::BTreeSet, rc::Rc};
+use std::{cell::RefCell, collections::BTreeSet};
 
 use jrsonnet_evaluator::{
 	bail,
@@ -9,6 +9,7 @@
 	val::{equals, ArrValue},
 	Context, Either, IStr, ObjValue, ObjValueBuilder, ResultExt, Thunk, Val,
 };
+use jrsonnet_gcmodule::Cc;
 
 use crate::{extvar_source, Settings};
 
@@ -47,7 +48,7 @@
 }
 
 #[builtin(fields(
-	settings: Rc<RefCell<Settings>>,
+	settings: Cc<RefCell<Settings>>,
 ))]
 pub fn builtin_ext_var(this: &builtin_ext_var, ctx: Context, x: IStr) -> Result<Val> {
 	let ctx = ctx.state().create_default_context(extvar_source(&x, ""));
@@ -62,7 +63,7 @@
 }
 
 #[builtin(fields(
-	settings: Rc<RefCell<Settings>>,
+	settings: Cc<RefCell<Settings>>,
 ))]
 pub fn builtin_native(this: &builtin_native, x: IStr) -> Val {
 	this.settings
@@ -74,7 +75,7 @@
 }
 
 #[builtin(fields(
-	settings: Rc<RefCell<Settings>>,
+	settings: Cc<RefCell<Settings>>,
 ))]
 pub fn builtin_trace(
 	this: &builtin_trace,
modifiedcrates/jrsonnet-stdlib/src/regex.rsdiffbeforeafterboth
1use std::{cell::RefCell, hash::BuildHasherDefault, num::NonZeroUsize, rc::Rc};1use std::{cell::RefCell, num::NonZeroUsize, rc::Rc};
22
3use ::regex::Regex;3use ::regex::Regex;
4use jrsonnet_evaluator::{4use jrsonnet_evaluator::{
5 error::{ErrorKind::*, Result},5 error::{ErrorKind::*, Result},
6 rustc_hash::FxBuildHasher,
6 val::StrValue,7 val::StrValue,
7 IStr, ObjValueBuilder, Val,8 IStr, ObjValueBuilder, Val,
8};9};
10use jrsonnet_gcmodule::Acyclic;
9use jrsonnet_macros::builtin;11use jrsonnet_macros::builtin;
10use lru::LruCache;12use lru::LruCache;
11use rustc_hash::FxHasher;13
1214#[derive(Acyclic)]
13pub struct RegexCacheInner {15pub struct RegexCacheInner {
14 cache: RefCell<LruCache<IStr, Rc<Regex>, BuildHasherDefault<FxHasher>>>,16 cache: RefCell<LruCache<IStr, Rc<Regex>, FxBuildHasher>>,
15}17}
16impl Default for RegexCacheInner {18impl Default for RegexCacheInner {
17 fn default() -> Self {19 fn default() -> Self {
18 Self {20 Self {
19 cache: RefCell::new(LruCache::with_hasher(21 cache: RefCell::new(LruCache::with_hasher(
20 NonZeroUsize::new(20).unwrap(),22 NonZeroUsize::new(20).unwrap(),
21 BuildHasherDefault::default(),23 FxBuildHasher::default(),
22 )),24 )),
23 }25 }
24 }26 }
modifiedflake.lockdiffbeforeafterboth
--- a/flake.lock
+++ b/flake.lock
@@ -1,17 +1,11 @@
 {
   "nodes": {
     "crane": {
-      "inputs": {
-        "nixpkgs": [
-          "nixpkgs"
-        ]
-      },
       "locked": {
-        "lastModified": 1724377159,
-        "narHash": "sha256-ixjje1JO8ucKT41hs6n2NCde1Vc0+Zc2p2gUbJpCsMw=",
+        "lastModified": 1770419512,
         "owner": "ipetkov",
         "repo": "crane",
-        "rev": "3e47b7a86c19142bd3675da49d6acef488b4dac1",
+        "rev": "2510f2cbc3ccd237f700bb213756a8f35c32d8d7",
         "type": "github"
       },
       "original": {
@@ -27,11 +21,10 @@
         ]
       },
       "locked": {
-        "lastModified": 1722555600,
-        "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
+        "lastModified": 1769996383,
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
+        "rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
         "type": "github"
       },
       "original": {
@@ -42,15 +35,15 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1724519568,
-        "narHash": "sha256-CmfrenY4cEi/mIslKy8XOGdqxUUVgT6/qMzNcAN/7z8=",
+        "lastModified": 1770468184,
         "owner": "nixos",
         "repo": "nixpkgs",
-        "rev": "eb0e6df0cdd2641ec0651cd9802ff4cff3b3e915",
+        "rev": "a124a10ea33a73329c42d67f30efcdbfb60a4e04",
         "type": "github"
       },
       "original": {
         "owner": "nixos",
+        "ref": "release-25.11",
         "repo": "nixpkgs",
         "type": "github"
       }
@@ -71,11 +64,10 @@
         ]
       },
       "locked": {
-        "lastModified": 1755743804,
-        "narHash": "sha256-M6qT02voARH5e9eTXQBzpYIE/hAp6jPgBCyxLmw5uBM=",
+        "lastModified": 1770433312,
         "owner": "oxalica",
         "repo": "rust-overlay",
-        "rev": "80322e975e27d834451d6b66e63f8abae9d74bf2",
+        "rev": "9922ff9f99a6436756cbe6f5d11f9c3630e58cf0",
         "type": "github"
       },
       "original": {
@@ -85,20 +77,11 @@
       }
     },
     "shelly": {
-      "inputs": {
-        "flake-parts": [
-          "flake-parts"
-        ],
-        "nixpkgs": [
-          "nixpkgs"
-        ]
-      },
       "locked": {
-        "lastModified": 1718420551,
-        "narHash": "sha256-NU8NBXVPj0KuY4Tl/LtZPrbX3PmmmgPuhk/1pzm9cyk=",
+        "lastModified": 1756323923,
         "owner": "CertainLach",
         "repo": "shelly",
-        "rev": "4f70221f3f9ad9058f590eefb25251b6760aaa47",
+        "rev": "b5dd29a500db04f54a9f1c2bf81cdd84df8b0cd7",
         "type": "github"
       },
       "original": {
modifiedflake.nixdiffbeforeafterboth
--- a/flake.nix
+++ b/flake.nix
@@ -1,7 +1,7 @@
 {
   description = "Jrsonnet";
   inputs = {
-    nixpkgs.url = "github:nixos/nixpkgs";
+    nixpkgs.url = "github:nixos/nixpkgs/release-25.11";
     rust-overlay = {
       url = "github:oxalica/rust-overlay";
       inputs.nixpkgs.follows = "nixpkgs";
@@ -10,148 +10,162 @@
       url = "github:hercules-ci/flake-parts";
       inputs.nixpkgs-lib.follows = "nixpkgs";
     };
-    crane = {
-      url = "github:ipetkov/crane";
-      inputs.nixpkgs.follows = "nixpkgs";
-    };
-    shelly = {
-      url = "github:CertainLach/shelly";
-      inputs = {
-        flake-parts.follows = "flake-parts";
-        nixpkgs.follows = "nixpkgs";
-      };
-    };
+    crane.url = "github:ipetkov/crane";
+    shelly.url = "github:CertainLach/shelly";
   };
-  outputs = inputs @ {
-    nixpkgs,
-    flake-parts,
-    rust-overlay,
-    crane,
-    shelly,
-    ...
-  }:
-    flake-parts.lib.mkFlake {inherit inputs;} {
-      imports = [shelly.flakeModule];
-      systems = ["x86_64-linux" "aarch64-linux" "armv7l-linux" "armv6l-linux" "mingw-w64"];
-      perSystem = {
-        config,
-        system,
-        ...
-      }: let
-        pkgs = import nixpkgs {
-          inherit system;
-          overlays = [rust-overlay.overlays.default];
-          config.allowUnsupportedSystem = true;
-        };
-        rust = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
-        craneLib = (crane.mkLib pkgs).overrideToolchain rust;
-      in {
-        legacyPackages = {
-          jsonnetImpls = {
-            go-jsonnet = pkgs.callPackage ./nix/go-jsonnet.nix {};
-            sjsonnet = pkgs.callPackage ./nix/sjsonnet.nix {};
-            jsonnet = pkgs.callPackage ./nix/jsonnet.nix {};
-            # I didn't managed to build it, and nixpkgs version is marked as broken
-            # haskell-jsonnet = pkgs.callPackage ./nix/haskell-jsonnet.nix { };
-            rsjsonnet = pkgs.callPackage ./nix/rsjsonnet.nix {};
+  outputs =
+    inputs@{
+      nixpkgs,
+      flake-parts,
+      rust-overlay,
+      crane,
+      shelly,
+      ...
+    }:
+    flake-parts.lib.mkFlake { inherit inputs; } {
+      imports = [ shelly.flakeModule ];
+      systems = inputs.nixpkgs.lib.systems.flakeExposed;
+      perSystem =
+        {
+          config,
+          system,
+          ...
+        }:
+        let
+          pkgs = import nixpkgs {
+            inherit system;
+            overlays = [ rust-overlay.overlays.default ];
+            config.allowUnsupportedSystem = true;
+          };
+          rust = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
+          craneLib = (crane.mkLib pkgs).overrideToolchain rust;
+        in
+        {
+          legacyPackages = {
+            jsonnetImpls = {
+              go-jsonnet = pkgs.callPackage ./nix/go-jsonnet.nix { };
+              sjsonnet = pkgs.callPackage ./nix/sjsonnet.nix { };
+              jsonnet = pkgs.callPackage ./nix/jsonnet.nix { };
+              # I didn't managed to build it, and nixpkgs version is marked as broken
+              # haskell-jsonnet = pkgs.callPackage ./nix/haskell-jsonnet.nix { };
+              rsjsonnet = pkgs.callPackage ./nix/rsjsonnet.nix { };
+            };
           };
-        };
-        packages = rec {
-          default = jrsonnet;
+          packages = rec {
+            default = jrsonnet;
 
-          jrsonnet = pkgs.callPackage ./nix/jrsonnet.nix {
-            inherit craneLib;
-          };
-          jrsonnet-nightly = pkgs.callPackage ./nix/jrsonnet.nix {
-            inherit craneLib;
-            withNightlyFeatures = true;
-          };
-          jrsonnet-experimental = pkgs.callPackage ./nix/jrsonnet.nix {
-            inherit craneLib;
-            withExperimentalFeatures = true;
-          };
+            jrsonnet = pkgs.callPackage ./nix/jrsonnet.nix {
+              inherit craneLib;
+            };
+            jrsonnet-nightly = pkgs.callPackage ./nix/jrsonnet.nix {
+              inherit craneLib;
+              withNightlyFeatures = true;
+            };
+            jrsonnet-experimental = pkgs.callPackage ./nix/jrsonnet.nix {
+              inherit craneLib;
+              withExperimentalFeatures = true;
+            };
 
-          jrsonnet-release = pkgs.callPackage ./nix/jrsonnet-release.nix {
-            rustPlatform = pkgs.makeRustPlatform {
-              rustc = rust;
-              cargo = rust;
+            jrsonnet-release = pkgs.callPackage ./nix/jrsonnet-release.nix {
+              rustPlatform = pkgs.makeRustPlatform {
+                rustc = rust;
+                cargo = rust;
+              };
             };
-          };
 
-          benchmarks = pkgs.callPackage ./nix/benchmarks.nix {
-            inherit (config.legacyPackages.jsonnetImpls) go-jsonnet sjsonnet jsonnet rsjsonnet;
-            jrsonnetVariants = [
-              {
-                drv = jrsonnet.override {forBenchmarks = true;};
-                name = "";
-              }
-            ];
+            benchmarks = pkgs.callPackage ./nix/benchmarks.nix {
+              inherit (config.legacyPackages.jsonnetImpls)
+                go-jsonnet
+                sjsonnet
+                jsonnet
+                rsjsonnet
+                ;
+              jrsonnetVariants = [
+                {
+                  drv = jrsonnet.override { forBenchmarks = true; };
+                  name = "";
+                }
+              ];
+            };
+            benchmarks-quick = pkgs.callPackage ./nix/benchmarks.nix {
+              inherit (config.legacyPackages.jsonnetImpls)
+                go-jsonnet
+                sjsonnet
+                jsonnet
+                rsjsonnet
+                ;
+              quick = true;
+              jrsonnetVariants = [
+                {
+                  drv = jrsonnet.override { forBenchmarks = true; };
+                  name = "";
+                }
+              ];
+            };
+            benchmarks-against-release = pkgs.callPackage ./nix/benchmarks.nix {
+              inherit (config.legacyPackages.jsonnetImpls)
+                go-jsonnet
+                sjsonnet
+                jsonnet
+                rsjsonnet
+                ;
+              jrsonnetVariants = [
+                {
+                  drv = jrsonnet.override { forBenchmarks = true; };
+                  name = "current";
+                }
+                {
+                  drv = jrsonnet-nightly.override { forBenchmarks = true; };
+                  name = "current-nightly";
+                }
+                {
+                  drv = jrsonnet-release.override { forBenchmarks = true; };
+                  name = "release";
+                }
+              ];
+            };
+            benchmarks-quick-against-release = pkgs.callPackage ./nix/benchmarks.nix {
+              inherit (config.legacyPackages.jsonnetImpls)
+                go-jsonnet
+                sjsonnet
+                jsonnet
+                rsjsonnet
+                ;
+              quick = true;
+              jrsonnetVariants = [
+                {
+                  drv = jrsonnet.override { forBenchmarks = true; };
+                  name = "current";
+                }
+                {
+                  drv = jrsonnet-nightly.override { forBenchmarks = true; };
+                  name = "current-nightly";
+                }
+                {
+                  drv = jrsonnet-release.override { forBenchmarks = true; };
+                  name = "release";
+                }
+              ];
+            };
           };
-          benchmarks-quick = pkgs.callPackage ./nix/benchmarks.nix {
-            inherit (config.legacyPackages.jsonnetImpls) go-jsonnet sjsonnet jsonnet rsjsonnet;
-            quick = true;
-            jrsonnetVariants = [
-              {
-                drv = jrsonnet.override {forBenchmarks = true;};
-                name = "";
-              }
-            ];
-          };
-          benchmarks-against-release = pkgs.callPackage ./nix/benchmarks.nix {
-            inherit (config.legacyPackages.jsonnetImpls) go-jsonnet sjsonnet jsonnet rsjsonnet;
-            jrsonnetVariants = [
-              {
-                drv = jrsonnet.override {forBenchmarks = true;};
-                name = "current";
-              }
-              {
-                drv = jrsonnet-nightly.override {forBenchmarks = true;};
-                name = "current-nightly";
-              }
-              {
-                drv = jrsonnet-release.override {forBenchmarks = true;};
-                name = "release";
-              }
-            ];
-          };
-          benchmarks-quick-against-release = pkgs.callPackage ./nix/benchmarks.nix {
-            inherit (config.legacyPackages.jsonnetImpls) go-jsonnet sjsonnet jsonnet rsjsonnet;
-            quick = true;
-            jrsonnetVariants = [
-              {
-                drv = jrsonnet.override {forBenchmarks = true;};
-                name = "current";
-              }
-              {
-                drv = jrsonnet-nightly.override {forBenchmarks = true;};
-                name = "current-nightly";
-              }
-              {
-                drv = jrsonnet-release.override {forBenchmarks = true;};
-                name = "release";
-              }
-            ];
+          shelly.shells.default = {
+            factory = craneLib.devShell;
+            packages =
+              with pkgs;
+              [
+                cargo-edit
+                cargo-outdated
+                cargo-watch
+                cargo-insta
+                cargo-hack
+                lld
+                hyperfine
+                graphviz
+              ]
+              ++ lib.optionals (!stdenv.isDarwin) [
+                valgrind
+              ];
           };
         };
-        shelly.shells.default = {
-          factory = craneLib.devShell;
-          packages = with pkgs;
-            [
-              alejandra
-              cargo-edit
-              cargo-asm
-              cargo-outdated
-              cargo-watch
-              cargo-insta
-              lld
-              hyperfine
-              graphviz
-            ]
-            ++ lib.optionals (!stdenv.isDarwin) [
-              valgrind
-              kcachegrind
-            ];
-        };
-      };
     };
 }
addedresultdiffbeforeafterboth
--- /dev/null
+++ b/result
@@ -0,0 +1 @@
+/nix/store/nd6v7jksg1dqhpx4x4vqgy5ry1nkb9lk-jrsonnet-current
\ No newline at end of file
modifiedrust-toolchain.tomldiffbeforeafterboth
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "1.89.0"
+channel = "1.93.0"
 components = ["rustfmt", "clippy", "rust-analyzer", "rust-src"]
modifiedtests/golden/issue172.jsonnet.goldendiffbeforeafterboth
--- a/tests/golden/issue172.jsonnet.golden
+++ b/tests/golden/issue172.jsonnet.golden
@@ -1,4 +1,4 @@
-variable is not defined: b
-    issue172.jsonnet:1:45-47: variable <b> access
+local is not defined: b
+    issue172.jsonnet:1:45-47: local <b> access
     issue172.jsonnet:1:4-10:  field <value> access
     elem <0> evaluation
\ No newline at end of file
modifiedtests/golden/missing_binding.jsonnet.goldendiffbeforeafterboth
--- a/tests/golden/missing_binding.jsonnet.golden
+++ b/tests/golden/missing_binding.jsonnet.golden
@@ -1,3 +1,3 @@
-variable is not defined: sta
-There is variable with similar name present: std
-    missing_binding.jsonnet:1:1-5: variable <sta> access
\ No newline at end of file
+local is not defined: sta
+There is a local with similar name present: std
+    missing_binding.jsonnet:1:1-5: local <sta> access
\ No newline at end of file
modifiedtests/tests/common.rsdiffbeforeafterboth
--- a/tests/tests/common.rs
+++ b/tests/tests/common.rs
@@ -56,25 +56,10 @@
 
 #[builtin]
 fn param_names(fun: FuncVal) -> Vec<String> {
-	match fun {
-		FuncVal::Id => vec!["x".to_string()],
-		FuncVal::Normal(func) => func
-			.params
-			.iter()
-			.map(|p| p.0.name().unwrap_or_else(|| "<unnamed>".into()).to_string())
-			.collect(),
-		FuncVal::StaticBuiltin(b) => b
-			.params()
-			.iter()
-			.map(|p| p.name().as_str().unwrap_or("<unnamed>").to_string())
-			.collect(),
-		FuncVal::Builtin(b) => b
-			.params()
-			.iter()
-			.map(|p| p.name().as_str().unwrap_or("<unnamed>").to_string())
-			.collect(),
-		FuncVal::Thunk(_) => vec![],
-	}
+	fun.params()
+		.into_iter()
+		.map(|v| v.name().as_str().unwrap_or("<unnamed>").to_owned())
+		.collect()
 }
 
 #[derive(Trace)]
modifiedxtask/src/sourcegen/kinds.rsdiffbeforeafterboth
--- a/xtask/src/sourcegen/kinds.rs
+++ b/xtask/src/sourcegen/kinds.rs
@@ -158,7 +158,6 @@
 }
 use std::{collections::HashSet, str::FromStr};
 
-pub use define_kinds;
 use indexmap::IndexMap;
 use proc_macro2::{Ident, TokenStream};
 use quote::{format_ident, quote};
@@ -266,8 +265,8 @@
 		error("STRING_BLOCK_MISSING_INDENT", lexer = true);
 		lit("IDENT") => r"[_a-zA-Z][_a-zA-Z0-9]*";
 		lit("WHITESPACE") => r"[ \t\n\r]+";
-		lit("SINGLE_LINE_SLASH_COMMENT") => r"//[^\r\n]*(\r\n|\n)?";
-		lit("SINGLE_LINE_HASH_COMMENT") => r"#[^\r\n]*(\r\n|\n)?";
+		lit("SINGLE_LINE_SLASH_COMMENT") => r"//[^\r\n]*?(\r\n|\n)?";
+		lit("SINGLE_LINE_HASH_COMMENT") => r"#[^\r\n]*?(\r\n|\n)?";
 		lit("MULTI_LINE_COMMENT") => r"/\*([^*]|\*[^/])*\*/";
 		error("COMMENT_TOO_SHORT") => r"/\*/";
 		error("COMMENT_UNTERMINATED") =>  r"/\*([^*/]|\*[^/])+";
modifiedxtask/src/sourcegen/mod.rsdiffbeforeafterboth
--- a/xtask/src/sourcegen/mod.rs
+++ b/xtask/src/sourcegen/mod.rs
@@ -4,7 +4,7 @@
 use ast::{lower, AstSrc};
 use itertools::Itertools;
 use kinds::{KindsSrc, TokenKind};
-use proc_macro2::{Punct, Spacing, TokenStream};
+use proc_macro2::{Ident, Punct, Spacing, Span, TokenStream};
 use quote::{format_ident, quote};
 use ungrammar::Grammar;
 use util::{ensure_file_contents, reformat, to_pascal_case, to_upper_snake_case};
@@ -533,8 +533,11 @@
 	if "{}[]()$".contains(token) {
 		let c = token.chars().next().unwrap();
 		quote! { #c }
-	} else if token.contains('$') {
+	} else if token.contains(|v| v == '$') {
 		quote! { #token }
+	} else if token.chars().all(|v| ('a'..='z').contains(&v)) {
+		let i = Ident::new(&token, Span::call_site());
+		quote! { #i }
 	} else {
 		let cs = token.chars().map(|c| Punct::new(c, Spacing::Joint));
 		quote! { #(#cs)* }