| Age | Commit message (Collapse) | Author |
|
`#[pin_data]` inserts outlive bounds between lifetimes to allow closure
callbacks to rely on their relationship. In some cases, these relations are
implied by fields, and Rust generates `explicit_outlives_requirements`
allow-by-default lint, which is turned out by kernel as part of
rust-2018-idioms lint group.
As `#[pin_data]` is a proc macro and it cannot know if the bounds are
already implied, suppress such lints for generated code.
Link: https://patch.msgid.link/20261011133904.600785-1-gary@kernel.org
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
There are many cases where structs that have interior mutability, but they
do not need the invariance over captured lifetimes as the lifetime is
captured upon construction, and new data of that particular lifetime does
not flow back into the struct.
For these use cases, the same mechanism as pin-init self-reference may be
used. Add support for existential lifetimes, introduced by having where
clauses such as
exists<'a>: 'b
The lifetime `'a` above is minted similar to field lifetimes. Because `'a`
is an erased lifetime living longer than `'b`, the only variance
requirement that we have is that `'b` cannot be contravariant; that defense
is fulfilled by adding `PhantomData<&'b ()>` so the struct is either
covariant or invariant over `'b`.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-20-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
For fields that self-references, it is desirable that projection can
happen on shared references too, so lifetime between different fields can
be correlated. Add support for that with `with_project_ref`.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-19-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
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>
|
|
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>
|
|
Add support for explicit self-referential annotations.
`#[uses]` attribute is used to mark what other field lifetimes are
captured by this field, and also the variance of the type in respect to the
field lifetimes. For example,
#[uses('a: covariant, 'b: invariant)]
indicates that the field captures the field lifetime `'a` covariantly, and
field lifetime `'b` invariantly. Many types are covariant, so this is the
default variance if the variance is omitted (e.g. `#[uses('a)]`),
consistent with the automatically inferred borrow.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-15-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Allow fields to be mutably referenced by other fields in addition to shared
references. In order for this to be sound, the fields that can be mutably
borrowed are blocked from being accessed via field access syntax or
projection to maintain the aliasing requirements.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-14-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
`#[borrowed]` attribute explicitly marks a field as potentially being
borrowed by other fields.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-13-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
drop order
Add the outlive relations per field drop order. This allows a single
lifetime to be used when a field potentially borrow from two different
fields, by allowing the longer-living field lifetime to be shortened to a
shorter-living field lifetime.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-12-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Enable self-referential support, and add example and test cases.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-11-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
The `project` method needs to perform covariant coercion on covariant
fields, causing them to no longer being mutable. Implement a `with_project`
that does not require covariant coercion by using higher-ranked trait
bounds, thus allow the fields to be assignable inside the callback.
This mechanism can also be used to access non-covariant fields.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-10-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
This adds the projection for fields that are shared borrowed or that
borrows other fields but is covariant. Both cases allow a shared reference
to be accessed.
No mutable references can be created for these cases for different reasons:
* For fields that are shared borrowed, aliasing restriction prevents
creation of mutable reference
* For fields that borrow other fields, their proper type contains field
lifetimes. These lifetimes cannot be made available in the returned
`project` struct (because there is no way to represent existential
lifetime in return position). For covariant types, it is possible to
shorten these lifetimes to that of `&self`; but doing so requires the
reference to also be covariant over the pointee type, so we cannot give
out `&mut` as it is invariant over the pointee.
Due to field-referencing fields being wrapped inside `Erase`, the normal
accessor syntax stop working; create accessor methods for these fields
instead.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-9-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
We now have the checks to ensure that lifetime relations are what is
expected, we can generate the slot projections in `generate_pin_data` so
self-referential struct can be implemented.
New slot and guard types are defined (`SelfRefSlot` and `SelfRefDropGuard`)
which gives the generated let bindings longer lifetime than the guard
themselves.
Have `__make_closure` take `data` back as an argument. This gives
`#[pin_data]` an opportunity to change the type to add lifetimes.
Higher-ranked trait bound on `__make_closure` is used to ensure that the
initialization closure cannot make arbitrary assumptions of those
lifetimes.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-8-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
We implicitly infer covariance for fields that self-references. This needs
to be checked to ensure that the fields are really covariant, so the rest
of expansion code can rely on this fact.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-7-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Check drop order to ensure that usage of lifetime inside self-referential
struct is consistent with the order that the fields will dropped in drop
glue.
First, fields are checked according to their index to ensure that if `a`
borrows from `b`, `b` must outlive `a`. This is simple and produces a very
good diagnostic when misused.
Lifetime bounds can also be indirectly crafted with implied bounds that
make fields well-formed. For example, in this struct
struct Foo {
x: &'b &'a (),
a: String,
y: PrintOnDrop<&'b str>,
b: String,
}
`&'b &'a ()` will imply that `a` outlive `b`, which is inconsistent with
the actual drop order. For this case, create a `__drop_order_check`
function with field lifetimes and outlive relationship of them as generic
parameter, and ask Rust to prove that the types are well-formed inside the
generated function, to ensure that the bad implied bounds cannot happen.
The `__drop_order_check` also need to correlate lifetimes or types captured
by generics and the field lifetimes. Do this by inserting outlive bounds
when a field mentions a specific type or lifetime parameter.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-6-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
For fields that are borrowed, a mutable reference to the struct no longer
mean that it has the permission to access these fields. Therefore, the
memory that they refer to must be pinned.
Wrap these fields inside a `Borrowed` struct which pins it. They may be
accessed directly (if they're not themselves referencing other struct
fields), so implement a `Deref`.
As such fields are always pinned, there is no need to generate a
conditional `Unpin` implementations that implements `Unpin` when all fields
are. Simply generate a never satisfiable `Unpin` implementation to prevent
user from adding their own.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-4-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Fields that borrow other fields have lifetimes that are within the struct
and these are not part of the struct generics. Therefore, these fields need
to have their lifetime erased.
A naive implementation would be to replace their lifetimes with `'static`.
However, doing so is unsound for multiple reasons:
* Users may directly access such field with field access syntax, and get
exposed with wrong lifetime;
* Auto trait implementations will cause the struct to be implementing auto
traits when the type only implements the auto trait for specific
lifetime. This is similar to how specialization can be unsound if
specialized on lifetime.
Create a `Erase` type, which has `for<'a> fn(&'a ()) -> Foo<'a>` as generic
parameter. Internally, it uses a helper trait to resolve that to
`Foo<'static>`. The first issue is solved by not exposing any public
accessor on that type. The second issue is solved by add custom `Send` and
`Sync` implementations that requires `Send` to be implemented for all
lifetimes, thus closing the lifetime specialization hole. The actual
implementation is a bit more convoluted because it supports erasing
multiple lifetimes.
This is more or less a stable polyfill of the unstable `unsafe_binder`
feature, without `unsafe_binders`'s no drop glue requirement.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-3-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
As a first step towards adding self-referential data structures in
pin-init, add parsing support.
Scan all field types for unbounded lifetimes, and if the names that of
fields, it is inferred as a self-referential field lifetime. No explicit
annotations are supported yet.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261008-dev-selfref-v2-2-e280b3c8fba5@garyguo.net/
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Organize parsing and generation into two separate phases, with a single
`StructInfo` in the middle. This allows analysis and processing to happen
with a single struct and avoid having to pass different information into
the token stream generation functions.
A drawback of this approach is that as we consume the `Fields`, we cannot
expand the original struct using `quote!(#struct_)` anymore, and the field
needs to be re-constructed in `generate_struct_def` function. However, this
is only a temporary drawback, as the upcoming pin-init self-referential
feature will require modification of the generated struct anyway.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-8-da716f740d6d@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
"pin" is a very overloaded word in pin-init. For the generated projection
structs, the lifetime refer to that of the whole struct, so rename the
lifetime used in expansion from `'__pin` to `'__this` instead.
The `__pin_phantom_data` field is renamed to `__this` for the same reason
and for clarity purpose, capture a `PhantomData` of the mutable reference
to the struct.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-7-da716f740d6d@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
function
The `pin_data` function is getting big. Split the `#[cfg]` handling which
does not interact with other part of expansion to its own `expand_with_cfg`
function.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-6-da716f740d6d@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
()` block
Most users would not need to mention the generated projection struct. With
the upcoming self-referential support, there needs to be additional
projection structs. Instead of give them publicly visible names, simply
make the name not publicly accessible.
A heavy user of pin projection outside kernel is for async programming.
I've checked tokio codebase there is a single use case and that's for
enums.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-5-da716f740d6d@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
More attributes are to be added which has the requirement that they should
only be specified once. Add a utility code to extract attributes for a
specific path and report error when appeared multiple times.
Convert `#[pin]` parsing to use the added utility.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-4-da716f740d6d@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
There're many cases where we want to merge multiple generics together.
Currently this is done by cloning generics and modifying it, making the
code less readable.
Add a utility code that allow printing multiple generics together, ensuring
correct ordering between lifetime and other parameters.
Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-3-da716f740d6d@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Currently, type inference of the initialized type is done by use the
function calling syntax `PATH::__pin_data` or `PATH::__init_data` to obtain
the required init data type, without needing the user to explicitly mention
all generics. Switch to always use `HasInitData::__init_data` to provide
that inference, which will not produce method-not-found errors as it is
always available.
Change `__pin_data` to take `InitData<Self>` as the receiver, so for types
that require `HasPinData`, `HasPinData::__pin_data(data)` can be used to
obtain the needed type without having to mention the user-provided path
again. The expanded code also uses the span of the type, so diagnostics
will hint to user that the type is causing the issue.
With this change, the error message when `HasPinData` is not implemented
changes from
error[E0599]: no associated function or constant named `__pin_data` found for struct `Foo` in the current scope
--> tests/ui/compile-fail/init/missing_pin_data.rs:9:9
|
3 | struct Foo {
| ---------- associated function or constant `__pin_data` not found for this struct
...
9 | pin_init!(Self { a: 42 })
| ^^^^^^^^^^^^^^^^^^^^^^^^^ associated function or constant not found in `Foo`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `__pin_data`, perhaps you need to implement it:
candidate #1: `pin_init::__internal::HasPinData`
to
error[E0277]: the trait bound `Foo: pin_init::__internal::HasPinData` is not satisfied
--> tests/ui/compile-fail/init/missing_pin_data.rs:9:19
|
9 | pin_init!(Self { a: 42 })
| ^^^^ unsatisfied trait bound
|
help: the trait `pin_init::__internal::HasPinData` is not implemented for `Foo`
--> tests/ui/compile-fail/init/missing_pin_data.rs:3:1
|
3 | struct Foo {
| ^^^^^^^^^^
Link: https://patch.msgid.link/20260923-dev-pin-data-diag-v1-3-e4d7193569e5@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Remove the unsafe markers of `__init_data` and `__pin_data`. These methods
are for inference help and does not need to be unsafe.
The `HasInitData` cannot be implemented outside pin-init, so the `unsafe
trait` marker is not necessary.
Link: https://patch.msgid.link/20260923-dev-pin-data-diag-v1-1-e4d7193569e5@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
for `Unpin`
`#[pin_data]` generates a `Unpin` implementation for the user, which
requires reasoning using field types. This is rejected by rustc as "trivial
bounds", which can only be specified using the
`#![feature(trivial_bounds)]`.
Currently we use an extra lifetime in `__Unpin` to work around this; use
HRTB to introduce a dummy lifetime can achieve the same, which the
`Zeroable` implementation already uses.
Unify the `Unpin` impl to also use the same HRTB trick that `Zeroable`
uses. This produces slightly better error message and slightly shorter
expansion.
Link: https://patch.msgid.link/20260922211320.1390159-1-gary@kernel.org
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
`#[pin_data]` rejects tuple structs because it assumes every field has a
name, which it uses for the projection field, the `__Unpin` field and the
pin-data accessor.
Identify fields by `syn::Member` instead, so that tuple fields are referred
to by their index in generated field accesses. The names that generated
items still need are derived from the index as `_0`, `_1`, etc.
The projection of a tuple struct is a tuple struct itself, so projected
fields are accessed with the same `.0`, `.1` syntax as on the input
type rather than through synthesised names.
Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
[ Moved utility code to util.rs as extension trait - Gary ]
Link: https://patch.msgid.link/20260904-tuple-struct-v1-2-72c50bd037fd@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Create a new `util.rs` to host utility code that are generic and can be
shared by multiple macros.
Link: https://patch.msgid.link/20260904-tuple-struct-v1-1-72c50bd037fd@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Currently `pin-init` crate is missing many inline annotations. They are all
generic so still get inlined in normal builds, but are not inlined in
`-C opt-level=s` build. Mark these functions as `#[inline]` so they are
considered for inlining regardless.
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Attribute macros are invoked without cfg being resolved. This adds quite a
bit complexity to the macro because all of the macro needs to be careful to
attach necessary cfgs. This becomes especially tricky for tuple structs.
Thus, it is convenient if cfgs are all resolved like derive macros.
The most optimal way to handle this is via `TokenStream::expand_expr`, but
that is still unstable. We can also create an internal derive macro and
transform the attribute macro invocation to be derive macro, but doing
requires us to serialize all extracted information in a form of helper
attributes; it would also make it more difficult if we want to make changes
to the struct (which the self-reference feature would need).
Implement an approach where we generate two cfg-gated macro invocations
with cfg resolved within the invocation. This would mean when the loop
falls through, all field cfgs are resolved, so remove all handling of
cfg_attrs for the rest of the macro.
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Most warnings are suppressed from external macro expansions by default.
Thus remove `allow` and `expect`s for them.
Note that `unfulfilled_lint_expectations` is one of them too. This means
that all of our `expect`s inside macros do nothing, and actually mislead
people to the lints would be actually emitted without them.
Reviewed-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20260710-pin-init-sync-v1-4-8fa16cde87ae@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Duplicated `#[pin]` has no effect, thus error if misused.
Reported-by: Mohamad Alsadhan <mo@sdhn.cc>
Closes: https://github.com/Rust-for-Linux/pin-init/issues/119
Signed-off-by: Luiz Georg <luizgngeorg@gmail.com>
Link: https://patch.msgid.link/20260710-pin-init-sync-v1-1-8fa16cde87ae@garyguo.net
[ Reworded commit message, and change the logic so code generation still
continue after reporting error - Gary ]
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Allows `non_snake_case` lint on struct fields generated by `#[pin_data]`.
Since the same warning will be reported by the compiler on the struct
definition, having extra warnings for the generated code is unnecessary
and confusing.
Signed-off-by: Mirko Adzic <adzicmirko97@gmail.com>
Link: https://patch.msgid.link/20260527-pin-init-sync-v1-2-e20335ed2501@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
When using a macro with custom attributes in a `#[pin_data]` struct it
can mess up the generated code. The generated code needs nothing more than
the `#[cfg]` attribute, thus strip away all other attributes.
[ Rebased and updated to only include `#[cfg]` instead of both `#[cfg]` and
`#[doc]`; doc is not needed for the generated hidden items. - Gary ]
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Link: https://patch.msgid.link/20260527-pin-init-sync-v1-1-e20335ed2501@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Instead of projecting using pointer to a field project the full slot. This
further shifts the code generation from the initializer site to the struct
definition site, which means less code is generated overall.
It also makes the safety comment easier to justify, as now the projection
is done by the `#[pin_data]` macro which has full visibility of pinnedness
of fields.
The field alignment could also be checked on the `#[pin_data]` side;
however, since `init!()` macro works for other type of structs, we cannot
remove the alignment check from `init!`/`pin_init!` side anyway, so I opted
to still keep the alignment check in init.rs.
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
By projecting slots, the `pin_init!` and `init!` code path can be more
unified. This also reduces the amount of macro-generated code and shifts
them to the shared infrastructure.
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
The `InitData` and `PinData` traits do not need to exist, the inference
helpers could be inherent methods instead.
There is no risk for calling the wrong methods even when user defines it,
as inherent methods take priority over trait methods.
With this change, it unlocks the possibility of attaching additional bounds
to the method per type, which is not possible for trait methods.
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Instead of projecting the created reference, simply create drop guards with
different marker types and have the `let_binding()` method of guards of
different marker produce different type instead.
This allows more flexible lifetime as this is now controlled by the guard.
This will be needed when implementing self-referential fields.
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Currently, the `pin_init` library has an `Invariant` type alias, and it is
instantiated using `PhantomData`. Generated code from `pin_data` on the
other hand cannot access the crate-local type alias, so it generates
`PhantomData<fn(T) -> T>` directly. This is all very inconsistent, despite
the exact same use case of ensuring invariance.
Add `PhantomInvariant` and `PhantomInvariantLifetime` and switch all users
that need to express the concept of invariance to use these. They're
polyfills of unstable types in the same names in the Rust standard library.
Link: https://patch.msgid.link/20260512-pin-init-sync-v1-3-81963130dfbd@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Introduce `FieldInfo` struct to encapsulate field and other relevant data,
instead of carrying a pair of `(pinned, field)` in all places. This allows
us to add more information to the struct in the future.
Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Co-developed-by: Gary Guo <gary@garyguo.net>
Link: https://patch.msgid.link/20260512-pin-init-sync-v1-2-81963130dfbd@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
`handle_field` is currently a function, which precludes it from referencing
things in the scope of the parent function. Given that it's only called
once, inline its contents to the closure that invokes it instead, so it can
directly reference `struct_name` without having to pass in as argument.
Link: https://patch.msgid.link/20260512-pin-init-sync-v1-1-81963130dfbd@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
Tuples implement `FromIterator` since Rust 1.79. Remove the `collect_tuple`
polyfill now the MSRV is above 1.79.
To avoid over-identing the closure, I move the `Field` destructure from the
closure parameter to a let binding. This keeps the diff small.
Link: https://patch.msgid.link/20260501134445.3809731-1-gary@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
The `PhantomPinned` detection is just a lint, and is emitted as an error
because there is no `compile_warning!()` macro, and
`proc-macro-diagnostics` is not stable.
Use of `#[deprecated = ""]` attribute to approximate custom proc-macro
warnings. A new line is added before message for visual clarity.
An example warning with this trick looks like this:
warning: use of deprecated function `_::warn`:
The field `pin` of type `PhantomPinned` only has an effect if it has the `#[pin]` attribute
--> test.rs:9:5
|
9 | pin: marker::PhantomPinned,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Suggested-by: Benno Lossin <lossin@kernel.org>
Link: https://github.com/Rust-for-Linux/pin-init/issues/51
Link: https://patch.msgid.link/20260428-pin-init-sync-v1-10-07f9bd3859fb@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
The `generate_projections` and `generate_the_pin_data` function already
receive filtered field lists, they do not need to filter out `#[pin]`
again.
Reviewed-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20260428-pin-init-sync-v1-6-07f9bd3859fb@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
`#[pin_data]` failed to propagate the struct's `where` clause to the
generated projection struct. As a result, bounds written in a `where`
clause could be dropped during expansion, causing type errors when
fields depended on those bounds.
Fix this by adding the missing `where` clause to the generated
projection struct.
Reported-by: Andreas Hindborg <a.hindborg@kernel.org>
Closes: https://rust-for-linux.zulipchat.com/#narrow/channel/561532-pin-init/topic/generic.20bounds.20and.20.60.23.5Bpin_data.5D.60/with/578381591
Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Reviewed-by: Gary Guo <gary@garyguo.net>
[ Reworded commit message - Gary ]
Link: https://patch.msgid.link/20260428-pin-init-sync-v1-5-07f9bd3859fb@garyguo.net
Signed-off-by: Gary Guo <gary@garyguo.net>
|
|
The `#[pin_data]` macro uses some auxiliary traits to ensure that a user
does not implement `Drop` for the annotated struct, as that is unsound
and can lead to UB. However, if the struct that is annotated is
`!Sized`, the current bounds do not work, because `Sized` is an implicit
bound for generics.
This is *not* a soundness hole of pin-init, as it currently is
impossible to construct an unsized struct using pin-init.
Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
Reviewed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Benno Lossin <lossin@kernel.org>
|
|
Rewrite the attribute macro `#[pin_data]` using `syn`. No functional
changes intended aside from improved error messages on syntactic and
semantical errors. For example if one forgets a comma at the end of a
field:
#[pin_data]
struct Foo {
a: Box<Foo>
b: Box<Foo>
}
The declarative macro reports the following errors:
error: expected `,`, or `}`, found `b`
--> tests/ui/compile-fail/pin_data/missing_comma.rs:5:16
|
5 | a: Box<Foo>
| ^ help: try adding a comma: `,`
error: recursion limit reached while expanding `$crate::__pin_data!`
--> tests/ui/compile-fail/pin_data/missing_comma.rs:3:1
|
3 | #[pin_data]
| ^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`$CRATE`)
= note: this error originates in the macro `$crate::__pin_data` which comes from the expansion of the attribute macro `pin_data` (in Nightly builds, run with -Z macro-backtrace for more info)
The new `syn` version reports:
error: expected `,`, or `}`, found `b`
--> tests/ui/compile-fail/pin_data/missing_comma.rs:5:16
|
5 | a: Box<Foo>
| ^ help: try adding a comma: `,`
error: expected `,`
--> tests/ui/compile-fail/pin_data/missing_comma.rs:6:5
|
6 | b: Box<Foo>
| ^
Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
Reviewed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Benno Lossin <lossin@kernel.org>
|
|
workarounds
`syn` makes parsing Rust from proc-macros a lot simpler. `pin-init` has
not used `syn` up until now, because the we did not support it. That
changed in commit 54e3eae85562 ("Merge patch series "`syn` support""),
so we can finally utilize the added ergonomics of parsing proc-macro
input with `syn`.
Previously we only had the `proc-macro` library available, whereas the
user-space version also used `proc-macro2` and `quote`. Now both are
available, so remove the workarounds.
Due to these changes, clippy emits warnings about unnecessary
`.to_string()` as `proc-macro2` provides an additional `PartialEq` impl
on `Ident`, so the warnings are fixed.
[ Adjusted wording from upstream version and added build system changes
for the kernel - Benno ]
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Tamir Duberstein <tamird@gmail.com>
Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
Signed-off-by: Benno Lossin <lossin@kernel.org>
|
|
Synchronize the internal macros crate with the user-space version that
uses the quote crate [1] instead of a custom `quote!` macro. The imports
in the different version are achieved using `cfg` on the kernel config
value. This cfg is always set in the kernel and never set in the
user-space version.
Since the quote crate requires the proc_macro2 crate, imports also need
to be adjusted and `.into()` calls have to be inserted.
Link: https://crates.io/crates/quote [1]
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
Reviewed-by: Fiona Behrens <me@Kloenk.dev>
Link: https://lore.kernel.org/r/20250308110339.2997091-19-benno.lossin@proton.me
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
|