Skip to content

Conditional return seems to hold the reference forever #124070

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
fzyzcjy opened this issue Apr 17, 2024 · 2 comments
Closed

Conditional return seems to hold the reference forever #124070

fzyzcjy opened this issue Apr 17, 2024 · 2 comments
Labels
A-borrow-checker Area: The borrow checker C-bug Category: This is a bug. fixed-by-polonius Compiling with `-Zpolonius` fixes this issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@fzyzcjy
Copy link

fzyzcjy commented Apr 17, 2024

Hi, thanks for the language! However, I am facing a compilation error and cannot use it :(

I tried this code:

fn main() {}

struct S {
    field: String,
}

impl S {
    fn f(&mut self) -> &str {
        let a = &mut self.field;

        if false { // `false`, or `true`, or whatever condition
            return a;
        }
        // drop(a); // You can add this, but still error

        return &self.field;
    }
}

P.S. The real world case requires mut (though this simple demo does not).

I expected to see this happen: explanation
No error.

IMHO, there are two cases:
If the if gets true, it will immediately return, and everything is OK
If the if gets false, the variable a is never used afterwards. You can also add that drop (but still error). Thus, it should not have problem.

Instead, this happened: explanation

error[E0502]: cannot borrow `self.field` as immutable because it is also borrowed as mutable
  --> src/main.rs:15:16
   |
8  |     fn f(&mut self) -> &str {
   |          - let's call the lifetime of this reference `'1`
9  |         let a = &mut self.field;
   |                 --------------- mutable borrow occurs here
10 |         if true {
11 |             return a;
   |                    - returning this value requires that `self.field` is borrowed for `'1`
...
15 |         return &self.field;
   |                ^^^^^^^^^^^ immutable borrow occurs here


Meta

rustc --version --verbose:

rustc 1.79.0-nightly (805813650 2024-03-31)
binary: rustc
commit-hash: 805813650248c1a2f6f271460d728d1bb852d2a7
commit-date: 2024-03-31
host: x86_64-apple-darwin
release: 1.79.0-nightly
LLVM version: 18.1.2
Backtrace

<backtrace>

P.S. More (roughly equivalent) examples that do not work

fn main() {}

struct S {
    field: String,
}

fn f(arg: &mut S) -> &mut str {
    let a = &mut arg.field;
    if true {
        return a;
    }
    drop(a);

    return &mut arg.field;
}

P.S. Another maybe related example that does not work

fn main() {}

struct S {
    field: String,
}

fn f(arg: &mut S) -> &mut str {
    let a = &mut arg.field;
    let b = if true {
        a
    } else {
        drop(a);
        &mut arg.field
    };
    b
}

gives

error[E0499]: cannot borrow `arg.field` as mutable more than once at a time
  --> src/main.rs:13:9
   |
7  | fn f(arg: &mut S) -> &mut str {
   |           - let's call the lifetime of this reference `'1`
8  |     let a = &mut arg.field;
   |             -------------- first mutable borrow occurs here
...
13 |         &mut arg.field
   |         ^^^^^^^^^^^^^^ second mutable borrow occurs here
14 |     };
15 |     b
   |     - returning this value requires that `arg.field` is borrowed for `'1`

Cross-posted: https://users.rust-lang.org/t/conditional-return-seems-to-hold-the-reference-forever/110090

@fzyzcjy fzyzcjy added the C-bug Category: This is a bug. label Apr 17, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Apr 17, 2024
@fzyzcjy fzyzcjy changed the title Cannot borrow self.field as immutable because it is also borrowed as mutable, while it indeed can borrow Rust cannot understand conditional return Apr 17, 2024
@fzyzcjy fzyzcjy changed the title Rust cannot understand conditional return Conditional return seems to hold the reference forever Apr 17, 2024
@fmease fmease added A-borrow-checker Area: The borrow checker T-types Relevant to the types team, which will review and decide on the PR/issue. fixed-by-polonius Compiling with `-Zpolonius` fixes this issue. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Apr 17, 2024
@Noratrieb
Copy link
Member

This is a known issue with the borrow checker that's intended to be fixed with polonius, the next generation borrow checker.
Closing as a known issue and duplicate of many other issues, for example #51545

@Noratrieb Noratrieb closed this as not planned Won't fix, can't repro, duplicate, stale Apr 17, 2024
@fzyzcjy
Copy link
Author

fzyzcjy commented Apr 17, 2024

I see, thank you! However, it seems that polonius will not be there in the near future, so I wonder what workaround should I do?

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-borrow-checker Area: The borrow checker C-bug Category: This is a bug. fixed-by-polonius Compiling with `-Zpolonius` fixes this issue. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants