From c56be6971a7d27100b1fc9cbeda6efa4a2cbea59 Mon Sep 17 00:00:00 2001 From: Amos Wenger Date: Sun, 20 Oct 2024 23:26:28 +0200 Subject: [PATCH] As pointed out, FieldSlot must be invariant --- Cargo.lock | 215 +++++++++++++++++- Justfile | 2 +- merde_core/Cargo.toml | 3 + merde_core/src/deserialize.rs | 6 +- merde_core/src/deserialize/tests.rs | 6 + merde_core/tests/ui/static-borrow-lifetime.rs | 11 + .../tests/ui/static-borrow-lifetime.stderr | 13 ++ merde_core/tests/ui/static-s-lifetime.rs | 11 + merde_core/tests/ui/static-s-lifetime.stderr | 13 ++ merde_core/tests/ui/subtyping.rs | 14 ++ merde_core/tests/ui/subtyping.stderr | 23 ++ 11 files changed, 311 insertions(+), 6 deletions(-) create mode 100644 merde_core/tests/ui/static-borrow-lifetime.rs create mode 100644 merde_core/tests/ui/static-borrow-lifetime.stderr create mode 100644 merde_core/tests/ui/static-s-lifetime.rs create mode 100644 merde_core/tests/ui/static-s-lifetime.stderr create mode 100644 merde_core/tests/ui/subtyping.rs create mode 100644 merde_core/tests/ui/subtyping.stderr diff --git a/Cargo.lock b/Cargo.lock index d53be75..43b2ba2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,6 +94,12 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "fallible-iterator" version = "0.3.0" @@ -117,6 +123,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "hashbrown" version = "0.14.5" @@ -127,13 +139,19 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "hashlink" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -142,7 +160,17 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", ] [[package]] @@ -197,6 +225,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + [[package]] name = "merde" version = "6.2.1" @@ -219,6 +253,7 @@ dependencies = [ "rubicon", "rusqlite", "serde", + "trybuild", ] [[package]] @@ -413,6 +448,27 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -436,6 +492,21 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "target-triple" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078" + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "time" version = "0.3.36" @@ -467,6 +538,55 @@ dependencies = [ "time-core", ] +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "trybuild" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dcd332a5496c026f1e14b7f3d2b7bd98e509660c04239c58b0ba38a12daded4" +dependencies = [ + "glob", + "serde", + "serde_derive", + "serde_json", + "target-triple", + "termcolor", + "toml", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -491,6 +611,97 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "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]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[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_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[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_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + [[package]] name = "yaml-rust2" version = "0.8.1" diff --git a/Justfile b/Justfile index 7e58f1e..85b1697 100644 --- a/Justfile +++ b/Justfile @@ -28,4 +28,4 @@ check: miri: cargo +nightly miri run --example opinions -F json - cargo +nightly miri test -p merde_core + cargo +nightly miri test -p merde_core fieldslot diff --git a/merde_core/Cargo.toml b/merde_core/Cargo.toml index 3ee2dd4..f509066 100644 --- a/merde_core/Cargo.toml +++ b/merde_core/Cargo.toml @@ -32,3 +32,6 @@ compact_str = ["dep:compact_str"] compact_bytes = ["dep:compact_bytes"] serde = ["dep:serde", "compact_str/serde"] rusqlite = ["dep:rusqlite"] + +[dev-dependencies] +trybuild = "1.0.101" diff --git a/merde_core/src/deserialize.rs b/merde_core/src/deserialize.rs index 87857fb..cd751a8 100644 --- a/merde_core/src/deserialize.rs +++ b/merde_core/src/deserialize.rs @@ -342,14 +342,14 @@ mod mini_typeid { } /// Allows filling in a field of a struct while deserializing. -pub struct FieldSlot<'s, 'borrow> { +pub struct FieldSlot<'s, 'borrow: 's> { option: *mut Option<()>, type_id_of_field: TypeId, type_name_of_field: &'static str, - _phantom: PhantomData<(&'s (), &'borrow mut ())>, + _phantom: PhantomData<&'borrow mut &'s mut ()>, } -impl<'s, 'borrow> FieldSlot<'s, 'borrow> { +impl<'s, 'borrow: 's> FieldSlot<'s, 'borrow> { /// Construct a new `FieldSlot`, ready to be filled #[inline(always)] #[doc(hidden)] diff --git a/merde_core/src/deserialize/tests.rs b/merde_core/src/deserialize/tests.rs index ea9bd93..010293c 100644 --- a/merde_core/src/deserialize/tests.rs +++ b/merde_core/src/deserialize/tests.rs @@ -33,3 +33,9 @@ fn test_fieldslot_with_assign_mismatched_type() { let slot = FieldSlot::new(&mut option); slot.fill::(42); } + +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff --git a/merde_core/tests/ui/static-borrow-lifetime.rs b/merde_core/tests/ui/static-borrow-lifetime.rs new file mode 100644 index 0000000..c46f2d5 --- /dev/null +++ b/merde_core/tests/ui/static-borrow-lifetime.rs @@ -0,0 +1,11 @@ +use merde_core::FieldSlot; + +fn main() { + let mut option: Option = None; + let slot = FieldSlot::new(&mut option); + + #[allow(clippy::needless_lifetimes)] + fn take_static_fieldslot<'s>(_f: FieldSlot<'s, 'static>) {} + + take_static_fieldslot(slot); +} diff --git a/merde_core/tests/ui/static-borrow-lifetime.stderr b/merde_core/tests/ui/static-borrow-lifetime.stderr new file mode 100644 index 0000000..94726f8 --- /dev/null +++ b/merde_core/tests/ui/static-borrow-lifetime.stderr @@ -0,0 +1,13 @@ +error[E0597]: `option` does not live long enough + --> tests/ui/static-borrow-lifetime.rs:5:31 + | +4 | let mut option: Option = None; + | ---------- binding `option` declared here +5 | let slot = FieldSlot::new(&mut option); + | ---------------^^^^^^^^^^^- + | | | + | | borrowed value does not live long enough + | argument requires that `option` is borrowed for `'static` +... +11 | } + | - `option` dropped here while still borrowed diff --git a/merde_core/tests/ui/static-s-lifetime.rs b/merde_core/tests/ui/static-s-lifetime.rs new file mode 100644 index 0000000..44fb8b4 --- /dev/null +++ b/merde_core/tests/ui/static-s-lifetime.rs @@ -0,0 +1,11 @@ +use merde_core::FieldSlot; + +fn main() { + let mut option: Option = None; + let slot = FieldSlot::new(&mut option); + + #[allow(clippy::needless_lifetimes)] + fn take_static_fieldslot<'borrow>(_f: FieldSlot<'static, 'borrow>) {} + + take_static_fieldslot(slot); +} diff --git a/merde_core/tests/ui/static-s-lifetime.stderr b/merde_core/tests/ui/static-s-lifetime.stderr new file mode 100644 index 0000000..bc36689 --- /dev/null +++ b/merde_core/tests/ui/static-s-lifetime.stderr @@ -0,0 +1,13 @@ +error[E0597]: `option` does not live long enough + --> tests/ui/static-s-lifetime.rs:5:31 + | +4 | let mut option: Option = None; + | ---------- binding `option` declared here +5 | let slot = FieldSlot::new(&mut option); + | ---------------^^^^^^^^^^^- + | | | + | | borrowed value does not live long enough + | argument requires that `option` is borrowed for `'static` +... +11 | } + | - `option` dropped here while still borrowed diff --git a/merde_core/tests/ui/subtyping.rs b/merde_core/tests/ui/subtyping.rs new file mode 100644 index 0000000..8a6a747 --- /dev/null +++ b/merde_core/tests/ui/subtyping.rs @@ -0,0 +1,14 @@ +use merde_core::FieldSlot; + +fn main() { + let mut option: Option = None; + let slot = FieldSlot::new(&mut option); + + fn prove_invariance<'long, 'short: 'long>( + long: FieldSlot<'long, 'long>, + ) -> FieldSlot<'short, 'short> { + long // Error: mismatched types + } + + assert!(option.is_none()); +} diff --git a/merde_core/tests/ui/subtyping.stderr b/merde_core/tests/ui/subtyping.stderr new file mode 100644 index 0000000..7c36c59 --- /dev/null +++ b/merde_core/tests/ui/subtyping.stderr @@ -0,0 +1,23 @@ +warning: unused variable: `slot` + --> tests/ui/subtyping.rs:5:9 + | +5 | let slot = FieldSlot::new(&mut option); + | ^^^^ help: if this is intentional, prefix it with an underscore: `_slot` + | + = note: `#[warn(unused_variables)]` on by default + +error: lifetime may not live long enough + --> tests/ui/subtyping.rs:10:9 + | +7 | fn prove_invariance<'long, 'short: 'long>( + | ----- ------ lifetime `'short` defined here + | | + | lifetime `'long` defined here +... +10 | long // Error: mismatched types + | ^^^^ function was supposed to return data with lifetime `'short` but it is returning data with lifetime `'long` + | + = help: consider adding the following bound: `'long: 'short` + = note: requirement occurs because of the type `FieldSlot<'_, '_>`, which makes the generic argument `'_` invariant + = note: the struct `FieldSlot<'s, 'borrow>` is invariant over the parameter `'s` + = help: see for more information about variance