- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Description
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:
rust/src/librustc_mir/util/borrowck_errors.rs
Lines 77 to 84 in c933440
| 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:
rust/src/librustc_mir/util/borrowck_errors.rs
Line 494 in c933440
| 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> {