Skip to content

Lifetimes bug on beta 1.31: the associated type may not live long enough  #55756

Closed
@mersinvald

Description

@mersinvald
Contributor

A reduced test case (play):

#![crate_type="lib"]

pub trait Database<'a> {
    type Guard: 'a;
}

pub struct Stateful<'a, D: 'a>(&'a D);

impl<'b, D: for <'a> Database<'a>> Stateful<'b, D> {
    pub fn callee<'a>(&'a self) -> <D as Database<'a>>::Guard {
        unimplemented!()
    }
    pub fn caller<'a>(&'a self) -> <D as Database<'a>>::Guard {
        let state = self.callee();
        unimplemented!()
    }
}

Error diagnostic output in details block below

error[E0311]: the associated type `<D as Database<'_>>::Guard` may not live long enough
  --> src/lib.rs:14:13
   |
14 |         let state = self.callee();
   |             ^^^^^
   |
   = help: consider adding an explicit lifetime bound for `<D as Database<'_>>::Guard`
note: the associated type `<D as Database<'_>>::Guard` must be valid for the block suffix following statement 0 at 14:9...
  --> src/lib.rs:14:9
   |
14 | /         let state = self.callee();
15 | |         unimplemented!()
16 | |     }
   | |_____^
note: ...so that variable is valid at time of its declaration
  --> src/lib.rs:14:13
   |
14 |         let state = self.callee();
   |             ^^^^^

error[E0311]: the associated type `<D as Database<'_>>::Guard` may not live long enough
  --> src/lib.rs:14:13
   |
14 |         let state = self.callee();
   |             ^^^^^
   |
   = help: consider adding an explicit lifetime bound for `<D as Database<'_>>::Guard`
note: the associated type `<D as Database<'_>>::Guard` must be valid for the block at 13:63...
  --> src/lib.rs:13:63
   |
13 |       pub fn caller<'a>(&'a self) -> <D as Database<'a>>::Guard {
   |  _______________________________________________________________^
14 | |         let state = self.callee();
15 | |         unimplemented!()
16 | |     }
   | |_____^
note: ...so that references are valid when the destructor runs
  --> src/lib.rs:14:13
   |
14 |         let state = self.callee();
   |             ^^^^^

error[E0311]: the associated type `<D as Database<'_>>::Guard` may not live long enough
  --> src/lib.rs:14:21
   |
14 |         let state = self.callee();
   |                     ^^^^^^^^^^^^^
   |
   = help: consider adding an explicit lifetime bound for `<D as Database<'_>>::Guard`
note: the associated type `<D as Database<'_>>::Guard` must be valid for the method call at 14:21...
  --> src/lib.rs:14:21
   |
14 |         let state = self.callee();
   |                     ^^^^^^^^^^^^^
note: ...so type `<D as Database<'_>>::Guard` of expression is valid during the expression
  --> src/lib.rs:14:21
   |
14 |         let state = self.callee();
   |                     ^^^^^^^^^^^^^

error[E0311]: the associated type `<D as Database<'_>>::Guard` may not live long enough
  --> src/lib.rs:14:21
   |
14 |         let state = self.callee();
   |                     ^^^^^^^^^^^^^
   |
   = help: consider adding an explicit lifetime bound for `<D as Database<'_>>::Guard`
note: the associated type `<D as Database<'_>>::Guard` must be valid for the destruction scope surrounding statement at 14:9...
  --> src/lib.rs:14:9
   |
14 |         let state = self.callee();
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that references are valid when the destructor runs
  --> src/lib.rs:14:21
   |
14 |         let state = self.callee();
   |                     ^^^^^^^^^^^^^

error: aborting due to 4 previous errors

Original bug report

Versions

rustc 1.31.0-beta.4 (04da282 2018-11-01)
cargo 1.31.0-beta (efb7972a0 2018-10-24)

Expected behavior

Everything compiling correctly like it does on stable 1.30

Actual behavior

A lot of lifetime-related errors:

error[E0311]: the associated type `<D as trie::Database<'_>>::Guard` may not live long enough                                                                                                                                    
   --> /home/mike/dev/etcdev/sputnikvm/stateful/src/lib.rs:536:23                                                                                                                                                                
    |                                                                                                                                                                                                                            
536 |         let account = state.get(&address);                                                                                                                                                                                 
    |                       ^^^^^^^^^^^^^^^^^^^                                                                                                                                                                                  
    |                                                                                                                                                                                                                            
    = help: consider adding an explicit lifetime bound for `<D as trie::Database<'_>>::Guard`                                                                                                                                    
note: the associated type `<D as trie::Database<'_>>::Guard` must be valid for the method call at 536:23...                                                                                                                      
   --> /home/mike/dev/etcdev/sputnikvm/stateful/src/lib.rs:536:23                                                                                                                                                                
    |                                                                                                                                                                                                                            
536 |         let account = state.get(&address);                                                                                                                                                                                 
    |                       ^^^^^^^^^^^^^^^^^^^                                                                                                                                                                                  
note: ...so that a type/lifetime parameter is in scope here                                                                                                                                                                      
   --> /home/mike/dev/etcdev/sputnikvm/stateful/src/lib.rs:536:23                                                                                                                                                                
    |                                                                                                                                                                                                                            
536 |         let account = state.get(&address);                                                                                                                                                                                 
    |                       ^^^^^^^^^^^^^^^^^^^                                                                                                                                                                                  
                                                 

It has been an issue in nightly 1.31 for a long time now, but I haven't reported the issue while it was just nightly. Now the regression is in beta channel and may land in stable, breaking existing code.

My own findings on the subject: regression is related to an old lifetime system, it's not reproducible with nll feature on, so on nightly the code can be compiled with nll, but not without it. Same holds for beta now except nll isn't quite there yet.

The subjected codebase: https://github.com/ETCDEVTeam/sputnikvm/tree/master/stateful

Activity

changed the title [-]Liferimes bug on beta 1.31: the associated type may not live long enough [/-] [+]Lifetimes bug on beta 1.31: the associated type may not live long enough [/+] on Nov 7, 2018
pnkfelix

pnkfelix commented on Nov 8, 2018

@pnkfelix
Member

visiting for T-compiler triage. P-high. Assigning to self for initial investigation.

self-assigned this
on Nov 8, 2018
Mark-Simulacrum

Mark-Simulacrum commented on Nov 9, 2018

@Mark-Simulacrum
Member
pnkfelix

pnkfelix commented on Nov 12, 2018

@pnkfelix
Member

Bisected against when https://source.that.world/source/evm-rs.git stopped building.

Successfully built: rustc 1.30.0-nightly (4141a40 2018-09-25)
Error during compilation: rustc 1.30.0-nightly (ae7fe84 2018-09-26)

pnkfelix

pnkfelix commented on Nov 12, 2018

@pnkfelix
Member

Heres the bors merge record from that time frame:

% git log 4141a40..ae7fe84 --format=oneline --author=bors
ae7fe84 Auto merge of #54561 - matthiaskrgr:clippy_up, r=kennytm
c7df1f5 Auto merge of #54453 - nikomatsakis:nll-issue-53121-shred-outlives, r=pnkfelix
6846f22 Auto merge of #51946 - japaric:emit-stack-sizes, r=nikomatsakis
e783d2b Auto merge of #54199 - nikomatsakis:predicate_may_hold-failure, r=eddyb
c3a1a0d Auto merge of #53824 - ljedrz:begone_onevector, r=michaelwoerister
a2b27c1 Auto merge of #54497 - ralexstokes:stabilize_pattern_parentheses, r=nikomatsakis
beff387 Auto merge of #54548 - nrc:update, r=kennytm
0b2eae7 Auto merge of #54164 - mikhail-m1:54131, r=pnkfelix
92aff72 Auto merge of #54575 - pietroalbini:rollup, r=pietroalbini
%

pnkfelix

pnkfelix commented on Nov 12, 2018

@pnkfelix
Member

The most obvious culprit to my eye is PR #54453. That PR might have been intended to be restricted to NLL, I'm not sure (it touches code outside of rustc_mir, certainly). It does seem like the crate in question is not opting into NLL nor the 2018 editon.

Update: of course they aren't opting into NLL. This issue is tagged NLL-fixed-by-NLL

pnkfelix

pnkfelix commented on Nov 12, 2018

@pnkfelix
Member

Here is a reduced test case (play):

#![crate_type="lib"]

pub trait Database<'a> {
    type Guard: 'a;
}

pub struct Stateful<'a, D: 'a>(&'a D);

impl<'b, D: for <'a> Database<'a>> Stateful<'b, D> {
    pub fn callee<'a>(&'a self) -> <D as Database<'a>>::Guard {
        unimplemented!()
    }
    pub fn caller<'a>(&'a self) -> <D as Database<'a>>::Guard {
        let state = self.callee();
        unimplemented!()
    }
}
pnkfelix

pnkfelix commented on Nov 12, 2018

@pnkfelix
Member

I am not sure if I'm going to have time to look into this further before I go on leave (for ~2 weeks), and yet it seems like a potentially important thing to address. Unassigning self.

removed their assignment
on Nov 12, 2018

20 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-borrow-checkerArea: The borrow checkerP-highHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.fixed-by-NLLBugs fixed, but only when NLL is enabled.regression-from-stable-to-betaPerformance or correctness regression from stable to beta.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Participants

    @nikomatsakis@pnkfelix@oli-obk@nagisa@TheWaWaR

    Issue actions

      Lifetimes bug on beta 1.31: the associated type may not live long enough · Issue #55756 · rust-lang/rust