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

self-referencial struct: mutable borrow not dropped? #138496

Open
axos88 opened this issue Mar 14, 2025 · 2 comments
Open

self-referencial struct: mutable borrow not dropped? #138496

axos88 opened this issue Mar 14, 2025 · 2 comments
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged.

Comments

@axos88
Copy link

axos88 commented Mar 14, 2025

I tried this code:

struct Foo<'a> {
  name: Option<&'a str>,
  foo: String
}

impl<'a> Foo<'a> {
  fn op1(&'a mut self) {
    // self.name = Some(&self.foo);
  }

  fn op2(&self) {
  }
}


fn x() {
  let mut foo = Foo { name: None, foo: "foo".to_string() };

  foo.op1();
  foo.op2(); // Cannot borrow as immutable because borrowed as mutable
}

I expected to see this happen: should compile.

Instead, this happened: compiler seems to think foo.op2() hangs onto the mutable borrow in op1

Meta

rustc --version --verbose:

$ rustc --version --verbose
rustc 1.87.0-nightly (cbfdf0b01 2025-03-13)
binary: rustc
commit-hash: cbfdf0b014cb04982a9cbeec1578001001167f6e
commit-date: 2025-03-13
host: x86_64-unknown-linux-gnu
release: 1.87.0-nightly
LLVM version: 20.1.0


@axos88 axos88 added the C-bug Category: This is a bug. label Mar 14, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Mar 14, 2025
@axos88 axos88 changed the title mutable borrow not dropped? self-referencial struct: mutable borrow not dropped? Mar 14, 2025
@bjorn3
Copy link
Member

bjorn3 commented Mar 14, 2025

op1 takes &'a mut Foo<'a> as argument, which forces 'a to be invariant as &'a mut T requires the lifetimes in T to be invariant. This means that it can neither be extended nor shortened. Normally when you pass an &mut T to a function, the argument will be reborrowed for a shorter lifetime allowing you to use the reference again after the function returns. When the lifetime is invariant however reborrowing is not possible and instead the mutable reference itself gets moved into the function, preventing any further use.

@bjorn3 bjorn3 added C-discussion Category: Discussion or questions that doesn't represent real issues. and removed C-bug Category: This is a bug. labels Mar 14, 2025
@axos88
Copy link
Author

axos88 commented Mar 14, 2025

I'm not entirely sure i follow, but let me summarize in my own words:

Usually when calling a method requiring &mut self, it is borrowed with a short lifetime, 'b:'a in this case.

In this case we are locking 'b = 'a, so the borrow is not released after the call.

Would a solution be to have op1 receive a 'b self reference instead? What would be a solution to this?

The code above should work. Moving the struct would cause issues, but lets suppose its pinned for the sake of discussion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged.
Projects
None yet
Development

No branches or pull requests

3 participants