Skip to content

Unhelpful error message E0505 for self-referencing lifetime constraint #63701

@upsuper

Description

@upsuper

Given the following code:

trait Handler {}
struct Easy2<H: Handler>(H);

struct Context<'r>(Option<&'r [u8]>);
impl<'r> Handler for &'r mut Context<'r> {}

fn perform<'a>(ctx: &'a mut Context<'a>) {
    Easy2(ctx);
}
fn build_response(_ctx: Context) {}

fn call() {
    let mut ctx = Context(None);
    perform(&mut ctx);
    build_response(ctx);
}

Rust reports:

error[E0505]: cannot move out of `ctx` because it is borrowed
  --> src/lib.rs:15:20
   |
14 |     perform(&mut ctx);
   |             -------- borrow of `ctx` occurs here
15 |     build_response(ctx);
   |                    ^^^
   |                    |
   |                    move out of `ctx` occurs here
   |                    borrow later used here

This seems to be a confusing error, and doesn't help diagnosing where the problem is. The real fix here is to remove the lifetime annotations on perform and have impl Handler use different lifetimes for the two places, but this is totally unobvious from the error message.

It might be more helpful if it can point out that this is still borrowed because ctx forms a self-reference due to <'a>(ctx: &'a mut Context<'a>) and the field.

And it might also be useful to warn impl<'r> Handler for &'r mut Context<'r>. I'm not sure whether a declaration like this where self-reference can arise has any legit use cases. It might be helpful to suggest people giving them two different lifetimes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-borrow-checkerArea: The borrow checkerA-diagnosticsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsC-enhancementCategory: An issue proposing an enhancement or a PR with one.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