Repository: rust
Issue: Unclear unsoundness warning when reborrowing data using late-bound lifetimes across multiple trait definitions
Labels: A-diagnostics,A-destructors,A-borrow-checker,T-compiler,D-confusing

This is a cross post from the [users forum](https://users.rust-lang.org/t/unclear-borrow-checker-warning-about-unsound-late-bound-lifetimes/25688) where I was redirected to here:

While working on a project I hit a brick wall when designing a more complicated way to reborrow an object so that a different interface is exposed. This is the definition of the types used (stripped down):
```rust
trait WorkspaceLog {
    fn get(&self) -> usize;
}

struct TheLog<'a>(&'a FSWorkspaceController<'a>);

impl<'a> WorkspaceLog for TheLog<'a> {
    fn get(&self) -> usize {
        ((self.0).0).0
    }
}

trait WorkspaceController<'a> {
    type Log: WorkspaceLog+'a;

    fn get_log(&'a self) -> Self::Log;
    fn set_log(&mut self, x: usize);
}

struct FilesystemOverlay(usize);

struct FSWorkspaceController<'a>(&'a mut FilesystemOverlay);

impl<'a, 'b> WorkspaceController<'b> for FSWorkspaceController<'a> {
    type Log = TheLog<'b>;

    fn get_log(&'b self) -> Self::Log {
        TheLog(&*self)
    }
    
    fn set_log(&mut self, x: usize) {
        (self.0).0 = x;
    }
}

trait AsWorkspaceController<'a, 'b> {
    type Controller: WorkspaceController<'b>+'a;

    fn get_controller(&'a mut self) -> Self::Controller;
}

impl<'a, 'b> AsWorkspaceController<'a, 'b> for FilesystemOverlay {
    type Controller = FSWorkspaceController<'a>;

    fn get_controller(&'a mut self) -> FSWorkspaceController<'a> {
        FSWorkspaceController(self)
    }
}
```
Now, if I directly use the type FilesystemOverlay everything is just fine:
```rust
fn init1(control_dir: &mut FilesystemOverlay) -> usize {
    let controller = control_dir.get_controller();
    let log = controller.get_log();
    log.get()
}
```
However, if I try to generalize control_dir, I get a problem:
```rust
fn init2<O>(control_dir: &mut O) -> usize
    where for<'a, 'b> O: AsWorkspaceController<'a, 'b> {
    let controller = control_dir.get_controller();
    let log = controller.get_log();
    log.get()
}
```
Although this compiles, there is a warning which might eventually be turned into an error:
```none
warning[E0597]: `controller` does not live long enough
  --> src/main.rs:59:15
   |
59 |     let log = controller.get_log();
   |               ^^^^^^^^^^ borrowed value does not live long enough
60 |     log.get()
61 | }
   | -
   | |
   | `controller` dropped here while still borrowed
   | borrow might be used here, when `controller` is dropped and runs the destructor for type `<O as AsWorkspaceController<'_, '_>>::Controller`
   |
   = warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
           It represents potential unsoundness in your code.
           This warning will become a hard error in the future.
```
It is unclear to me why the compiler thinks that controller is still borrowed and the warning doesn't carry any information which object controller is borrowed to. In addition I wonder why the compiler thinks it's unsound: As `log` was constructed after `controller` and may be dropped before since the lifetime of `log` is late-bound, and the compiler is free to choose a shorter lifetime.

[This](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=deb828422637e1f9cbca4fa573425ef0) is the full code on the playground.