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

DbTxn must_use doesn't work #578

Open
kayabaNerve opened this issue Jul 5, 2024 · 6 comments
Open

DbTxn must_use doesn't work #578

kayabaNerve opened this issue Jul 5, 2024 · 6 comments
Labels
bug Something isn't working

Comments

@kayabaNerve
Copy link
Member

This is presumably somewhat a bug in Rust itself. I just need to make a MRE and evaluate it.

Identified due to #561.

@kayabaNerve kayabaNerve added the bug Something isn't working label Jul 5, 2024
@kayabaNerve
Copy link
Member Author

rust-lang/rust#102238 (comment) for my comment on the relevant issue.

@kayabaNerve
Copy link
Member Author

#[must_use]
trait X {}

fn y<Z: X>(z: Z) -> Z {
  z
}

fn a<Z: X>(z: Z) {
    y(z);
}

#[must_use]
struct A;
impl X for A {}

fn main() {
  a(A);
}

for the MRE.

@kayabaNerve
Copy link
Member Author

We can wrap the DbTxn generic in a struct which is must_use to workaround this. It's ugly but would be safe.

@kayabaNerve
Copy link
Member Author

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=82ba3d8b66d59ac5a9faa415032775e3

must_use only requires use on a branch, not on all branches :///

@kayabaNerve
Copy link
Member Author

The struct (and the correct application of must_use) would only guarantee the txn is bound, not moved out of scope.

Opened an issue calling for a new clippy lint for an expanded interpretation of must_use: rust-lang/rust-clippy#13997

@kayabaNerve
Copy link
Member Author

kayabaNerve commented Jan 15, 2025

I did try the idea in rust-lang/rust-clippy#13997 (comment). While it is incomplete, I wanted to see if it was sufficiently complete for our use case. For the remaining edge cases, we could write unsafe_droppable_txn and manually review it with extra scrutiny.

The compiler will generate code to drop the txn if the txn is held across an await point (in case the future is dropped). We'd have to wrap the txn in a droppable struct before each await point, unwrapping it after. That'd be a notable ergonomic pain.

We'd also have to move to panic=abort if the txn is held across code which may panic. I'm actually fine with this regarding production deployments. I believe we only have unwind due to Substrate and we should review why that was needed/preferred and downscope such that only the Substrate crates have it. The issue is that we can't build tests with abort, and this code would only compile under abort, unless we use a nightly flag -Zpanic_abort_tests. The question would be can we have this assert trigger only if compiling with abort, so unwind still works but we get the static verification by a build with abort?

kayabaNerve added a commit that referenced this issue Jan 15, 2025
coordinator/cosign/src/delay.rs literally demonstrates how we'd need to rewrite
our handling of transactions with this change. It can be cleaned up a bit but
already identifies ergonomic issues. It also doesn't model passing an &mut txn
to an async function, which would also require using the droppable wrapper
struct.

To locally see this build, run

RUSTFLAGS="-Zpanic_abort_tests -C panic=abort" cargo +nightly build -p serai-cosign --all-targets

To locally see this fail to build, run

cargo build -p serai-cosign --all-targets

While it doesn't say which line causes it fail to build, the only distinction
is panic=unwind.

For more context, please see #578.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant