diff options
| author | Gary Guo <gary@garyguo.net> | 2026-09-09 19:37:00 +0100 |
|---|---|---|
| committer | Gary Guo <gary@garyguo.net> | 2026-10-11 11:06:47 +0100 |
| commit | 91a255fea7306c5b07f6b26d740be31fdc8bfa41 (patch) | |
| tree | 4a6ab1776b4f054313deab14613d2a6f765a16b0 /tools/perf/scripts/python/bin | |
| parent | 59a9b11bccdb308f242ba6abc4638d64816781b1 (diff) | |
rust: pin-init: internal: pin_data: make field lifetime invariance imply type invariance
If invariant field captures a field lifetime, then we also need to make
sure that field is also invariant. Imagine this struct:
#[pin_data]
struct SelfRef<'a> {
#[uses('outer: invariant)]
part: Mutex<&'outer str>,
outer: &'a String,
}
fn new<'a>(str: &'a String) -> impl PinInit<SelfRef<'a>, Infallible> {
pin_init!(SelfRef {
outer: str,
part: Mutex::new(*outer),
})
}
If we make this struct covariant over `'a`, then we can have the following
case:
let mut long = "hello world".to_owned();
let s = Box::pin_init(new(&long)).unwrap();
{
let mut short = "hello world".to_owned();
// If `s` is covariant, this would be okay, because we shorten from
// `SelfRef<'long>` to `SelfRef<'short>`.
s.with_project_ref(|p| {
*p.part.lock().unwrap() = &short;
});
}
Conceptually, a field's type must outlive the field's lifetime, so if we
have a covariant `'a`, we can have a shortened `SelfRef<'short_a>` where
`'outer` outlives `'short_a`. But the wellformedness requirement of the
field will imply `'short_a: 'outer`, which enables the `&'short_a` to
`'outer` coercion, effectively making the field lifetime `'f` behave
covariantly, too, breaking the requirement that it is invariant.
Therefore, compute an invariant closure and use an additional generics on
`Borrowed` to allow capturing things invariantly. Note that we do capture
all parameters explicitly rather than capture the field type invariantly,
because if type aliases are involved, we might be syntactically determining
that the field uses a type parameter but actually not, causing the
invariance enforcement to be missed.
Outlive bounds between field lifetimes can also cause the same issue (an
invariant field lifetime cannot be a lower bound of a covariant field
lifetime). Since we cannot deduce whether any implied bounds from type
wellformness would create such outlive relationships, prevent such bounds
from happening by using a split outlive chain.
Note that this is not a soundness hole in itself in absence of
`with_project_ref`, because with single field accessors only, the field
lifetimes of the fields are not connected; in methods like `with_project`
lifetimes are invariant so shortening cannot happen. However, such method
is likely desirable, so include the variance rule before it has been
heavily relied upon.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-16-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
Diffstat (limited to 'tools/perf/scripts/python/bin')
0 files changed, 0 insertions, 0 deletions
