Open
Conversation
Instead of having the reference creation serving dual-purpose as both for let bindings and alignment check, detangle them so that the alignment check is done explicitly in `make_field_check`. This is more robust again refactors that may change the way let bindings are created. Reviewed-by: Alice Ryhl <aliceryhl@google.com> Signed-off-by: Gary Guo <gary@garyguo.net>
When a field has been initialized, `init!`/`pin_init!` create a reference
or pinned reference to the field so it can be accessed later during the
initialization of other fields. However, the reference it created is
incorrectly `&'static` rather than just the scope of the initializer.
This means that you can do
init!(Foo {
a: 1,
_: {
let b: &'static u32 = a;
}
})
which is unsound.
This is caused by `&mut (*#slot).#ident`, which actually allows arbitrary
lifetime, so this is effectively `'static`. Somewhat ironically, the safety
justification of creating the accessor is.. "SAFETY: TODO".
Fix it by adding `let_binding` method on `DropGuard` to shorten lifetime.
This results exactly what we want for these accessors. The safety and
invariant comments of `DropGuard` have been reworked; instead of reasoning
about what caller can do with the guard, express it in a way that the
ownership is transferred to the guard and `forget` takes it back, so the
unsafe operations within the `DropGuard` can be more easily justified.
Fixes: db96c51 ("add references to previously initialized fields")
Signed-off-by: Gary Guo <gary@garyguo.net>
`InitializerKind::Code` is a special case where it does not initialize a field, and thus generate no guard and accesssors. Handle it earlier and make the rest of the code more linear. 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>
The `InitData` and `PinData` trait does 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, we can use `impl Trait` as the return type of these methods. Thus, return `impl Init` or `impl PinInit` directly and simplify the code generation of `init!` and `pin_init!` macro. The method is renamed to `__make_init` accordingly. 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>
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>
7407d8b to
a91a85e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on #132
Use different guard types to determine the type of let bindings generated, and also move much of the logic of the generated code to
__internal.rs. Each commit explains the rationale on its own.