dtolnay / dtolnay/no-panic

Fails to compile after applying `no_panic`

Open
#74 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
1.2k
Forks
20
PR merge metrics
No merged PRs in 30d

Description

I have a function that looks [like this](https://github.com/nazar-pc/abundance/blob/6370d5c9ab00982ea9023c830696f575fcceac65/crates/contracts/system/ab-system-contract-simple-wallet-base/src/utils.rs#L15-L25):
```rust
pub fn initialize_state(env: &mut Env<'_>, public_key: &[u8; 32]) -> Result<(), ContractError> {
let state =
env.simple_wallet_base_initialize(Address::SYSTEM_SIMPLE_WALLET_BASE, public_key)?;

env.state_initialize(
MethodContext::Reset,
Address::SYSTEM_STATE,
&env.own_address(),
&VariableBytes::from_buffer(state.as_bytes(), &state.size()),
)
}
```

Adding this to it results in compilation error:
```
#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
```

```
error[E0597]: `state` does not live long enough
--> crates/contracts/system/ab-system-contract-simple-wallet-base/src/utils.rs:24:37
|
15 | #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
| -
| |
| `state` dropped here while still borrowed
| ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `impl Deref> + '_`
16 | pub fn initialize_state(env: &mut Env<'_>, public_key: &[u8; 32]) -> Result<(), ContractError> {
17 | let state =
| ----- binding `state` declared here
...
24 | &VariableBytes::from_buffer(state.as_bytes(), &state.size()),
| ---------------------------^^^^^---------------------------
| | |
| | borrowed value does not live long enough
| a temporary with access to the borrow is created here ...
|
= note: the temporary is part of an expression at the end of a block;
consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block
|
20 ~ let x = env.state_initialize(
21 | MethodContext::Reset,
...
24 | &VariableBytes::from_buffer(state.as_bytes(), &state.size()),
25 ~ ); x
|
```

Here is what it is being expanded to:
```
pub fn initialize_state(
mut env: &mut Env<'_>,
mut public_key: &[u8; 32],
) -> Result<(), ContractError> {
struct __NoPanic;
unsafe extern "C" {
#[link_name = "\n\nERROR[no-panic]: detected panic in function `initialize_state`\n"]
fn trigger() -> !;
}
impl ::core::ops::Drop for __NoPanic {
fn drop(&mut self) {
unsafe {
trigger();
}
}
}
let __guard = __NoPanic;
let __result = (move || -> Result<(), ContractError> {
let env = env;
let public_key = public_key;
let state = env
.simple_wallet_base_initialize(
Address::SYSTEM_SIMPLE_WALLET_BASE,
public_key,
)?;
env.state_initialize(
MethodContext::Reset,
Address::SYSTEM_STATE,
&env.own_address(),
&VariableBytes::from_buffer(state.as_bytes(), &state.size()),
)
})();
::core::mem::forget(__guard);
__result
}
```

Interestingly, simply wrapping function body with extra `{}` fixes compilation issue, so I think macro should be fixed to support this too.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.