Skip to content

refactor the BorrowckErrors trait to take fn(self) #48783

Closed
@nikomatsakis

Description

@nikomatsakis

The [BorrowckErrors trait] is used to report errors from both HIR and MIR-based borrowck:

pub trait BorrowckErrors {

It contains various methods currently defined to take &self:

fn cannot_move_when_borrowed(&self, span: Span, desc: &str, o: Origin)
-> DiagnosticBuilder<'_>
{
let err = struct_span_err!(self, span, E0505,
"cannot move out of `{}` because it is borrowed{OGN}",
desc, OGN=o);
self.cancel_if_wrong_origin(err, o)
}

However, it is implemented on the TyCtxt type:

impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> {

This type is actually an alias for an &-reference, so that means that the final self winds up passing a double reference. This is not bad in and of itself, but @spastorino encountered in #48682 that the current setup causes conflicts around the tcx when using an &mut self method. In particular, if you do something like this:

let err = self.tcx.cannot_use_while_mutably_borrowed(...);
..

this will borrow &self.tcx for as long as err is in use, preventing us from invoking other &mut self methods.

For now, we worked around this problem by storing the tcx into a local variable:

let tcx = self.tcx;

But if the methods were defined instead as fn(self), then it would have worked fine the original way.

Making this transformation would involve a few changes though. First off, right now the returned DiagnosticBuilder values carry the lifetime of the incoming &self reference. We would want to change that to the lifetime of the TyCtxt, so we would need to modify the trait to carry a lifetime parameter:

/// This trait is expected to be implemented on a reference.
/// The `'r` is the lifetime of that reference.
trait BorrowckErrors<'cx> {
    ...
    fn cannot_use_when_mutably_borrowed(
        self, // changed to self
        span: Span,
        ...
    ) -> DiagnosticBuilder<'cx> {
        ... // as before
    }
    ...
}

Then it would be implememented for TyCtxt like:

impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> { ... }

And we would have to modify the other impl like so:

impl<'a, b, 'tcx: 'b> BorrowckErrors<'a> for &'a BorrowckCtxt<'b, 'tcx> {

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-NLLArea: Non-lexical lifetimes (NLL)C-cleanupCategory: PRs that clean code up or issues documenting cleanup.E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions