mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
rust: pin-init: internal: pin_data: complete invariant borrow support
Non-covariant types can already be accessed inside projections. As
projections are only generated for `Pin<&mut T>`, they're not accessible
otherwise. Add `with_{field_name}` methods so fields can be accessed using
closures with just `&T`.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-17-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
This commit is contained in:
parent
91a255fea7
commit
e55acb7337
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
#[pin_data]
|
||||
struct SelfRef {
|
||||
#[uses('_: invariant)]
|
||||
not_cov: Box<dyn Fn(&'str str) -> bool + 'str>,
|
||||
|
||||
part: &'str str,
|
||||
str: String,
|
||||
|
||||
|
|
@ -20,6 +23,7 @@ fn use_self_ref() {
|
|||
part: &str[..5],
|
||||
mut_str: "hello world".to_owned(),
|
||||
mut_part: &mut mut_str[..5],
|
||||
not_cov: Box::new(move |s| s == str),
|
||||
}));
|
||||
|
||||
// Access via projection.
|
||||
|
|
@ -41,6 +45,14 @@ fn use_self_ref() {
|
|||
foo.as_mut().with_project(|proj| {
|
||||
proj.mut_part.make_ascii_uppercase();
|
||||
});
|
||||
|
||||
// Access non-covariant type using `with_` accessor.
|
||||
foo.with_not_cov(|not_cov| {
|
||||
not_cov("");
|
||||
});
|
||||
|
||||
// Access non-covariant type using `with_project`.
|
||||
foo.as_mut().with_project(|proj| (proj.not_cov)(proj.str));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -1441,7 +1441,24 @@ fn generate_projections(info: &StructInfo) -> TokenStream {
|
|||
}
|
||||
))
|
||||
} else {
|
||||
continue;
|
||||
let f_doc = format!("Access the `{ident}` field on a shared reference of `Self`.");
|
||||
let vis = &f.field.vis;
|
||||
let with_ident = format_ident!("with_{ident}");
|
||||
|
||||
let all_lifetimes: Vec<_> = f.captures.iter().map(|b| &b.lifetime).collect();
|
||||
let ty = &f.field.ty;
|
||||
|
||||
accessors.push(quote!(
|
||||
#[doc = #f_doc]
|
||||
#[inline]
|
||||
#vis fn #with_ident<'__this, R>(
|
||||
&'__this self,
|
||||
f: impl for<#(#all_lifetimes,)*> ::core::ops::FnOnce(&'__this #ty) -> R,
|
||||
) -> R {
|
||||
// SAFETY: we have `Erase<..>` which we know is layout compatible with `f.ty`.
|
||||
f(unsafe { ::core::mem::transmute(&self.#member) })
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user