outlives: ignore lifetimes shallowly found in ty::FnDef
s.
This commit is contained in:
parent
7fb5187d04
commit
f86f03263c
@ -42,6 +42,31 @@ fn type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'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()),
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,27 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
// 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);
|
||||
@ -136,7 +157,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
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(..) | // ...
|
||||
@ -144,15 +165,14 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
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);
|
||||
|
13
src/test/ui/lifetimes/issue-70917-lifetimes-in-fn-def.rs
Normal file
13
src/test/ui/lifetimes/issue-70917-lifetimes-in-fn-def.rs
Normal file
@ -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() {}
|
Loading…
Reference in New Issue
Block a user