Skip to content

Commit

Permalink
outlives: ignore lifetimes shallowly found in ty::FnDefs.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Apr 16, 2020
1 parent 7fb5187 commit f86f032
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 6 deletions.
25 changes: 25 additions & 0 deletions src/librustc_infer/infer/outlives/verify.rs
Expand Up @@ -42,6 +42,31 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
match ty.kind {
ty::Param(p) => self.param_bound(p),
ty::Projection(data) => self.projection_bound(data),
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(),
),
}
}
_ => self.recursive_bound(ty.into()),
}
}
Expand Down
32 changes: 26 additions & 6 deletions src/librustc_middle/ty/outlives.rs
Expand Up @@ -62,6 +62,27 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
// in the `subtys` iterator (e.g., when encountering a
// projection).
match ty.kind {
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);
}
}
}
}

ty::Closure(_, ref substs) => {
for upvar_ty in substs.as_closure().upvar_tys() {
compute_components(tcx, upvar_ty, out);
Expand Down Expand Up @@ -136,23 +157,22 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
ty::Float(..) | // OutlivesScalar
ty::Never | // ...
ty::Adt(..) | // OutlivesNominalType
ty::Opaque(..) | // OutlivesNominalType (ish)
ty::Opaque(..) | // OutlivesNominalType (ish)
ty::Foreign(..) | // OutlivesNominalType
ty::Str | // OutlivesScalar (ish)
ty::Array(..) | // ...
ty::Slice(..) | // ...
ty::RawPtr(..) | // ...
ty::Ref(..) | // OutlivesReference
ty::Tuple(..) | // ...
ty::FnDef(..) | // OutlivesFunction (*)
ty::FnPtr(_) | // OutlivesFunction (*)
ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*)
ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*)
ty::Placeholder(..) |
ty::Bound(..) |
ty::Error => {
// (*) 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
// (*) 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
// list is maintained explicitly, because bound regions
// themselves can be readily identified.
compute_components_recursive(tcx, ty.into(), out);
Expand Down
13 changes: 13 additions & 0 deletions src/test/ui/lifetimes/issue-70917-lifetimes-in-fn-def.rs
@@ -0,0 +1,13 @@
// 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() {}

0 comments on commit f86f032

Please sign in to comment.