Skip to content

Commit

Permalink
As pointed out, FieldSlot must be invariant
Browse files Browse the repository at this point in the history
  • Loading branch information
fasterthanlime committed Oct 20, 2024
1 parent 56c3a26 commit c56be69
Show file tree
Hide file tree
Showing 11 changed files with 311 additions and 6 deletions.
215 changes: 213 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions merde_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
6 changes: 3 additions & 3 deletions merde_core/src/deserialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
6 changes: 6 additions & 0 deletions merde_core/src/deserialize/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@ fn test_fieldslot_with_assign_mismatched_type() {
let slot = FieldSlot::new(&mut option);
slot.fill::<i32>(42);
}

#[test]
fn ui() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/*.rs");
}
11 changes: 11 additions & 0 deletions merde_core/tests/ui/static-borrow-lifetime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use merde_core::FieldSlot;

fn main() {
let mut option: Option<i32> = None;
let slot = FieldSlot::new(&mut option);

#[allow(clippy::needless_lifetimes)]
fn take_static_fieldslot<'s>(_f: FieldSlot<'s, 'static>) {}

take_static_fieldslot(slot);
}
13 changes: 13 additions & 0 deletions merde_core/tests/ui/static-borrow-lifetime.stderr
Original file line number Diff line number Diff line change
@@ -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<i32> = 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
11 changes: 11 additions & 0 deletions merde_core/tests/ui/static-s-lifetime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use merde_core::FieldSlot;

fn main() {
let mut option: Option<i32> = None;
let slot = FieldSlot::new(&mut option);

#[allow(clippy::needless_lifetimes)]
fn take_static_fieldslot<'borrow>(_f: FieldSlot<'static, 'borrow>) {}

take_static_fieldslot(slot);
}
13 changes: 13 additions & 0 deletions merde_core/tests/ui/static-s-lifetime.stderr
Original file line number Diff line number Diff line change
@@ -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<i32> = 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
14 changes: 14 additions & 0 deletions merde_core/tests/ui/subtyping.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use merde_core::FieldSlot;

fn main() {
let mut option: Option<i32> = 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());
}
Loading

0 comments on commit c56be69

Please sign in to comment.