| // SPDX-License-Identifier: Apache-2.0 OR MIT | |
| use proc_macro2::TokenStream; | |
| use quote::quote; | |
| use syn::{parse::Nothing, parse_quote, spanned::Spanned, ImplItem, ItemImpl, Token}; | |
| use crate::diagnostics::{DiagCtxt, ErrorGuaranteed}; | |
| pub(crate) fn pinned_drop( | |
| _args: Nothing, | |
| mut input: ItemImpl, | |
| dcx: &mut DiagCtxt, | |
| ) -> Result<TokenStream, ErrorGuaranteed> { | |
| if let Some(unsafety) = input.unsafety { | |
| dcx.error(unsafety, "implementing `PinnedDrop` is safe"); | |
| } | |
| input.unsafety = Some(Token); | |
| match &mut input.trait_ { | |
| Some((not, path, _for)) => { | |
| if let Some(not) = not { | |
| dcx.error(not, "cannot implement `!PinnedDrop`"); | |
| } | |
| for (seg, expected) in path | |
| .segments | |
| .iter() | |
| .rev() | |
| .zip(["PinnedDrop", "pin_init", ""]) | |
| { | |
| if expected.is_empty() || seg.ident != expected { | |
| dcx.error(seg, "bad import path for `PinnedDrop`"); | |
| } | |
| if !seg.arguments.is_none() { | |
| dcx.error(&seg.arguments, "unexpected arguments for `PinnedDrop` path"); | |
| } | |
| } | |
| *path = parse_quote!(::pin_init::PinnedDrop); | |
| } | |
| None => { | |
| let span = input | |
| .impl_token | |
| .span | |
| .join(input.self_ty.span()) | |
| .unwrap_or(input.impl_token.span); | |
| dcx.error( | |
| span, | |
| "expected `impl ... PinnedDrop for ...`, got inherent impl", | |
| ); | |
| } | |
| } | |
| for item in &mut input.items { | |
| if let ImplItem::Fn(fn_item) = item { | |
| if fn_item.sig.ident == "drop" { | |
| fn_item | |
| .sig | |
| .inputs | |
| .push(parse_quote!(_: ::pin_init::__internal::OnlyCallFromDrop)); | |
| } | |
| } | |
| } | |
| Ok(quote!(#input)) | |
| } |