Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions examples/selfref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT

use pin_init::*;

#[pin_data]
struct SelfRef {
#[not_covariant]
not_cov: Box<dyn Fn(&'str str) -> bool + 'str>,

part: &'str str,
str: String,

#[borrows(mut mut_str)]
mut_part: &'mut_str mut str,
mut_str: String,
}

fn use_self_ref() {
stack_pin_init!(let foo = pin_init!(SelfRef {
str: "hello world".to_owned(),
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.
println!("{}", foo.as_mut().project().part);

// Access via accessor.
println!("{}", foo.part());

// Access via `with_project`, gives mutable reference.
foo.as_mut().with_project(|proj| {
*proj.part = &proj.str[5..];
});

println!("{}", foo.part());

// Access fields that mutable borrow others are similar to those of shared borrow.
println!("{}", foo.as_mut().project().mut_part);
println!("{}", foo.mut_part());
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() {
use_self_ref();
}
2 changes: 1 addition & 1 deletion internal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ proc-macro = true
[dependencies]
quote = "1.0"
proc-macro2 = "1.0"
syn = { version = "2.0.86", features = ["full", "parsing", "visit-mut"] }
syn = { version = "2.0.86", features = ["full", "parsing", "visit", "visit-mut"] }

[build-dependencies]
rustc_version = "0.4"
Expand Down
5 changes: 3 additions & 2 deletions internal/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ pub(crate) fn expand(
let data = Ident::new("__data", Span::mixed_site());
let init_fields = init_fields(&fields, pinned, &data, &slot);
let field_check = make_field_check(&fields, init_kind, &path);

Ok(quote! {{
// Get the data about fields from the supplied type.
// SAFETY: TODO
Expand All @@ -156,7 +157,7 @@ pub(crate) fn expand(
};
// Ensure that `#data` really is of type `#data` and help with type inference:
let init = #data.__make_closure::<_, #error>(
move |slot| {
move |slot, #data| {
#zeroable_check
#this
#init_fields
Expand All @@ -166,7 +167,7 @@ pub(crate) fn expand(
}
);
let init = move |slot| -> ::core::result::Result<(), #error> {
init(slot).map(|__InitOk| ())
init(slot, #data.__with_lt()).map(|__InitOk| ())
};
// SAFETY: TODO
unsafe { ::pin_init::#init_from_closure::<_, #error>(init) }
Expand Down
2 changes: 2 additions & 0 deletions internal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

// Documentation is done in the pin-init crate instead.
#![allow(missing_docs)]
#![cfg_attr(USE_RUSTC_FEATURES, feature(extract_if))]

use proc_macro::TokenStream;
use syn::parse_macro_input;
Expand All @@ -18,6 +19,7 @@ mod diagnostics;
mod init;
mod pin_data;
mod pinned_drop;
mod util;
mod zeroable;

#[proc_macro_attribute]
Expand Down
Loading
Loading