enable undocumented_unsafe_blocks lint

There was only one unsafe block (thankfully) but it also had no docs.
I did some reading and found out this in fact safe, but only for cursed
reasons, and documented them. Also, the name of the type was misleading,
as the entire point is the aliasing, and `Box` is already non-aliasing.
This commit is contained in:
Charles Hall 2024-05-12 19:10:31 -07:00
parent 844b32f097
commit 2b6a933538
No known key found for this signature in database
GPG key ID: 7B8E0645816E07CF
2 changed files with 23 additions and 7 deletions

View file

@ -57,6 +57,7 @@ string_to_string = "warn"
suspicious_xor_used_as_pow = "warn" suspicious_xor_used_as_pow = "warn"
tests_outside_test_module = "warn" tests_outside_test_module = "warn"
try_err = "warn" try_err = "warn"
undocumented_unsafe_blocks = "warn"
unnecessary_safety_comment = "warn" unnecessary_safety_comment = "warn"
unnecessary_safety_doc = "warn" unnecessary_safety_doc = "warn"
unnecessary_self_imports = "warn" unnecessary_self_imports = "warn"

View file

@ -19,7 +19,7 @@ thread_local! {
struct PreparedStatementIterator<'a> { struct PreparedStatementIterator<'a> {
pub(crate) iterator: Box<dyn Iterator<Item = TupleOfBytes> + 'a>, pub(crate) iterator: Box<dyn Iterator<Item = TupleOfBytes> + 'a>,
pub(crate) _statement_ref: NonAliasingBox<rusqlite::Statement<'a>>, pub(crate) _statement_ref: AliasableBox<rusqlite::Statement<'a>>,
} }
impl Iterator for PreparedStatementIterator<'_> { impl Iterator for PreparedStatementIterator<'_> {
@ -30,10 +30,25 @@ impl Iterator for PreparedStatementIterator<'_> {
} }
} }
struct NonAliasingBox<T>(*mut T); struct AliasableBox<T>(*mut T);
impl<T> Drop for NonAliasingBox<T> { impl<T> Drop for AliasableBox<T> {
fn drop(&mut self) { fn drop(&mut self) {
drop(unsafe { Box::from_raw(self.0) }); // SAFETY: This is cursed and relies on non-local reasoning.
//
// In order for this to be safe:
//
// * All aliased references to this value must have been dropped first,
// for example by coming after its referrers in struct fields, because
// struct fields are automatically dropped in order from top to bottom
// in the absence of an explicit Drop impl. Otherwise, the referrers
// may read into deallocated memory.
// * This type must not be copyable or cloneable. Otherwise, double-free
// can occur.
//
// These conditions are met, but again, note that changing safe code in
// this module can result in unsoundness if any of these constraints are
// violated.
unsafe { drop(Box::from_raw(self.0)) }
} }
} }
@ -171,7 +186,7 @@ impl SqliteTable {
.unwrap(), .unwrap(),
)); ));
let statement_ref = NonAliasingBox(statement); let statement_ref = AliasableBox(statement);
//let name = self.name.clone(); //let name = self.name.clone();
@ -270,7 +285,7 @@ impl KvTree for SqliteTable {
.unwrap(), .unwrap(),
)); ));
let statement_ref = NonAliasingBox(statement); let statement_ref = AliasableBox(statement);
let iterator = Box::new( let iterator = Box::new(
statement statement
@ -292,7 +307,7 @@ impl KvTree for SqliteTable {
.unwrap(), .unwrap(),
)); ));
let statement_ref = NonAliasingBox(statement); let statement_ref = AliasableBox(statement);
let iterator = Box::new( let iterator = Box::new(
statement statement