Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

As pointed out, FieldSlot must be invariant #102

Merged
merged 1 commit into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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