|
1 | 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT |
2 | 2 |
|
3 | 3 | use proc_macro2::{Span, TokenStream}; |
4 | | -use quote::{format_ident, quote, quote_spanned}; |
| 4 | +use quote::{format_ident, quote}; |
5 | 5 | use syn::{ |
6 | 6 | braced, |
7 | 7 | parse::{End, Parse}, |
@@ -229,102 +229,57 @@ fn init_fields( |
229 | 229 | } |
230 | 230 | }; |
231 | 231 |
|
232 | | - let init = match kind { |
233 | | - InitializerKind::Value { ident, value } => { |
234 | | - let mut value_ident = ident.clone(); |
235 | | - let value_prep = value.as_ref().map(|value| &value.1).map(|value| { |
236 | | - // Setting the span of `value_ident` to `value`'s span improves error messages |
237 | | - // when the type of `value` is wrong. |
238 | | - value_ident.set_span(value.span()); |
239 | | - quote!(let #value_ident = #value;) |
240 | | - }); |
241 | | - // Again span for better diagnostics |
242 | | - let write = quote_spanned!(ident.span()=> ::core::ptr::write); |
243 | | - quote! { |
244 | | - #(#attrs)* |
245 | | - { |
246 | | - #value_prep |
247 | | - // SAFETY: TODO |
248 | | - unsafe { #write(&raw mut (*#slot).#ident, #value_ident) }; |
249 | | - } |
250 | | - } |
251 | | - } |
252 | | - InitializerKind::Init { ident, value, .. } => { |
253 | | - // Again span for better diagnostics |
254 | | - let init = format_ident!("init", span = value.span()); |
255 | | - let value_init = if pinned { |
256 | | - quote! { |
257 | | - // SAFETY: |
258 | | - // - `slot` is valid, because we are inside of an initializer closure, we |
259 | | - // return when an error/panic occurs. |
260 | | - // - We also use `#data` to require the correct trait (`Init` or `PinInit`) |
261 | | - // for `#ident`. |
262 | | - unsafe { #data.#ident(&raw mut (*#slot).#ident, #init)? }; |
263 | | - } |
264 | | - } else { |
265 | | - quote! { |
266 | | - // SAFETY: `slot` is valid, because we are inside of an initializer |
267 | | - // closure, we return when an error/panic occurs. |
268 | | - unsafe { |
269 | | - ::pin_init::Init::__init( |
270 | | - #init, |
271 | | - &raw mut (*#slot).#ident, |
272 | | - )? |
273 | | - }; |
274 | | - } |
275 | | - }; |
276 | | - quote! { |
277 | | - #(#attrs)* |
278 | | - { |
279 | | - let #init = #value; |
280 | | - #value_init |
281 | | - } |
282 | | - } |
283 | | - } |
284 | | - InitializerKind::Code { .. } => unreachable!(), |
285 | | - }; |
286 | | - |
287 | | - // `mixed_site` ensures that the guard is not accessible to the user-controlled code. |
288 | | - let guard = format_ident!("__{ident}_guard", span = Span::mixed_site()); |
289 | | - |
290 | | - let guard_creation = if pinned { |
291 | | - let project_ident = format_ident!("__project_{ident}"); |
| 232 | + let slot = if pinned { |
292 | 233 | quote! { |
293 | 234 | // SAFETY: |
294 | 235 | // - `&raw mut (*slot).#ident` points to the `#ident` field of `slot`. |
295 | 236 | // - `&raw mut (*slot).#ident` is valid. |
296 | 237 | // - `make_field_check` checks that `&raw mut (*slot).#ident` is properly aligned. |
297 | | - // - `(*slot).#ident` has been initialized above. |
298 | | - // - We only need the ownership to the pointee back when initialization has |
299 | | - // succeeded, where we `forget` the guard. |
300 | | - unsafe { #data.#project_ident(&raw mut (*slot).#ident) } |
| 238 | + // - `make_field_check` prevents `#ident` from being used twice, therefore |
| 239 | + // `(*slot).#ident` is exclusively accessed and has not been initialized. |
| 240 | + (unsafe { #data.#ident(&raw mut (*#slot).#ident) }) |
301 | 241 | } |
302 | 242 | } else { |
303 | 243 | quote! { |
| 244 | + // For `init!()` macro, everything is unpinned. |
304 | 245 | // SAFETY: |
305 | 246 | // - `&raw mut (*slot).#ident` is valid. |
306 | 247 | // - `make_field_check` checks that `&raw mut (*slot).#ident` is properly aligned. |
307 | | - // - `(*slot).#ident` has been initialized above. |
308 | | - // - We only need the ownership to the pointee back when initialization has |
309 | | - // succeeded, where we `forget` the guard. |
310 | | - unsafe { |
311 | | - ::pin_init::__internal::DropGuard::<::pin_init::__internal::Unpinned, _>::new( |
312 | | - &raw mut (*slot).#ident |
313 | | - ) |
| 248 | + // - `make_field_check` prevents `#ident` from being used twice, therefore |
| 249 | + // `(*slot).#ident` is exclusively accessed and has not been initialized. |
| 250 | + (unsafe { ::pin_init::__internal::Slot::<::pin_init::__internal::Unpinned, _>::new(&raw mut (*#slot).#ident) }) |
| 251 | + } |
| 252 | + }; |
| 253 | + |
| 254 | + // `mixed_site` ensures that the guard is not accessible to the user-controlled code. |
| 255 | + let guard = format_ident!("__{ident}_guard", span = Span::mixed_site()); |
| 256 | + |
| 257 | + let init = match kind { |
| 258 | + InitializerKind::Value { ident, value } => { |
| 259 | + let value = value |
| 260 | + .as_ref() |
| 261 | + .map(|(_, value)| quote!(#value)) |
| 262 | + .unwrap_or_else(|| quote!(#ident)); |
| 263 | + |
| 264 | + quote! { |
| 265 | + #(#attrs)* |
| 266 | + let mut #guard = #slot.write(#value); |
| 267 | + |
314 | 268 | } |
315 | 269 | } |
| 270 | + InitializerKind::Init { value, .. } => { |
| 271 | + quote! { |
| 272 | + #(#attrs)* |
| 273 | + let mut #guard = #slot.init(#value)?; |
| 274 | + } |
| 275 | + } |
| 276 | + InitializerKind::Code { .. } => unreachable!(), |
316 | 277 | }; |
317 | 278 |
|
318 | 279 | res.extend(quote! { |
319 | 280 | #init |
320 | 281 |
|
321 | 282 | #(#cfgs)* |
322 | | - let mut #guard = #guard_creation; |
323 | | - |
324 | | - #(#cfgs)* |
325 | | - // NOTE: The reference is derived from the guard so that it only lives as long as the |
326 | | - // guard does and cannot escape the scope. If it's created via `&mut (*#slot).#ident` |
327 | | - // like the unaligned field guard, it will become effectively `'static`. |
328 | 283 | #[allow(unused_variables)] |
329 | 284 | let #ident = #guard.let_binding(); |
330 | 285 | }); |
|
0 commit comments