From patchwork Mon Apr 24 08:11:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benno Lossin X-Patchwork-Id: 86900 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2587727vqo; Mon, 24 Apr 2023 01:31:26 -0700 (PDT) X-Google-Smtp-Source: AKy350aoFfSN1EyN9KlNv5lVEgahw/hqRbdhDhj/Nc5DOhphOtgCLJkQneJuSkBtUbu3pj6s07A2 X-Received: by 2002:a17:903:890:b0:1a1:b3bb:cd5b with SMTP id kt16-20020a170903089000b001a1b3bbcd5bmr11475049plb.62.1682325086055; Mon, 24 Apr 2023 01:31:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1682325086; cv=none; d=google.com; s=arc-20160816; b=mrDUiRzpjh1lEtpG70vuHm/c+8o/fvG8lgemIxB8lDt9mOYFCFVCziPPB2YSJmcS58 9uDeJ4BlZok+EK1Chzy8RVsW8dTMkx14BKrjh3NmsepLwKm6GTeuFP8jjBd/yE8D4jXS V0k44Ju8uSHfvBB5NqV8qjoX4sqlHmYum7fCYFirv293zOYPWCk0J7TXdQjrc7/6K46T xwYoJIpG0DSbs2oq5LWBm9yGljKNBAOpvMUZcxLFO9wI/9zJ13o4QuGMjyhtdEExQ6XY rgGqoJoMVzVpg8WB8AJjCYW6/leTFvjvaPxAYFYB+lWFEYgX7tX0GqK3USdEh9XcZv/H B8Rg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :feedback-id:message-id:subject:cc:from:to:dkim-signature:date; bh=9tXLJw7aS2XfS2d3gc4JfQ1c+axPiaqoVKfXWCkw42E=; b=L6jaUCUKBfGOGQaoJlbso+fvmTRMUi9NhgROKHw8gR0OMUIVKazUaLCTjCcru1NuMA tmakOQplub/nW83kca5GpFn6LsptRbVAETOgN4IQ2OJfVBGTmiQxH61W39/62TRkSKcz UJxW3CJJZXmVFf/MGRzRoIur8iwH/OAG8oUVDX2QYYG+9LQhSP8SAnYi1WAX3fL8cmBJ qMmbZy3/gMvP9XRFoqPb/wclr2KMc5aY8IyME2AHCqfE3JNSljC72ChmaCe1r1TlY5RQ ph/Gi1sjSsaWjqiOa2mLE6MkUG1Z7oSk2kepvecgXh02GnSl1MyOTENtm04LP/hAZ2/E hXUQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@proton.me header.s=protonmail header.b=bf4SNBhM; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=proton.me Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id u9-20020a170903124900b001a979141a25si1950882plh.243.2023.04.24.01.31.08; Mon, 24 Apr 2023 01:31:26 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@proton.me header.s=protonmail header.b=bf4SNBhM; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=proton.me Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231564AbjDXIL7 (ORCPT + 99 others); Mon, 24 Apr 2023 04:11:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49530 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231551AbjDXILs (ORCPT ); Mon, 24 Apr 2023 04:11:48 -0400 Received: from mail-0301.mail-europe.com (mail-0301.mail-europe.com [188.165.51.139]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 38FA910E7; Mon, 24 Apr 2023 01:11:47 -0700 (PDT) Date: Mon, 24 Apr 2023 08:11:33 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proton.me; s=protonmail; t=1682323903; x=1682583103; bh=9tXLJw7aS2XfS2d3gc4JfQ1c+axPiaqoVKfXWCkw42E=; h=Date:To:From:Cc:Subject:Message-ID:Feedback-ID:From:To:Cc:Date: Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=bf4SNBhMwTguIdAncVzh5qLxV1ZYWi5GolZ7vhl4PHQALjDS4AaYfZPVsJxi3p4Xy J9c0TDW7wOHdvqGNedNTQfjXceAGYPKLW05jU0wRyPNiFDDJW5uDo1eVsOUag1aqkj dzDynwvOS/V1XjvKh9Wvz/1PjZksRH24dtFWDY1KvqhbNtAisuGuzEmhYvZrqCA53v 59BuMDz2nIa3f41puY8UTwzFHvaMTBrIHbfP4W6q71ha+k477z6NSu9tcTXK3Uie0C h8JsTD9qERL7wpGzDU7nSSHk8//0sM7gDHTiWgE4CT+VN4lF6+yTEj158C8QFJO6J1 fu/YtqWt9PCBw== To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= From: Benno Lossin Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, patches@lists.linux.dev, Benno Lossin Subject: [PATCH 1/4] rust: macros: fix usage of `#[allow]` in `quote!` Message-ID: <20230424081112.99890-1-benno.lossin@proton.me> Feedback-ID: 71780778:user:proton MIME-Version: 1.0 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1764045709586048138?= X-GMAIL-MSGID: =?utf-8?q?1764045709586048138?= When using `quote!` as part of an expression that was not the last one in a function, the `#[allow(clippy::vec_init_then_push)]` attribute would be present on an expression, which is not allowed. This patch refactors that part of the macro to use a statement instead. Signed-off-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Alice Ryhl Reviewed-by: Gary Guo --- rust/macros/quote.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) base-commit: ea76e08f4d901a450619831a255e9e0a4c0ed162 -- 2.40.0 diff --git a/rust/macros/quote.rs b/rust/macros/quote.rs index c8e08b3c1e4c..dddbb4e6f4cb 100644 --- a/rust/macros/quote.rs +++ b/rust/macros/quote.rs @@ -39,12 +39,14 @@ impl ToTokens for TokenStream { /// [`quote_spanned!`](https://docs.rs/quote/latest/quote/macro.quote_spanned.html) macro from the /// `quote` crate but provides only just enough functionality needed by the current `macros` crate. macro_rules! quote_spanned { - ($span:expr => $($tt:tt)*) => { - #[allow(clippy::vec_init_then_push)] - { - let mut tokens = ::std::vec::Vec::new(); - let span = $span; - quote_spanned!(@proc tokens span $($tt)*); + ($span:expr => $($tt:tt)*) => {{ + let mut tokens; + #[allow(clippy::vec_init_then_push)] + { + tokens = ::std::vec::Vec::new(); + let span = $span; + quote_spanned!(@proc tokens span $($tt)*); + } ::proc_macro::TokenStream::from_iter(tokens) }}; (@proc $v:ident $span:ident) => {}; From patchwork Mon Apr 24 08:11:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benno Lossin X-Patchwork-Id: 86902 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2588844vqo; Mon, 24 Apr 2023 01:33:58 -0700 (PDT) X-Google-Smtp-Source: AKy350a70lDvTsFSoNpdl4NBPSJmj2oe4zu2SeB8fqOTBJ8or/NviYAzndYIzmOdq42LCoSz6Ib3 X-Received: by 2002:a05:6a20:7491:b0:f5:ae09:ce02 with SMTP id p17-20020a056a20749100b000f5ae09ce02mr1009789pzd.18.1682325237836; Mon, 24 Apr 2023 01:33:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1682325237; cv=none; d=google.com; s=arc-20160816; b=hguZdvzHlSEsq6XzUmo6TFWaqh1wJ7U7u0DDBSQBYgTcztHjMsWK8VZEcjl84RgeLU LRyz9peYoBJV3x2zzE9vOrD8hTwA8TgqICSHlDHQkDs1gZVQbIPb1u38JvNU/qejPtvn umP+YzmVVypJeTG5D4TF5WwRI4z1ksZfF5NW2j0K+TySlBhkqn5fxhjgipanjqj5QBwA QQVPe9cYLbTbJSMQNui5tTbPbM6Vm/uE7qIYCCUj0IJp1qHaka37nOglwJrfjGiD23l3 rdV1IHXR8/Q/YJYRKIgSZDABmNGi8YSjDykQcAM2i0kjEjy4+sUxMH5fMOMfY6MaMeWc 4hzQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :feedback-id:references:in-reply-to:message-id:subject:cc:from:to :dkim-signature:date; bh=RUNMyd4H4XD6TO4X8sc2wnYhEAx+HVkNXO8MNMYE5N8=; b=k3xO7A2EjknVvz/CEBMo46ABsbHhfXVU8VUQZeL8eJ3h+QrxlS96AzfubYyzYFZWeH zrPaKSjYCbzJZpWzcVxVUVKD1s9R8BPxvjM8qBNaP6kDFyIyKbKiugFnUnSrZo4S/v54 q7SamLqGJJ3qLpDxgxUXZXxrh2xCb911yTXIXnp4ixd8KXirB5dM2SbhpyNKNeOJ0QOi UEVvdC1cZa7nomRhJZtZy9VRusrPrVnTFrYuuqFpD4LaARPZFo+8fTJsT0gxxvnI+Vak //J2lVBpb3ul2ZNyXBHVaT0H8Ad8i8bE60QYR6QrEQYTs+NgjII1U5I9kux2yCV4actM JoLQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@proton.me header.s=protonmail header.b=Q62kl+6T; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=proton.me Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id r20-20020a6560d4000000b00524b0097b6csi10287365pgv.816.2023.04.24.01.33.46; Mon, 24 Apr 2023 01:33:57 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@proton.me header.s=protonmail header.b=Q62kl+6T; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=proton.me Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231574AbjDXIL5 (ORCPT + 99 others); Mon, 24 Apr 2023 04:11:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49532 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231550AbjDXILs (ORCPT ); Mon, 24 Apr 2023 04:11:48 -0400 Received: from mail-40131.protonmail.ch (mail-40131.protonmail.ch [185.70.40.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7CD04E58; Mon, 24 Apr 2023 01:11:45 -0700 (PDT) Date: Mon, 24 Apr 2023 08:11:38 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proton.me; s=protonmail; t=1682323903; x=1682583103; bh=RUNMyd4H4XD6TO4X8sc2wnYhEAx+HVkNXO8MNMYE5N8=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=Q62kl+6TuKHTrT+CMX/qBxhc7l80lq1xvUnqqeAJLDaR56S1C1rKHaKRs7oAEU8iA jU7ek97cmOruPkIYkPNyxVGjFshqBnwqhE/l/MMBvCPqjFra20lV5vlrVz1KbSlSsk Eo9uZmHoagw7g9q7tF768d/OB0N8khZ4zsK7omdd1tJNFym5LUuld+PWX9f4X/jCjq b39K9dw5o3uJplQPD2udnLf7cCcMX+c2Ro/ltxGySqM6F+MTRXsjqjLtkGIv2JHLbA XBF54msZfql8B4iFkuFau8m6wNTyzokrWpunuVgQXDrIfQ+AewfsxI/Hqy9VvNRoqx asVt3nwX5BjMA== To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= From: Benno Lossin Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, patches@lists.linux.dev, Benno Lossin Subject: [PATCH 2/4] rust: macros: refactor generics parsing of `#[pin_data]` into its own function Message-ID: <20230424081112.99890-2-benno.lossin@proton.me> In-Reply-To: <20230424081112.99890-1-benno.lossin@proton.me> References: <20230424081112.99890-1-benno.lossin@proton.me> Feedback-ID: 71780778:user:proton MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1764045868955340708?= X-GMAIL-MSGID: =?utf-8?q?1764045868955340708?= Other macros might also want to parse generics. Additionally this makes the code easier to read, as the next commit will introduce more code in `#[pin_data]`. Also add more comments to explain how parsing generics work. Signed-off-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Alice Ryhl Reviewed-by: Gary Guo --- rust/macros/helpers.rs | 86 ++++++++++++++++++++++++++++++++++++++++- rust/macros/pin_data.rs | 70 +++++---------------------------- 2 files changed, 94 insertions(+), 62 deletions(-) -- 2.40.0 diff --git a/rust/macros/helpers.rs b/rust/macros/helpers.rs index b2bdd4d8c958..afb0f2e3a36a 100644 --- a/rust/macros/helpers.rs +++ b/rust/macros/helpers.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 -use proc_macro::{token_stream, Group, TokenTree}; +use proc_macro::{token_stream, Group, Punct, Spacing, TokenStream, TokenTree}; pub(crate) fn try_ident(it: &mut token_stream::IntoIter) -> Option { if let Some(TokenTree::Ident(ident)) = it.next() { @@ -69,3 +69,87 @@ pub(crate) fn expect_end(it: &mut token_stream::IntoIter) { panic!("Expected end"); } } + +pub(crate) struct Generics { + pub(crate) impl_generics: Vec, + pub(crate) ty_generics: Vec, +} + +/// Parses the given `TokenStream` into `Generics` and the rest. +/// +/// The generics are not present in the rest, but a where clause might remain. +pub(crate) fn parse_generics(input: TokenStream) -> (Generics, Vec) { + // `impl_generics`, the declared generics with their bounds. + let mut impl_generics = vec![]; + // Only the names of the generics, without any bounds. + let mut ty_generics = vec![]; + // Tokens not related to the generics e.g. the `where` token and definition. + let mut rest = vec![]; + // The current level of `<`. + let mut nesting = 0; + let mut toks = input.into_iter(); + // If we are at the beginning of a generic parameter. + let mut at_start = true; + for tt in &mut toks { + match tt.clone() { + TokenTree::Punct(p) if p.as_char() == '<' => { + if nesting >= 1 { + // This is inside of the generics and part of some bound. + impl_generics.push(tt); + } + nesting += 1; + } + TokenTree::Punct(p) if p.as_char() == '>' => { + // This is a parsing error, so we just end it here. + if nesting == 0 { + break; + } else { + nesting -= 1; + if nesting >= 1 { + // We are still inside of the generics and part of some bound. + impl_generics.push(tt); + } + if nesting == 0 { + break; + } + } + } + tt => { + if nesting == 1 { + // Here depending on the token, it might be a generic variable name. + match &tt { + // Ignore const. + TokenTree::Ident(i) if i.to_string() == "const" => {} + TokenTree::Ident(_) if at_start => { + ty_generics.push(tt.clone()); + // We also already push the `,` token, this makes it easier to append + // generics. + ty_generics.push(TokenTree::Punct(Punct::new(',', Spacing::Alone))); + at_start = false; + } + TokenTree::Punct(p) if p.as_char() == ',' => at_start = true, + // Lifetimes begin with `'`. + TokenTree::Punct(p) if p.as_char() == '\'' && at_start => { + ty_generics.push(tt.clone()); + } + _ => {} + } + } + if nesting >= 1 { + impl_generics.push(tt); + } else if nesting == 0 { + // If we haven't entered the generics yet, we still want to keep these tokens. + rest.push(tt); + } + } + } + } + rest.extend(toks); + ( + Generics { + impl_generics, + ty_generics, + }, + rest, + ) +} diff --git a/rust/macros/pin_data.rs b/rust/macros/pin_data.rs index 954149d77181..c593b05d9e8c 100644 --- a/rust/macros/pin_data.rs +++ b/rust/macros/pin_data.rs @@ -1,71 +1,19 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT -use proc_macro::{Punct, Spacing, TokenStream, TokenTree}; +use crate::helpers::{parse_generics, Generics}; +use proc_macro::TokenStream; pub(crate) fn pin_data(args: TokenStream, input: TokenStream) -> TokenStream { // This proc-macro only does some pre-parsing and then delegates the actual parsing to // `kernel::__pin_data!`. - // - // In here we only collect the generics, since parsing them in declarative macros is very - // elaborate. We also do not need to analyse their structure, we only need to collect them. - // `impl_generics`, the declared generics with their bounds. - let mut impl_generics = vec![]; - // Only the names of the generics, without any bounds. - let mut ty_generics = vec![]; - // Tokens not related to the generics e.g. the `impl` token. - let mut rest = vec![]; - // The current level of `<`. - let mut nesting = 0; - let mut toks = input.into_iter(); - // If we are at the beginning of a generic parameter. - let mut at_start = true; - for tt in &mut toks { - match tt.clone() { - TokenTree::Punct(p) if p.as_char() == '<' => { - if nesting >= 1 { - impl_generics.push(tt); - } - nesting += 1; - } - TokenTree::Punct(p) if p.as_char() == '>' => { - if nesting == 0 { - break; - } else { - nesting -= 1; - if nesting >= 1 { - impl_generics.push(tt); - } - if nesting == 0 { - break; - } - } - } - tt => { - if nesting == 1 { - match &tt { - TokenTree::Ident(i) if i.to_string() == "const" => {} - TokenTree::Ident(_) if at_start => { - ty_generics.push(tt.clone()); - ty_generics.push(TokenTree::Punct(Punct::new(',', Spacing::Alone))); - at_start = false; - } - TokenTree::Punct(p) if p.as_char() == ',' => at_start = true, - TokenTree::Punct(p) if p.as_char() == '\'' && at_start => { - ty_generics.push(tt.clone()); - } - _ => {} - } - } - if nesting >= 1 { - impl_generics.push(tt); - } else if nesting == 0 { - rest.push(tt); - } - } - } - } - rest.extend(toks); + let ( + Generics { + impl_generics, + ty_generics, + }, + mut rest, + ) = parse_generics(input); // This should be the body of the struct `{...}`. let last = rest.pop(); quote!(::kernel::__pin_data! { From patchwork Mon Apr 24 08:11:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benno Lossin X-Patchwork-Id: 86904 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2595538vqo; Mon, 24 Apr 2023 01:50:55 -0700 (PDT) X-Google-Smtp-Source: AKy350Z1o2C/fSTIBnPhDP+iRkRtBvbhW8S8ZGI+urpxKGbInZhXQHHVH0imeN0etWyhCg1eN5Ho X-Received: by 2002:a17:903:2309:b0:1a1:ee8c:eef5 with SMTP id d9-20020a170903230900b001a1ee8ceef5mr16527623plh.7.1682326255251; Mon, 24 Apr 2023 01:50:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1682326255; cv=none; d=google.com; s=arc-20160816; b=fp+9X5m14bt6OTLYYVUPTOuSmbOSl1TkWLeyKRGq81rDA2x/d/4vOyNsLLVxRwukCM r25Vm3GWR7aCwzX3uXUvC4INMmpDOxKo0rUk4AGY1nTBo/MU+hulX7aLgMuhs5Iu2E+8 47GhO+dThqPJBlZa+UNRONHc8shu+6RPk4Fq7CIbao1ymnVPq8op7FIL6eG664yHs+Am rM9gK5Av9n6KX/x6VhlhrKu3ZCuEXQrwgSKMwjCdW33wnFhV1aqHwRvEmsHegNVHO+0z K6Eo3gRGXg56UouP4jIjSx2WNv9xH+KxoQ7Tz4GGX7wUvb0QhrULrYc9wyjsm25yX/1s 2/cw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :feedback-id:references:in-reply-to:message-id:subject:cc:from:to :dkim-signature:date; bh=xsbkQLlU/8z2bpso9Wuc5fgrVJCsTlQwnkd8h5OEwvU=; b=jgeeKuG/U5iz6Pzn52VawDNJc1g5kPdWvX2Ba3L834onsftOl62WdwNHEM09lOImBm O0+oFSkh675pVUQM7SJDhDbojh3cAF4MVfQPkstxkEqqgAWf8LDUfv6S7XNiT4sntPpr QzVc7/bw9YNAaJQe2P9p4kgpg7WGJCGLonYiDQrV/aZzc4j0eFjUFZ7NjyIVjXTTZmIP a2ZR33+3dpYOAFpY0a9TyJ44KvUzX98P89dA8b0OgOwL+QGwUTjEL+62mXQIvGRqQ89q TtL2hg+URRBvtXQwzOnWiwxEzl2EmlthtliM4A/WIn27WpSbRFK1y1iDHWl2mx9TJbxg 7T4A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@proton.me header.s=protonmail header.b=kqFIpKXH; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=proton.me Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id c10-20020a170902d48a00b001a81e552dc7si11360812plg.637.2023.04.24.01.50.40; Mon, 24 Apr 2023 01:50:55 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@proton.me header.s=protonmail header.b=kqFIpKXH; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=proton.me Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231600AbjDXIML (ORCPT + 99 others); Mon, 24 Apr 2023 04:12:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49948 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231572AbjDXIMF (ORCPT ); Mon, 24 Apr 2023 04:12:05 -0400 Received: from mail-4316.protonmail.ch (mail-4316.protonmail.ch [185.70.43.16]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 167A71733 for ; Mon, 24 Apr 2023 01:11:57 -0700 (PDT) Date: Mon, 24 Apr 2023 08:11:43 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proton.me; s=protonmail; t=1682323916; x=1682583116; bh=xsbkQLlU/8z2bpso9Wuc5fgrVJCsTlQwnkd8h5OEwvU=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=kqFIpKXHsXe4ce/a6ZebDqdoMZtkzYCsVdVV/oVVFk9qV/N8DvQP7fcO6BJDb/5xd rE7h4WP7hnTkSOzFte4OMLFvaqIJkaJxiKdG4N5nw4aDMMBB0DrmYGaXFqG1N50UJR XnYrRYSG/cdD0YtH/21BZj3Qcou4nRjSWQocJ0NWMCMd4QC+RAKB8dbm+9+Iu9gUdL nl4JTBvGUuCys0ordxlD0m/dxla8zNLDMSuQgl8zcE1h9o85Tna0W/I4Tv8wpF8a2t lfypQCpWvRd72Bf7pfQVrpoSDlsvYSsbpKY9+HFTlh3j9rEr2W6649rQUxwaJAzlZn O8esjaT61K8eQ== To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= From: Benno Lossin Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, patches@lists.linux.dev, Benno Lossin , Alice Ryhl Subject: [PATCH 3/4] rust: macros: replace Self with the concrete type in #[pin_data] Message-ID: <20230424081112.99890-3-benno.lossin@proton.me> In-Reply-To: <20230424081112.99890-1-benno.lossin@proton.me> References: <20230424081112.99890-1-benno.lossin@proton.me> Feedback-ID: 71780778:user:proton MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1764046935552650148?= X-GMAIL-MSGID: =?utf-8?q?1764046935552650148?= When using `#[pin_data]` on a struct that used `Self` in the field types, a type error would be emitted when trying to use `pin_init!`. Since an internal type would be referenced by `Self` instead of the defined struct. This patch fixes this issue by replacing all occurrences of `Self` in the `#[pin_data]` macro with the concrete type circumventing the issue. Since rust allows type definitions inside of blocks, which are expressions, the macro also checks for these and emits a compile error when it finds `trait`, `enum`, `union`, `struct` or `impl`. These keywords allow creating new `Self` contexts, which conflicts with the current implementation of replacing every `Self` ident. If these were allowed, some `Self` idents would be replaced incorrectly. Signed-off-by: Benno Lossin Reported-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Alice Ryhl Reviewed-by: Gary Guo --- rust/macros/pin_data.rs | 108 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 4 deletions(-) -- 2.40.0 diff --git a/rust/macros/pin_data.rs b/rust/macros/pin_data.rs index c593b05d9e8c..6d58cfda9872 100644 --- a/rust/macros/pin_data.rs +++ b/rust/macros/pin_data.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT use crate::helpers::{parse_generics, Generics}; -use proc_macro::TokenStream; +use proc_macro::{Group, Punct, Spacing, TokenStream, TokenTree}; pub(crate) fn pin_data(args: TokenStream, input: TokenStream) -> TokenStream { // This proc-macro only does some pre-parsing and then delegates the actual parsing to @@ -12,16 +12,116 @@ pub(crate) fn pin_data(args: TokenStream, input: TokenStream) -> TokenStream { impl_generics, ty_generics, }, - mut rest, + rest, ) = parse_generics(input); + // The struct definition might contain the `Self` type. Since `__pin_data!` will define a new + // type with the same generics and bounds, this poses a problem, since `Self` will refer to the + // new type as opposed to this struct definition. Therefore we have to replace `Self` with the + // concrete name. + + // Errors that occur when replacing `Self` with `struct_name`. + let mut errs = TokenStream::new(); + // The name of the struct with ty_generics. + let struct_name = rest + .iter() + .skip_while(|tt| !matches!(tt, TokenTree::Ident(i) if i.to_string() == "struct")) + .nth(1) + .and_then(|tt| match tt { + TokenTree::Ident(_) => { + let tt = tt.clone(); + let mut res = vec![tt]; + if !ty_generics.is_empty() { + // We add this, so it is maximally compatible with e.g. `Self::CONST` which + // will be replaced by `StructName::<$generics>::CONST`. + res.push(TokenTree::Punct(Punct::new(':', Spacing::Joint))); + res.push(TokenTree::Punct(Punct::new(':', Spacing::Alone))); + res.push(TokenTree::Punct(Punct::new('<', Spacing::Alone))); + res.extend(ty_generics.iter().cloned()); + res.push(TokenTree::Punct(Punct::new('>', Spacing::Alone))); + } + Some(res) + } + _ => None, + }) + .unwrap_or_else(|| { + // If we did not find the name of the struct then we will use `Self` as the replacement + // and add a compile error to ensure it does not compile. + errs.extend( + "::core::compile_error!(\"Could not locate type name.\");" + .parse::() + .unwrap(), + ); + "Self".parse::().unwrap().into_iter().collect() + }); + let impl_generics = impl_generics + .into_iter() + .flat_map(|tt| replace_self_and_deny_type_defs(&struct_name, tt, &mut errs)) + .collect::>(); + let mut rest = rest + .into_iter() + .flat_map(|tt| { + // We ignore top level `struct` tokens, since they would emit a compile error. + if matches!(&tt, TokenTree::Ident(i) if i.to_string() == "struct") { + vec![tt] + } else { + replace_self_and_deny_type_defs(&struct_name, tt, &mut errs) + } + }) + .collect::>(); // This should be the body of the struct `{...}`. let last = rest.pop(); - quote!(::kernel::__pin_data! { + let mut quoted = quote!(::kernel::__pin_data! { parse_input: @args(#args), @sig(#(#rest)*), @impl_generics(#(#impl_generics)*), @ty_generics(#(#ty_generics)*), @body(#last), - }) + }); + quoted.extend(errs); + quoted +} + +/// Replaces `Self` with `struct_name` and errors on `enum`, `trait`, `struct` `union` and `impl` +/// keywords. +/// +/// The error is appended to `errs` to allow normal parsing to continue. +fn replace_self_and_deny_type_defs( + struct_name: &Vec, + tt: TokenTree, + errs: &mut TokenStream, +) -> Vec { + match tt { + TokenTree::Ident(ref i) + if i.to_string() == "enum" + || i.to_string() == "trait" + || i.to_string() == "struct" + || i.to_string() == "union" + || i.to_string() == "impl" => + { + errs.extend( + format!( + "::core::compile_error!(\"Cannot use `{i}` inside of struct definition with \ + `#[pin_data]`.\");" + ) + .parse::() + .unwrap() + .into_iter() + .map(|mut tok| { + tok.set_span(tt.span()); + tok + }), + ); + vec![tt] + } + TokenTree::Ident(i) if i.to_string() == "Self" => struct_name.clone(), + TokenTree::Literal(_) | TokenTree::Punct(_) | TokenTree::Ident(_) => vec![tt], + TokenTree::Group(g) => vec![TokenTree::Group(Group::new( + g.delimiter(), + g.stream() + .into_iter() + .flat_map(|tt| replace_self_and_deny_type_defs(struct_name, tt, errs)) + .collect(), + ))], + } } From patchwork Mon Apr 24 08:11:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benno Lossin X-Patchwork-Id: 86898 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2587349vqo; Mon, 24 Apr 2023 01:30:35 -0700 (PDT) X-Google-Smtp-Source: AKy350YG2NFExUa7+ZAYuzTHjYuS30zyWH5imnP9CaLvcVtfhHMLqmNe7eZ+H7F27JCSFbwzhqgl X-Received: by 2002:a05:6a20:3ca4:b0:f0:a92a:5088 with SMTP id b36-20020a056a203ca400b000f0a92a5088mr16853412pzj.44.1682325035548; Mon, 24 Apr 2023 01:30:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1682325035; cv=none; d=google.com; s=arc-20160816; b=O0UZIMb0NpqN0oocReEDTfm9T5sOJIT9K4G+l34xauAza09iGWz9dwOWg+c71xO7gL ObaMqugEqDUqk3zdIk7zTyaBcKRNeFF27ImkMCLOkvW9XazkP13mgwJ4TYgoN7hRxFWD YAoFHUZA8zjoEnZ6FBNKXgBgP/6ViXtbWRov4d5Stldv4CeC7XPXRrtOyZ4n1FWaiEKj fO5vXfFQEwtDbV1IPvsqetOiyrs28YL6ZKFnuBpQIlEuWttcZAfyaIc/ViRw1/+vPuOJ a2XDWnhXTi31LA4/q05Vnj0cKM98qqNR5fcFQDjw3rxNHsNRp06MURYsDiU05EohA2tk rzUA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :feedback-id:references:in-reply-to:message-id:subject:cc:from:to :dkim-signature:date; bh=jlSr6JF5Fnj5YiX5jFHLOW1OnwcKWvvXtJXoTFNi8uY=; b=g7lJdgOwrS8TP/OP+k3ciWnoPXnYDTC60h9g/iWhvkCOSBT15WuP1Yv0UwriHnA0dm iV0jmffqYICWiFxxr/ps0VPs7arTUlcTIJE9CAcnWW1reZWjEOTHLLR1M501r59vQvcu t1Q9xguo1oXNJNQtHwIKDtHqSAKxJXqwBYM+I/RquQhmO1FDZHMNeEzdrZPbPLJjMH+5 TXw5l0eJ0nrh/Kese14vhsmNXbuSDDJOvuP/VvQpe5IkPaVPRJn7swtOWglJ+We3p8iM yk2s1XoBsfDJKpM0YgZCwX9VTVcBn6dZlNPSpGG1g9mNlrObxem8I0FHvkDfLZgNIEiF flSw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@proton.me header.s=protonmail header.b=Hd+UjMji; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=proton.me Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id r20-20020a6560d4000000b00524b0097b6csi10287365pgv.816.2023.04.24.01.30.23; Mon, 24 Apr 2023 01:30:35 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@proton.me header.s=protonmail header.b=Hd+UjMji; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=proton.me Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231593AbjDXIMN (ORCPT + 99 others); Mon, 24 Apr 2023 04:12:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49648 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231592AbjDXIMF (ORCPT ); Mon, 24 Apr 2023 04:12:05 -0400 Received: from mail-40131.protonmail.ch (mail-40131.protonmail.ch [185.70.40.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 173BF1737; Mon, 24 Apr 2023 01:11:58 -0700 (PDT) Date: Mon, 24 Apr 2023 08:11:49 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proton.me; s=protonmail; t=1682323916; x=1682583116; bh=jlSr6JF5Fnj5YiX5jFHLOW1OnwcKWvvXtJXoTFNi8uY=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=Hd+UjMji73bffnr1Vd7qGnI0gYyHhvDR3/n45+Gfw58wgqIOFOcGSMuwpRKgQeth/ DmKuJXL0rbWpKlI5BZh+Wmc9HGvIEBHiPhkGeMZ6hSJ/P4RYnhZyEhpdjObeOmSuP2 rUTZQ3wDumN7rDJU02zlQQ4HbPIhyufzCQXn3IsbtPml+McirbW83ClpdrVN67CZYw RfrnQZzA56YgWDuArvzsrIyen+m7u4/utiV7flzHkux9KJWX24TdoUUgoCKggFMEyv 7ayrFBpY0kNbTPx50ai59tgOXcfUZteWa/v5Y4GXzsMt9l0J/+5N+kJd8cVk6kU8qg aHiIK774RJgBw== To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= From: Benno Lossin Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, patches@lists.linux.dev, Benno Lossin Subject: [PATCH 4/4] rust: init: update macro expansion example in docs Message-ID: <20230424081112.99890-4-benno.lossin@proton.me> In-Reply-To: <20230424081112.99890-1-benno.lossin@proton.me> References: <20230424081112.99890-1-benno.lossin@proton.me> Feedback-ID: 71780778:user:proton MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1764045656483172104?= X-GMAIL-MSGID: =?utf-8?q?1764045656483172104?= Also improve the explaining comments. Signed-off-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Alice Ryhl Reviewed-by: Gary Guo --- rust/kernel/init/macros.rs | 85 +++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 37 deletions(-) -- 2.40.0 diff --git a/rust/kernel/init/macros.rs b/rust/kernel/init/macros.rs index 541cfad1d8be..00aa4e956c0a 100644 --- a/rust/kernel/init/macros.rs +++ b/rust/kernel/init/macros.rs @@ -16,8 +16,9 @@ //! //! We will look at the following example: //! -//! ```rust +//! ```rust,ignore //! # use kernel::init::*; +//! # use core::pin::Pin; //! #[pin_data] //! #[repr(C)] //! struct Bar { @@ -71,11 +72,12 @@ //! //! Here is the definition of `Bar` from our example: //! -//! ```rust +//! ```rust,ignore //! # use kernel::init::*; //! #[pin_data] //! #[repr(C)] //! struct Bar { +//! #[pin] //! t: T, //! pub x: usize, //! } @@ -83,7 +85,7 @@ //! //! This expands to the following code: //! -//! ```rust +//! ```rust,ignore //! // Firstly the normal definition of the struct, attributes are preserved: //! #[repr(C)] //! struct Bar { @@ -116,20 +118,22 @@ //! unsafe fn t( //! self, //! slot: *mut T, -//! init: impl ::kernel::init::Init, +//! // Since `t` is `#[pin]`, this is `PinInit`. +//! init: impl ::kernel::init::PinInit, //! ) -> ::core::result::Result<(), E> { -//! unsafe { ::kernel::init::Init::__init(init, slot) } +//! unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) } //! } //! pub unsafe fn x( //! self, //! slot: *mut usize, +//! // Since `x` is not `#[pin]`, this is `Init`. //! init: impl ::kernel::init::Init, //! ) -> ::core::result::Result<(), E> { //! unsafe { ::kernel::init::Init::__init(init, slot) } //! } //! } //! // Implement the internal `HasPinData` trait that associates `Bar` with the pin-data struct -//! // that we constructed beforehand. +//! // that we constructed above. //! unsafe impl ::kernel::init::__internal::HasPinData for Bar { //! type PinData = __ThePinData; //! unsafe fn __pin_data() -> Self::PinData { @@ -160,6 +164,8 @@ //! struct __Unpin<'__pin, T> { //! __phantom_pin: ::core::marker::PhantomData &'__pin ()>, //! __phantom: ::core::marker::PhantomData) -> Bar>, +//! // Our only `#[pin]` field is `t`. +//! t: T, //! } //! #[doc(hidden)] //! impl<'__pin, T> @@ -193,7 +199,7 @@ //! //! Here is the impl on `Bar` defining the new function: //! -//! ```rust +//! ```rust,ignore //! impl Bar { //! fn new(t: T) -> impl PinInit { //! pin_init!(Self { t, x: 0 }) @@ -203,7 +209,7 @@ //! //! This expands to the following code: //! -//! ```rust +//! ```rust,ignore //! impl Bar { //! fn new(t: T) -> impl PinInit { //! { @@ -232,25 +238,31 @@ //! // that will refer to this struct instead of the one defined above. //! struct __InitOk; //! // This is the expansion of `t,`, which is syntactic sugar for `t: t,`. -//! unsafe { ::core::ptr::write(&raw mut (*slot).t, t) }; +//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).t), t) }; //! // Since initialization could fail later (not in this case, since the error -//! // type is `Infallible`) we will need to drop this field if it fails. This -//! // `DropGuard` will drop the field when it gets dropped and has not yet -//! // been forgotten. We make a reference to it, so users cannot `mem::forget` -//! // it from the initializer, since the name is the same as the field. +//! // type is `Infallible`) we will need to drop this field if there is an +//! // error later. This `DropGuard` will drop the field when it gets dropped +//! // and has not yet been forgotten. We make a reference to it, so users +//! // cannot `mem::forget` it from the initializer, since the name is the same +//! // as the field (including hygiene). //! let t = &unsafe { -//! ::kernel::init::__internal::DropGuard::new(&raw mut (*slot).t) +//! ::kernel::init::__internal::DropGuard::new( +//! ::core::addr_of_mut!((*slot).t), +//! ) //! }; //! // Expansion of `x: 0,`: //! // Since this can be an arbitrary expression we cannot place it inside of //! // the `unsafe` block, so we bind it here. //! let x = 0; -//! unsafe { ::core::ptr::write(&raw mut (*slot).x, x) }; +//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) }; +//! // We again create a `DropGuard`. //! let x = &unsafe { -//! ::kernel::init::__internal::DropGuard::new(&raw mut (*slot).x) +//! ::kernel::init::__internal::DropGuard::new( +//! ::core::addr_of_mut!((*slot).x), +//! ) //! }; //! -//! // Here we use the type checker to ensuer that every field has been +//! // Here we use the type checker to ensure that every field has been //! // initialized exactly once, since this is `if false` it will never get //! // executed, but still type-checked. //! // Additionally we abuse `slot` to automatically infer the correct type for @@ -272,7 +284,7 @@ //! }; //! } //! // Since initialization has successfully completed, we can now forget the -//! // guards. +//! // guards. This is not `mem::forget`, since we only have `&DropGuard`. //! unsafe { ::kernel::init::__internal::DropGuard::forget(t) }; //! unsafe { ::kernel::init::__internal::DropGuard::forget(x) }; //! } @@ -280,7 +292,7 @@ //! // `__InitOk` that we need to return. //! Ok(__InitOk) //! }); -//! // Change the return type of the closure. +//! // Change the return type from `__InitOk` to `()`. //! let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> { //! init(slot).map(|__InitOk| ()) //! }; @@ -299,7 +311,7 @@ //! Since we already took a look at `#[pin_data]` on `Bar`, this section will only explain the //! differences/new things in the expansion of the `Foo` definition: //! -//! ```rust +//! ```rust,ignore //! #[pin_data(PinnedDrop)] //! struct Foo { //! a: usize, @@ -310,7 +322,7 @@ //! //! This expands to the following code: //! -//! ```rust +//! ```rust,ignore //! struct Foo { //! a: usize, //! b: Bar, @@ -330,8 +342,6 @@ //! unsafe fn b( //! self, //! slot: *mut Bar, -//! // Note that this is `PinInit` instead of `Init`, this is because `b` is -//! // structurally pinned, as marked by the `#[pin]` attribute. //! init: impl ::kernel::init::PinInit, E>, //! ) -> ::core::result::Result<(), E> { //! unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) } @@ -359,14 +369,13 @@ //! struct __Unpin<'__pin> { //! __phantom_pin: ::core::marker::PhantomData &'__pin ()>, //! __phantom: ::core::marker::PhantomData Foo>, -//! // Since this field is `#[pin]`, it is listed here. //! b: Bar, //! } //! #[doc(hidden)] //! impl<'__pin> ::core::marker::Unpin for Foo where __Unpin<'__pin>: ::core::marker::Unpin {} //! // Since we specified `PinnedDrop` as the argument to `#[pin_data]`, we expect `Foo` to //! // implement `PinnedDrop`. Thus we do not need to prevent `Drop` implementations like -//! // before, instead we implement it here and delegate to `PinnedDrop`. +//! // before, instead we implement `Drop` here and delegate to `PinnedDrop`. //! impl ::core::ops::Drop for Foo { //! fn drop(&mut self) { //! // Since we are getting dropped, no one else has a reference to `self` and thus we @@ -388,7 +397,7 @@ //! //! Here is the `PinnedDrop` impl for `Foo`: //! -//! ```rust +//! ```rust,ignore //! #[pinned_drop] //! impl PinnedDrop for Foo { //! fn drop(self: Pin<&mut Self>) { @@ -399,7 +408,7 @@ //! //! This expands to the following code: //! -//! ```rust +//! ```rust,ignore //! // `unsafe`, full path and the token parameter are added, everything else stays the same. //! unsafe impl ::kernel::init::PinnedDrop for Foo { //! fn drop(self: Pin<&mut Self>, _: ::kernel::init::__internal::OnlyCallFromDrop) { @@ -410,10 +419,10 @@ //! //! ## `pin_init!` on `Foo` //! -//! Since we already took a look at `pin_init!` on `Bar`, this section will only explain the -//! differences/new things in the expansion of `pin_init!` on `Foo`: +//! Since we already took a look at `pin_init!` on `Bar`, this section will only show the expansion +//! of `pin_init!` on `Foo`: //! -//! ```rust +//! ```rust,ignore //! let a = 42; //! let initializer = pin_init!(Foo { //! a, @@ -423,7 +432,7 @@ //! //! This expands to the following code: //! -//! ```rust +//! ```rust,ignore //! let a = 42; //! let initializer = { //! struct __InitOk; @@ -438,13 +447,15 @@ //! >(data, move |slot| { //! { //! struct __InitOk; -//! unsafe { ::core::ptr::write(&raw mut (*slot).a, a) }; -//! let a = &unsafe { ::kernel::init::__internal::DropGuard::new(&raw mut (*slot).a) }; +//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) }; +//! let a = &unsafe { +//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a)) +//! }; //! let b = Bar::new(36); -//! // Here we use `data` to access the correct field and require that `b` is of type -//! // `PinInit, Infallible>`. -//! unsafe { data.b(&raw mut (*slot).b, b)? }; -//! let b = &unsafe { ::kernel::init::__internal::DropGuard::new(&raw mut (*slot).b) }; +//! unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? }; +//! let b = &unsafe { +//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b)) +//! }; //! //! #[allow(unreachable_code, clippy::diverging_sub_expression)] //! if false {