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

Conditional return seems to hold the reference forever #124070

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in 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