0

I faced some troubles with borrow checker. Here is the code:

extern crate odbc_safe;

use odbc_safe::*;

fn main() {
    let env = match Environment::new() {
        Return::Success(env) => env,
        _ => panic!(""),
    };
    let env = match env.declare_version_3_8() {
        Return::Success(env) => env,
        _ => panic!(""),
    };
    if let Return::Success(ds) = DataSource::with_parent(&env) {

    }
}

You can see that it depends on odbc_safe crate. I got failed to reproduce problem without this dependency, so the code is such is. Anyway, it doesn't compile with an error:

error[E0597]: `env` does not live long enough
  --> src\main.rs:14:59
   |
14 |     if let Return::Success(ds) = DataSource::with_parent(&env) {
   |                                                           ^^^ borrowed value does not live long enough
...
17 | }
   | - `env` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

This behaviour is strange to me, since ds dies at the end of if-let and frees the reference to env. But it's more strange that if I add a semicolon to the end of if-let statement, making it an expression, then the code compiles normally. Thus follow code does compile normally:

extern crate odbc_safe;

use odbc_safe::*;

fn main() {
    let env = match Environment::new() {
        Return::Success(env) => env,
        _ => panic!(""),
    };
    let env = match env.declare_version_3_8() {
        Return::Success(env) => env,
        _ => panic!(""),
    };
    if let Return::Success(ds) = DataSource::with_parent(&env) {

    };
}

As I said, I got no luck to reproduce the trouble with no odbc_safe depenency. I tried to mimic types from it, but everything worked as expected.

rust version: stable-x86_64-pc-windows-gnu (default) rustc 1.33.0 (2aa4c46cf 2019-02-28)

odbc_safe version: 0.4.1

Any ideas what is going on?

a.yekimov
  • 316
  • 1
  • 8
  • "But it's more strange that if I add a semicolon to the end of if-let statement, making it an expression, then the code compiles normally." Isn't it the opposite? `if-let` is an expression, if you add a semicolon you make it into a statement. – Alexey Romanov Mar 16 '19 at 07:42
  • I'm sure it't not. Expressions returns values. Look above at `let env = match`... `match {};` here is expression too. – a.yekimov Mar 16 '19 at 07:49
  • Ok. In this context, at the end of function, things really gets opposide. Anyway, I don't understand why borrow checker is complaining? The error should be "if may be missing an else clause". – a.yekimov Mar 16 '19 at 08:06
  • 1
    this is well known behavior in rust, related to lifetimes of temporary variables. For example, check this issue: https://github.com/rust-lang/rust/issues/22449 – Laney Mar 16 '19 at 09:10
  • Thank you. I searched through many examples from this and related issues. All of them involves "temoraries". But in my case I see no "temoraries". But I agree that the case looks similar. Anyway, with NLL feature up there is no compilation error, so I'm wating for NLL in stable. – a.yekimov Mar 16 '19 at 10:48
  • @a.yekimov NLL has been available in stable Rust for multiple releases now. Use edition 2018. – Shepmaster Mar 16 '19 at 14:25
  • In fact I already do. But without #![feature(nll)] in nightly the code doesn't compile. I'm confused. – a.yekimov Mar 16 '19 at 17:24

1 Answers1

0

It looks like an issue exists for the case: https://github.com/rust-lang/rust/issues/21114. Thanks to @Laney.

a.yekimov
  • 316
  • 1
  • 8