Change:
A reduced test case (): Error diagnostic output in details block below <details</detailsrustc 1.31.0-beta.4 ( 2018-11-01) cargo 1.31.0-beta ( 2018-10-24) Everything compiling correctly like it does on stable 1.30 A lot of lifetime-related errors: 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 feature on, so on the code can be compiled with , but not without it. Same holds for beta now except isn't quite there yet. The subjected codebase:
visiting for T-compiler triage. P-high. Assigning to self for initial investigation.
Based on crater run, looks like this also affects: , cc , cc , cc (cc ?) cc
Bisected against when stopped building. Successfully built: rustc 1.30.0-nightly ( 2018-09-25) Error during compilation: rustc 1.30.0-nightly ( 2018-09-26)
Heres the bors merge record from that time frame: % git log .. --format=oneline --author=bors Auto merge of - matthiaskrgr:clippyup, r=kennytm Auto merge of - nikomatsakis:nll-issue--shred-outlives, r=pnkfelix Auto merge of - japaric:emit-stack-sizes, r=nikomatsakis Auto merge of - nikomatsakis:predicatemayhold-failure, r=eddyb Auto merge of - ljedrz:begoneonevector, r=michaelwoerister Auto merge of - ralexstokes:stabilizepatternparentheses, r=nikomatsakis Auto merge of - nrc:update, r=kennytm Auto merge of - mikhail-m1:, r=pnkfelix Auto merge of - pietroalbini:rollup, r=pietroalbini %
The most obvious culprit to my eye is PR . 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
Here is a reduced test case ():
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.
I have now confirmed that PR is what injected this regression. cc
I did a bit of investigation. Some internal notes: In the reduced test case, anyway, the problem seems to arise precisely because we are now a bit more flexible than we used to be. In particular, the type of is something like but the region is not directly constrained. The constraints arise because we have constraints like and we used to convert that into a rule that , which led to us inferring that must equal . There is a workaround therefore of adding an explicit type annotation (): I remember that when I was doing this I had some "contingency plans" for handling this scenario should it be a problem. I'll try to remember what they were =)
Also, it's interesting that NLL makes this test case pass. Off hand, I'm not sure entirely sure why that is.
OK, so I investigated NLL a bit. The reason is actually somewhat interesting. NLL introduces an additional liveness check -- it says: This rule is much "cruder" than the outlives check here. In particular, if you have a variable , then for it to pass this liveness check, must include all points where occurs. We could adopt a similar distinction in lexical region checking with relative ease -- basically a "live at" relation that is more conservative than outlives. I'm not sure how well justified it is though. (This is a bit weird because of eager normalization: if we were able to normalize to another type (e.g., ), then we would not impose this requirement on , because we would be representing its type as merely . This will change with lazy normalization. It is conceivable that this could cause programs to stop type-checking. I guess we'll worry about it then.)
says they know what the problem is and hope to have a fix soon (today).
Hmm, so, I have a fix. Though looking more closely at the test, I think I see a nicer fix. The problem is that we now observe two potentially applicable rules when trying to find bounds for : <T as Database<'a::Guard: 'a // from the where clauses for<'b{ <T as Database<'b::Guard: 'b } // from the trait definition Because of this, we decide to take no action to influence inference, which means that winds up unconstrained, leading to the ultimate error. My current fix basically overrides this with a coarser rule (one which works fine, however, in this example). A smarter fix would be to observe that the first rule (the one talking about ) is in fact "specialization" of the latter, in which case we could conclude that we should relate to the bound we need. I am trying to decide which approach is lowest risk -- the current fix, as I wrote, actually makes us compatible with how NLL is handling things. I am planning to overhaul this whole setup in the not-that-distinct future, since the current solver is essentially "unnecessarily stupid". Some options: Land my current fix, which is relatively simple and (I think) low risk. Perhaps follow-up with an attempt to create a test case and a FIXME? Try to do the better fix Given the deadline, I'm leaning towards the first path.
Testing the more conservative fix from :
btw, in the future, we would definitely appreciate bug reports against nightly! That is indeed part of the point of nightly, to help us find regressions before they make it into beta =)
I don't know how to test the final two cases that cited -- I guess I need to checkout some github repositories? -- but based on the logs they seem like the same root problem and hence I expect it is fixed.
Yes, you'd need to build and to check them locally.
Confirm success build both on: -
Sure, I understand I should've report it once encountered. Would be less stressful for both parties. Thanks for fixing the issue!

Discussion:
// rule might not apply (but another rule might). For now, we err // on the side of adding too few edges into the graph. <ins> // Compute the bounds we can derive from the trait definition. // These are guaranteed to apply, no matter the inference // results. let trait_bounds: Vec<_> = self.verify_bound .projection_declared_bounds_from_trait(projection_ty) .collect(); </ins> // Compute the bounds we can derive from the environment. This // is an "approximate" match -- in some cases, these bounds // may not apply. <del> let approx_env_bounds = self.verify_bound </del> <ins> let mut approx_env_bounds = self.verify_bound </ins> .projection_approx_declared_bounds_from_env(projection_ty); debug!( "projection_must_outlive: approx_env_bounds={:?}", approx_env_bounds ); <del> // Compute the bounds we can derive from the trait definition. // These are guaranteed to apply, no matter the inference // results. let trait_bounds: Vec<_> = self.verify_bound .projection_declared_bounds_from_trait(projection_ty) .collect(); </del> <ins> // Remove outlives bounds that we get from the environment but // which are also deducable from the trait. This arises (cc // #55756) in cases where you have e.g. `<T as Foo<'a>>::Item: // 'a` in the environment but `trait Foo<'b> { type Item: 'b // }` in the trait definition. approx_env_bounds.retain(|bound| { match bound.0.sty { ty::Projection(projection_ty) => { self.verify_bound.projection_declared_bounds_from_trait(projection_ty) .all(|r| r != bound.1) } _ => panic!("expected only projection types from env, not {:?}", bound.0), } }); </ins> // If declared bounds list is empty, the only applicable rule is // OutlivesProjectionComponent. If there are inference variables,

<ins> // Regression test for #55756. // // In this test, the result of `self.callee` is a projection `<D as // Database<'?0>>::Guard`. As it may contain a destructor, the dropck // rules require that this type outlivess the scope of `state`. Unfortunately, // our region inference is not smart enough to figure out how to // translate a requirement like // //     <D as Database<'0>>::guard: 'r // // into a requirement that `'0: 'r` -- in particular, it fails to do // so because it *also* knows that `<D as Database<'a>>::Guard: 'a` // from the trait definition. Faced with so many choices, the current // solver opts to do nothing. // // Fixed by tweaking the solver to recognize that the constraint from // the environment duplicates one from the trait. // // compile-pass #![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!() } } </ins>