Skip to content

Accessing fields through a Deref impl leads to confusing error messages #81365

Closed
@Aaron1011

Description

@Aaron1011

The following code:

use std::ops::Deref;

struct DerefTarget {
    target_field: bool
}
struct Container {
    target: DerefTarget,
    container_field: bool,
}

impl Deref for Container {
    type Target = DerefTarget;
    fn deref(&self) -> &Self::Target {
        &self.target
    }
}

impl Container {
    fn bad_borrow(&mut self) {
        let first = &self.target_field;
        self.container_field = true;
        first;
    }
}

causes the following error message:

error[E0506]: cannot assign to `self.container_field` because it is borrowed
  --> src/lib.rs:21:9
   |
20 |         let first = &self.target_field;
   |                      ---- borrow of `self.container_field` occurs here
21 |         self.container_field = true;
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here
22 |         first;
   |         ----- borrow later used here

This error is caused by the fact that &self.target_field does through the Deref impl on Container. As a result, &self is borrowed, not just the desired field. Changing this line to let first = &self.target.target_field makes the code compile.

However, the error message doesn't explain any of this. It claims that the usage of self is a borrow of self.container_field, without noting that this is due to the Deref impl.

We should do something similar to #75304 for borrows, and make it clear when lifetimes are being affected by implicit Deref calls.

Metadata

Metadata

Labels

A-borrow-checkerArea: The borrow checkerA-diagnosticsArea: Messages for errors, warnings, and lintsC-bugCategory: This is a bug.D-confusingDiagnostics: Confusing error or lint that should be reworked.D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions