Change:
On linux, the following works: (rustc version is rustc 1.44.0-nightly ( 2020-04-05)) The following does not work: Build fails with: (rustc version is: rustc 1.44.0-nightly ( 2020-04-07))
Reproducer:
` reports that the regression happened in , i.e. cc
Reduced ( -): Are we supposed to ignore only lifetime parameters in s? If the reasoning is that the only thing you can do with a is call it, why aren't all generics ignored? cc
I should say, I didn't expect to fix a lifetime vs type inconsistency, the goal was to fix type vs const inconsistencies. Somehow we have a behavior with no tests, I'm not sure how intentional it was.
(I'm perfectly happy to issue a point release, 0.9.6, to proptest btw if we decide the new compiler behavior is correct and proptest is in the wrong.)
Assigning and leaving nomination for . This was .
Let me leave a brief comment explaining what is going on, because it took me a bit to figure out what was talking about. The type in question is one of the "anonymous types" that we construct for functions. You can think of these types as being roughly , where is the name of the function and are the generic types from the function definition. In , the type would be something like . We are processing a constraint like . The ordinary "outlives" rules for such types require that each component be , so in this case it would require that , which is not known to be true. These rules were defined in . I'm not sure why the old code seemingly ignored this requirement. It seems like a bug to me though, a kind of artifact of the structure of the code that fixed "in passing" by making the code operate more uniformly.
Notes from the language team meeting yesterday: We believe changes to be a fix, and not a bug. We try to assess the impact using crater (not sure how you do that -- maybe you can help?) It seems to have broken proptest (I mistakenly suggested it broke structopt; it has not), but I am the maintainer of that crate so I am happy to publish a point release (I'll try to do so today). We could add a special case to have a warning period or accept this indefinitely (Speaking personally, I would prefer the former.) Niko does not believe the previous behavior is unsound, but interactions with could perhaps change that.
run start=master# end=masterb2be09fcaff937480d1fbbe8b31646e361c7a mode=check-only
:okhand: Experiment created and queued. :mag: You can check out and . :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
Touched on briefly at the today. But since we are awaiting crater results, there is nothing for us to discuss at the moment. Leaving nominated for discussion at next week's triage meeting (or hopefully sooner, async), since by then the crater results should be available.
:construction: Experiment is now running :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
I've gone ahead and released which has a fix for the problem here.
:tada: Experiment is completed! :barchart: 194 regressed and 1 fixed ( total) :newspaper: . :warning: If you notice any spurious failure ! :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
All these depend on , except:    ( is marked as a regressions but looks like a spurious issue maybe in crater)
But oof, that's a lot of regressions. Looking at and , both issues seem to be related to lua. Not sure about clint.
We should probably allow this, since it's sound (AFAIK). If nothing else, we should be more intentional about a breaking change.
I'm thinking similarly. To recap what I said in the meeting, we could allow this -- it might even be something we want to consider generalizing to other types. It would I think be sound but would require caution if/when we introduce , I think. In particular something like would be bad, because we would think that , but doesn't hold (see RFC 1214 for more details). However, I would like to modify RFC 1214 anyway so that we have it so that lifetime variables which appear in some positions of types are considered "unconstrained" and then cannot appear in associated types. I particularly wanted to do this for things like (though it'd be a breaking change), and this same technique could apply to lifetimes/types that appear in types).
Removed nomination as per . This was already discussed on last compiler meeting and we'll probably again tomorrow because it's an unassigned regression.
Found where I introduced the breaking change: these were using : And was ignoring 's substs: Doesn't even look like the behavior was intentional, but at least now I know where to restore it (however it is annoying that this code is duplicated...). EDIT: opened with the fix.
yeah, I expected to see some code like that -- I agree the behavior was not intentional.

Discussion:
match ty.kind { ty::Param(p) => self.param_bound(p), ty::Projection(data) => self.projection_bound(data), <ins> ty::FnDef(_, substs) => { // HACK(eddyb) ignore lifetimes found shallowly in `substs`. // This is inconsistent with `ty::Adt` (including all substs), // but consistent with previous (accidental) behavior. // See https://github.com/rust-lang/rust/issues/70917 // for further background and discussion. let mut bounds = substs .iter() .filter_map(|&child| match child.unpack() { GenericArgKind::Type(ty) => Some(self.type_bound(ty)), GenericArgKind::Lifetime(_) => None, GenericArgKind::Const(_) => Some(self.recursive_bound(child)), }) .filter(|bound| { // Remove bounds that must hold, since they are not interesting. !bound.must_hold() }); match (bounds.next(), bounds.next()) { (Some(first), None) => first, (first, second) => VerifyBound::AllBounds( first.into_iter().chain(second).chain(bounds).collect(), ), } } </ins> _ => self.recursive_bound(ty.into()), } }

// in the `subtys` iterator (e.g., when encountering a // projection). match ty.kind { <ins> ty::FnDef(_, substs) => { // HACK(eddyb) ignore lifetimes found shallowly in `substs`. // This is inconsistent with `ty::Adt` (including all substs) // and with `ty::Closure` (ignoring all substs other than // upvars, of which a `ty::FnDef` doesn't have any), but // consistent with previous (accidental) behavior. // See https://github.com/rust-lang/rust/issues/70917 // for further background and discussion. for &child in substs { match child.unpack() { GenericArgKind::Type(ty) => { compute_components(tcx, ty, out); } GenericArgKind::Lifetime(_) => {} GenericArgKind::Const(_) => { compute_components_recursive(tcx, child, out); } } } } </ins> ty::Closure(_, ref substs) => { for upvar_ty in substs.as_closure().upvar_tys() { compute_components(tcx, upvar_ty, out);

ty::Float(..) |       // OutlivesScalar ty::Never |           // ... ty::Adt(..) |         // OutlivesNominalType <del> ty::Opaque(..) |        // OutlivesNominalType (ish) </del> <ins> ty::Opaque(..) |      // OutlivesNominalType (ish) </ins> ty::Foreign(..) |     // OutlivesNominalType ty::Str |             // OutlivesScalar (ish) ty::Array(..) |       // ...

ty::RawPtr(..) |      // ... ty::Ref(..) |         // OutlivesReference ty::Tuple(..) |       // ... <del> ty::FnDef(..) |       // OutlivesFunction (*) </del> ty::FnPtr(_) |        // OutlivesFunction (*) <del> ty::Dynamic(..) |       // OutlivesObject, OutlivesFragment (*) </del> <ins> ty::Dynamic(..) |     // OutlivesObject, OutlivesFragment (*) </ins> ty::Placeholder(..) | ty::Bound(..) | ty::Error => { <del> // (*) Bare functions and traits are both binders. In the // RFC, this means we would add the bound regions to the // "bound regions list".  In our representation, no such </del> <ins> // (*) Function pointers and trait objects are both binders. // In the RFC, this means we would add the bound regions to // the "bound regions list".  In our representation, no such </ins> // list is maintained explicitly, because bound regions // themselves can be readily identified. compute_components_recursive(tcx, ty.into(), out);

<ins> // check-pass fn assert_static<T: 'static>(_: T) {} // NOTE(eddyb) the `'a: 'a` may look a bit strange, but we *really* want // `'a` to be an *early-bound* parameter, otherwise it doesn't matter anyway. fn capture_lifetime<'a: 'a>() {} fn test_lifetime<'a>() { assert_static(capture_lifetime::<'a>); } fn main() {} </ins>