Lifetimes bug on beta 1.31: the associated type may not live long enough #55756
Description
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