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

Different Behaviors When Using from and into with Implemented From<&mut T> #125064

Closed
xinchengxx opened this issue May 13, 2024 · 2 comments
Closed
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@xinchengxx
Copy link

Bug Description

The issue arises when attempting to convert &mut C to two different structs (A and B) using the From trait within the drop method. The behavior differs depending on whether from or into is used, leading to unexpected compiler errors.

Reproduction Code

impl From<&mut C> for A {
  fn from(_: &mut C) -> Self {
    Self
  }
}
impl From<&mut C> for B {
  fn from(_: &mut C) -> Self {
    Self
  }
}

Next, I attempt to use these implementations within a drop method. I expect that using a mutable reference should allow obtaining both A and B instances. However, this behaves differently depending on whether from or into is utilized.

  fn drop(&mut self) {
    let a = A::from(self);
    let b = B::from(self);
}
  fn drop(&mut self) {
    let a: A = self.into();
    let b: B = self.into();
}

The first code snippet fails to compile with the following error:

error[E0382]: use of moved value: `self`
  --> main.rs:20:21
   |
18 |   fn drop(&mut self) {
   |           --------- move occurs because `self` has type `&mut C`, which does not implement the `Copy` trait
19 |     let a = A::from(self);
   |                     ---- value moved here
20 |     let b = B::from(self);
   |                     ^^^^ value used here after move

error: aborting due to 1 previous error; 2 warnings emitted

For more information about this error, try `rustc --explain E0382`.

But the second code snippet compiles successfully.

I think both of the code snippets should compile successfully.

The underlying issue might stem from the From trait's specialization process. It seems that when the trait is implemented for &mut C, the compiler does not recognize it specifically as a reference, and thus expects ownership. This inconsistency between reference handling and ownership expectation could lead to the aforementioned compilation errors.

Meta

rustc --version --verbose:

rustc 1.76.0 (07dca489a 2024-02-04)
binary: rustc
commit-hash: 07dca489ac2d933c78d3c5158e3f43beefeb02ce
commit-date: 2024-02-04
host: x86_64-unknown-linux-gnu
release: 1.76.0
LLVM version: 17.0.6
@xinchengxx xinchengxx added the C-bug Category: This is a bug. label May 13, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label May 13, 2024
@jieyouxu jieyouxu added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. 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. and removed C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels May 13, 2024
@cuviper
Copy link
Member

cuviper commented May 14, 2024

The .into() form is implicitly reborrowing, and in the other you can do that manually like A::from(&mut *self). This doesn't have anything to do with From/Into in particular, just the type of method call -- e.g. Into::<A>::into(self) will also move without reborrowing.

I think we're still missing good docs on this: rust-lang/reference#788

@xinchengxx
Copy link
Author

Thanks.

@saethlin saethlin removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label May 14, 2024
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. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants