Repository: cedar-policy/cedar
Pull request #1376 (2024-12-16 20:57:39)

Apply clippy auto-fixes
## Description of changes

Apply clippy fixes to test code. Also disabled `cognitive_complexity` warnings.

## Issue #, if available

## Checklist for requesting a review

The change in this PR is (choose one, and delete the other options):

- [x] A change "invisible" to users (e.g., documentation, changes to "internal" crates like `cedar-policy-core`, `cedar-validator`, etc.)

I confirm that this PR (choose one, and delete the other options):

- [x] Does not update the CHANGELOG because my change does not significantly impact released code.

I confirm that [`cedar-spec`](https://github.com/cedar-policy/cedar-spec) (choose one, and delete the other options):

- [x] Does not require updates because my change does not impact the Cedar formal model or DRT infrastructure.

I confirm that [`docs.cedarpolicy.com`](https://docs.cedarpolicy.com/) (choose one, and delete the other options):

- [x] Does not require updates because my change does not impact the Cedar language specification.



Patch:
diff --git a/Cargo.lock b/Cargo.lock
index dbdb44df..b90336ba 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -98,9 +98,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.94"
+version = "1.0.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
+checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
 
 [[package]]
 name = "arbitrary"
@@ -184,30 +184,15 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
 
-[[package]]
-name = "bit-set"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
-dependencies = [
- "bit-vec 0.6.3",
-]
-
 [[package]]
 name = "bit-set"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
 dependencies = [
- "bit-vec 0.8.0",
+ "bit-vec",
 ]
 
-[[package]]
-name = "bit-vec"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
-
 [[package]]
 name = "bit-vec"
 version = "0.8.0"
@@ -287,9 +272,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
 
 [[package]]
 name = "cc"
-version = "1.2.4"
+version = "1.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf"
+checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333"
 dependencies = [
  "shlex",
 ]
@@ -320,7 +305,7 @@ dependencies = [
  "serde_json",
  "serde_with",
  "smol_str",
- "thiserror 2.0.7",
+ "thiserror 2.0.9",
  "tsify",
  "wasm-bindgen",
 ]
@@ -345,7 +330,7 @@ dependencies = [
  "serde",
  "serde_json",
  "tempfile",
- "thiserror 2.0.7",
+ "thiserror 2.0.9",
 ]
 
 [[package]]
@@ -374,7 +359,7 @@ dependencies = [
  "serde_with",
  "smol_str",
  "stacker",
- "thiserror 2.0.7",
+ "thiserror 2.0.9",
  "tsify",
  "wasm-bindgen",
 ]
@@ -417,7 +402,7 @@ dependencies = [
  "similar-asserts",
  "smol_str",
  "stacker",
- "thiserror 2.0.7",
+ "thiserror 2.0.9",
  "tsify",
  "unicode-security",
  "wasm-bindgen",
@@ -559,14 +544,14 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
 
 [[package]]
 name = "console"
-version = "0.15.8"
+version = "0.15.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
+checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b"
 dependencies = [
  "encode_unicode",
- "lazy_static",
  "libc",
- "windows-sys 0.52.0",
+ "once_cell",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -814,9 +799,9 @@ dependencies = [
 
 [[package]]
 name = "encode_unicode"
-version = "0.3.6"
+version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
+checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
 
 [[package]]
 name = "enum-ordinalize"
@@ -868,9 +853,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
 
 [[package]]
 name = "float-cmp"
-version = "0.9.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
+checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8"
 dependencies = [
  "num-traits",
 ]
@@ -1014,9 +999,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
 
 [[package]]
 name = "glob"
-version = "0.3.1"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
 
 [[package]]
 name = "globset"
@@ -1376,7 +1361,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "06093b57658c723a21da679530e061a8c25340fa5a6f98e313b542268c7e2a1f"
 dependencies = [
  "ascii-canvas",
- "bit-set 0.8.0",
+ "bit-set",
  "ena",
  "itertools 0.13.0",
  "lalrpop-util",
@@ -1409,15 +1394,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "libc"
-version = "0.2.168"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d"
-
-[[package]]
-name = "libm"
-version = "0.2.11"
+version = "0.2.169"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
+checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
 
 [[package]]
 name = "linked-hash-map"
@@ -1537,9 +1516,9 @@ dependencies = [
 
 [[package]]
 name = "miniz_oxide"
-version = "0.8.0"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
+checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394"
 dependencies = [
  "adler2",
 ]
@@ -1587,14 +1566,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
 dependencies = [
  "autocfg",
- "libm",
 ]
 
 [[package]]
 name = "object"
-version = "0.36.5"
+version = "0.36.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
 dependencies = [
  "memchr",
 ]
@@ -1734,9 +1712,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
 [[package]]
 name = "predicates"
-version = "3.1.2"
+version = "3.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97"
+checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573"
 dependencies = [
  "anstyle",
  "difflib",
@@ -1748,15 +1726,15 @@ dependencies = [
 
 [[package]]
 name = "predicates-core"
-version = "1.0.8"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931"
+checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa"
 
 [[package]]
 name = "predicates-tree"
-version = "1.0.11"
+version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13"
+checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c"
 dependencies = [
  "predicates-core",
  "termtree",
@@ -1803,12 +1781,12 @@ dependencies = [
 
 [[package]]
 name = "proptest"
-version = "1.5.0"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d"
+checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50"
 dependencies = [
- "bit-set 0.5.3",
- "bit-vec 0.6.3",
+ "bit-set",
+ "bit-vec",
  "bitflags",
  "lazy_static",
  "num-traits",
@@ -1890,9 +1868,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
 
 [[package]]
 name = "quote"
-version = "1.0.37"
+version = "1.0.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
 dependencies = [
  "proc-macro2",
 ]
@@ -2095,9 +2073,9 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.18"
+version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
+checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
 
 [[package]]
 name = "rusty-fork"
@@ -2149,9 +2127,9 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.216"
+version = "1.0.217"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e"
+checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
 dependencies = [
  "serde_derive",
 ]
@@ -2169,9 +2147,9 @@ dependencies = [
 
 [[package]]
 name = "serde_derive"
-version = "1.0.216"
+version = "1.0.217"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
+checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2191,9 +2169,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.133"
+version = "1.0.134"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
+checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d"
 dependencies = [
  "indexmap 2.7.0",
  "itoa",
@@ -2213,9 +2191,9 @@ dependencies = [
 
 [[package]]
 name = "serde_with"
-version = "3.11.0"
+version = "3.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817"
+checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa"
 dependencies = [
  "base64",
  "chrono",
@@ -2231,9 +2209,9 @@ dependencies = [
 
 [[package]]
 name = "serde_with_macros"
-version = "3.11.0"
+version = "3.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d"
+checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e"
 dependencies = [
  "darling",
  "proc-macro2",
@@ -2369,9 +2347,9 @@ checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
 
 [[package]]
 name = "syn"
-version = "2.0.90"
+version = "2.0.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
+checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2424,9 +2402,9 @@ dependencies = [
 
 [[package]]
 name = "termtree"
-version = "0.4.1"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
+checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
 
 [[package]]
 name = "textwrap"
@@ -2449,11 +2427,11 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "2.0.7"
+version = "2.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767"
+checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc"
 dependencies = [
- "thiserror-impl 2.0.7",
+ "thiserror-impl 2.0.9",
 ]
 
 [[package]]
@@ -2469,9 +2447,9 @@ dependencies = [
 
 [[package]]
 name = "thiserror-impl"
-version = "2.0.7"
+version = "2.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36"
+checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2537,9 +2515,9 @@ dependencies = [
 
 [[package]]
 name = "tinyvec"
-version = "1.8.0"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
+checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8"
 dependencies = [
  "tinyvec_macros",
 ]
diff --git a/cedar-policy-cli/Cargo.toml b/cedar-policy-cli/Cargo.toml
index 6c7a2514..5f55c704 100644
--- a/cedar-policy-cli/Cargo.toml
+++ b/cedar-policy-cli/Cargo.toml
@@ -37,8 +37,8 @@ protobufs = ["dep:prost", "dep:prost-build", "cedar-policy/protobufs", "cedar-po
 [dev-dependencies]
 assert_cmd = "2.0"
 tempfile = "3"
-glob = "0.3.1"
-predicates = "3.1.0"
+glob = "0.3.2"
+predicates = "3.1.3"
 rstest = "0.23.0"
 
 # We override the name of the binary for src/main.rs, which otherwise would be
diff --git a/cedar-policy-core/Cargo.toml b/cedar-policy-core/Cargo.toml
index 9c0fa7ba..31992c6d 100644
--- a/cedar-policy-core/Cargo.toml
+++ b/cedar-policy-core/Cargo.toml
@@ -14,7 +14,7 @@ repository.workspace = true
 
 [dependencies]
 serde = { version = "1.0", features = ["derive", "rc"] }
-serde_with = { version = "3.0", features = ["json"] }
+serde_with = { version = "3.12", features = ["json"] }
 serde_json = "1.0"
 lalrpop-util = { version = "0.22.0", features = ["lexer"] }
 lazy_static = "1.4"
diff --git a/cedar-policy-core/src/ast/annotation.rs b/cedar-policy-core/src/ast/annotation.rs
index ac7b2eb3..b7899d19 100644
--- a/cedar-policy-core/src/ast/annotation.rs
+++ b/cedar-policy-core/src/ast/annotation.rs
@@ -26,6 +26,7 @@ use super::AnyId;
 
 /// Struct which holds the annotations for a policy
 #[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Debug)]
+#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
 pub struct Annotations(
     #[serde(default)]
     #[serde(skip_serializing_if = "BTreeMap::is_empty")]
@@ -165,3 +166,17 @@ impl From<&Annotation> for crate::ast::proto::Annotation {
         }
     }
 }
+
+#[cfg(feature = "arbitrary")]
+impl<'a> arbitrary::Arbitrary<'a> for Annotation {
+    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
+        Ok(Self {
+            val: u.arbitrary::<&str>()?.into(),
+            loc: None,
+        })
+    }
+
+    fn size_hint(depth: usize) -> (usize, Option<usize>) {
+        <&str as arbitrary::Arbitrary>::size_hint(depth)
+    }
+}
diff --git a/cedar-policy-core/src/ast/extension.rs b/cedar-policy-core/src/ast/extension.rs
index d8b8e05e..db1555d0 100644
--- a/cedar-policy-core/src/ast/extension.rs
+++ b/cedar-policy-core/src/ast/extension.rs
@@ -34,6 +34,7 @@ mod names {
 
     lazy_static::lazy_static! {
         /// Extension type names that support operator overloading
+        // INVARIANT: this set must not be empty.
         pub static ref TYPES_WITH_OPERATOR_OVERLOADING : BTreeSet<Name> =
             BTreeSet::from_iter(
                 [Name::parse_unqualified_name("datetime").expect("valid identifier"),
diff --git a/cedar-policy-core/src/ast/policy_set.rs b/cedar-policy-core/src/ast/policy_set.rs
index af844f8a..1508c792 100644
--- a/cedar-policy-core/src/ast/policy_set.rs
+++ b/cedar-policy-core/src/ast/policy_set.rs
@@ -630,11 +630,10 @@ mod test {
         .expect("Failed to parse");
         pset.add_template(template).expect("Add failed");
 
-        let env: HashMap<SlotId, EntityUID> = [(
+        let env: HashMap<SlotId, EntityUID> = std::iter::once((
             SlotId::principal(),
             r#"Test::"test""#.parse().expect("Failed to parse"),
-        )]
-        .into_iter()
+        ))
         .collect();
 
         let r = pset.link(PolicyID::from_string("t"), PolicyID::from_string("id"), env);
@@ -669,11 +668,10 @@ mod test {
             )
             .expect("Failed to parse"),
         );
-        let env1: HashMap<SlotId, EntityUID> = [(
+        let env1: HashMap<SlotId, EntityUID> = std::iter::once((
             SlotId::principal(),
             r#"Test::"test1""#.parse().expect("Failed to parse"),
-        )]
-        .into_iter()
+        ))
         .collect();
 
         let p1 = Template::link(Arc::clone(&template), PolicyID::from_string("link"), env1)
@@ -686,11 +684,10 @@ mod test {
             "Adding link should implicitly add the template"
         );
 
-        let env2: HashMap<SlotId, EntityUID> = [(
+        let env2: HashMap<SlotId, EntityUID> = std::iter::once((
             SlotId::principal(),
             r#"Test::"test2""#.parse().expect("Failed to parse"),
-        )]
-        .into_iter()
+        ))
         .collect();
 
         let p2 = Template::link(
@@ -717,11 +714,10 @@ mod test {
             )
             .expect("Failed to parse"),
         );
-        let env3: HashMap<SlotId, EntityUID> = [(
+        let env3: HashMap<SlotId, EntityUID> = std::iter::once((
             SlotId::resource(),
             r#"Test::"test3""#.parse().expect("Failed to parse"),
-        )]
-        .into_iter()
+        ))
         .collect();
 
         let p4 = Template::link(
@@ -781,9 +777,7 @@ mod test {
         set.link(
             PolicyID::from_string("template"),
             PolicyID::from_string("id"),
-            [(SlotId::principal(), EntityUID::with_eid("eid"))]
-                .into_iter()
-                .collect(),
+            std::iter::once((SlotId::principal(), EntityUID::with_eid("eid"))).collect(),
         )
         .expect("Linking failed!");
         assert_eq!(set.static_policies().count(), 1);
diff --git a/cedar-policy-core/src/entities.rs b/cedar-policy-core/src/entities.rs
index b5c039b7..6ea78cef 100644
--- a/cedar-policy-core/src/entities.rs
+++ b/cedar-policy-core/src/entities.rs
@@ -508,6 +508,7 @@ pub enum TCComputation {
 #[cfg(test)]
 // PANIC SAFETY unit tests
 #[allow(clippy::panic)]
+#[allow(clippy::cognitive_complexity)]
 mod json_parsing_tests {
 
     use super::*;
@@ -1731,13 +1732,13 @@ mod json_parsing_tests {
     }
 
     /// helper function
-    fn test_entities() -> (Entity, Entity, Entity, Entity) {
-        (
+    fn test_entities() -> [Entity; 4] {
+        [
             Entity::with_uid(EntityUID::with_eid("test_principal")),
             Entity::with_uid(EntityUID::with_eid("test_action")),
             Entity::with_uid(EntityUID::with_eid("test_resource")),
             Entity::with_uid(EntityUID::with_eid("test")),
-        )
+        ]
     }
 
     /// Test that we can take an Entities, write it to JSON, parse that JSON
@@ -1750,9 +1751,8 @@ mod json_parsing_tests {
             roundtrip(&empty_entities).expect("should roundtrip without errors")
         );
 
-        let (e0, e1, e2, e3) = test_entities();
         let entities = Entities::from_entities(
-            [e0, e1, e2, e3],
+            test_entities(),
             None::<&NoEntitiesSchema>,
             TCComputation::ComputeNow,
             Extensions::none(),
@@ -1960,17 +1960,18 @@ mod json_parsing_tests {
 
 // PANIC SAFETY: Unit Test Code
 #[allow(clippy::panic)]
+#[allow(clippy::cognitive_complexity)]
 #[cfg(test)]
-// PANIC SAFETY unit tests
-#[allow(clippy::panic)]
 mod entities_tests {
     use super::*;
 
     #[test]
     fn empty_entities() {
         let e = Entities::new();
-        let es = e.iter().collect::<Vec<_>>();
-        assert!(es.is_empty(), "This vec should be empty");
+        assert!(
+            e.iter().next().is_none(),
+            "The entity store should be empty"
+        );
     }
 
     /// helper function
@@ -2051,6 +2052,7 @@ mod entities_tests {
 
 // PANIC SAFETY: Unit Test Code
 #[allow(clippy::panic)]
+#[allow(clippy::cognitive_complexity)]
 #[cfg(test)]
 mod schema_based_parsing_tests {
     use super::json::NullEntityTypeDescription;
@@ -2079,9 +2081,7 @@ mod schema_based_parsing_tests {
                 r#"Action::"view""# => Some(Arc::new(Entity::new_with_attr_partial_value(
                     action.clone(),
                     [(SmolStr::from("foo"), PartialValue::from(34))],
-                    [r#"Action::"readOnly""#.parse().expect("valid uid")]
-                        .into_iter()
-                        .collect(),
+                    std::iter::once(r#"Action::"readOnly""#.parse().expect("valid uid")).collect(),
                 ))),
                 r#"Action::"readOnly""# => Some(Arc::new(Entity::with_uid(
                     r#"Action::"readOnly""#.parse().expect("valid uid"),
@@ -2175,11 +2175,10 @@ mod schema_based_parsing_tests {
                         (
                             "inner3".into(),
                             AttributeType::required(SchemaType::Record {
-                                attrs: [(
+                                attrs: std::iter::once((
                                     "innerinner".into(),
                                     AttributeType::required(employee_ty()),
-                                )]
-                                .into_iter()
+                                ))
                                 .collect(),
                                 open_attrs: false,
                             }),
diff --git a/cedar-policy-core/src/est/annotation.rs b/cedar-policy-core/src/est/annotation.rs
index eb4df1e4..847e78fb 100644
--- a/cedar-policy-core/src/est/annotation.rs
+++ b/cedar-policy-core/src/est/annotation.rs
@@ -25,6 +25,7 @@ extern crate tsify;
 /// Similar to [`ast::Annotations`] but allow annotation value to be `null`
 #[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Debug)]
 #[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
+#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
 pub struct Annotations(
     #[serde(default)]
     #[serde(skip_serializing_if = "BTreeMap::is_empty")]
diff --git a/cedar-policy-core/src/evaluator.rs b/cedar-policy-core/src/evaluator.rs
index 6f91d810..864eaca9 100644
--- a/cedar-policy-core/src/evaluator.rs
+++ b/cedar-policy-core/src/evaluator.rs
@@ -31,7 +31,7 @@ pub use err::EvaluationError;
 pub(crate) use err::*;
 use evaluation_errors::*;
 use itertools::Either;
-use nonempty::{nonempty, NonEmpty};
+use nonempty::nonempty;
 use smol_str::SmolStr;
 
 #[cfg(not(target_arch = "wasm32"))]
@@ -427,9 +427,11 @@ impl<'e> Evaluator<'e> {
                             (ValueKind::ExtensionValue(x), _) if x.supports_operator_overloading() => Err(EvaluationError::type_error_single(Type::Extension { name: x.typename() }, &arg2)),
                             (_, ValueKind::ExtensionValue(y)) if y.supports_operator_overloading() => Err(EvaluationError::type_error_single(Type::Extension { name: y.typename() }, &arg1)),
                             (ValueKind::ExtensionValue(x), ValueKind::ExtensionValue(y)) if x.typename() == y.typename() => Err(EvaluationError::type_error_with_advice(Extensions::types_with_operator_overloading().map(|name| Type::Extension { name} ), &arg1, "Only extension types `datetime` and `duration` support operator overloading".to_string())),
-                            // PANIC SAFETY: we're collecting a non-empty vec
-                            #[allow(clippy::unwrap_used)]
-                            _ => Err(EvaluationError::type_error_with_advice(NonEmpty::collect(Extensions::types_with_operator_overloading().map(|name| Type::Extension { name} ).into_iter().chain(std::iter::once(Type::Long))).unwrap(), &arg1, "Only `Long` and extension types `datetime`, `duration` support comparison".to_string()))
+                            _ => {
+                                let mut expected_types = Extensions::types_with_operator_overloading().map(|name| Type::Extension { name });
+                                expected_types.push(Type::Long);
+                                Err(EvaluationError::type_error_with_advice(expected_types, &arg1, "Only `Long` and extension types `datetime`, `duration` support comparison".to_string()))
+                            }
                         }
                     }
                     BinaryOp::Add | BinaryOp::Sub | BinaryOp::Mul => {
@@ -986,6 +988,7 @@ fn stack_size_check() -> Result<()> {
 
 // PANIC SAFETY: Unit Test Code
 #[allow(clippy::panic)]
+#[allow(clippy::cognitive_complexity)]
 #[cfg(test)]
 pub(crate) mod test {
     use std::str::FromStr;
@@ -5031,9 +5034,8 @@ pub(crate) mod test {
             Either::Right(expr) => {
                 println!("{expr}");
                 assert!(expr.contains_unknown());
-                let m: HashMap<_, _> = [("principal".into(), Value::from(euid))]
-                    .into_iter()
-                    .collect();
+                let m: HashMap<_, _> =
+                    std::iter::once(("principal".into(), Value::from(euid))).collect();
                 let new_expr = expr.substitute_typed(&m).unwrap();
                 assert_eq!(
                     e.partial_interpret(&new_expr, &HashMap::new())
diff --git a/cedar-policy-core/src/extensions.rs b/cedar-policy-core/src/extensions.rs
index 0419899d..57bf8587 100644
--- a/cedar-policy-core/src/extensions.rs
+++ b/cedar-policy-core/src/extensions.rs
@@ -99,12 +99,17 @@ impl Extensions<'static> {
         &EXTENSIONS_NONE
     }
 
-    /// Iterate over extension types that support operator overloading
+    /// Obtain the non-empty vector of types supporting operator overloading
     pub fn types_with_operator_overloading() -> NonEmpty<Name> {
         // PANIC SAFETY: There are more than one element in `TYPES_WITH_OPERATOR_OVERLOADING`
         #[allow(clippy::unwrap_used)]
         NonEmpty::collect(TYPES_WITH_OPERATOR_OVERLOADING.iter().cloned()).unwrap()
     }
+
+    /// Iterate over extension types that support operator overloading
+    pub fn iter_type_with_operator_overloading() -> impl Iterator<Item = &'static Name> {
+        TYPES_WITH_OPERATOR_OVERLOADING.iter()
+    }
 }
 
 impl<'a> Extensions<'a> {
diff --git a/cedar-policy-core/src/extensions/datetime.rs b/cedar-policy-core/src/extensions/datetime.rs
index 31e43aca..5b97b485 100644
--- a/cedar-policy-core/src/extensions/datetime.rs
+++ b/cedar-policy-core/src/extensions/datetime.rs
@@ -719,6 +719,7 @@ pub fn extension() -> Extension {
 }
 
 #[cfg(test)]
+#[allow(clippy::cognitive_complexity)]
 mod tests {
     use std::{str::FromStr, sync::Arc};
 
diff --git a/cedar-policy-core/src/extensions/ipaddr.rs b/cedar-policy-core/src/extensions/ipaddr.rs
index a5c62304..590f962b 100644
--- a/cedar-policy-core/src/extensions/ipaddr.rs
+++ b/cedar-policy-core/src/extensions/ipaddr.rs
@@ -444,6 +444,7 @@ pub fn extension() -> Extension {
 // PANIC SAFETY: Unit Test Code
 #[allow(clippy::panic)]
 #[cfg(test)]
+#[allow(clippy::cognitive_complexity)]
 mod tests {
     use super::*;
     use crate::ast::{Expr, Type, Value};
diff --git a/cedar-policy-core/src/parser.rs b/cedar-policy-core/src/parser.rs
index 428adb6b..b6d06dc0 100644
--- a/cedar-policy-core/src/parser.rs
+++ b/cedar-policy-core/src/parser.rs
@@ -327,6 +327,7 @@ pub(crate) mod test_utils {
 
 // PANIC SAFETY: Unit Test Code
 #[allow(clippy::panic, clippy::indexing_slicing)]
+#[allow(clippy::cognitive_complexity)]
 #[cfg(test)]
 /// Tests for the top-level parsing APIs
 mod tests {
diff --git a/cedar-policy-core/src/parser/cst_to_ast.rs b/cedar-policy-core/src/parser/cst_to_ast.rs
index bb329ea4..882ce448 100644
--- a/cedar-policy-core/src/parser/cst_to_ast.rs
+++ b/cedar-policy-core/src/parser/cst_to_ast.rs
@@ -2046,6 +2046,7 @@ fn construct_expr_record(kvs: Vec<(SmolStr, ast::Expr)>, loc: Loc) -> Result<ast
 #[allow(clippy::panic)]
 // PANIC SAFETY: Unit Test Code
 #[allow(clippy::indexing_slicing)]
+#[allow(clippy::cognitive_complexity)]
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/cedar-policy-core/src/parser/text_to_cst.rs b/cedar-policy-core/src/parser/text_to_cst.rs
index aaf7cce1..e3a953c1 100644
--- a/cedar-policy-core/src/parser/text_to_cst.rs
+++ b/cedar-policy-core/src/parser/text_to_cst.rs
@@ -1003,12 +1003,7 @@ mod tests {
             .expect("parser error")
             .node
             .expect("no data");
-        let success = policies
-            .0
-            .into_iter()
-            .filter_map(|p| p.node)
-            .collect::<Vec<_>>();
-        assert!(success.len() == 2);
+        assert_eq!(policies.0.into_iter().filter_map(|p| p.node).count(), 2);
     }
 
     #[test]
diff --git a/cedar-policy-validator/Cargo.toml b/cedar-policy-validator/Cargo.toml
index 6a4b3548..bc42f34a 100644
--- a/cedar-policy-validator/Cargo.toml
+++ b/cedar-policy-validator/Cargo.toml
@@ -14,7 +14,7 @@ repository.workspace = true
 cedar-policy-core = { version = "=4.3.0", path = "../cedar-policy-core" }
 serde = { version = "1.0", features = ["derive"] }
 serde_json = { version = "1.0", features = ["preserve_order"] }
-serde_with = "3.0"
+serde_with = "3.12"
 miette = "7.4.0"
 thiserror = "2.0"
 itertools = "0.13"
diff --git a/cedar-policy-validator/src/cedar_schema/err.rs b/cedar-policy-validator/src/cedar_schema/err.rs
index 394f759f..d5b65b2b 100644
--- a/cedar-policy-validator/src/cedar_schema/err.rs
+++ b/cedar-policy-validator/src/cedar_schema/err.rs
@@ -437,7 +437,7 @@ pub enum ToJsonSchemaError {
 }
 
 impl ToJsonSchemaError {
-    pub(crate) fn duplicate_context(name: impl ToSmolStr, loc1: Loc, loc2: Loc) -> Self {
+    pub(crate) fn duplicate_context(name: &impl ToSmolStr, loc1: Loc, loc2: Loc) -> Self {
         Self::DuplicateContext(DuplicateContext {
             name: name.to_smolstr(),
             loc1,
@@ -445,7 +445,7 @@ impl ToJsonSchemaError {
         })
     }
 
-    pub(crate) fn duplicate_decls(decl: impl ToSmolStr, loc1: Loc, loc2: Loc) -> Self {
+    pub(crate) fn duplicate_decls(decl: &impl ToSmolStr, loc1: Loc, loc2: Loc) -> Self {
         Self::DuplicateDeclarations(DuplicateDeclarations {
             decl: decl.to_smolstr(),
             loc1,
@@ -454,7 +454,7 @@ impl ToJsonSchemaError {
     }
 
     pub(crate) fn duplicate_namespace(
-        namespace_id: impl ToSmolStr,
+        namespace_id: &impl ToSmolStr,
         loc1: Option<Loc>,
         loc2: Option<Loc>,
     ) -> Self {
@@ -465,7 +465,7 @@ impl ToJsonSchemaError {
         })
     }
 
-    pub(crate) fn duplicate_principal(name: impl ToSmolStr, loc1: Loc, loc2: Loc) -> Self {
+    pub(crate) fn duplicate_principal(name: &impl ToSmolStr, loc1: Loc, loc2: Loc) -> Self {
         Self::DuplicatePrincipalOrResource(DuplicatePrincipalOrResource {
             name: name.to_smolstr(),
             kind: PR::Principal,
@@ -474,7 +474,7 @@ impl ToJsonSchemaError {
         })
     }
 
-    pub(crate) fn duplicate_resource(name: impl ToSmolStr, loc1: Loc, loc2: Loc) -> Self {
+    pub(crate) fn duplicate_resource(name: &impl ToSmolStr, loc1: Loc, loc2: Loc) -> Self {
         Self::DuplicatePrincipalOrResource(DuplicatePrincipalOrResource {
             name: name.to_smolstr(),
             kind: PR::Resource,
@@ -483,7 +483,7 @@ impl ToJsonSchemaError {
         })
     }
 
-    pub(crate) fn no_principal(name: impl ToSmolStr, loc: Loc) -> Self {
+    pub(crate) fn no_principal(name: &impl ToSmolStr, loc: Loc) -> Self {
         Self::NoPrincipalOrResource(NoPrincipalOrResource {
             kind: PR::Principal,
             name: name.to_smolstr(),
@@ -491,7 +491,7 @@ impl ToJsonSchemaError {
         })
     }
 
-    pub(crate) fn no_resource(name: impl ToSmolStr, loc: Loc) -> Self {
+    pub(crate) fn no_resource(name: &impl ToSmolStr, loc: Loc) -> Self {
         Self::NoPrincipalOrResource(NoPrincipalOrResource {
             kind: PR::Resource,
             name: name.to_smolstr(),
@@ -499,14 +499,14 @@ impl ToJsonSchemaError {
         })
     }
 
-    pub(crate) fn reserved_name(name: impl ToSmolStr, loc: Loc) -> Self {
+    pub(crate) fn reserved_name(name: &impl ToSmolStr, loc: Loc) -> Self {
         Self::ReservedName(ReservedName {
             name: name.to_smolstr(),
             loc,
         })
     }
 
-    pub(crate) fn reserved_keyword(keyword: impl ToSmolStr, loc: Loc) -> Self {
+    pub(crate) fn reserved_keyword(keyword: &impl ToSmolStr, loc: Loc) -> Self {
         Self::ReservedSchemaKeyword(ReservedSchemaKeyword {
             keyword: keyword.to_smolstr(),
             loc,
diff --git a/cedar-policy-validator/src/cedar_schema/to_json_schema.rs b/cedar-policy-validator/src/cedar_schema/to_json_schema.rs
index f696c2f9..d84190c7 100644
--- a/cedar-policy-validator/src/cedar_schema/to_json_schema.rs
+++ b/cedar-policy-validator/src/cedar_schema/to_json_schema.rs
@@ -197,7 +197,7 @@ impl TryFrom<Annotated<Namespace>> for json_schema::NamespaceDefinition<RawName>
                 let id = UnreservedId::try_from(decl.data.name.node)
                     .map_err(|e| ToJsonSchemaError::reserved_name(e.name(), name_loc.clone()))?;
                 let ctid = json_schema::CommonTypeId::new(id)
-                    .map_err(|e| ToJsonSchemaError::reserved_keyword(e.id, name_loc))?;
+                    .map_err(|e| ToJsonSchemaError::reserved_keyword(&e.id, name_loc))?;
                 Ok((
                     ctid,
                     CommonType {
@@ -273,7 +273,7 @@ fn convert_app_decls(
             } => match context {
                 Some(existing_context) => {
                     return Err(ToJsonSchemaError::duplicate_context(
-                        name.clone(),
+                        name,
                         existing_context.loc,
                         loc,
                     )
@@ -300,7 +300,7 @@ fn convert_app_decls(
             } => match principal_types {
                 Some(existing_tys) => {
                     return Err(ToJsonSchemaError::duplicate_principal(
-                        name.clone(),
+                        name,
                         existing_tys.loc,
                         loc,
                     )
@@ -325,12 +325,9 @@ fn convert_app_decls(
                 loc,
             } => match resource_types {
                 Some(existing_tys) => {
-                    return Err(ToJsonSchemaError::duplicate_resource(
-                        name.clone(),
-                        existing_tys.loc,
-                        loc,
-                    )
-                    .into());
+                    return Err(
+                        ToJsonSchemaError::duplicate_resource(name, existing_tys.loc, loc).into(),
+                    );
                 }
                 None => {
                     resource_types = Some(Node::with_source_loc(
@@ -344,10 +341,10 @@ fn convert_app_decls(
     Ok(json_schema::ApplySpec {
         resource_types: resource_types
             .map(|node| node.node)
-            .ok_or_else(|| ToJsonSchemaError::no_resource(name.clone(), name_loc.clone()))?,
+            .ok_or_else(|| ToJsonSchemaError::no_resource(&name, name_loc.clone()))?,
         principal_types: principal_types
             .map(|node| node.node)
-            .ok_or_else(|| ToJsonSchemaError::no_principal(name.clone(), name_loc.clone()))?,
+            .ok_or_else(|| ToJsonSchemaError::no_principal(&name, name_loc.clone()))?,
         context: context.map(|c| c.node).unwrap_or_default(),
     })
 }
@@ -524,7 +521,7 @@ where
     for (key, node) in i {
         match map.entry(key.clone()) {
             Entry::Occupied(entry) => Err(ToJsonSchemaError::duplicate_decls(
-                key,
+                &key,
                 entry.get().loc.clone(),
                 node.loc,
             )),
@@ -614,7 +611,7 @@ fn update_namespace_record(
 ) -> Result<(), ToJsonSchemaErrors> {
     match map.entry(name.clone()) {
         Entry::Occupied(entry) => Err(ToJsonSchemaError::duplicate_namespace(
-            name.map_or("".into(), |n| n.to_smolstr()),
+            &name.map_or("".into(), |n| n.to_smolstr()),
             record.loc,
             entry.get().loc.clone(),
         )
diff --git a/cedar-policy-validator/src/diagnostics.rs b/cedar-policy-validator/src/diagnostics.rs
index 4ee0fd20..7d11f3eb 100644
--- a/cedar-policy-validator/src/diagnostics.rs
+++ b/cedar-policy-validator/src/diagnostics.rs
@@ -225,14 +225,14 @@ impl ValidationError {
     pub(crate) fn expected_one_of_types(
         source_loc: Option<Loc>,
         policy_id: PolicyID,
-        expected: impl IntoIterator<Item = Type>,
+        expected: Vec<Type>,
         actual: Type,
         help: Option<validation_errors::UnexpectedTypeHelp>,
     ) -> Self {
         validation_errors::UnexpectedType {
             source_loc,
             policy_id,
-            expected: expected.into_iter().collect::<BTreeSet<_>>(),
+            expected,
             actual,
             help,
         }
diff --git a/cedar-policy-validator/src/diagnostics/validation_errors.rs b/cedar-policy-validator/src/diagnostics/validation_errors.rs
index d4485ee2..ec578017 100644
--- a/cedar-policy-validator/src/diagnostics/validation_errors.rs
+++ b/cedar-policy-validator/src/diagnostics/validation_errors.rs
@@ -174,7 +174,7 @@ pub struct UnexpectedType {
     /// Policy ID where the error occurred
     pub policy_id: PolicyID,
     /// Type(s) which were expected
-    pub expected: BTreeSet<Type>,
+    pub expected: Vec<Type>,
     /// Type which was encountered
     pub actual: Type,
     /// Optional help for resolving the error
diff --git a/cedar-policy-validator/src/json_schema.rs b/cedar-policy-validator/src/json_schema.rs
index f51b2f6a..d5825c69 100644
--- a/cedar-policy-validator/src/json_schema.rs
+++ b/cedar-policy-validator/src/json_schema.rs
@@ -107,6 +107,11 @@ where
         raw.into_iter()
             .map(|(key, value)| {
                 let key = if key.is_empty() {
+                    if !value.annotations.is_empty() {
+                        Err(serde::de::Error::custom(format!(
+                            "annotations are not allowed on the empty namespace"
+                        )))?
+                    }
                     None
                 } else {
                     Some(Name::from_normalized_str(&key).map_err(|err| {
@@ -1787,15 +1792,16 @@ impl<'a> arbitrary::Arbitrary<'a> for TypeOfAttribute<RawName> {
         Ok(Self {
             ty: u.arbitrary::<Type<RawName>>()?,
             required: u.arbitrary()?,
-            annotations: cedar_policy_core::est::Annotations::new(),
+            annotations: u.arbitrary()?,
         })
     }
 
     fn size_hint(depth: usize) -> (usize, Option<usize>) {
-        arbitrary::size_hint::and(
+        arbitrary::size_hint::and_all(&[
             <Type<RawName> as arbitrary::Arbitrary>::size_hint(depth),
             <bool as arbitrary::Arbitrary>::size_hint(depth),
-        )
+            <cedar_policy_core::est::Annotations as arbitrary::Arbitrary>::size_hint(depth),
+        ])
     }
 }
 
@@ -2773,8 +2779,7 @@ mod test_json_roundtrip {
                 entity_types: BTreeMap::new(),
                 actions: BTreeMap::new(),
                 annotations: Annotations::new(),
-            }
-            .into(),
+            },
         )]));
         roundtrip(fragment);
     }
@@ -2788,8 +2793,7 @@ mod test_json_roundtrip {
                 entity_types: BTreeMap::new(),
                 actions: BTreeMap::new(),
                 annotations: Annotations::new(),
-            }
-            .into(),
+            },
         )]));
         roundtrip(fragment);
     }
@@ -2810,8 +2814,7 @@ mod test_json_roundtrip {
                         }))),
                         tags: None,
                         annotations: Annotations::new(),
-                    }
-                    .into(),
+                    },
                 )]),
                 actions: BTreeMap::from([(
                     "action".into(),
@@ -2829,12 +2832,10 @@ mod test_json_roundtrip {
                         }),
                         member_of: None,
                         annotations: Annotations::new(),
-                    }
-                    .into(),
+                    },
                 )]),
                 annotations: Annotations::new(),
-            }
-            .into(),
+            },
         )]));
         roundtrip(fragment);
     }
@@ -2858,13 +2859,11 @@ mod test_json_roundtrip {
                             ))),
                             tags: None,
                             annotations: Annotations::new(),
-                        }
-                        .into(),
+                        },
                     )]),
                     actions: BTreeMap::new(),
                     annotations: Annotations::new(),
-                }
-                .into(),
+                },
             ),
             (
                 None,
@@ -2887,12 +2886,10 @@ mod test_json_roundtrip {
                             }),
                             member_of: None,
                             annotations: Annotations::new(),
-                        }
-                        .into(),
+                        },
                     )]),
                     annotations: Annotations::new(),
-                }
-                .into(),
+                },
             ),
         ]));
         roundtrip(fragment);
@@ -3053,7 +3050,7 @@ mod annotations {
     use super::Fragment;
 
     #[test]
-    fn basic() {
+    fn empty_namespace() {
         let src = serde_json::json!(
         {
            "" : {
@@ -3065,11 +3062,29 @@ mod annotations {
            }
         });
         let schema: Result<Fragment<RawName>, _> = serde_json::from_value(src);
+        assert_matches!(schema, Err(err) => {
+            assert_eq!(&err.to_string(), "annotations are not allowed on the empty namespace");
+        });
+    }
+
+    #[test]
+    fn basic() {
+        let src = serde_json::json!(
+        {
+           "N" : {
+            "entityTypes": {},
+            "actions": {},
+            "annotations": {
+                "doc": "this is a doc"
+            }
+           }
+        });
+        let schema: Result<Fragment<RawName>, _> = serde_json::from_value(src);
         assert_matches!(schema, Ok(_));
 
         let src = serde_json::json!(
         {
-           "" : {
+           "N" : {
             "entityTypes": {
                 "a": {
                     "annotations": {
@@ -3094,7 +3109,7 @@ mod annotations {
 
         let src = serde_json::json!(
         {
-           "" : {
+           "N" : {
             "entityTypes": {
                 "a": {
                     "annotations": {
@@ -3126,7 +3141,7 @@ mod annotations {
         assert_matches!(schema, Ok(_));
 
         let src = serde_json::json!({
-            "": {
+            "N": {
             "entityTypes": {},
             "actions": {},
             "commonTypes": {
@@ -3154,7 +3169,7 @@ mod annotations {
         assert_matches!(schema, Ok(_));
 
         let src = serde_json::json!({
-            "": {
+            "N": {
                 "entityTypes": {
                     "User" : {
                         "shape" : {
@@ -3181,7 +3196,7 @@ mod annotations {
 
         // nested record
         let src = serde_json::json!({
-            "": {
+            "N": {
                 "entityTypes": {
                     "User" : {
                         "shape" : {
@@ -3242,7 +3257,7 @@ mod annotations {
     fn unknown_fields() {
         let src = serde_json::json!(
         {
-            "": {
+            "N": {
                 "entityTypes": {
             "UserGroup": {
                 "shape44": {
@@ -3259,7 +3274,7 @@ mod annotations {
 
         let src = serde_json::json!(
         {
-            "": {
+            "N": {
                 "entityTypes": {},
                 "actions": {},
                 "commonTypes": {
@@ -3277,7 +3292,7 @@ mod annotations {
 
         let src = serde_json::json!(
         {
-            "": {
+            "N": {
                 "entityTypes": {},
                 "actions": {},
                 "commonTypes": {
@@ -3292,7 +3307,7 @@ mod annotations {
 
         let src = serde_json::json!(
         {
-            "": {
+            "N": {
                 "entityTypes": {},
                 "actions": {},
                 "commonTypes": {
@@ -3313,7 +3328,7 @@ mod annotations {
 
         let src = serde_json::json!(
         {
-            "": {
+            "N": {
                 "entityTypes": {},
                 "actions": {},
                 "commonTypes": {
@@ -3342,7 +3357,7 @@ mod annotations {
 
         let src = serde_json::json!(
         {
-            "": {
+            "N": {
                 "entityTypes": {
             "UserGroup": {
                 "shape": {
@@ -3362,7 +3377,7 @@ mod annotations {
 
         let src = serde_json::json!(
         {
-            "": {
+            "N": {
                 "entityTypes": {},
                 "actions": {
                     "a": {
@@ -3380,7 +3395,7 @@ mod annotations {
 
         let src = serde_json::json!(
         {
-           "" : {
+           "N" : {
             "entityTypes": {},
             "actions": {},
             "foo": "",
@@ -3411,7 +3426,7 @@ mod annotations {
 
         let src = serde_json::json!(
         {
-           "" : {
+           "N" : {
             "entityTypes": {},
             "actions": {},
             "commonTypes": {
diff --git a/cedar-policy-validator/src/schema.rs b/cedar-policy-validator/src/schema.rs
index c3241fc8..c668b04d 100644
--- a/cedar-policy-validator/src/schema.rs
+++ b/cedar-policy-validator/src/schema.rs
@@ -3588,6 +3588,7 @@ pub(crate) mod test {
 mod test_579; // located in separate file test_579.rs
 
 #[cfg(test)]
+#[allow(clippy::cognitive_complexity)]
 mod test_rfc70 {
     use super::test::utils::*;
     use super::ValidatorSchema;
@@ -4578,6 +4579,7 @@ mod test_rfc70 {
 
 /// Tests involving entity tags (RFC 82)
 #[cfg(test)]
+#[allow(clippy::cognitive_complexity)]
 mod entity_tags {
     use super::{test::utils::*, *};
     use cedar_policy_core::{
diff --git a/cedar-policy-validator/src/typecheck.rs b/cedar-policy-validator/src/typecheck.rs
index b488e465..36e87e63 100644
--- a/cedar-policy-validator/src/typecheck.rs
+++ b/cedar-policy-validator/src/typecheck.rs
@@ -1245,8 +1245,8 @@ impl<'a> Typechecker<'a> {
             }
 
             BinaryOp::Less | BinaryOp::LessEq => {
-                let expected_types = Extensions::types_with_operator_overloading()
-                    .into_iter()
+                let expected_types = Extensions::iter_type_with_operator_overloading()
+                    .cloned()
                     .map(Type::extension)
                     .chain(std::iter::once(Type::primitive_long()))
                     .collect_vec();
diff --git a/cedar-policy-validator/src/types.rs b/cedar-policy-validator/src/types.rs
index ade1f88b..da4a162f 100644
--- a/cedar-policy-validator/src/types.rs
+++ b/cedar-policy-validator/src/types.rs
@@ -675,7 +675,7 @@ impl Type {
     pub(crate) fn support_operator_overloading(&self) -> bool {
         match self {
             Self::ExtensionType { name } => {
-                Extensions::types_with_operator_overloading().contains(name)
+                Extensions::iter_type_with_operator_overloading().contains(name)
             }
             _ => false,
         }
diff --git a/cedar-policy/Cargo.toml b/cedar-policy/Cargo.toml
index 5558a8b6..6dfddb30 100644
--- a/cedar-policy/Cargo.toml
+++ b/cedar-policy/Cargo.toml
@@ -23,7 +23,7 @@ miette = "7.4.0"
 thiserror = "2.0"
 smol_str = { version = "0.3", features = ["serde"] }
 dhat = { version = "0.3.2", optional = true }
-serde_with = "3.3.0"
+serde_with = "3.12.0"
 nonempty = "0.10"
 prost = { version = "0.13", optional = true }
 
@@ -72,7 +72,7 @@ cedar-policy-core = { version = "=4.3.0", features = [
 # NON-CRYPTOGRAPHIC random number generators
 oorandom = "11.1"
 
-proptest = "1.0.0"
+proptest = "1.6.0"
 
 [[bench]]
 name = "cedar_benchmarks"
diff --git a/cedar-policy/src/ffi/check_parse.rs b/cedar-policy/src/ffi/check_parse.rs
index 28e45f2b..eb18f080 100644
--- a/cedar-policy/src/ffi/check_parse.rs
+++ b/cedar-policy/src/ffi/check_parse.rs
@@ -260,12 +260,12 @@ mod test {
     use serde_json::json;
 
     #[track_caller]
-    fn assert_check_parse_is_ok(parse_result: CheckParseAnswer) {
+    fn assert_check_parse_is_ok(parse_result: &CheckParseAnswer) {
         assert_matches!(parse_result, CheckParseAnswer::Success);
     }
 
     #[track_caller]
-    fn assert_check_parse_is_err(parse_result: CheckParseAnswer) -> Vec<DetailedError> {
+    fn assert_check_parse_is_err(parse_result: &CheckParseAnswer) -> &[DetailedError] {
         assert_matches!(
             parse_result,
             CheckParseAnswer::Failure { errors } => errors
@@ -278,7 +278,7 @@ mod test {
                 "staticPolicies": "permit(principal, action, resource);"
         });
         let answer = serde_json::from_value(check_parse_policy_set_json(call).unwrap()).unwrap();
-        assert_check_parse_is_ok(answer);
+        assert_check_parse_is_ok(&answer);
     }
 
     #[test]
@@ -287,7 +287,7 @@ mod test {
             "staticPolicies": "forbid(principal, action, resource); permit(principal == User::\"alice\", action == Action::\"view\", resource in Albums::\"alice_albums\");"
         });
         let answer = serde_json::from_value(check_parse_policy_set_json(call).unwrap()).unwrap();
-        assert_check_parse_is_ok(answer);
+        assert_check_parse_is_ok(&answer);
     }
 
     #[test]
@@ -296,9 +296,9 @@ mod test {
             "staticPolicies": "forbid(principal, action, resource);permit(2pac, action, resource)"
         });
         let answer = serde_json::from_value(check_parse_policy_set_json(call).unwrap()).unwrap();
-        let errs = assert_check_parse_is_err(answer);
+        let errs = assert_check_parse_is_err(&answer);
         assert_exactly_one_error(
-            &errs,
+            errs,
             "failed to parse policies from string: unexpected token `2`",
             None,
         );
@@ -312,14 +312,14 @@ mod test {
             }
         });
         let answer = serde_json::from_value(check_parse_policy_set_json(call).unwrap()).unwrap();
-        assert_check_parse_is_ok(answer);
+        assert_check_parse_is_ok(&answer);
     }
 
     #[test]
     fn check_parse_schema_succeeds_empty_schema() {
         let call = json!({});
         let answer = serde_json::from_value(check_parse_schema_json(call).unwrap()).unwrap();
-        assert_check_parse_is_ok(answer);
+        assert_check_parse_is_ok(&answer);
     }
 
     #[test]
@@ -331,7 +331,7 @@ mod test {
           }
         });
         let answer = serde_json::from_value(check_parse_schema_json(call).unwrap()).unwrap();
-        assert_check_parse_is_ok(answer);
+        assert_check_parse_is_ok(&answer);
     }
 
     #[test]
@@ -342,9 +342,9 @@ mod test {
           }
         });
         let answer = serde_json::from_value(check_parse_schema_json(call).unwrap()).unwrap();
-        let errs = assert_check_parse_is_err(answer);
+        let errs = assert_check_parse_is_err(&answer);
         assert_exactly_one_error(
-            &errs,
+            errs,
             "failed to parse schema from JSON: missing field `actions`",
             None,
         );
@@ -389,7 +389,7 @@ mod test {
             }
         });
         let answer = serde_json::from_value(check_parse_entities_json(call).unwrap()).unwrap();
-        assert_check_parse_is_ok(answer);
+        assert_check_parse_is_ok(&answer);
     }
 
     #[test]
@@ -410,7 +410,7 @@ mod test {
             ]
         });
         let answer = serde_json::from_value(check_parse_entities_json(call).unwrap()).unwrap();
-        assert_check_parse_is_ok(answer);
+        assert_check_parse_is_ok(&answer);
     }
 
     #[test]
@@ -445,9 +445,9 @@ mod test {
             }
         });
         let answer = serde_json::from_value(check_parse_entities_json(call).unwrap()).unwrap();
-        let errs = assert_check_parse_is_err(answer);
+        let errs = assert_check_parse_is_err(&answer);
         assert_exactly_one_error(
-            &errs,
+            errs,
             "error during entity deserialization: in uid field of <unknown entity>, expected a literal entity reference, but got `\"TheNamespace::User::\\\"alice\\\"\"`",
             Some("literal entity references can be made with `{ \"type\": \"SomeType\", \"id\": \"SomeId\" }`")
         );
@@ -491,7 +491,7 @@ mod test {
 
         });
         let answer = serde_json::from_value(check_parse_context_json(call).unwrap()).unwrap();
-        assert_check_parse_is_ok(answer);
+        assert_check_parse_is_ok(&answer);
     }
 
     #[test]
@@ -531,7 +531,7 @@ mod test {
             }
         });
         let answer = serde_json::from_value(check_parse_context_json(call).unwrap()).unwrap();
-        let errs = assert_check_parse_is_err(answer);
-        assert_exactly_one_error(&errs, "while parsing context, expected the record to have an attribute `referrer`, but it does not", None);
+        let errs = assert_check_parse_is_err(&answer);
+        assert_exactly_one_error(errs, "while parsing context, expected the record to have an attribute `referrer`, but it does not", None);
     }
 }


Test patch:
diff --git a/cedar-policy-cli/tests/sample.rs b/cedar-policy-cli/tests/sample.rs
index bf2c14d2..ae36bca5 100644
--- a/cedar-policy-cli/tests/sample.rs
+++ b/cedar-policy-cli/tests/sample.rs
@@ -106,7 +106,7 @@ fn run_link_test(
     links_file: impl Into<String>,
     template_id: impl Into<String>,
     linked_id: impl Into<String>,
-    env: HashMap<SlotId, String>,
+    env: impl IntoIterator<Item = (SlotId, String)>,
     expected: CedarExitCode,
 ) {
     let cmd = LinkArgs {
@@ -117,7 +117,9 @@ fn run_link_test(
         },
         template_id: template_id.into(),
         new_id: linked_id.into(),
-        arguments: Arguments { data: env },
+        arguments: Arguments {
+            data: HashMap::from_iter(env),
+        },
     };
     let output = link(&cmd);
     assert_eq!(output, expected);
@@ -792,9 +794,7 @@ fn test_link_samples() {
         &linked_file_name,
         "AccessVacation",
         "AliceAccess",
-        [(SlotId::principal(), "User::\"alice\"".to_string())]
-            .into_iter()
-            .collect(),
+        [(SlotId::principal(), "User::\"alice\"".to_string())],
         CedarExitCode::Failure,
     );
 
@@ -803,9 +803,7 @@ fn test_link_samples() {
         &linked_file_name,
         "AccessVacation",
         "AliceAccess",
-        [(SlotId::principal(), "invalid".to_string())]
-            .into_iter()
-            .collect(),
+        [(SlotId::principal(), "invalid".to_string())],
         CedarExitCode::Failure,
     );
 
@@ -814,9 +812,7 @@ fn test_link_samples() {
         &linked_file_name,
         "AccessVacation",
         "AliceAccess",
-        [(SlotId::principal(), "User::\"alice\"".to_string())]
-            .into_iter()
-            .collect(),
+        [(SlotId::principal(), "User::\"alice\"".to_string())],
         CedarExitCode::Success,
     );
 
@@ -845,9 +841,7 @@ fn test_link_samples() {
         &linked_file_name,
         "AccessVacation",
         "BobAccess",
-        [(SlotId::principal(), "User::\"bob\"".to_string())]
-            .into_iter()
-            .collect(),
+        [(SlotId::principal(), "User::\"bob\"".to_string())],
         CedarExitCode::Success,
     );
 
diff --git a/cedar-policy-validator/src/cedar_schema/test.rs b/cedar-policy-validator/src/cedar_schema/test.rs
index bf72a6ab..4cf7628c 100644
--- a/cedar-policy-validator/src/cedar_schema/test.rs
+++ b/cedar-policy-validator/src/cedar_schema/test.rs
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#![allow(clippy::cognitive_complexity)]
 
 // PANIC SAFETY: unit tests
 #[allow(clippy::panic)]
@@ -737,7 +738,7 @@ namespace Baz {action "Foo" appliesTo {
                 }),
             );
             assert_has_type(
-                &attributes.get("viewACL").unwrap(),
+                attributes.get("viewACL").unwrap(),
                 json_schema::Type::Type(json_schema::TypeVariant::EntityOrCommon {
                     type_name: "DocumentShare".parse().unwrap(),
                 }),
diff --git a/cedar-policy-validator/src/typecheck/test.rs b/cedar-policy-validator/src/typecheck/test.rs
index 813a73e6..ce734326 100644
--- a/cedar-policy-validator/src/typecheck/test.rs
+++ b/cedar-policy-validator/src/typecheck/test.rs
@@ -19,6 +19,7 @@
 #![allow(clippy::panic)]
 // PANIC SAFETY unit tests
 #![allow(clippy::indexing_slicing)]
+#![allow(clippy::cognitive_complexity)]
 
 pub(crate) mod test_utils;
 
diff --git a/cedar-policy-validator/src/typecheck/test/expr.rs b/cedar-policy-validator/src/typecheck/test/expr.rs
index 5a80d8a0..f2979935 100644
--- a/cedar-policy-validator/src/typecheck/test/expr.rs
+++ b/cedar-policy-validator/src/typecheck/test/expr.rs
@@ -653,7 +653,7 @@ fn has_typecheck_fails() {
         ValidationError::expected_one_of_types(
             get_loc(src, "true"),
             expr_id_placeholder(),
-            [Type::any_entity_reference(), Type::any_record()],
+            vec![Type::any_entity_reference(), Type::any_record()],
             Type::singleton_boolean(true),
             None,
         )
@@ -701,7 +701,7 @@ fn record_get_attr_typecheck_fails() {
         ValidationError::expected_one_of_types(
             get_loc(src, "2"),
             expr_id_placeholder(),
-            [Type::any_entity_reference(), Type::any_record()],
+            vec![Type::any_entity_reference(), Type::any_record()],
             Type::primitive_long(),
             None,
         )
@@ -821,7 +821,7 @@ fn in_typecheck_fails() {
             ValidationError::expected_one_of_types(
                 get_loc(src, "true"),
                 expr_id_placeholder(),
-                [
+                vec![
                     Type::set(Type::any_entity_reference()),
                     Type::any_entity_reference(),
                 ],
@@ -1115,12 +1115,10 @@ fn less_than_typechecks() {
 
 #[test]
 fn less_than_typecheck_fails() {
-    let expected_types = std::iter::once(Type::primitive_long())
-        .chain(
-            Extensions::types_with_operator_overloading()
-                .into_iter()
-                .map(Type::extension),
-        )
+    let expected_types = Extensions::types_with_operator_overloading()
+        .into_iter()
+        .map(Type::extension)
+        .chain(std::iter::once(Type::primitive_long()))
         .collect_vec();
     let src = "true < false";
     let errors =
diff --git a/cedar-policy-validator/src/typecheck/test/namespace.rs b/cedar-policy-validator/src/typecheck/test/namespace.rs
index e7ad8149..c3d5c0a8 100644
--- a/cedar-policy-validator/src/typecheck/test/namespace.rs
+++ b/cedar-policy-validator/src/typecheck/test/namespace.rs
@@ -148,7 +148,7 @@ fn namespaced_entity_can_type_error() {
         ValidationError::expected_one_of_types(
             get_loc(src, r#"N::S::Foo::"alice""#),
             expr_id_placeholder(),
-            std::iter::once(Type::primitive_long()),
+            vec![Type::primitive_long()],
             Type::named_entity_reference_from_str("N::S::Foo"),
             None,
         )
diff --git a/cedar-policy-validator/src/typecheck/test/partial.rs b/cedar-policy-validator/src/typecheck/test/partial.rs
index 1238f623..eeda516c 100644
--- a/cedar-policy-validator/src/typecheck/test/partial.rs
+++ b/cedar-policy-validator/src/typecheck/test/partial.rs
@@ -405,11 +405,11 @@ mod fails_empty_schema {
             [ValidationError::expected_one_of_types(
                 get_loc(src, r#""a""#),
                 PolicyID::from_string("policy0"),
-                std::iter::once(Type::primitive_long()).chain(
-                    Extensions::types_with_operator_overloading()
-                        .into_iter()
-                        .map(Type::extension),
-                ),
+                Extensions::types_with_operator_overloading()
+                    .into_iter()
+                    .map(Type::extension)
+                    .chain(std::iter::once(Type::primitive_long()))
+                    .collect(),
                 Type::primitive_string(),
                 None,
             )],
@@ -653,11 +653,11 @@ mod fail_partial_schema {
             [ValidationError::expected_one_of_types(
                 get_loc(src, "principal.name"),
                 PolicyID::from_string("policy0"),
-                std::iter::once(Type::primitive_long()).chain(
-                    Extensions::types_with_operator_overloading()
-                        .into_iter()
-                        .map(Type::extension),
-                ),
+                Extensions::types_with_operator_overloading()
+                    .into_iter()
+                    .map(Type::extension)
+                    .chain(std::iter::once(Type::primitive_long()))
+                    .collect(),
                 Type::primitive_string(),
                 None,
             )],
diff --git a/cedar-policy-validator/src/typecheck/test/policy.rs b/cedar-policy-validator/src/typecheck/test/policy.rs
index c10f1975..92b7510a 100644
--- a/cedar-policy-validator/src/typecheck/test/policy.rs
+++ b/cedar-policy-validator/src/typecheck/test/policy.rs
@@ -845,7 +845,7 @@ fn type_error_is_not_reported_for_every_cross_product_element() {
         ValidationError::expected_one_of_types(
             get_loc(src, "true"),
             PolicyID::from_string("0"),
-            std::iter::once(Type::primitive_long()),
+            vec![Type::primitive_long()],
             Type::True,
             None,
         )
diff --git a/cedar-policy-validator/src/typecheck/test/test_utils.rs b/cedar-policy-validator/src/typecheck/test/test_utils.rs
index c45db448..db94a61b 100644
--- a/cedar-policy-validator/src/typecheck/test/test_utils.rs
+++ b/cedar-policy-validator/src/typecheck/test/test_utils.rs
@@ -124,7 +124,7 @@ pub(crate) fn assert_types_eq(schema: &ValidatorSchema, expected: &Type, actual:
 
 /// Assert that every `T` in `actual` appears in `expected`, and vice versa.
 #[track_caller]
-pub(crate) fn assert_sets_equal<T: Hash + Eq>(
+pub(crate) fn assert_sets_equal<T: Hash + Eq + std::fmt::Debug>(
     expected: impl IntoIterator<Item = T>,
     actual: impl IntoIterator<Item = T>,
 ) {
diff --git a/cedar-policy/src/prop_test_policy_set.rs b/cedar-policy/src/prop_test_policy_set.rs
index 6772311f..4d81a632 100644
--- a/cedar-policy/src/prop_test_policy_set.rs
+++ b/cedar-policy/src/prop_test_policy_set.rs
@@ -112,7 +112,7 @@ impl PolicySetModel {
                         panic!("template to link map should have Vec for existing template")
                     }
                 };
-                assert!(self.link_to_template_map.get(policy_name).is_none());
+                assert!(!self.link_to_template_map.contains_key(policy_name));
                 self.link_to_template_map
                     .insert(policy_name.to_owned(), template_name.clone());
             }
diff --git a/cedar-policy/src/tests.rs b/cedar-policy/src/tests.rs
index e8b0fb77..7ed580b0 100644
--- a/cedar-policy/src/tests.rs
+++ b/cedar-policy/src/tests.rs
@@ -17,6 +17,7 @@
 #![cfg(test)]
 // PANIC SAFETY unit tests
 #![allow(clippy::panic)]
+#![allow(clippy::cognitive_complexity, clippy::too_many_lines)]
 
 use super::*;
 
@@ -4858,7 +4859,7 @@ mod policy_set_est_tests {
     #[test]
     fn test_partition_fold_err() {
         let even_or_odd = |s: &str| {
-            i64::from_str_radix(s, 10).map(|i| {
+            s.parse::<i64>().map(|i| {
                 if i % 2 == 0 {
                     Either::Left(i)
                 } else {
@@ -5074,10 +5075,11 @@ mod policy_set_est_tests {
                 r#"User::"John""#.parse().unwrap()
             )]))
         );
-        if let Err(_) = policyset
+        if policyset
             .get_linked_policies(PolicyId::new("template"))
             .unwrap()
             .exactly_one()
+            .is_err()
         {
             panic!("Should have exactly one");
         };
@@ -6323,30 +6325,25 @@ mod reserved_keywords_in_policies {
     }
 
     #[track_caller]
-    fn assert_valid_expression(src: String) {
-        assert_matches!(Expression::from_str(&src), Ok(_));
+    fn assert_valid_expression(src: &str) {
+        assert_matches!(Expression::from_str(src), Ok(_));
     }
 
     #[track_caller]
-    fn assert_invalid_expression(src: String, error: String, underline: String) {
-        let expected_err = ExpectedErrorMessageBuilder::error(&error)
-            .exactly_one_underline(&underline)
+    fn assert_invalid_expression(src: &str, error: &str, underline: &str) {
+        let expected_err = ExpectedErrorMessageBuilder::error(error)
+            .exactly_one_underline(underline)
             .build();
-        assert_matches!(Expression::from_str(&src), Err(err) => expect_err(&*src, &Report::new(err), &expected_err));
+        assert_matches!(Expression::from_str(src), Err(err) => expect_err(src, &Report::new(err), &expected_err));
     }
 
     #[track_caller]
-    fn assert_invalid_expression_with_help(
-        src: String,
-        error: String,
-        underline: String,
-        help: String,
-    ) {
-        let expected_err = ExpectedErrorMessageBuilder::error(&error)
-            .exactly_one_underline(&underline)
-            .help(&help)
+    fn assert_invalid_expression_with_help(src: &str, error: &str, underline: &str, help: &str) {
+        let expected_err = ExpectedErrorMessageBuilder::error(error)
+            .exactly_one_underline(underline)
+            .help(help)
             .build();
-        assert_matches!(Expression::from_str(&src), Err(err) => expect_err(&*src, &Report::new(err), &expected_err));
+        assert_matches!(Expression::from_str(src), Err(err) => expect_err(src, &Report::new(err), &expected_err));
     }
 
     #[test]
@@ -6367,16 +6364,16 @@ mod reserved_keywords_in_policies {
             .chain(RESERVED_NAMESPACE.iter())
             .chain(OTHER_SPECIAL_IDENTS.iter())
             .for_each(|id| {
-                assert_valid_expression(format!("{{ \"{id}\": 1 }}"));
-                assert_valid_expression(format!("principal has \"{id}\""));
-                assert_valid_expression(format!("principal[\"{id}\"] == \"foo\""));
+                assert_valid_expression(&format!("{{ \"{id}\": 1 }}"));
+                assert_valid_expression(&format!("principal has \"{id}\""));
+                assert_valid_expression(&format!("principal[\"{id}\"] == \"foo\""));
             });
 
         // No restrictions on OTHER_SPECIAL_IDENTS
         for id in &OTHER_SPECIAL_IDENTS {
-            assert_valid_expression(format!("{{ {id}: 1 }}"));
-            assert_valid_expression(format!("principal has {id}"));
-            assert_valid_expression(format!("principal.{id} == \"foo\""));
+            assert_valid_expression(&format!("{{ {id}: 1 }}"));
+            assert_valid_expression(&format!("principal has {id}"));
+            assert_valid_expression(&format!("principal.{id} == \"foo\""));
         }
 
         // RESERVED_IDENTS cannot be used as keys without quotes
@@ -6385,66 +6382,62 @@ mod reserved_keywords_in_policies {
             match id {
                 "true" | "false" => {
                     assert_invalid_expression_with_help(
-                        format!("{{ {id}: 1 }}"),
-                        format!("invalid attribute name: {id}"),
-                        id.into(),
-                        "attribute names can either be identifiers or string literals".into(),
+                        &format!("{{ {id}: 1 }}"),
+                        &format!("invalid attribute name: {id}"),
+                        id,
+                        "attribute names can either be identifiers or string literals",
                     );
                     assert_invalid_expression(
-                        format!("principal has {id}"),
-                        RESERVED_IDENT_MSG(id),
-                        id.to_string(),
+                        &format!("principal has {id}"),
+                        &RESERVED_IDENT_MSG(id),
+                        id,
                     );
                 }
                 "if" => {
                     assert_invalid_expression(
-                        format!("{{ {id}: 1 }}"),
-                        RESERVED_IDENT_MSG(id),
-                        format!("{id}: 1"),
+                        &format!("{{ {id}: 1 }}"),
+                        &RESERVED_IDENT_MSG(id),
+                        &format!("{id}: 1"),
                     );
                     assert_invalid_expression(
-                        format!("principal has {id}"),
-                        RESERVED_IDENT_MSG(id),
-                        id.to_string(),
+                        &format!("principal has {id}"),
+                        &RESERVED_IDENT_MSG(id),
+                        id,
                     );
                 }
                 _ => {
                     assert_invalid_expression(
-                        format!("{{ {id}: 1 }}"),
-                        RESERVED_IDENT_MSG(id),
-                        id.into(),
+                        &format!("{{ {id}: 1 }}"),
+                        &RESERVED_IDENT_MSG(id),
+                        id,
                     );
                     assert_invalid_expression(
-                        format!("principal has {id}"),
-                        RESERVED_IDENT_MSG(id),
-                        id.into(),
+                        &format!("principal has {id}"),
+                        &RESERVED_IDENT_MSG(id),
+                        id,
                     );
                 }
             }
             // this case leads to a consistent error for all keywords
             assert_invalid_expression(
-                format!("principal.{id} == \"foo\""),
-                RESERVED_IDENT_MSG(id),
-                id.into(),
+                &format!("principal.{id} == \"foo\""),
+                &RESERVED_IDENT_MSG(id),
+                id,
             );
         }
 
         // RESERVED_NAMESPACE cannot be used as keys without quotes
         for id in RESERVED_NAMESPACE {
+            assert_invalid_expression(&format!("{{ {id}: 1 }}"), &RESERVED_NAMESPACE_MSG(id), id);
             assert_invalid_expression(
-                format!("{{ {id}: 1 }}"),
-                RESERVED_NAMESPACE_MSG(id),
-                id.into(),
+                &format!("principal has {id}"),
+                &RESERVED_NAMESPACE_MSG(id),
+                id,
             );
             assert_invalid_expression(
-                format!("principal has {id}"),
-                RESERVED_NAMESPACE_MSG(id),
-                id.into(),
-            );
-            assert_invalid_expression(
-                format!("principal.{id} == \"foo\""),
-                RESERVED_NAMESPACE_MSG(id),
-                id.into(),
+                &format!("principal.{id} == \"foo\""),
+                &RESERVED_NAMESPACE_MSG(id),
+                id,
             );
         }
     }
@@ -6453,35 +6446,31 @@ mod reserved_keywords_in_policies {
     fn test_reserved_namespace_elements() {
         // No restrictions on OTHER_SPECIAL_IDENTS
         for id in &OTHER_SPECIAL_IDENTS {
-            assert_valid_expression(format!("foo::{id}::\"bar\""));
-            assert_valid_expression(format!("principal is {id}::foo"));
+            assert_valid_expression(&format!("foo::{id}::\"bar\""));
+            assert_valid_expression(&format!("principal is {id}::foo"));
         }
 
         // RESERVED_IDENTS cannot be used in namespaces
         for id in RESERVED_IDENTS {
+            assert_invalid_expression(&format!("foo::{id}::\"bar\""), &RESERVED_IDENT_MSG(id), id);
             assert_invalid_expression(
-                format!("foo::{id}::\"bar\""),
-                RESERVED_IDENT_MSG(id),
-                id.into(),
-            );
-            assert_invalid_expression(
-                format!("principal is {id}::foo"),
-                RESERVED_IDENT_MSG(id),
-                id.into(),
+                &format!("principal is {id}::foo"),
+                &RESERVED_IDENT_MSG(id),
+                id,
             );
         }
 
         // RESERVED_NAMESPACE cannot be used in namespaces
         for id in RESERVED_NAMESPACE {
             assert_invalid_expression(
-                format!("foo::{id}::\"bar\""),
-                RESERVED_NAMESPACE_MSG(&format!("foo::{id}")),
-                format!("foo::{id}"),
+                &format!("foo::{id}::\"bar\""),
+                &RESERVED_NAMESPACE_MSG(&format!("foo::{id}")),
+                &format!("foo::{id}"),
             );
             assert_invalid_expression(
-                format!("principal is {id}::foo"),
-                RESERVED_NAMESPACE_MSG(&format!("{id}::foo")),
-                format!("{id}::foo"),
+                &format!("principal is {id}::foo"),
+                &RESERVED_NAMESPACE_MSG(&format!("{id}::foo")),
+                &format!("{id}::foo"),
             );
         }
     }
@@ -6493,40 +6482,32 @@ mod reserved_keywords_in_policies {
 
         for id in RESERVED_IDENTS {
             assert_invalid_expression(
-                format!("extension::function::{id}(\"foo\")"),
-                RESERVED_IDENT_MSG(id),
-                id.into(),
-            );
-            assert_invalid_expression(
-                format!("context.{id}(1)"),
-                RESERVED_IDENT_MSG(id),
-                id.into(),
+                &format!("extension::function::{id}(\"foo\")"),
+                &RESERVED_IDENT_MSG(id),
+                id,
             );
+            assert_invalid_expression(&format!("context.{id}(1)"), &RESERVED_IDENT_MSG(id), id);
         }
 
         for id in RESERVED_NAMESPACE {
             assert_invalid_expression(
-                format!("extension::function::{id}(\"foo\")"),
-                RESERVED_NAMESPACE_MSG(&format!("extension::function::{id}")),
-                format!("extension::function::{id}"),
-            );
-            assert_invalid_expression(
-                format!("context.{id}(1)"),
-                RESERVED_NAMESPACE_MSG(id),
-                id.into(),
+                &format!("extension::function::{id}(\"foo\")"),
+                &RESERVED_NAMESPACE_MSG(&format!("extension::function::{id}")),
+                &format!("extension::function::{id}"),
             );
+            assert_invalid_expression(&format!("context.{id}(1)"), &RESERVED_NAMESPACE_MSG(id), id);
         }
 
         for id in OTHER_SPECIAL_IDENTS {
             assert_invalid_expression(
-                format!("extension::function::{id}(\"foo\")"),
-                format!("`extension::function::{id}` is not a valid function"),
-                format!("extension::function::{id}(\"foo\")"),
+                &format!("extension::function::{id}(\"foo\")"),
+                &format!("`extension::function::{id}` is not a valid function"),
+                &format!("extension::function::{id}(\"foo\")"),
             );
             assert_invalid_expression(
-                format!("context.{id}(1)"),
-                format!("`{id}` is not a valid method"),
-                format!("context.{id}(1)"),
+                &format!("context.{id}(1)"),
+                &format!("`{id}` is not a valid method"),
+                &format!("context.{id}(1)"),
             );
         }
     }