Recently ran into a situation where self referential structs would have been a nice solution, and while I found a decent amount of discussion around the topic I didn't find a satisfying solution. So begrudgingly I unpacked to unsafe hammer and got to work.
I'd really appreciate any feedback from API to soundness. Note, the documentation is still very rudimentary and I plan to properly document all functions and traits. But before that it would be great if some more experienced people than me could take a look at the unsafe in https://github.com/Voultapher/once_self_cell/blob/main/src/once_self_cell.rs , going through the nomicon I couldn't find a way this could be used to trigger UB, and so far miri agrees with me https://github.com/Voultapher/once_self_cell/runs/1538569928
One of the core motivations for this was that rental is heavy to compile and no longer maintained, while this is pretty minimal:
Compiling once_cell v1.5.2
Compiling once_self_cell v0.1.0
Completed once_cell v1.5.2 in 0.9s
Completed once_self_cell v0.1.0 in 0.3s
dtolnay
December 11, 2020, 7:38pm
2
This looks like something going wrong in safe code:
use once_self_cell::sync::OnceSelfCell;
use std::fmt::Debug;
struct Ref<'a, T: Debug>(&'a T);
#[derive(Debug)]
enum Void {}
fn main() {
OnceSelfCell::new(None::<Vec<Void>>).get_or_init_dependent(Ref);
}
impl<'a, T: Debug> Drop for Ref<'a, T> {
fn drop(&mut self) {
println!("{:?}", self.0);
}
}
$ cargo run
Compiling testing v0.0.0 (/git/repro)
Finished dev [unoptimized + debuginfo] target(s) in 0.08s
Running `target/debug/repro`
Illegal instruction (core dumped)
5 Likes
use once_self_cell::sync::OnceSelfCell;
fn main() {
let c: OnceSelfCell<()> = OnceSelfCell::new(());
let () = c.get_or_init_dependent(|_| ());
let bad: &i32 = c.get_or_init_dependent(|_| 42);
println!("{}", bad);
}
Segmentation fault (core dumped)
Also note, that such a question is perhaps more fitting on users.rust-lang.org ; with the code-review tag.
6 Likes
system
Closed
March 14, 2021, 8:43pm
5
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.