From nobody Thu Oct 9 06:05:18 2025 Received: from mail-qt1-f178.google.com (mail-qt1-f178.google.com [209.85.160.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 65492235346; Thu, 19 Jun 2025 15:06:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750345596; cv=none; b=pUXJ0gtijTitY+ag3uRIPu5SJ4eMCH8ZR0Vpqz6cIpD/aA+DrM3+DTqUHjcCtEdh8W52mpjBVn3XBG8AlG5YXLH5D7a7kl5uBLhYmOoaNlpc4uYW98aQvJPmG3QhdODyuuCR+6bx2FuwsvLzrJHAnYpjQInFlGbEvqmQffhU69s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750345596; c=relaxed/simple; bh=EBOv2iJUrNuFvpf6DgfwXDAQle4Ii2A9b6MwmYUjoEA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=l+D/UhOtV2NWqc1DV7gRHIVZ6y+MML01s8CdSqd+hkvZmROkB+TBkKMmwNa136LtHXYEd/Z3rhLkKsUProU/w124KpSlPeJBLJ2w/E0hi9gpoo1cKZvwWEhNPiZIMWmvvB4vrVTpRKm/GwcxpOHcy7v681HSB90x9N5az4TirCc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=SguMwELY; arc=none smtp.client-ip=209.85.160.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="SguMwELY" Received: by mail-qt1-f178.google.com with SMTP id d75a77b69052e-4a774209cf0so6327151cf.0; Thu, 19 Jun 2025 08:06:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1750345593; x=1750950393; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=bM2aOZbws9YwwuYVjK1ug8LtX85CzdHif6CnDf/GxLg=; b=SguMwELYqOXzrouyRq+qewvN8D67tfxB3T8aJZcKqyP+BfQt2e84lMIJ7XVnm4dcHc 0MEpYFBc0hsgHaVoBvNxcVNJs36vaKg1q4gU+YuSV6dEQmKh+tbjD7nZVAvPUNLYMgfA OLEV7wvy2FlrggBQNBGk5D83i5F9Nlbp8B8neWP3phJRLVYb3FkvCeTfZ9EZyk+ZNFcb 4uBM2MK5bOcQ1F4c0OSZSpPM330KhWhmh9nj2a28fY0i153dTeW/P+v9U4iUS13S90TC U8plf1E56xcoKwyQg0BbQ2ftfOrcaVNkqqLk+bh0hHIHItqXfhdkVDgbJYzQSWe6XIOo Jc3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750345593; x=1750950393; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bM2aOZbws9YwwuYVjK1ug8LtX85CzdHif6CnDf/GxLg=; b=HlppUm5Cg92wQBHEnK8NRiRXEl/Ly9YMMYhCEtoZ65X1nav+p+enWJ6ebgq9/5lTEF ZGmJ2ppxfWKYGhB0zGiocSqmDHbZixOk2jqw5nh8BkmVYXr0Eu0AdpmRM3IeggMONkh7 rzOz18q97vKChVpwNmwQj+5Pj4jJhuor583rI7eH5IkKqnoxgVNCm/MAY+hXTJYmueH1 ViSDcHf3EBoyFShsNs3sZM34hhzvBcsluSwzDXr1496lKjoxl+1K43/Oq5xjlLmqJyCs gZdb0qYQDMuv/c8Oy6uyKWIL5krjRmj4ObhpjHKvjkMYyaxoHrRxf4w/QJaqG/huwvr4 8R3g== X-Forwarded-Encrypted: i=1; AJvYcCUNGTLQD+6pZoqYR7DayRbrDccX34/cHzc6wjt3TGbqlRcgTmCv5WzzuLN6MYyiCpS4Fnd6oWv5qmze@vger.kernel.org, AJvYcCUS7lGXHFMtDyj7PV6E3KXcd/7RwIHBTjrA2T+ujhBF/s16P3u20mWqKEnF5tCjiDSMP+5Y5qhuKnGh6qPZh4/7@vger.kernel.org, AJvYcCUbDzyRz0yMDrIz0mHlM6GLMelyAkFXBESXzJuVBVP+M8PuyUV4N4jQczvraV1sBIeudobqf1RJJYHr@vger.kernel.org, AJvYcCUdEgh+7Z+YJl/VyFntAmX5kLMzCxBr/h69canm8ougUn/7emuuyMOeM8PyNQLQ50y97GvRlIMpDTY=@vger.kernel.org, AJvYcCVAbFV94xqZHwS76UqB0kL4R5gLZ2Xw+ir/DRTVSo5DTfY5qzB6tuKuECK3/skxBXDebKN6ze4M2gsKLPA=@vger.kernel.org, AJvYcCWrtCN+lR+4SSLKMpvTYGxu7wVhP8OZfkRhMGSAVE1ZqODSO1A4svRQpEhHMjOI1EXdUvTlQgSP@vger.kernel.org, AJvYcCXFVADAyvF6F5QkUx9A/QUAH6tKUaonL7kDnaJlT0Fk0n5OwKSyBQ9KmBg1CQsA5sXjjve6TwPEm5TV@vger.kernel.org, AJvYcCXQNlh6m937hA6wIvSh6ejG78+DnTjSyGY36+HSf747ib+ksXfn04aYaaA+C86p823i8X9p83ELvMFNcn0F@vger.kernel.org X-Gm-Message-State: AOJu0Yw4E9e47CeWD8iw2Aw9SI06b4naOl4mqWygnbwgizNa1lWejy9z /es1ZvqV+HJ4vaJgFfK4EC/VOheFiNTMYiWlocB5GXMCJc7HPQlgEOSY X-Gm-Gg: ASbGnct7lwBmD0nPFl2kDh5MeTLJvE6RjbLUIfcDa0J7vv/ib991KBbTxC1XjA8rGO9 elLbl2DfiFe1VcBRb4qBnQhZWzQ80F/tGqtAYL13y/jG3bVdYwkJf6oywagMLWTN/lNlxTj9Q0g rdwC35oAtTc9cLabqLnDuLiGt5apOxGoauKCfwWPxbN+yj40zLFtrcL8Q73mG+oLhPwGu/9Ojlj PgwN66IOHSTKbJtt3HzWAkae96wiGTuijEuOeKCnm++r1UGBPtD+QXdsGGzLiRiYHJ1cCr41uR8 SclDqapjX5csmRWbXDw8CJVWLbBZdQHq2xEeGC7eo1XEZ//QZafdmpQtYGXsczFHsmyYOZ70Emc = X-Google-Smtp-Source: AGHT+IH6uoGJ80i+gmE2Fu3xsbwnovJZH3MPF8JNjcwJ3CVhnE00RGYIPfowX1mIbGAqF/jdU2etbQ== X-Received: by 2002:a05:622a:188c:b0:4a7:29f2:313 with SMTP id d75a77b69052e-4a73c619203mr287096761cf.42.1750345593031; Thu, 19 Jun 2025 08:06:33 -0700 (PDT) Received: from tamird-mac.local ([2600:4041:5be7:7c00:5c8a:fc6a:b57c:e57f]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-4a7785aaacdsm250531cf.39.2025.06.19.08.06.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Jun 2025 08:06:32 -0700 (PDT) From: Tamir Duberstein Date: Thu, 19 Jun 2025 11:06:25 -0400 Subject: [PATCH v12 1/5] rust: macros: reduce collections in `quote!` macro Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250619-cstr-core-v12-1-80c9c7b45900@gmail.com> References: <20250619-cstr-core-v12-0-80c9c7b45900@gmail.com> In-Reply-To: <20250619-cstr-core-v12-0-80c9c7b45900@gmail.com> To: Michal Rostecki , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Andreas Hindborg , Alice Ryhl , Trevor Gross , Brendan Higgins , David Gow , Rae Moar , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Greg Kroah-Hartman , "Rafael J. Wysocki" , Luis Chamberlain , Russ Weight , FUJITA Tomonori , Rob Herring , Saravana Kannan , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Bjorn Helgaas , Arnd Bergmann , Jens Axboe , Benno Lossin , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Dave Ertman , Ira Weiny , Leon Romanovsky , Breno Leitao , Viresh Kumar , Michael Turquette , Stephen Boyd Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, dri-devel@lists.freedesktop.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, llvm@lists.linux.dev, linux-pci@vger.kernel.org, nouveau@lists.freedesktop.org, linux-block@vger.kernel.org, linux-pm@vger.kernel.org, linux-clk@vger.kernel.org, Tamir Duberstein X-Mailer: b4 0.15-dev Remove a handful of unncessary intermediate vectors and token streams; mainly the top-level stream can be directly extended with the notable exception of groups. Remove an unnecessary `#[allow(dead_code)]` added in commit dbd5058ba60c ("rust: make pin-init its own crate"). Signed-off-by: Tamir Duberstein Acked-by: Greg Kroah-Hartman Reviewed-by: Alice Ryhl --- rust/macros/quote.rs | 104 ++++++++++++++++++++++++-----------------------= ---- 1 file changed, 49 insertions(+), 55 deletions(-) diff --git a/rust/macros/quote.rs b/rust/macros/quote.rs index 92cacc4067c9..acc140c18653 100644 --- a/rust/macros/quote.rs +++ b/rust/macros/quote.rs @@ -2,7 +2,6 @@ =20 use proc_macro::{TokenStream, TokenTree}; =20 -#[allow(dead_code)] pub(crate) trait ToTokens { fn to_tokens(&self, tokens: &mut TokenStream); } @@ -47,121 +46,116 @@ fn to_tokens(&self, tokens: &mut TokenStream) { /// `quote` crate but provides only just enough functionality needed by th= e current `macros` crate. macro_rules! quote_spanned { ($span:expr =3D> $($tt:tt)*) =3D> {{ - let mut tokens: ::std::vec::Vec<::proc_macro::TokenTree>; - #[allow(clippy::vec_init_then_push)] + let mut tokens =3D ::proc_macro::TokenStream::new(); { - tokens =3D ::std::vec::Vec::new(); let span =3D $span; quote_spanned!(@proc tokens span $($tt)*); } - ::proc_macro::TokenStream::from_iter(tokens) + tokens }}; (@proc $v:ident $span:ident) =3D> {}; (@proc $v:ident $span:ident #$id:ident $($tt:tt)*) =3D> { - let mut ts =3D ::proc_macro::TokenStream::new(); - $crate::quote::ToTokens::to_tokens(&$id, &mut ts); - $v.extend(ts); + $crate::quote::ToTokens::to_tokens(&$id, &mut $v); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident #(#$id:ident)* $($tt:tt)*) =3D> { for token in $id { - let mut ts =3D ::proc_macro::TokenStream::new(); - $crate::quote::ToTokens::to_tokens(&token, &mut ts); - $v.extend(ts); + $crate::quote::ToTokens::to_tokens(&token, &mut $v); } quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident ( $($inner:tt)* ) $($tt:tt)*) =3D> { #[allow(unused_mut)] - let mut tokens =3D ::std::vec::Vec::<::proc_macro::TokenTree>::new= (); + let mut tokens =3D ::proc_macro::TokenStream::new(); quote_spanned!(@proc tokens $span $($inner)*); - $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new( + $v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new( ::proc_macro::Delimiter::Parenthesis, - ::proc_macro::TokenStream::from_iter(tokens) - ))); + tokens, + ))]); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident [ $($inner:tt)* ] $($tt:tt)*) =3D> { - let mut tokens =3D ::std::vec::Vec::new(); + let mut tokens =3D ::proc_macro::TokenStream::new(); quote_spanned!(@proc tokens $span $($inner)*); - $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new( + $v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new( ::proc_macro::Delimiter::Bracket, - ::proc_macro::TokenStream::from_iter(tokens) - ))); + tokens, + ))]); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident { $($inner:tt)* } $($tt:tt)*) =3D> { - let mut tokens =3D ::std::vec::Vec::new(); + let mut tokens =3D ::proc_macro::TokenStream::new(); quote_spanned!(@proc tokens $span $($inner)*); - $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new( + $v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new( ::proc_macro::Delimiter::Brace, - ::proc_macro::TokenStream::from_iter(tokens) - ))); + tokens, + ))]); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident :: $($tt:tt)*) =3D> { - $v.push(::proc_macro::TokenTree::Punct( - ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Joint) - )); - $v.push(::proc_macro::TokenTree::Punct( - ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone) - )); + $v.extend([::proc_macro::Spacing::Joint, ::proc_macro::Spacing::Al= one].map(|spacing| { + ::proc_macro::TokenTree::Punct(::proc_macro::Punct::new(':', s= pacing)) + })); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident : $($tt:tt)*) =3D> { - $v.push(::proc_macro::TokenTree::Punct( - ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone) - )); + $v.extend([::proc_macro::TokenTree::Punct( + ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone), + )]); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident , $($tt:tt)*) =3D> { - $v.push(::proc_macro::TokenTree::Punct( - ::proc_macro::Punct::new(',', ::proc_macro::Spacing::Alone) - )); + $v.extend([::proc_macro::TokenTree::Punct( + ::proc_macro::Punct::new(',', ::proc_macro::Spacing::Alone), + )]); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident @ $($tt:tt)*) =3D> { - $v.push(::proc_macro::TokenTree::Punct( - ::proc_macro::Punct::new('@', ::proc_macro::Spacing::Alone) - )); + $v.extend([::proc_macro::TokenTree::Punct( + ::proc_macro::Punct::new('@', ::proc_macro::Spacing::Alone), + )]); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident ! $($tt:tt)*) =3D> { - $v.push(::proc_macro::TokenTree::Punct( - ::proc_macro::Punct::new('!', ::proc_macro::Spacing::Alone) - )); + $v.extend([::proc_macro::TokenTree::Punct( + ::proc_macro::Punct::new('!', ::proc_macro::Spacing::Alone), + )]); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident ; $($tt:tt)*) =3D> { - $v.push(::proc_macro::TokenTree::Punct( - ::proc_macro::Punct::new(';', ::proc_macro::Spacing::Alone) - )); + $v.extend([::proc_macro::TokenTree::Punct( + ::proc_macro::Punct::new(';', ::proc_macro::Spacing::Alone), + )]); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident + $($tt:tt)*) =3D> { - $v.push(::proc_macro::TokenTree::Punct( - ::proc_macro::Punct::new('+', ::proc_macro::Spacing::Alone) - )); + $v.extend([::proc_macro::TokenTree::Punct( + ::proc_macro::Punct::new('+', ::proc_macro::Spacing::Alone), + )]); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident =3D $($tt:tt)*) =3D> { - $v.push(::proc_macro::TokenTree::Punct( - ::proc_macro::Punct::new('=3D', ::proc_macro::Spacing::Alo= ne) - )); + $v.extend([::proc_macro::TokenTree::Punct( + ::proc_macro::Punct::new('=3D', ::proc_macro::Spacing::Alone), + )]); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident # $($tt:tt)*) =3D> { - $v.push(::proc_macro::TokenTree::Punct( - ::proc_macro::Punct::new('#', ::proc_macro::Spacing::Alone) - )); + $v.extend([::proc_macro::TokenTree::Punct( + ::proc_macro::Punct::new('#', ::proc_macro::Spacing::Alone), + )]); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident _ $($tt:tt)*) =3D> { - $v.push(::proc_macro::TokenTree::Ident(::proc_macro::Ident::new("_= ", $span))); + $v.extend([::proc_macro::TokenTree::Ident( + ::proc_macro::Ident::new("_", $span), + )]); quote_spanned!(@proc $v $span $($tt)*); }; (@proc $v:ident $span:ident $id:ident $($tt:tt)*) =3D> { - $v.push(::proc_macro::TokenTree::Ident(::proc_macro::Ident::new(st= ringify!($id), $span))); + $v.extend([::proc_macro::TokenTree::Ident( + ::proc_macro::Ident::new(stringify!($id), $span), + )]); quote_spanned!(@proc $v $span $($tt)*); }; } --=20 2.50.0 From nobody Thu Oct 9 06:05:18 2025 Received: from mail-qt1-f172.google.com (mail-qt1-f172.google.com [209.85.160.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 69B5423BCF1; Thu, 19 Jun 2025 15:06:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750345599; cv=none; b=EeeLYT2UmwLNSqziQ+1cuVV9nEdfAcV0TQRagotOZDIm+obIsIIL417d0JoewmZdZJAzKLXO0a/8gdl5RF11Y/agzLDgpt3znyuii5F/nCFTtpVFD1tjpl42NKLPtMfiJ7oYZ8rd5T0ddjt6RxQRUsu7aTgPFegqVjNgT37Nej0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750345599; c=relaxed/simple; bh=652hO8kSY2Y7rKN/lqlwnWCQa72Wp05SaveoQPmcY+I=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uL+ueiRdHsd6Jayanz4pDEkbgWHP9rFupT7Jf8+Nx1yLL1UtcuwOMOQPYD4S8WGcP8BIAxbuE0i8UUUIRrjeK1QzzpjWuKNAcNAx1YA3M4vwQ37Q1JLgeHxhcnFEGt5TAoDoyGOt1ivfELfGfbAazGwOtnGl2KuLHPAVm+DONwE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=k3QahhfD; arc=none smtp.client-ip=209.85.160.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="k3QahhfD" Received: by mail-qt1-f172.google.com with SMTP id d75a77b69052e-4a52d82adcaso11524431cf.0; Thu, 19 Jun 2025 08:06:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1750345596; x=1750950396; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=JgT2Z8TprClAw+xYmIIX7R8VNFxm+Lobj0oWagX6uZM=; b=k3QahhfDCSdxLTNxKnG3qTnoloEwcMdyVnEZ8RsD8TTJSLVOYijvZXHf4e0efrCW1P JZFUvVu1yQvd/yE+1ZCEVzWxiUbVECGdGSFRuhDbWoOEeB/1NwCHOhJ1vgf2/gvRlRIN RGpS+wi5ppIOx94/9wc40XgB3roOOcSYrK9AyMqpNLXCV/ITCtNjUxH4/yus3DY8jYRi x28dPNp0jDlFeTtRQHPLd/NACTFh1kBAH3BViKxHulppGkKxvawwyrD6iBr9CvJqsZWb fIZ5yfbV3cJCgBHL9gPDvf8jxllODeEwGC5RXnC49+kLZOHyvy/tRJN0u/s9/FLa0F7H D2zw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750345596; x=1750950396; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JgT2Z8TprClAw+xYmIIX7R8VNFxm+Lobj0oWagX6uZM=; b=T/kWsJ2kYscZADLXwEPCbZb3armKnzMyvq+1pzz93UgqX/YMrWUzVDt62nIRkyzmOQ hQ6RMkC6yNtHskMWp2UBKr5nhjC9vnJXiSsiVa50/0UblvO5aOMVFakpihPUAUZ/fHCQ PXSzalIW3+oOI34ItB3fjs27AP0aI1OU2dKzBbwuf0HKzuvmIB0mi7xl/6wS94Sw8zIp M2jCM0mFqGh9ymNQdzHaPaf1HBOUqpIOYizjJtHu3jMOahjc9rSd2vkrAnt5xusTbJij Y5A1kombapts3YRm8WJveE4KRNCQIm8iKlTLsNOPmWZivo7O9kfMyjUVpuRD7eUK+oDZ of5g== X-Forwarded-Encrypted: i=1; AJvYcCUCRyIMoTOAwvf7+BU5x2SLCqxdCw6nQqiedz5aJa04qMCcCvF3H+ik+VBuQx6mCqXtlrEdxdMEyPRW@vger.kernel.org, AJvYcCUDErTuKN2QIk231LnwZAOUzKxDitTbUyaurMhwRrPlwxalzEXCzr/szPN1qTnOPTbhabvJlaef1J0WEbp4oqrm@vger.kernel.org, AJvYcCUPnG74RIYszUDQedGmUrTMTy1wImXPIEYFUveSgY+4046xGzKg071RMrCIwFG4iTD1hRyjtVFb@vger.kernel.org, AJvYcCV5hJY8smqDUMp6Or/jh5chK6NGbH6DAZQIQeifSb/8KwK2/zZ+oDJv5jx7EV69FQ52EtwFhKCpUSU=@vger.kernel.org, AJvYcCVnMh+f2v0YgudWjDDmyGpgTJ+KbQ+rf1Zo/oZVAuWrVPWUU0NVrsJSlrlaFtpJsjFcBwsY5l4Gy7luVaRz@vger.kernel.org, AJvYcCXhSuJwVm0juwxXo9nBA8yKveFpR/C9roR2gzOYLhtyCFew4CBB8ZJMYZnGxC2C9i3gZavkl9+2gIjp@vger.kernel.org, AJvYcCXjTP+R+yXRoKG3QeReslgITe+3Lyz7AxYkwbDkOaSC1QctcrNPy+LpVedqOtfsaQCGBE0ErPQVCfhq@vger.kernel.org, AJvYcCXlf9B6UxC555fn5RfAKQ4JPuuio+YwAzGUc3+yvAIw15fQ+VIeGCYJsyo3HgZIuMVzVRRe3oJ4vD34pwQ=@vger.kernel.org X-Gm-Message-State: AOJu0Yz8XKC6GF2iQpCdTY1a9KIWYHGv6zigZAozbCTLQYP2c0QbvzZ7 9xddyENOBK/eorP5l3TXCyB9DWjfj9SYUS+S50q//Z8LPP4ONj0n7sXy X-Gm-Gg: ASbGncs02RIZQMz6Go5DE7bbvz1O6juokcRtNtYMURiB8a0j1sDst6z1kE/0DqnuaSv cOsguiAgqFHlh+j4b/+GCEDE8xejXUCxY62fn0f5yAFv/v6TBOXVQYAuv158XMcNEIjbge8T+Vo Ev0+QJwbtchNxEgA8t9Jt5+LCQHt6MjqS43zPHyoA0xd0f8wiTY4Rp2sXNB7eOJOUSCXQ7lqpA/ ZLhsMr0P6ATBH8ElDXDfR0Z//cGq50t4Ajv/xXYv7kkrzvAo7KS1fM4CSyXwQt2KaxFmnIzQDrD 8beMNguWJDh/da8DlFnCDblH0HFeAKRqXNUmO7jFLf74zHrR4IYzSKeOv6MgSlYOfN8Wt8GIuLI = X-Google-Smtp-Source: AGHT+IFqly3VlSb0CHoZUyik+mcR0q2d44yP5dAoWKEyuDK2FJ5WsXRH47i/XmnaiAe5BBcEmv5KAA== X-Received: by 2002:a05:622a:1a29:b0:476:6cd3:d898 with SMTP id d75a77b69052e-4a73c4ca299mr342015121cf.18.1750345595821; Thu, 19 Jun 2025 08:06:35 -0700 (PDT) Received: from tamird-mac.local ([2600:4041:5be7:7c00:5c8a:fc6a:b57c:e57f]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-4a7785aaacdsm250531cf.39.2025.06.19.08.06.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Jun 2025 08:06:35 -0700 (PDT) From: Tamir Duberstein Date: Thu, 19 Jun 2025 11:06:26 -0400 Subject: [PATCH v12 2/5] rust: support formatting of foreign types Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250619-cstr-core-v12-2-80c9c7b45900@gmail.com> References: <20250619-cstr-core-v12-0-80c9c7b45900@gmail.com> In-Reply-To: <20250619-cstr-core-v12-0-80c9c7b45900@gmail.com> To: Michal Rostecki , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Andreas Hindborg , Alice Ryhl , Trevor Gross , Brendan Higgins , David Gow , Rae Moar , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Greg Kroah-Hartman , "Rafael J. Wysocki" , Luis Chamberlain , Russ Weight , FUJITA Tomonori , Rob Herring , Saravana Kannan , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Bjorn Helgaas , Arnd Bergmann , Jens Axboe , Benno Lossin , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Dave Ertman , Ira Weiny , Leon Romanovsky , Breno Leitao , Viresh Kumar , Michael Turquette , Stephen Boyd Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, dri-devel@lists.freedesktop.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, llvm@lists.linux.dev, linux-pci@vger.kernel.org, nouveau@lists.freedesktop.org, linux-block@vger.kernel.org, linux-pm@vger.kernel.org, linux-clk@vger.kernel.org, Tamir Duberstein X-Mailer: b4 0.15-dev Introduce a `fmt!` macro which wraps all arguments in `kernel::fmt::Adapter` and a `kernel::fmt::Display` trait. This enables formatting of foreign types (like `core::ffi::CStr`) that do not implement `core::fmt::Display` due to concerns around lossy conversions whi= ch do not apply in the kernel. Replace all direct calls to `format_args!` with `fmt!`. Replace all implementations of `core::fmt::Display` with implementations of `kernel::fmt::Display`. Suggested-by: Alice Ryhl Link: https://rust-for-linux.zulipchat.com/#narrow/channel/288089-General/t= opic/Custom.20formatting/with/516476467 Signed-off-by: Tamir Duberstein Acked-by: Greg Kroah-Hartman Reviewed-by: Alice Ryhl --- drivers/block/rnull.rs | 2 +- drivers/gpu/nova-core/gpu.rs | 4 +- rust/kernel/block/mq.rs | 2 +- rust/kernel/device.rs | 2 +- rust/kernel/fmt.rs | 89 +++++++++++++++++++++++++++++++++++++++ rust/kernel/kunit.rs | 6 +-- rust/kernel/lib.rs | 1 + rust/kernel/prelude.rs | 3 +- rust/kernel/print.rs | 4 +- rust/kernel/seq_file.rs | 2 +- rust/kernel/str.rs | 22 ++++------ rust/macros/fmt.rs | 99 ++++++++++++++++++++++++++++++++++++++++= ++++ rust/macros/lib.rs | 19 +++++++++ rust/macros/quote.rs | 7 ++++ scripts/rustdoc_test_gen.rs | 2 +- 15 files changed, 236 insertions(+), 28 deletions(-) diff --git a/drivers/block/rnull.rs b/drivers/block/rnull.rs index d07e76ae2c13..6366da12c5a5 100644 --- a/drivers/block/rnull.rs +++ b/drivers/block/rnull.rs @@ -51,7 +51,7 @@ fn init(_module: &'static ThisModule) -> impl PinInit { .logical_block_size(4096)? .physical_block_size(4096)? .rotational(false) - .build(format_args!("rnullb{}", 0), tagset) + .build(fmt!("rnullb{}", 0), tagset) })(); =20 try_pin_init!(Self { diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs index 60b86f370284..e6b208175ff9 100644 --- a/drivers/gpu/nova-core/gpu.rs +++ b/drivers/gpu/nova-core/gpu.rs @@ -91,7 +91,7 @@ pub(crate) fn arch(&self) -> Architecture { // Hence, replace with something like strum_macros derive(Display). // // For now, redirect to fmt::Debug for convenience. -impl fmt::Display for Chipset { +impl kernel::fmt::Display for Chipset { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{self:?}") } @@ -132,7 +132,7 @@ fn from_boot0(boot0: regs::NV_PMC_BOOT_0) -> Self { } } =20 -impl fmt::Display for Revision { +impl kernel::fmt::Display for Revision { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:x}.{:x}", self.major, self.minor) } diff --git a/rust/kernel/block/mq.rs b/rust/kernel/block/mq.rs index fb0f393c1cea..842be88aa1cf 100644 --- a/rust/kernel/block/mq.rs +++ b/rust/kernel/block/mq.rs @@ -82,7 +82,7 @@ //! Arc::pin_init(TagSet::new(1, 256, 1), flags::GFP_KERNEL)?; //! let mut disk =3D gen_disk::GenDiskBuilder::new() //! .capacity_sectors(4096) -//! .build(format_args!("myblk"), tagset)?; +//! .build(fmt!("myblk"), tagset)?; //! //! # Ok::<(), kernel::error::Error>(()) //! ``` diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index dea06b79ecb5..cdc6c8161e24 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -345,7 +345,7 @@ macro_rules! impl_device_context_into_aref { macro_rules! dev_printk { ($method:ident, $dev:expr, $($f:tt)*) =3D> { { - ($dev).$method(::core::format_args!($($f)*)); + ($dev).$method($crate::prelude::fmt!($($f)*)); } } } diff --git a/rust/kernel/fmt.rs b/rust/kernel/fmt.rs new file mode 100644 index 000000000000..348d16987de6 --- /dev/null +++ b/rust/kernel/fmt.rs @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Formatting utilities. + +use core::fmt; + +/// Internal adapter used to route allow implementations of formatting tra= its for foreign types. +/// +/// It is inserted automatically by the [`fmt!`] macro and is not meant to= be used directly. +/// +/// [`fmt!`]: crate::prelude::fmt! +#[doc(hidden)] +pub struct Adapter(pub T); + +macro_rules! impl_fmt_adapter_forward { + ($($trait:ident),* $(,)?) =3D> { + $( + impl fmt::$trait for Adapter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self(t) =3D self; + fmt::$trait::fmt(t, f) + } + } + )* + }; +} + +impl_fmt_adapter_forward!(Debug, LowerHex, UpperHex, Octal, Binary, Pointe= r, LowerExp, UpperExp); + +/// A copy of [`fmt::Display`] that allows us to implement it for foreign = types. +/// +/// Types should implement this trait rather than [`fmt::Display`]. Togeth= er with the [`Adapter`] +/// type and [`fmt!`] macro, it allows for formatting foreign types (e.g. = types from core) which do +/// not implement [`fmt::Display`] directly. +/// +/// [`fmt!`]: crate::prelude::fmt! +pub trait Display { + /// Same as [`fmt::Display::fmt`]. + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result; +} + +impl Display for &T { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(*self, f) + } +} + +impl fmt::Display for Adapter<&T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self(t) =3D self; + Display::fmt(t, f) + } +} + +macro_rules! impl_display_forward { + ($( + $( { $($generics:tt)* } )? $ty:ty $( { where $($where:tt)* } )? + ),* $(,)?) =3D> { + $( + impl$($($generics)*)? Display for $ty $(where $($where)*)? { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } + } + )* + }; +} + +impl_display_forward!( + bool, + char, + core::panic::PanicInfo<'_>, + fmt::Arguments<'_>, + i128, + i16, + i32, + i64, + i8, + isize, + str, + u128, + u16, + u32, + u64, + u8, + usize, + {} crate::sync::Arc {where crate::sync::Arc: fmt::Dis= play}, + {} crate::sync::UniqueArc {where crate::sync::UniqueArc<= T>: fmt::Display}, +); diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs index 4b8cdcb21e77..20ae65c2a18e 100644 --- a/rust/kernel/kunit.rs +++ b/rust/kernel/kunit.rs @@ -71,14 +71,14 @@ macro_rules! kunit_assert { // mistake (it is hidden to prevent that). // // This mimics KUnit's failed assertion format. - $crate::kunit::err(format_args!( + $crate::kunit::err($crate::prelude::fmt!( " # {}: ASSERTION FAILED at {FILE}:{LINE}\n", $name )); - $crate::kunit::err(format_args!( + $crate::kunit::err($crate::prelude::fmt!( " Expected {CONDITION} to be true, but is false\n" )); - $crate::kunit::err(format_args!( + $crate::kunit::err($crate::prelude::fmt!( " Failure not reported to KUnit since this is a non= -KUnit task\n" )); break 'out; diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 6b4774b2b1c3..aadcfaa5c759 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -77,6 +77,7 @@ pub mod faux; #[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)] pub mod firmware; +pub mod fmt; pub mod fs; pub mod init; pub mod io; diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index 2f30a398dddd..41cebd906c4c 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -22,7 +22,7 @@ pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec= , Vec}; =20 #[doc(no_inline)] -pub use macros::{export, kunit_tests, module, vtable}; +pub use macros::{export, fmt, kunit_tests, module, vtable}; =20 pub use pin_init::{init, pin_data, pin_init, pinned_drop, InPlaceWrite, In= it, PinInit, Zeroable}; =20 @@ -31,7 +31,6 @@ // `super::std_vendor` is hidden, which makes the macro inline for some re= ason. #[doc(no_inline)] pub use super::dbg; -pub use super::fmt; pub use super::{dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info= , dev_notice, dev_warn}; pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr= _notice, pr_warn}; =20 diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs index 9783d960a97a..0f5e15128005 100644 --- a/rust/kernel/print.rs +++ b/rust/kernel/print.rs @@ -149,7 +149,7 @@ macro_rules! print_macro ( // takes borrows on the arguments, but does not extend the scope o= f temporaries. // Therefore, a `match` expression is used to keep them around, si= nce // the scrutinee is kept until the end of the `match`. - match format_args!($($arg)+) { + match $crate::prelude::fmt!($($arg)+) { // SAFETY: This hidden macro should only be called by the docu= mented // printing macros which ensure the format string is one of th= e fixed // ones. All `__LOG_PREFIX`s are null-terminated as they are g= enerated @@ -168,7 +168,7 @@ macro_rules! print_macro ( // The `CONT` case. ($format_string:path, true, $($arg:tt)+) =3D> ( $crate::print::call_printk_cont( - format_args!($($arg)+), + $crate::prelude::fmt!($($arg)+), ); ); ); diff --git a/rust/kernel/seq_file.rs b/rust/kernel/seq_file.rs index 7a9403eb6e5b..627bc2f7b3d2 100644 --- a/rust/kernel/seq_file.rs +++ b/rust/kernel/seq_file.rs @@ -47,7 +47,7 @@ pub fn call_printf(&self, args: core::fmt::Arguments<'_>)= { #[macro_export] macro_rules! seq_print { ($m:expr, $($arg:tt)+) =3D> ( - $m.call_printf(format_args!($($arg)+)) + $m.call_printf($crate::prelude::fmt!($($arg)+)) ); } pub use seq_print; diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index a927db8e079c..3ef99ba2e93c 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -50,11 +50,11 @@ pub fn strip_prefix(&self, pattern: impl AsRef) -= > Option<&BStr> { } } =20 -impl fmt::Display for BStr { +impl crate::fmt::Display for BStr { /// Formats printable ASCII characters, escaping the rest. /// /// ``` - /// # use kernel::{fmt, b_str, str::{BStr, CString}}; + /// # use kernel::{prelude::fmt, b_str, str::{BStr, CString}}; /// let ascii =3D b_str!("Hello, BStr!"); /// let s =3D CString::try_from_fmt(fmt!("{}", ascii))?; /// assert_eq!(s.as_bytes(), "Hello, BStr!".as_bytes()); @@ -85,7 +85,7 @@ impl fmt::Debug for BStr { /// escaping the rest. /// /// ``` - /// # use kernel::{fmt, b_str, str::{BStr, CString}}; + /// # use kernel::{prelude::fmt, b_str, str::{BStr, CString}}; /// // Embedded double quotes are escaped. /// let ascii =3D b_str!("Hello, \"BStr\"!"); /// let s =3D CString::try_from_fmt(fmt!("{:?}", ascii))?; @@ -424,12 +424,12 @@ pub fn to_ascii_uppercase(&self) -> Result { } } =20 -impl fmt::Display for CStr { +impl crate::fmt::Display for CStr { /// Formats printable ASCII characters, escaping the rest. /// /// ``` /// # use kernel::c_str; - /// # use kernel::fmt; + /// # use kernel::prelude::fmt; /// # use kernel::str::CStr; /// # use kernel::str::CString; /// let penguin =3D c_str!("=F0=9F=90=A7"); @@ -459,7 +459,7 @@ impl fmt::Debug for CStr { /// /// ``` /// # use kernel::c_str; - /// # use kernel::fmt; + /// # use kernel::prelude::fmt; /// # use kernel::str::CStr; /// # use kernel::str::CString; /// let penguin =3D c_str!("=F0=9F=90=A7"); @@ -578,7 +578,7 @@ mod tests { =20 macro_rules! format { ($($f:tt)*) =3D> ({ - CString::try_from_fmt(::kernel::fmt!($($f)*))?.to_str()? + CString::try_from_fmt(crate::prelude::fmt!($($f)*))?.to_str()? }) } =20 @@ -840,7 +840,7 @@ fn write_str(&mut self, s: &str) -> fmt::Result { /// # Examples /// /// ``` -/// use kernel::{str::CString, fmt}; +/// use kernel::{str::CString, prelude::fmt}; /// /// let s =3D CString::try_from_fmt(fmt!("{}{}{}", "abc", 10, 20))?; /// assert_eq!(s.as_bytes_with_nul(), "abc1020\0".as_bytes()); @@ -930,9 +930,3 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Resul= t { fmt::Debug::fmt(&**self, f) } } - -/// A convenience alias for [`core::format_args`]. -#[macro_export] -macro_rules! fmt { - ($($f:tt)*) =3D> ( ::core::format_args!($($f)*) ) -} diff --git a/rust/macros/fmt.rs b/rust/macros/fmt.rs new file mode 100644 index 000000000000..edc37c220a89 --- /dev/null +++ b/rust/macros/fmt.rs @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0 + +use proc_macro::{Ident, TokenStream, TokenTree}; +use std::collections::BTreeSet; + +/// Please see [`crate::fmt`] for documentation. +pub(crate) fn fmt(input: TokenStream) -> TokenStream { + let mut input =3D input.into_iter(); + + let first_opt =3D input.next(); + let first_owned_str; + let mut names =3D BTreeSet::new(); + let first_lit =3D { + let Some((mut first_str, first_lit)) =3D (match first_opt.as_ref()= { + Some(TokenTree::Literal(first_lit)) =3D> { + first_owned_str =3D first_lit.to_string(); + Some(first_owned_str.as_str()).and_then(|first| { + let first =3D first.strip_prefix('"')?; + let first =3D first.strip_suffix('"')?; + Some((first, first_lit)) + }) + } + _ =3D> None, + }) else { + return first_opt.into_iter().chain(input).collect(); + }; + while let Some((_, rest)) =3D first_str.split_once('{') { + first_str =3D rest; + if let Some(rest) =3D first_str.strip_prefix('{') { + first_str =3D rest; + continue; + } + if let Some((name, rest)) =3D first_str.split_once('}') { + first_str =3D rest; + let name =3D name.split_once(':').map_or(name, |(name, _)|= name); + if !name.is_empty() && !name.chars().all(|c| c.is_ascii_di= git()) { + names.insert(name); + } + } + } + first_lit + }; + + let first_span =3D first_lit.span(); + let adapter =3D quote_spanned! { + first_span =3D> ::kernel::fmt::Adapter + }; + + let mut args =3D TokenStream::from_iter(first_opt); + { + let mut flush =3D |args: &mut TokenStream, current: &mut TokenStre= am| { + let current =3D std::mem::take(current); + if !current.is_empty() { + let (lhs, rhs) =3D (|| { + let mut current =3D current.into_iter(); + let mut acc =3D TokenStream::new(); + while let Some(tt) =3D current.next() { + // Split on `=3D` only once to handle cases like `= a =3D b =3D c`. + if matches!(&tt, TokenTree::Punct(p) if p.as_char(= ) =3D=3D '=3D') { + names.remove(acc.to_string().as_str()); + // Include the `=3D` itself to keep the handli= ng below uniform. + acc.extend([tt]); + return (Some(acc), current.collect::()); + } + acc.extend([tt]); + } + (None, acc) + })(); + args.extend(quote_spanned! { + first_span =3D> #lhs #adapter(&#rhs) + }); + } + }; + + let mut current =3D TokenStream::new(); + for tt in input { + match &tt { + TokenTree::Punct(p) if p.as_char() =3D=3D ',' =3D> { + flush(&mut args, &mut current); + &mut args + } + _ =3D> &mut current, + } + .extend([tt]); + } + flush(&mut args, &mut current); + } + + for name in names { + let name =3D Ident::new(name, first_span); + args.extend(quote_spanned! { + first_span =3D> , #name =3D #adapter(&#name) + }); + } + + quote_spanned! { + first_span =3D> ::core::format_args!(#args) + } +} diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index fa847cf3a9b5..980e70d253e4 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -15,6 +15,7 @@ mod quote; mod concat_idents; mod export; +mod fmt; mod helpers; mod kunit; mod module; @@ -201,6 +202,24 @@ pub fn export(attr: TokenStream, ts: TokenStream) -> T= okenStream { export::export(attr, ts) } =20 +/// Like [`core::format_args!`], but automatically wraps arguments in [`ke= rnel::fmt::Adapter`]. +/// +/// This macro allows generating `core::fmt::Arguments` while ensuring tha= t each argument is wrapped +/// with `::kernel::fmt::Adapter`, which customizes formatting behavior fo= r kernel logging. +/// +/// Named arguments used in the format string (e.g. `{foo}`) are detected = and resolved from local +/// bindings. All positional and named arguments are automatically wrapped. +/// +/// This macro is an implementation detail of other kernel logging macros = like [`pr_info!`] and +/// should not typically be used directly. +/// +/// [`kernel::fmt::Adapter`]: ../kernel/fmt/struct.Adapter.html +/// [`pr_info!`]: ../kernel/macro.pr_info.html +#[proc_macro] +pub fn fmt(input: TokenStream) -> TokenStream { + fmt::fmt(input) +} + /// Concatenate two identifiers. /// /// This is useful in macros that need to declare or reference items with = names diff --git a/rust/macros/quote.rs b/rust/macros/quote.rs index acc140c18653..ddfc21577539 100644 --- a/rust/macros/quote.rs +++ b/rust/macros/quote.rs @@ -48,6 +48,7 @@ macro_rules! quote_spanned { ($span:expr =3D> $($tt:tt)*) =3D> {{ let mut tokens =3D ::proc_macro::TokenStream::new(); { + #[allow(unused_variables)] let span =3D $span; quote_spanned!(@proc tokens span $($tt)*); } @@ -146,6 +147,12 @@ macro_rules! quote_spanned { )]); quote_spanned!(@proc $v $span $($tt)*); }; + (@proc $v:ident $span:ident & $($tt:tt)*) =3D> { + $v.extend([::proc_macro::TokenTree::Punct( + ::proc_macro::Punct::new('&', ::proc_macro::Spacing::Alone), + )]); + quote_spanned!(@proc $v $span $($tt)*); + }; (@proc $v:ident $span:ident _ $($tt:tt)*) =3D> { $v.extend([::proc_macro::TokenTree::Ident( ::proc_macro::Ident::new("_", $span), diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs index 1ca253594d38..507d36875196 100644 --- a/scripts/rustdoc_test_gen.rs +++ b/scripts/rustdoc_test_gen.rs @@ -201,7 +201,7 @@ macro_rules! assert_eq {{ // This follows the syntax for declaring test metadata in the proposed= KTAP v2 spec, which may // be used for the proposed KUnit test attributes API. Thus hopefully = this will make migration // easier later on. - ::kernel::kunit::info(format_args!(" # {kunit_name}.location: {real= _path}:{line}\n")); + ::kernel::kunit::info(fmt!(" # {kunit_name}.location: {real_path}:{= line}\n")); =20 /// The anchor where the test code body starts. #[allow(unused)] --=20 2.50.0 From nobody Thu Oct 9 06:05:18 2025 Received: from mail-qt1-f173.google.com (mail-qt1-f173.google.com [209.85.160.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BA9DA28C01D; Thu, 19 Jun 2025 15:06:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750345603; cv=none; b=YEy9km4wT6xYgB8Mlti3WX8cBMVO6fVZAhQmCR5jqjxSJNID183PdlUajUeDZWd5cXOKCkL8oxv8F0PQOpYAnLAynyk7bOA1aAQal6aGT3qX2ZHJSZM+yrxbegE1oMdFLrra6AjK6Y8jdLuKobclpF//4Br8bwWIJ6qSyoARJJc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750345603; c=relaxed/simple; bh=JSSKdlCXzZv3cvg62Oobqe6RiMskRcD0eglqPYTXxx0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lqtNDDLH7UIRpDXCqYXw6GHhEoj0aBVpLhWXChcUxK4+JKNTxID3h92ZqtcMM/3uT8ruh0YFA0O3cp4AW/nFHM45JhP5SlulYxCP5j7/Fa8WilLg3aRTzFrgVZTXLeF2sClXRWluJUNXsCu2LSKYy4/3/ILwvuiRd6IJpcMzftA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=G1+30PPt; arc=none smtp.client-ip=209.85.160.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="G1+30PPt" Received: by mail-qt1-f173.google.com with SMTP id d75a77b69052e-4a6f3f88613so7717411cf.1; Thu, 19 Jun 2025 08:06:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1750345599; x=1750950399; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=uYHSVmC06nyRCheM53AzBOMn98GjS34GcRl0Ij8d9FM=; b=G1+30PPtB/B+q+vHHfhcfbhHZCAxU9ln2JQ59sopT1IHTAKi4hLvvOXemp2VSPsaoE kttXnrdiSAXggqEf7lGri+hLVK6Wh0vmt9WWNFaTCchYMCR6h7JYPKn+O6nzHpx42LIF hSX7DTlIlw4dVTixh3sYQREVqCtVPVEzvAsFLwm15fpVHe0Ga2ARdzTR9ODb6ac2wOT7 esDtdazH9u5FT/jxbjyO4UTbGzTyU5PpWwNGryhkgFUdur/0HFI/AAaFBxcpt/PI7gxG 6neL9pDJtsF+ssHZDgpINEeknBRC1QNdvzRToDYHjAf1J4nOSpv7uuU6uetGAO/DhWAE wMYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750345599; x=1750950399; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uYHSVmC06nyRCheM53AzBOMn98GjS34GcRl0Ij8d9FM=; b=KAUoKPJRwJXNRbESBWVsLdHbyYdy6pTNHvykuuad0hL7wqj+qQDcrj1MftyCMpB+lI aTtj3xL8Dj2bRFffVnc8Cd9a6ZXtl+fFPezSe/cYh/9oKq3m3ouF7JUARfNfZaVxRAb2 OQ4K8bYgsnTM9hVvGRZUnbwMEGexyHmEvXHgMzYeU9cVi9193VEUI+CZDKfJ2pt2bbrS yml4Ke4VSrivKLPAanZZBz0uU//rtKyTe/NtZh8mP+kCFKpIq2vOj7ilVYuVEkncGaTS +VDmw3sSGJt9/FNLUXZMcEZX95HYCREapx2y21n9pkrvpLeCJ55hlyxqpkow7Pql0DxZ aPGA== X-Forwarded-Encrypted: i=1; AJvYcCU67vEFv0jYO58xHkNeSI6z7lAepOdat6lx7MOdsdNYU0/XAjx2BLVXaEkfiqLbML/t2vbjx4qG3qWWYhNS6Owx@vger.kernel.org, AJvYcCUGCo8XzvBl4nVPNs6nrBxSe68YcAOCnYT0BjzddzsLf/UCWB5THE5eRdVGDvba6EkZ2PIRAQOCFfIyVs15@vger.kernel.org, AJvYcCUHBIRaXk08DRH3TPYGwptqX7mPrazrbPc92zGhH7ydQR8/lbj/u5sG2nHZ3/xuRUsXbPK3liaCJdZE@vger.kernel.org, AJvYcCUhpKVavv0wh1lYeP9ibFyU4IW3ukOmfcEg591zq4PlS/jg0AVnGcEUIAsC5qbLV8eyG03+RQEH@vger.kernel.org, AJvYcCWD3r0Xe1BFN/HBs9c7fLXcnoWUdDh0dDdXzVjGwI2E5tW0qTUa3AB4K1zheeNoKsGLMmPEXE3dcEXP@vger.kernel.org, AJvYcCWdftdnTTATkt9RZa8TO7MvE+dDoFPjnCHUe3ljsAvcflwAb9AHXY+OLMrnLi5p00hIsa5TVDJ39MjqHas=@vger.kernel.org, AJvYcCXJUWxquZg0NtC0JvcDf2Kw01ghWDsydMlNnjwlSI1Pgo1eIicnQ9DhdzVmfdczBXmB0vpjH5+2EUA=@vger.kernel.org, AJvYcCXnVcDdweRREt2xNVyIoxn5J3HMSLFYZfZoZLH6dYsyvyIHkweN5lIiZezQTlsW51jYCkXpoFmj6zZL@vger.kernel.org X-Gm-Message-State: AOJu0YwdaJYL9pbTFo3Zsk5VaotkAbOl0nifSYFgXwe6AxBcSRjkYSJ7 3cYWMEkdo9OWZZhuJuab+0Klx6n47Xuq/pcP4K6f15ntnxAZ6gMZVjTc X-Gm-Gg: ASbGnctdmyC7ZOqoVp7gAlu3OG1m3xEHDykBprAEx1GSfq9+4qSc26viCOeMpOKq502 +jp8PpPB+Et73jQoGnd0BjMsh0xB5TeM/CUeHj+7nXFjx3NJT2+Pf0bNxg6x2AmQtsfyUT+X5k7 ckwdIv89F1smf/Z8LNzNq+kCL6DY7in+MXk3FTJoZ3/0unEMt4wKDzxNrd6AFNLZtE3LF0a8VRo M+Who6gCKtrYKhc/OqH6O+bi48OqYHD5fa2EnX4/BerV3M/WTBg0SnhxBIMPEPVvPATm2X5ylnJ jkxxfGXndg6ojTcRsuAqO6nrlMcRkyEElbxQGkN3eS9TAqpuixhXgGZU0uFtoztNRT+z/SJ9Njo = X-Google-Smtp-Source: AGHT+IHZKbPZ+GPvljvQmRPIS2BreCgsnlsz6cX3R/UILnkIOhMPXvwGP5rSblFyvYpWJ6yTIhisdA== X-Received: by 2002:a05:622a:91:b0:4a4:2cb0:2b29 with SMTP id d75a77b69052e-4a73c618998mr341014161cf.35.1750345598854; Thu, 19 Jun 2025 08:06:38 -0700 (PDT) Received: from tamird-mac.local ([2600:4041:5be7:7c00:5c8a:fc6a:b57c:e57f]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-4a7785aaacdsm250531cf.39.2025.06.19.08.06.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Jun 2025 08:06:38 -0700 (PDT) From: Tamir Duberstein Date: Thu, 19 Jun 2025 11:06:27 -0400 Subject: [PATCH v12 3/5] rust: replace `CStr` with `core::ffi::CStr` Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250619-cstr-core-v12-3-80c9c7b45900@gmail.com> References: <20250619-cstr-core-v12-0-80c9c7b45900@gmail.com> In-Reply-To: <20250619-cstr-core-v12-0-80c9c7b45900@gmail.com> To: Michal Rostecki , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Andreas Hindborg , Alice Ryhl , Trevor Gross , Brendan Higgins , David Gow , Rae Moar , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Greg Kroah-Hartman , "Rafael J. Wysocki" , Luis Chamberlain , Russ Weight , FUJITA Tomonori , Rob Herring , Saravana Kannan , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Bjorn Helgaas , Arnd Bergmann , Jens Axboe , Benno Lossin , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Dave Ertman , Ira Weiny , Leon Romanovsky , Breno Leitao , Viresh Kumar , Michael Turquette , Stephen Boyd Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, dri-devel@lists.freedesktop.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, llvm@lists.linux.dev, linux-pci@vger.kernel.org, nouveau@lists.freedesktop.org, linux-block@vger.kernel.org, linux-pm@vger.kernel.org, linux-clk@vger.kernel.org, Tamir Duberstein X-Mailer: b4 0.15-dev `kernel::ffi::CStr` was introduced in commit d126d2380131 ("rust: str: add `CStr` type") in November 2022 as an upstreaming of earlier work that was done in May 2021[0]. That earlier work, having predated the inclusion of `CStr` in `core`, largely duplicated the implementation of `std::ffi::CStr`. `std::ffi::CStr` was moved to `core::ffi::CStr` in Rust 1.64 in September 2022. Hence replace `kernel::str::CStr` with `core::ffi::CStr` to reduce our custom code footprint, and retain needed custom functionality through an extension trait. C-String literals were added in Rust 1.77, while our MSRV is 1.78. Thus opportunistically replace instances of `kernel::c_str!` with C-String literals where other code changes were already necessary or where existing code triggered clippy lints; the rest will be done in a later commit. Link: https://github.com/Rust-for-Linux/linux/commit/faa3cbcca03d0dec8f8e43= f1d8d5c0860d98a23f [0] Signed-off-by: Tamir Duberstein Acked-by: Greg Kroah-Hartman Reviewed-by: Alice Ryhl --- drivers/gpu/drm/drm_panic_qr.rs | 2 +- rust/kernel/auxiliary.rs | 4 +- rust/kernel/configfs.rs | 4 +- rust/kernel/cpufreq.rs | 2 +- rust/kernel/device.rs | 4 +- rust/kernel/drm/device.rs | 4 +- rust/kernel/error.rs | 4 +- rust/kernel/firmware.rs | 11 +- rust/kernel/kunit.rs | 6 +- rust/kernel/miscdevice.rs | 2 +- rust/kernel/net/phy.rs | 2 +- rust/kernel/of.rs | 2 +- rust/kernel/prelude.rs | 5 +- rust/kernel/seq_file.rs | 4 +- rust/kernel/str.rs | 394 +++++++++++-------------------------= ---- rust/kernel/sync/condvar.rs | 2 +- rust/kernel/sync/lock.rs | 2 +- rust/kernel/sync/lock/global.rs | 2 +- samples/rust/rust_configfs.rs | 2 +- 19 files changed, 140 insertions(+), 318 deletions(-) diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr= .rs index dd55b1cb764d..01e8ba9e6de1 100644 --- a/drivers/gpu/drm/drm_panic_qr.rs +++ b/drivers/gpu/drm/drm_panic_qr.rs @@ -948,7 +948,7 @@ fn draw_all(&mut self, data: impl Iterator= ) { // nul-terminated string. let url_cstr: &CStr =3D unsafe { CStr::from_char_ptr(url) }; let segments =3D &[ - &Segment::Binary(url_cstr.as_bytes()), + &Segment::Binary(url_cstr.to_bytes()), &Segment::Numeric(&data_slice[0..data_len]), ]; match EncodedMsg::new(segments, tmp_slice) { diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index d2cfe1eeefb6..89d961407adb 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -111,8 +111,8 @@ macro_rules! module_auxiliary_driver { impl DeviceId { /// Create a new [`DeviceId`] from name. pub const fn new(modname: &'static CStr, name: &'static CStr) -> Self { - let name =3D name.as_bytes_with_nul(); - let modname =3D modname.as_bytes_with_nul(); + let name =3D name.to_bytes_with_nul(); + let modname =3D modname.to_bytes_with_nul(); =20 // TODO: Replace with `bindings::auxiliary_device_id::default()` o= nce stabilized for // `const`. diff --git a/rust/kernel/configfs.rs b/rust/kernel/configfs.rs index 34d0bea4f9a5..ee83692fbb1e 100644 --- a/rust/kernel/configfs.rs +++ b/rust/kernel/configfs.rs @@ -263,7 +263,7 @@ pub fn new( try_pin_init!(Self { group <- pin_init::zeroed().chain(|v: &mut Opaque| { let place =3D v.get(); - let name =3D name.as_bytes_with_nul().as_ptr(); + let name =3D name.to_bytes_with_nul().as_ptr(); // SAFETY: It is safe to initialize a group once it has be= en zeroed. unsafe { bindings::config_group_init_type_name(place, name.cast= (), item_type.as_ptr()) @@ -613,7 +613,7 @@ impl Attribute pub const fn new(name: &'static CStr) -> Self { Self { attribute: Opaque::new(bindings::configfs_attribute { - ca_name: name.as_char_ptr(), + ca_name: crate::str::as_char_ptr_in_const_context(name), ca_owner: core::ptr::null_mut(), ca_mode: 0o660, show: Some(Self::show), diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs index 11b03e9d7e89..e98fa609cbea 100644 --- a/rust/kernel/cpufreq.rs +++ b/rust/kernel/cpufreq.rs @@ -1018,7 +1018,7 @@ impl Registration { }; =20 const fn copy_name(name: &'static CStr) -> [c_char; CPUFREQ_NAME_LEN] { - let src =3D name.as_bytes_with_nul(); + let src =3D name.to_bytes_with_nul(); let mut dst =3D [0; CPUFREQ_NAME_LEN]; =20 build_assert!(src.len() <=3D CPUFREQ_NAME_LEN); diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index cdc6c8161e24..d2b6c1ce02a5 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -12,7 +12,7 @@ use core::{fmt, marker::PhantomData, ptr}; =20 #[cfg(CONFIG_PRINTK)] -use crate::c_str; +use crate::str::CStrExt as _; =20 /// A reference-counted device. /// @@ -197,7 +197,7 @@ unsafe fn printk(&self, klevel: &[u8], msg: fmt::Argume= nts<'_>) { bindings::_dev_printk( klevel as *const _ as *const crate::ffi::c_char, self.as_raw(), - c_str!("%pA").as_char_ptr(), + c"%pA".as_char_ptr(), &msg as *const _ as *const crate::ffi::c_void, ) }; diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs index 624d7a4c83ea..ec1642c9b7b9 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -83,8 +83,8 @@ impl Device { major: T::INFO.major, minor: T::INFO.minor, patchlevel: T::INFO.patchlevel, - name: T::INFO.name.as_char_ptr() as *mut _, - desc: T::INFO.desc.as_char_ptr() as *mut _, + name: crate::str::as_char_ptr_in_const_context(T::INFO.name) as *m= ut _, + desc: crate::str::as_char_ptr_in_const_context(T::INFO.desc) as *m= ut _, =20 driver_features: drm::driver::FEAT_GEM, ioctls: T::IOCTLS.as_ptr(), diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index 3dee3139fcd4..933c048c04f1 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -164,6 +164,8 @@ pub fn name(&self) -> Option<&'static CStr> { if ptr.is_null() { None } else { + use crate::str::CStrExt as _; + // SAFETY: The string returned by `errname` is static and `NUL= `-terminated. Some(unsafe { CStr::from_char_ptr(ptr) }) } @@ -188,7 +190,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Resul= t { Some(name) =3D> f .debug_tuple( // SAFETY: These strings are ASCII-only. - unsafe { core::str::from_utf8_unchecked(name) }, + unsafe { core::str::from_utf8_unchecked(name.to_bytes(= )) }, ) .finish(), } diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs index 2494c96e105f..582ab648b14c 100644 --- a/rust/kernel/firmware.rs +++ b/rust/kernel/firmware.rs @@ -4,7 +4,14 @@ //! //! C header: [`include/linux/firmware.h`](srctree/include/linux/firmware.= h) =20 -use crate::{bindings, device::Device, error::Error, error::Result, ffi, st= r::CStr}; +use crate::{ + bindings, + device::Device, + error::Error, + error::Result, + ffi, + str::{CStr, CStrExt as _}, +}; use core::ptr::NonNull; =20 /// # Invariants @@ -290,7 +297,7 @@ const fn push_module_name(self) -> Self { let module_name =3D this.module_name; =20 if !this.module_name.is_empty() { - this =3D this.push_internal(module_name.as_bytes_with_nul()); + this =3D this.push_internal(module_name.to_bytes_with_nul()); =20 if N !=3D 0 { // Re-use the space taken by the NULL terminator and swap = it with the '.' separator. diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs index 20ae65c2a18e..4927aa0b656e 100644 --- a/rust/kernel/kunit.rs +++ b/rust/kernel/kunit.rs @@ -99,12 +99,12 @@ unsafe impl Sync for Location {} unsafe impl Sync for UnaryAssert {} =20 static LOCATION: Location =3D Location($crate::bindings::kunit= _loc { - file: FILE.as_char_ptr(), + file: $crate::str::as_char_ptr_in_const_context(FILE), line: LINE, }); static ASSERTION: UnaryAssert =3D UnaryAssert($crate::bindings= ::kunit_unary_assert { assert: $crate::bindings::kunit_assert {}, - condition: CONDITION.as_char_ptr(), + condition: $crate::str::as_char_ptr_in_const_context(CONDI= TION), expected_true: true, }); =20 @@ -199,7 +199,7 @@ pub const fn kunit_case( ) -> kernel::bindings::kunit_case { kernel::bindings::kunit_case { run_case: Some(run_case), - name: name.as_char_ptr(), + name: kernel::str::as_char_ptr_in_const_context(name), attr: kernel::bindings::kunit_attributes { speed: kernel::bindings::kunit_speed_KUNIT_SPEED_NORMAL, }, diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs index 939278bc7b03..00e148d9ea97 100644 --- a/rust/kernel/miscdevice.rs +++ b/rust/kernel/miscdevice.rs @@ -35,7 +35,7 @@ pub const fn into_raw(self) -> bindings::m= iscdevice { // SAFETY: All zeros is valid for this C type. let mut result: bindings::miscdevice =3D unsafe { MaybeUninit::zer= oed().assume_init() }; result.minor =3D bindings::MISC_DYNAMIC_MINOR as _; - result.name =3D self.name.as_char_ptr(); + result.name =3D crate::str::as_char_ptr_in_const_context(self.name= ); result.fops =3D MiscdeviceVTable::::build(); result } diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs index 32ea43ece646..34239106bd27 100644 --- a/rust/kernel/net/phy.rs +++ b/rust/kernel/net/phy.rs @@ -505,7 +505,7 @@ unsafe impl Sync for DriverVTable {} pub const fn create_phy_driver() -> DriverVTable { // INVARIANT: All the fields of `struct phy_driver` are initialized pr= operly. DriverVTable(Opaque::new(bindings::phy_driver { - name: T::NAME.as_char_ptr().cast_mut(), + name: crate::str::as_char_ptr_in_const_context(T::NAME).cast_mut(), flags: T::FLAGS, phy_id: T::PHY_DEVICE_ID.id, phy_id_mask: T::PHY_DEVICE_ID.mask_as_int(), diff --git a/rust/kernel/of.rs b/rust/kernel/of.rs index 04f2d8ef29cb..12ea65df46de 100644 --- a/rust/kernel/of.rs +++ b/rust/kernel/of.rs @@ -29,7 +29,7 @@ fn index(&self) -> usize { impl DeviceId { /// Create a new device id from an OF 'compatible' string. pub const fn new(compatible: &'static CStr) -> Self { - let src =3D compatible.as_bytes_with_nul(); + let src =3D compatible.to_bytes_with_nul(); // Replace with `bindings::of_device_id::default()` once stabilize= d for `const`. // SAFETY: FFI type is valid to be zero-initialized. let mut of: bindings::of_device_id =3D unsafe { core::mem::zeroed(= ) }; diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index 41cebd906c4c..244b660fa835 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -40,7 +40,10 @@ =20 pub use super::error::{code::*, Error, Result}; =20 -pub use super::{str::CStr, ThisModule}; +pub use super::{ + str::{CStr, CStrExt as _}, + ThisModule, +}; =20 pub use super::init::InPlaceInit; =20 diff --git a/rust/kernel/seq_file.rs b/rust/kernel/seq_file.rs index 627bc2f7b3d2..1011743dd0ce 100644 --- a/rust/kernel/seq_file.rs +++ b/rust/kernel/seq_file.rs @@ -4,7 +4,7 @@ //! //! C header: [`include/linux/seq_file.h`](srctree/include/linux/seq_file.= h) =20 -use crate::{bindings, c_str, types::NotThreadSafe, types::Opaque}; +use crate::{bindings, str::CStrExt as _, types::NotThreadSafe, types::Opaq= ue}; =20 /// A utility for generating the contents of a seq file. #[repr(transparent)] @@ -36,7 +36,7 @@ pub fn call_printf(&self, args: core::fmt::Arguments<'_>)= { unsafe { bindings::seq_printf( self.inner.get(), - c_str!("%pA").as_char_ptr(), + c"%pA".as_char_ptr(), &args as *const _ as *const crate::ffi::c_void, ); } diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index 3ef99ba2e93c..e884ec1ce5c8 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -4,7 +4,7 @@ =20 use crate::alloc::{flags::*, AllocError, KVec}; use core::fmt::{self, Write}; -use core::ops::{self, Deref, DerefMut, Index}; +use core::ops::{Deref, DerefMut, Index}; =20 use crate::prelude::*; =20 @@ -57,11 +57,11 @@ impl crate::fmt::Display for BStr { /// # use kernel::{prelude::fmt, b_str, str::{BStr, CString}}; /// let ascii =3D b_str!("Hello, BStr!"); /// let s =3D CString::try_from_fmt(fmt!("{}", ascii))?; - /// assert_eq!(s.as_bytes(), "Hello, BStr!".as_bytes()); + /// assert_eq!(s.to_bytes(), "Hello, BStr!".as_bytes()); /// /// let non_ascii =3D b_str!("=F0=9F=A6=80"); /// let s =3D CString::try_from_fmt(fmt!("{}", non_ascii))?; - /// assert_eq!(s.as_bytes(), "\\xf0\\x9f\\xa6\\x80".as_bytes()); + /// assert_eq!(s.to_bytes(), "\\xf0\\x9f\\xa6\\x80".as_bytes()); /// # Ok::<(), kernel::error::Error>(()) /// ``` fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -89,11 +89,11 @@ impl fmt::Debug for BStr { /// // Embedded double quotes are escaped. /// let ascii =3D b_str!("Hello, \"BStr\"!"); /// let s =3D CString::try_from_fmt(fmt!("{:?}", ascii))?; - /// assert_eq!(s.as_bytes(), "\"Hello, \\\"BStr\\\"!\"".as_bytes()); + /// assert_eq!(s.to_bytes(), "\"Hello, \\\"BStr\\\"!\"".as_bytes()); /// /// let non_ascii =3D b_str!("=F0=9F=98=BA"); /// let s =3D CString::try_from_fmt(fmt!("{:?}", non_ascii))?; - /// assert_eq!(s.as_bytes(), "\"\\xf0\\x9f\\x98\\xba\"".as_bytes()); + /// assert_eq!(s.to_bytes(), "\"\\xf0\\x9f\\x98\\xba\"".as_bytes()); /// # Ok::<(), kernel::error::Error>(()) /// ``` fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -175,55 +175,19 @@ macro_rules! b_str { }}; } =20 -/// Possible errors when using conversion functions in [`CStr`]. -#[derive(Debug, Clone, Copy)] -pub enum CStrConvertError { - /// Supplied bytes contain an interior `NUL`. - InteriorNul, +pub use core::ffi::CStr; =20 - /// Supplied bytes are not terminated by `NUL`. - NotNulTerminated, +/// Returns a C pointer to the string. +// It is a free function rather than a method on an extension trait becaus= e: +// +// - error[E0379]: functions in trait impls cannot be declared const +#[inline] +pub const fn as_char_ptr_in_const_context(c_str: &CStr) -> *const crate::f= fi::c_char { + c_str.as_ptr().cast() } =20 -impl From for Error { - #[inline] - fn from(_: CStrConvertError) -> Error { - EINVAL - } -} - -/// A string that is guaranteed to have exactly one `NUL` byte, which is a= t the -/// end. -/// -/// Used for interoperability with kernel APIs that take C strings. -#[repr(transparent)] -pub struct CStr([u8]); - -impl CStr { - /// Returns the length of this string excluding `NUL`. - #[inline] - pub const fn len(&self) -> usize { - self.len_with_nul() - 1 - } - - /// Returns the length of this string with `NUL`. - #[inline] - pub const fn len_with_nul(&self) -> usize { - if self.0.is_empty() { - // SAFETY: This is one of the invariant of `CStr`. - // We add a `unreachable_unchecked` here to hint the optimizer= that - // the value returned from this function is non-zero. - unsafe { core::hint::unreachable_unchecked() }; - } - self.0.len() - } - - /// Returns `true` if the string only includes `NUL`. - #[inline] - pub const fn is_empty(&self) -> bool { - self.len() =3D=3D 0 - } - +/// Extensions to [`CStr`]. +pub trait CStrExt { /// Wraps a raw C string pointer. /// /// # Safety @@ -231,54 +195,9 @@ pub const fn is_empty(&self) -> bool { /// `ptr` must be a valid pointer to a `NUL`-terminated C string, and = it must /// last at least `'a`. When `CStr` is alive, the memory pointed by `p= tr` /// must not be mutated. - #[inline] - pub unsafe fn from_char_ptr<'a>(ptr: *const crate::ffi::c_char) -> &'a= Self { - // SAFETY: The safety precondition guarantees `ptr` is a valid poi= nter - // to a `NUL`-terminated C string. - let len =3D unsafe { bindings::strlen(ptr) } + 1; - // SAFETY: Lifetime guaranteed by the safety precondition. - let bytes =3D unsafe { core::slice::from_raw_parts(ptr as _, len) = }; - // SAFETY: As `len` is returned by `strlen`, `bytes` does not cont= ain interior `NUL`. - // As we have added 1 to `len`, the last byte is known to be `NUL`. - unsafe { Self::from_bytes_with_nul_unchecked(bytes) } - } - - /// Creates a [`CStr`] from a `[u8]`. - /// - /// The provided slice must be `NUL`-terminated, does not contain any - /// interior `NUL` bytes. - pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, CStrCo= nvertError> { - if bytes.is_empty() { - return Err(CStrConvertError::NotNulTerminated); - } - if bytes[bytes.len() - 1] !=3D 0 { - return Err(CStrConvertError::NotNulTerminated); - } - let mut i =3D 0; - // `i + 1 < bytes.len()` allows LLVM to optimize away bounds check= ing, - // while it couldn't optimize away bounds checks for `i < bytes.le= n() - 1`. - while i + 1 < bytes.len() { - if bytes[i] =3D=3D 0 { - return Err(CStrConvertError::InteriorNul); - } - i +=3D 1; - } - // SAFETY: We just checked that all properties hold. - Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) }) - } - - /// Creates a [`CStr`] from a `[u8]` without performing any additional - /// checks. - /// - /// # Safety - /// - /// `bytes` *must* end with a `NUL` byte, and should only have a single - /// `NUL` byte (or the string will be truncated). - #[inline] - pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CS= tr { - // SAFETY: Properties of `bytes` guaranteed by the safety precondi= tion. - unsafe { core::mem::transmute(bytes) } - } + // This function exists to paper over the fact that `CStr::from_ptr` t= akes a `*const + // core::ffi::c_char` rather than a `*const crate::ffi::c_char`. + unsafe fn from_char_ptr<'a>(ptr: *const crate::ffi::c_char) -> &'a Sel= f; =20 /// Creates a mutable [`CStr`] from a `[u8]` without performing any /// additional checks. @@ -287,77 +206,16 @@ pub const fn from_bytes_with_nul(bytes: &[u8]) -> Res= ult<&Self, CStrConvertError /// /// `bytes` *must* end with a `NUL` byte, and should only have a single /// `NUL` byte (or the string will be truncated). - #[inline] - pub unsafe fn from_bytes_with_nul_unchecked_mut(bytes: &mut [u8]) -> &= mut CStr { - // SAFETY: Properties of `bytes` guaranteed by the safety precondi= tion. - unsafe { &mut *(bytes as *mut [u8] as *mut CStr) } - } + unsafe fn from_bytes_with_nul_unchecked_mut(bytes: &mut [u8]) -> &mut = Self; =20 /// Returns a C pointer to the string. - #[inline] - pub const fn as_char_ptr(&self) -> *const crate::ffi::c_char { - self.0.as_ptr() - } - - /// Convert the string to a byte slice without the trailing `NUL` byte. - #[inline] - pub fn as_bytes(&self) -> &[u8] { - &self.0[..self.len()] - } - - /// Convert the string to a byte slice containing the trailing `NUL` b= yte. - #[inline] - pub const fn as_bytes_with_nul(&self) -> &[u8] { - &self.0 - } - - /// Yields a [`&str`] slice if the [`CStr`] contains valid UTF-8. - /// - /// If the contents of the [`CStr`] are valid UTF-8 data, this - /// function will return the corresponding [`&str`] slice. Otherwise, - /// it will return an error with details of where UTF-8 validation fai= led. - /// - /// # Examples - /// - /// ``` - /// # use kernel::str::CStr; - /// let cstr =3D CStr::from_bytes_with_nul(b"foo\0")?; - /// assert_eq!(cstr.to_str(), Ok("foo")); - /// # Ok::<(), kernel::error::Error>(()) - /// ``` - #[inline] - pub fn to_str(&self) -> Result<&str, core::str::Utf8Error> { - core::str::from_utf8(self.as_bytes()) - } - - /// Unsafely convert this [`CStr`] into a [`&str`], without checking f= or - /// valid UTF-8. - /// - /// # Safety - /// - /// The contents must be valid UTF-8. - /// - /// # Examples - /// - /// ``` - /// # use kernel::c_str; - /// # use kernel::str::CStr; - /// let bar =3D c_str!("=E3=83=84"); - /// // SAFETY: String literals are guaranteed to be valid UTF-8 - /// // by the Rust compiler. - /// assert_eq!(unsafe { bar.as_str_unchecked() }, "=E3=83=84"); - /// ``` - #[inline] - pub unsafe fn as_str_unchecked(&self) -> &str { - // SAFETY: TODO. - unsafe { core::str::from_utf8_unchecked(self.as_bytes()) } - } + // This function exists to paper over the fact that `CStr::as_ptr` ret= urns a `*const + // core::ffi::c_char` rather than a `*const crate::ffi::c_char`. + fn as_char_ptr(&self) -> *const crate::ffi::c_char; =20 /// Convert this [`CStr`] into a [`CString`] by allocating memory and /// copying over the string data. - pub fn to_cstring(&self) -> Result { - CString::try_from(self) - } + fn to_cstring(&self) -> Result; =20 /// Converts this [`CStr`] to its ASCII lower case equivalent in-place. /// @@ -368,11 +226,7 @@ pub fn to_cstring(&self) -> Result { /// [`to_ascii_lowercase()`]. /// /// [`to_ascii_lowercase()`]: #method.to_ascii_lowercase - pub fn make_ascii_lowercase(&mut self) { - // INVARIANT: This doesn't introduce or remove NUL bytes in the C - // string. - self.0.make_ascii_lowercase(); - } + fn make_ascii_lowercase(&mut self); =20 /// Converts this [`CStr`] to its ASCII upper case equivalent in-place. /// @@ -383,11 +237,7 @@ pub fn make_ascii_lowercase(&mut self) { /// [`to_ascii_uppercase()`]. /// /// [`to_ascii_uppercase()`]: #method.to_ascii_uppercase - pub fn make_ascii_uppercase(&mut self) { - // INVARIANT: This doesn't introduce or remove NUL bytes in the C - // string. - self.0.make_ascii_uppercase(); - } + fn make_ascii_uppercase(&mut self); =20 /// Returns a copy of this [`CString`] where each character is mapped = to its /// ASCII lower case equivalent. @@ -398,13 +248,7 @@ pub fn make_ascii_uppercase(&mut self) { /// To lowercase the value in-place, use [`make_ascii_lowercase`]. /// /// [`make_ascii_lowercase`]: str::make_ascii_lowercase - pub fn to_ascii_lowercase(&self) -> Result { - let mut s =3D self.to_cstring()?; - - s.make_ascii_lowercase(); - - Ok(s) - } + fn to_ascii_lowercase(&self) -> Result; =20 /// Returns a copy of this [`CString`] where each character is mapped = to its /// ASCII upper case equivalent. @@ -415,13 +259,7 @@ pub fn to_ascii_lowercase(&self) -> Result { /// To uppercase the value in-place, use [`make_ascii_uppercase`]. /// /// [`make_ascii_uppercase`]: str::make_ascii_uppercase - pub fn to_ascii_uppercase(&self) -> Result { - let mut s =3D self.to_cstring()?; - - s.make_ascii_uppercase(); - - Ok(s) - } + fn to_ascii_uppercase(&self) -> Result; } =20 impl crate::fmt::Display for CStr { @@ -434,15 +272,15 @@ impl crate::fmt::Display for CStr { /// # use kernel::str::CString; /// let penguin =3D c_str!("=F0=9F=90=A7"); /// let s =3D CString::try_from_fmt(fmt!("{}", penguin))?; - /// assert_eq!(s.as_bytes_with_nul(), "\\xf0\\x9f\\x90\\xa7\0".as_byte= s()); + /// assert_eq!(s.to_bytes_with_nul(), "\\xf0\\x9f\\x90\\xa7\0".as_byte= s()); /// /// let ascii =3D c_str!("so \"cool\""); /// let s =3D CString::try_from_fmt(fmt!("{}", ascii))?; - /// assert_eq!(s.as_bytes_with_nul(), "so \"cool\"\0".as_bytes()); + /// assert_eq!(s.to_bytes_with_nul(), "so \"cool\"\0".as_bytes()); /// # Ok::<(), kernel::error::Error>(()) /// ``` fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for &c in self.as_bytes() { + for &c in self.to_bytes() { if (0x20..0x7f).contains(&c) { // Printable character. f.write_char(c as char)?; @@ -454,98 +292,75 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Res= ult { } } =20 -impl fmt::Debug for CStr { - /// Formats printable ASCII characters with a double quote on either e= nd, escaping the rest. - /// - /// ``` - /// # use kernel::c_str; - /// # use kernel::prelude::fmt; - /// # use kernel::str::CStr; - /// # use kernel::str::CString; - /// let penguin =3D c_str!("=F0=9F=90=A7"); - /// let s =3D CString::try_from_fmt(fmt!("{:?}", penguin))?; - /// assert_eq!(s.as_bytes_with_nul(), "\"\\xf0\\x9f\\x90\\xa7\"\0".as_= bytes()); - /// - /// // Embedded double quotes are escaped. - /// let ascii =3D c_str!("so \"cool\""); - /// let s =3D CString::try_from_fmt(fmt!("{:?}", ascii))?; - /// assert_eq!(s.as_bytes_with_nul(), "\"so \\\"cool\\\"\"\0".as_bytes= ()); - /// # Ok::<(), kernel::error::Error>(()) - /// ``` - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("\"")?; - for &c in self.as_bytes() { - match c { - // Printable characters. - b'\"' =3D> f.write_str("\\\"")?, - 0x20..=3D0x7e =3D> f.write_char(c as char)?, - _ =3D> write!(f, "\\x{c:02x}")?, - } - } - f.write_str("\"") - } +/// Converts a mutable C string to a mutable byte slice. +/// +/// # Safety +/// +/// The caller must ensure that the slice ends in a NUL byte and contains = no other NUL bytes before +/// the borrow ends and the underlying [`CStr`] is used. +unsafe fn to_bytes_mut(s: &mut CStr) -> &mut [u8] { + // SAFETY: the cast from `&CStr` to `&[u8]` is safe since `CStr` has t= he same layout as `&[u8]` + // (this is technically not guaranteed, but we rely on it here). The p= ointer dereference is + // safe since it comes from a mutable reference which is guaranteed to= be valid for writes. + unsafe { &mut *(s as *mut CStr as *mut [u8]) } } =20 -impl AsRef for CStr { +impl CStrExt for CStr { #[inline] - fn as_ref(&self) -> &BStr { - BStr::from_bytes(self.as_bytes()) + unsafe fn from_char_ptr<'a>(ptr: *const crate::ffi::c_char) -> &'a Sel= f { + // SAFETY: The safety preconditions are the same as for `CStr::fro= m_ptr`. + unsafe { CStr::from_ptr(ptr.cast()) } } -} =20 -impl Deref for CStr { - type Target =3D BStr; + #[inline] + unsafe fn from_bytes_with_nul_unchecked_mut(bytes: &mut [u8]) -> &mut = Self { + // SAFETY: the cast from `&[u8]` to `&CStr` is safe since the prop= erties of `bytes` are + // guaranteed by the safety precondition and `CStr` has the same l= ayout as `&[u8]` (this is + // technically not guaranteed, but we rely on it here). The pointe= r dereference is safe + // since it comes from a mutable reference which is guaranteed to = be valid for writes. + unsafe { &mut *(bytes as *mut [u8] as *mut CStr) } + } =20 #[inline] - fn deref(&self) -> &Self::Target { - self.as_ref() + fn as_char_ptr(&self) -> *const crate::ffi::c_char { + self.as_ptr().cast() } -} =20 -impl Index> for CStr { - type Output =3D CStr; + fn to_cstring(&self) -> Result { + CString::try_from(self) + } =20 - #[inline] - fn index(&self, index: ops::RangeFrom) -> &Self::Output { - // Delegate bounds checking to slice. - // Assign to _ to mute clippy's unnecessary operation warning. - let _ =3D &self.as_bytes()[index.start..]; - // SAFETY: We just checked the bounds. - unsafe { Self::from_bytes_with_nul_unchecked(&self.0[index.start..= ]) } + fn make_ascii_lowercase(&mut self) { + // SAFETY: This doesn't introduce or remove NUL bytes in the C str= ing. + unsafe { to_bytes_mut(self) }.make_ascii_lowercase(); } -} =20 -impl Index for CStr { - type Output =3D CStr; + fn make_ascii_uppercase(&mut self) { + // SAFETY: This doesn't introduce or remove NUL bytes in the C str= ing. + unsafe { to_bytes_mut(self) }.make_ascii_uppercase(); + } =20 - #[inline] - fn index(&self, _index: ops::RangeFull) -> &Self::Output { - self + fn to_ascii_lowercase(&self) -> Result { + let mut s =3D self.to_cstring()?; + + s.make_ascii_lowercase(); + + Ok(s) } -} =20 -mod private { - use core::ops; + fn to_ascii_uppercase(&self) -> Result { + let mut s =3D self.to_cstring()?; =20 - // Marker trait for index types that can be forward to `BStr`. - pub trait CStrIndex {} + s.make_ascii_uppercase(); =20 - impl CStrIndex for usize {} - impl CStrIndex for ops::Range {} - impl CStrIndex for ops::RangeInclusive {} - impl CStrIndex for ops::RangeToInclusive {} + Ok(s) + } } =20 -impl Index for CStr -where - Idx: private::CStrIndex, - BStr: Index, -{ - type Output =3D >::Output; - +impl AsRef for CStr { #[inline] - fn index(&self, index: Idx) -> &Self::Output { - &self.as_ref()[index] + fn as_ref(&self) -> &BStr { + BStr::from_bytes(self.to_bytes()) } } =20 @@ -576,6 +391,13 @@ macro_rules! c_str { mod tests { use super::*; =20 + impl From for Error { + #[inline] + fn from(_: core::ffi::FromBytesWithNulError) -> Error { + EINVAL + } + } + macro_rules! format { ($($f:tt)*) =3D> ({ CString::try_from_fmt(crate::prelude::fmt!($($f)*))?.to_str()? @@ -598,40 +420,28 @@ macro_rules! format { =20 #[test] fn test_cstr_to_str() -> Result { - let good_bytes =3D b"\xf0\x9f\xa6\x80\0"; - let checked_cstr =3D CStr::from_bytes_with_nul(good_bytes)?; - let checked_str =3D checked_cstr.to_str()?; + let cstr =3D c"\xf0\x9f\xa6\x80"; + let checked_str =3D cstr.to_str()?; assert_eq!(checked_str, "=F0=9F=A6=80"); Ok(()) } =20 #[test] fn test_cstr_to_str_invalid_utf8() -> Result { - let bad_bytes =3D b"\xc3\x28\0"; - let checked_cstr =3D CStr::from_bytes_with_nul(bad_bytes)?; - assert!(checked_cstr.to_str().is_err()); - Ok(()) - } - - #[test] - fn test_cstr_as_str_unchecked() -> Result { - let good_bytes =3D b"\xf0\x9f\x90\xA7\0"; - let checked_cstr =3D CStr::from_bytes_with_nul(good_bytes)?; - // SAFETY: The contents come from a string literal which contains = valid UTF-8. - let unchecked_str =3D unsafe { checked_cstr.as_str_unchecked() }; - assert_eq!(unchecked_str, "=F0=9F=90=A7"); + let cstr =3D c"\xc3\x28"; + assert!(cstr.to_str().is_err()); Ok(()) } =20 #[test] fn test_cstr_display() -> Result { - let hello_world =3D CStr::from_bytes_with_nul(b"hello, world!\0")?; + let hello_world =3D c"hello, world!"; assert_eq!(format!("{hello_world}"), "hello, world!"); - let non_printables =3D CStr::from_bytes_with_nul(b"\x01\x09\x0a\0"= )?; + let non_printables =3D c"\x01\x09\x0a"; assert_eq!(format!("{non_printables}"), "\\x01\\x09\\x0a"); - let non_ascii =3D CStr::from_bytes_with_nul(b"d\xe9j\xe0 vu\0")?; + let non_ascii =3D c"d\xe9j\xe0 vu"; assert_eq!(format!("{non_ascii}"), "d\\xe9j\\xe0 vu"); - let good_bytes =3D CStr::from_bytes_with_nul(b"\xf0\x9f\xa6\x80\0"= )?; + let good_bytes =3D c"\xf0\x9f\xa6\x80"; assert_eq!(format!("{good_bytes}"), "\\xf0\\x9f\\xa6\\x80"); Ok(()) } @@ -650,13 +460,13 @@ fn test_cstr_display_all_bytes() -> Result { =20 #[test] fn test_cstr_debug() -> Result { - let hello_world =3D CStr::from_bytes_with_nul(b"hello, world!\0")?; + let hello_world =3D c"hello, world!"; assert_eq!(format!("{hello_world:?}"), "\"hello, world!\""); - let non_printables =3D CStr::from_bytes_with_nul(b"\x01\x09\x0a\0"= )?; - assert_eq!(format!("{non_printables:?}"), "\"\\x01\\x09\\x0a\""); - let non_ascii =3D CStr::from_bytes_with_nul(b"d\xe9j\xe0 vu\0")?; + let non_printables =3D c"\x01\x09\x0a"; + assert_eq!(format!("{non_printables:?}"), "\"\\x01\\t\\n\""); + let non_ascii =3D c"d\xe9j\xe0 vu"; assert_eq!(format!("{non_ascii:?}"), "\"d\\xe9j\\xe0 vu\""); - let good_bytes =3D CStr::from_bytes_with_nul(b"\xf0\x9f\xa6\x80\0"= )?; + let good_bytes =3D c"\xf0\x9f\xa6\x80"; assert_eq!(format!("{good_bytes:?}"), "\"\\xf0\\x9f\\xa6\\x80\""); Ok(()) } @@ -843,11 +653,11 @@ fn write_str(&mut self, s: &str) -> fmt::Result { /// use kernel::{str::CString, prelude::fmt}; /// /// let s =3D CString::try_from_fmt(fmt!("{}{}{}", "abc", 10, 20))?; -/// assert_eq!(s.as_bytes_with_nul(), "abc1020\0".as_bytes()); +/// assert_eq!(s.to_bytes_with_nul(), "abc1020\0".as_bytes()); /// /// let tmp =3D "testing"; /// let s =3D CString::try_from_fmt(fmt!("{tmp}{}", 123))?; -/// assert_eq!(s.as_bytes_with_nul(), "testing123\0".as_bytes()); +/// assert_eq!(s.to_bytes_with_nul(), "testing123\0".as_bytes()); /// /// // This fails because it has an embedded `NUL` byte. /// let s =3D CString::try_from_fmt(fmt!("a\0b{}", 123)); @@ -917,7 +727,7 @@ impl<'a> TryFrom<&'a CStr> for CString { fn try_from(cstr: &'a CStr) -> Result { let mut buf =3D KVec::new(); =20 - buf.extend_from_slice(cstr.as_bytes_with_nul(), GFP_KERNEL)?; + buf.extend_from_slice(cstr.to_bytes_with_nul(), GFP_KERNEL)?; =20 // INVARIANT: The `CStr` and `CString` types have the same invaria= nts for // the string data, and we copied it over without changes. diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs index caebf03f553b..0b6bc7f2878d 100644 --- a/rust/kernel/sync/condvar.rs +++ b/rust/kernel/sync/condvar.rs @@ -8,7 +8,7 @@ use super::{lock::Backend, lock::Guard, LockClassKey}; use crate::{ ffi::{c_int, c_long}, - str::CStr, + str::{CStr, CStrExt as _}, task::{ MAX_SCHEDULE_TIMEOUT, TASK_FREEZABLE, TASK_INTERRUPTIBLE, TASK_NOR= MAL, TASK_UNINTERRUPTIBLE, }, diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index e82fa5be289c..a777a22976e0 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -7,7 +7,7 @@ =20 use super::LockClassKey; use crate::{ - str::CStr, + str::{CStr, CStrExt as _}, types::{NotThreadSafe, Opaque, ScopeGuard}, }; use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin}; diff --git a/rust/kernel/sync/lock/global.rs b/rust/kernel/sync/lock/global= .rs index d65f94b5caf2..79d0ef7fda86 100644 --- a/rust/kernel/sync/lock/global.rs +++ b/rust/kernel/sync/lock/global.rs @@ -5,7 +5,7 @@ //! Support for defining statics containing locks. =20 use crate::{ - str::CStr, + str::{CStr, CStrExt as _}, sync::lock::{Backend, Guard, Lock}, sync::{LockClassKey, LockedBy}, types::Opaque, diff --git a/samples/rust/rust_configfs.rs b/samples/rust/rust_configfs.rs index 60ddbe62cda3..02641dc06f25 100644 --- a/samples/rust/rust_configfs.rs +++ b/samples/rust/rust_configfs.rs @@ -94,7 +94,7 @@ impl configfs::AttributeOperations<0> for Configuration { =20 fn show(container: &Configuration, page: &mut [u8; PAGE_SIZE]) -> Resu= lt { pr_info!("Show message\n"); - let data =3D container.message; + let data =3D container.message.to_bytes(); page[0..data.len()].copy_from_slice(data); Ok(data.len()) } --=20 2.50.0 From nobody Thu Oct 9 06:05:19 2025 Received: from mail-qt1-f174.google.com (mail-qt1-f174.google.com [209.85.160.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 35E4B28B7FD; Thu, 19 Jun 2025 15:06:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750345606; cv=none; b=JDCR7k53BMAOQ+UCLxky2lKeOkZCpHFLAE2znYe0jYeWANWwnYS4wxMSpszeMfrx1VXCMiMP7chlV6qaom7hidq45aMQW8Laets7Z3OCk6uI6xYyLKU6v525hSK8PlIjwgBYWMLQd+bLdGCvWr9kVXK4aBN0xWpY+8F9jzP57kA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750345606; c=relaxed/simple; bh=eLZgSchp1Ugjy829Sx2jlauFP/5MYsUhNyk3ALWLH24=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ER0PdK9ZkuUVCkSOeKabOq47BmgOj571HJJDc5BKDJUt+d1ePsg3XAYTZKTADpzf+0XYdvCgLq/umvbgygDBADtN56CPmxzpdNaA3wxvVyW2pBmMXRmvfH+5K5/Jl1KzbpaIp8Wha7qv2MHDch+dZqxwSpDIY60eRYt2AVKJQhk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=j6CSNt+t; arc=none smtp.client-ip=209.85.160.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="j6CSNt+t" Received: by mail-qt1-f174.google.com with SMTP id d75a77b69052e-4a5851764e1so16273951cf.2; Thu, 19 Jun 2025 08:06:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1750345602; x=1750950402; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=5xoCQMyUZdiymxphEC03ILw2GU1bmk/Og/jkmdkTje0=; b=j6CSNt+tAA+Ffp67dMg9BFoP20cI2QQIgixdsZiJyHDg+7DjZmwH/Wu7EZyeaCBS61 cN2aniKfShMGPGK/OlLH7r3CEPEkRqZ8GpyeI/AjcOEq8DpporkXtYAM6eJy8qPnrAd8 D2lkW16kX7P4O10OqrUqy99w5ipqUaY17HcKRCqqBpI7gMYgoQ0vQ8hxiSe36FFmnS/3 xM4h97zgJrmuEMtWlqRruAvKn8fMD288zPlHPob5InnGVkWBUDMtATVpZv0WOR7W+eyW wxntV/AgLC6lz8u+/51gS4Pmyq6bfqRc5hbhxa22s2ra8Ia/agAGON/IX/dkinFH++S6 VExw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750345602; x=1750950402; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5xoCQMyUZdiymxphEC03ILw2GU1bmk/Og/jkmdkTje0=; b=ddE+bUrFdB43GLMGIGx9inYaBS5Byte23Y0igRZfltEi4gIzHM6NPJRcxsPJfgLbnL twx/y8jE2Y954qIc3yTknf+REnX5UMxfkxN8zlnjLIlf6ep2VzFQxkv6DaFu9APlEN1y 31hthqnFHd3DF90gp3tE41Ls/B+euiJ9lYLKtEM5b09cr4BFMh/jVvp91xNGTIhiDlTe IUbFoeW6Qh9bWhI4BMxNHfneJoKIZqiLR3zgZHyLGG95MGOPvGBKQ9rVhx5siXpsIEEj /FuD1aocOzKRyl5X1hEyv89XgWva2Dx/EVhF9qoZa5U2NnHbgtN8OUiOl8NoVlLMBdjr VlVA== X-Forwarded-Encrypted: i=1; AJvYcCW48NVRe2ErYyIX96kV2j2L1KgL8g6DCQ6tp/RScNPlxLQEYUTr8BxZu5Gs4Kldd+blJ/vVweJlQkY=@vger.kernel.org, AJvYcCWLHf2tKRhRo2YY53CCe7nuM8wyjJytGTTSWuywPf+8Ouhx1ekmKGXlXy6wNH+wl4mTKqNCfv5jO0J0@vger.kernel.org, AJvYcCWSMEUMXUohwhGtxCGTdvkW2fNW4lvz52cJRS9Q7GqwtJ9EssPoUyz2I5VAe2OtXW96ft34qR/Y@vger.kernel.org, AJvYcCWberZ7ZBwGY3C+DgD7n4VOyLyOG0ABT3zUs+GXK07Wt19mUVlGMHXnIBs3Ayo+OfH0UaL/3accpfSCAXX5@vger.kernel.org, AJvYcCWlB4E0qwWw881iKdQuHysVD+VdaVYv+zivezfM6qcQ9H5f0hR0PEqMbuj1NDEJobiVCuMx6czY22GChxEHR0l+@vger.kernel.org, AJvYcCWrA0xZ1R0JI4EO8nVpgiU4J/QWWVZWT1lCOjna6LVo7gDer3Xv4bc9UWerl7vgf1i646cqS+AWRlxx@vger.kernel.org, AJvYcCXR62wxvLZo1xWntoH2rzNJf7qFI+aS/cC4cL9szeU3W/FdUpS50+J5MUJqbrujO53ic1nL1WqNgjhz4m8=@vger.kernel.org, AJvYcCXtCjeZ0WuwswAaeIlKtXsIGg3Lu1mXnKphku+cjopFC9CUoRIfqU2kpOzDGvuUAPo3yiId2AsH7IWd@vger.kernel.org X-Gm-Message-State: AOJu0YxDaAvItVTU1egI6a+2JRcEWrdfW6YKNJMO0sFRg86iyruKBhBz sve4pLJ2Q8Lm34l5yp2KrENJlAdCVw4BHgR66QKmGBR+LnBVUdNNTwU9 X-Gm-Gg: ASbGnctpXwSV7Pn06uOutqQkau6L2gcUBY6O8moSyljlqn71U8QsaD4xPUUpvgeDk/m wH/mSgQG5iFAcMASyp7kEBPYA5jll31LAWfZ4fikTqu1/hLuAKN599FSqJPLCN6QfaqdBRTL0uj mGuhqHfpMYUD/G8WYaME+h+LQqG58yOLcL8CTpUW3mzvZauxAwL+euxYRBDcKVtCs5ZZ/YGZL7v dX1NnQI+rk5D5/K8Z6pBOg+GlOOp4yGN2mgvGWvekibLW2XiJ0VTLrY1NvNrWgR7a4JEFso0MX3 lWoOGVCEmMaeSP03OFyPM7Yyl2eRc/uytzgkLl1lhbVhQksN6yljn26gUm8IH23G818mpDCNi5A = X-Google-Smtp-Source: AGHT+IEqmTpc96rboKslmuRTquphlyw0Zcc9gekEPB0vHF2vqy/jAPnfqpoCelyKrMnO6WiuC0UBsA== X-Received: by 2002:ac8:668e:0:b0:4a4:4103:f301 with SMTP id d75a77b69052e-4a747b33f90mr243573421cf.0.1750345601664; Thu, 19 Jun 2025 08:06:41 -0700 (PDT) Received: from tamird-mac.local ([2600:4041:5be7:7c00:5c8a:fc6a:b57c:e57f]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-4a7785aaacdsm250531cf.39.2025.06.19.08.06.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Jun 2025 08:06:41 -0700 (PDT) From: Tamir Duberstein Date: Thu, 19 Jun 2025 11:06:28 -0400 Subject: [PATCH v12 4/5] rust: replace `kernel::c_str!` with C-Strings Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250619-cstr-core-v12-4-80c9c7b45900@gmail.com> References: <20250619-cstr-core-v12-0-80c9c7b45900@gmail.com> In-Reply-To: <20250619-cstr-core-v12-0-80c9c7b45900@gmail.com> To: Michal Rostecki , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Andreas Hindborg , Alice Ryhl , Trevor Gross , Brendan Higgins , David Gow , Rae Moar , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Greg Kroah-Hartman , "Rafael J. Wysocki" , Luis Chamberlain , Russ Weight , FUJITA Tomonori , Rob Herring , Saravana Kannan , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Bjorn Helgaas , Arnd Bergmann , Jens Axboe , Benno Lossin , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Dave Ertman , Ira Weiny , Leon Romanovsky , Breno Leitao , Viresh Kumar , Michael Turquette , Stephen Boyd Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, dri-devel@lists.freedesktop.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, llvm@lists.linux.dev, linux-pci@vger.kernel.org, nouveau@lists.freedesktop.org, linux-block@vger.kernel.org, linux-pm@vger.kernel.org, linux-clk@vger.kernel.org, Tamir Duberstein X-Mailer: b4 0.15-dev C-String literals were added in Rust 1.77. Replace instances of `kernel::c_str!` with C-String literals where possible and rename `kernel::c_str!` to `str_to_cstr!` to clarify its intended use. Closes: https://github.com/Rust-for-Linux/linux/issues/1075 Signed-off-by: Tamir Duberstein Acked-by: Greg Kroah-Hartman Acked-by: Stephen Boyd # clk Acked-by: Viresh Kumar Reviewed-by: Alice Ryhl --- drivers/block/rnull.rs | 2 +- drivers/cpufreq/rcpufreq_dt.rs | 5 ++--- drivers/gpu/drm/nova/driver.rs | 10 +++++----- drivers/gpu/nova-core/driver.rs | 6 +++--- drivers/net/phy/ax88796b_rust.rs | 7 +++---- drivers/net/phy/qt2025.rs | 5 ++--- rust/kernel/clk.rs | 6 ++---- rust/kernel/configfs.rs | 9 +++++---- rust/kernel/cpufreq.rs | 3 +-- rust/kernel/devres.rs | 2 +- rust/kernel/drm/ioctl.rs | 2 +- rust/kernel/firmware.rs | 6 +++--- rust/kernel/kunit.rs | 7 ++++--- rust/kernel/net/phy.rs | 6 ++---- rust/kernel/platform.rs | 4 ++-- rust/kernel/str.rs | 24 ++++++++++++++++-------- rust/kernel/sync.rs | 7 +++---- rust/kernel/sync/lock/global.rs | 3 ++- rust/kernel/workqueue.rs | 8 ++++---- rust/macros/kunit.rs | 10 +++++----- rust/macros/module.rs | 2 +- samples/rust/rust_configfs.rs | 5 ++--- samples/rust/rust_driver_auxiliary.rs | 4 ++-- samples/rust/rust_driver_faux.rs | 4 ++-- samples/rust/rust_driver_pci.rs | 4 ++-- samples/rust/rust_driver_platform.rs | 4 ++-- samples/rust/rust_misc_device.rs | 3 +-- scripts/rustdoc_test_gen.rs | 4 ++-- 28 files changed, 81 insertions(+), 81 deletions(-) diff --git a/drivers/block/rnull.rs b/drivers/block/rnull.rs index 6366da12c5a5..9aa79b862b63 100644 --- a/drivers/block/rnull.rs +++ b/drivers/block/rnull.rs @@ -55,7 +55,7 @@ fn init(_module: &'static ThisModule) -> impl PinInit { })(); =20 try_pin_init!(Self { - _disk <- new_mutex!(disk?, "nullb:disk"), + _disk <- new_mutex!(disk?, c"nullb:disk"), }) } } diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs index 43c87d0259b6..9056298fffda 100644 --- a/drivers/cpufreq/rcpufreq_dt.rs +++ b/drivers/cpufreq/rcpufreq_dt.rs @@ -3,7 +3,6 @@ //! Rust based implementation of the cpufreq-dt driver. =20 use kernel::{ - c_str, clk::Clk, cpu, cpufreq, cpumask::CpumaskVar, @@ -56,7 +55,7 @@ impl opp::ConfigOps for CPUFreqDTDriver {} =20 #[vtable] impl cpufreq::Driver for CPUFreqDTDriver { - const NAME: &'static CStr =3D c_str!("cpufreq-dt"); + const NAME: &'static CStr =3D c"cpufreq-dt"; const FLAGS: u16 =3D cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpufreq= ::flags::IS_COOLING_DEV; const BOOST_ENABLED: bool =3D true; =20 @@ -201,7 +200,7 @@ fn register_em(policy: &mut cpufreq::Policy) { OF_TABLE, MODULE_OF_TABLE, ::IdInfo, - [(of::DeviceId::new(c_str!("operating-points-v2")), ())] + [(of::DeviceId::new(c"operating-points-v2"), ())] ); =20 impl platform::Driver for CPUFreqDTDriver { diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs index b28b2e05cc15..87480ee8dbae 100644 --- a/drivers/gpu/drm/nova/driver.rs +++ b/drivers/gpu/drm/nova/driver.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 =20 -use kernel::{auxiliary, c_str, device::Core, drm, drm::gem, drm::ioctl, pr= elude::*, types::ARef}; +use kernel::{auxiliary, device::Core, drm, drm::gem, drm::ioctl, prelude::= *, types::ARef}; =20 use crate::file::File; use crate::gem::NovaObject; @@ -22,12 +22,12 @@ pub(crate) struct NovaData { major: 0, minor: 0, patchlevel: 0, - name: c_str!("nova"), - desc: c_str!("Nvidia Graphics"), + name: c"nova", + desc: c"Nvidia Graphics", }; =20 -const NOVA_CORE_MODULE_NAME: &CStr =3D c_str!("NovaCore"); -const AUXILIARY_NAME: &CStr =3D c_str!("nova-drm"); +const NOVA_CORE_MODULE_NAME: &CStr =3D c"NovaCore"; +const AUXILIARY_NAME: &CStr =3D c"nova-drm"; =20 kernel::auxiliary_device_table!( AUX_TABLE, diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index 8c86101c26cb..d76e992021ca 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 =20 -use kernel::{auxiliary, bindings, c_str, device::Core, pci, prelude::*}; +use kernel::{auxiliary, bindings, device::Core, pci, prelude::*}; =20 use crate::gpu::Gpu; =20 @@ -34,14 +34,14 @@ fn probe(pdev: &pci::Device, _info: &Self::IdInfo= ) -> Result(0, c_str!("nova-c= ore/bar0"))?; + let bar =3D pdev.iomap_region_sized::(0, c"nova-core/ba= r0")?; =20 let this =3D KBox::pin_init( try_pin_init!(Self { gpu <- Gpu::new(pdev, bar)?, _reg: auxiliary::Registration::new( pdev.as_ref(), - c_str!("nova-drm"), + c"nova-drm", 0, // TODO: Once it lands, use XArray; for now we don'= t use the ID. crate::MODULE_NAME )?, diff --git a/drivers/net/phy/ax88796b_rust.rs b/drivers/net/phy/ax88796b_ru= st.rs index bc73ebccc2aa..2d24628a4e58 100644 --- a/drivers/net/phy/ax88796b_rust.rs +++ b/drivers/net/phy/ax88796b_rust.rs @@ -5,7 +5,6 @@ //! //! C version of this driver: [`drivers/net/phy/ax88796b.c`](./ax88796b.c) use kernel::{ - c_str, net::phy::{self, reg::C22, DeviceId, Driver}, prelude::*, uapi, @@ -41,7 +40,7 @@ fn asix_soft_reset(dev: &mut phy::Device) -> Result { #[vtable] impl Driver for PhyAX88772A { const FLAGS: u32 =3D phy::flags::IS_INTERNAL; - const NAME: &'static CStr =3D c_str!("Asix Electronics AX88772A"); + const NAME: &'static CStr =3D c"Asix Electronics AX88772A"; const PHY_DEVICE_ID: DeviceId =3D DeviceId::new_with_exact_mask(0x003b= 1861); =20 // AX88772A is not working properly with some old switches (NETGEAR EN= 108TP): @@ -105,7 +104,7 @@ fn link_change_notify(dev: &mut phy::Device) { #[vtable] impl Driver for PhyAX88772C { const FLAGS: u32 =3D phy::flags::IS_INTERNAL; - const NAME: &'static CStr =3D c_str!("Asix Electronics AX88772C"); + const NAME: &'static CStr =3D c"Asix Electronics AX88772C"; const PHY_DEVICE_ID: DeviceId =3D DeviceId::new_with_exact_mask(0x003b= 1881); =20 fn suspend(dev: &mut phy::Device) -> Result { @@ -125,7 +124,7 @@ fn soft_reset(dev: &mut phy::Device) -> Result { =20 #[vtable] impl Driver for PhyAX88796B { - const NAME: &'static CStr =3D c_str!("Asix Electronics AX88796B"); + const NAME: &'static CStr =3D c"Asix Electronics AX88796B"; const PHY_DEVICE_ID: DeviceId =3D DeviceId::new_with_model_mask(0x003b= 1841); =20 fn soft_reset(dev: &mut phy::Device) -> Result { diff --git a/drivers/net/phy/qt2025.rs b/drivers/net/phy/qt2025.rs index 0b9400dcb4c1..9ccc75f70219 100644 --- a/drivers/net/phy/qt2025.rs +++ b/drivers/net/phy/qt2025.rs @@ -9,7 +9,6 @@ //! //! The QT2025 PHY integrates an Intel 8051 micro-controller. =20 -use kernel::c_str; use kernel::error::code; use kernel::firmware::Firmware; use kernel::net::phy::{ @@ -36,7 +35,7 @@ =20 #[vtable] impl Driver for PhyQT2025 { - const NAME: &'static CStr =3D c_str!("QT2025 10Gpbs SFP+"); + const NAME: &'static CStr =3D c"QT2025 10Gpbs SFP+"; const PHY_DEVICE_ID: phy::DeviceId =3D phy::DeviceId::new_with_exact_m= ask(0x0043a400); =20 fn probe(dev: &mut phy::Device) -> Result<()> { @@ -69,7 +68,7 @@ fn probe(dev: &mut phy::Device) -> Result<()> { // The micro-controller will start running from the boot ROM. dev.write(C45::new(Mmd::PCS, 0xe854), 0x00c0)?; =20 - let fw =3D Firmware::request(c_str!("qt2025-2.0.3.3.fw"), dev.as_r= ef())?; + let fw =3D Firmware::request(c"qt2025-2.0.3.3.fw", dev.as_ref())?; if fw.data().len() > SZ_16K + SZ_8K { return Err(code::EFBIG); } diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs index 6041c6d07527..c43a2aa154b6 100644 --- a/rust/kernel/clk.rs +++ b/rust/kernel/clk.rs @@ -100,13 +100,12 @@ mod common_clk { /// The following example demonstrates how to obtain and configure a c= lock for a device. /// /// ``` - /// use kernel::c_str; /// use kernel::clk::{Clk, Hertz}; /// use kernel::device::Device; /// use kernel::error::Result; /// /// fn configure_clk(dev: &Device) -> Result { - /// let clk =3D Clk::get(dev, Some(c_str!("apb_clk")))?; + /// let clk =3D Clk::get(dev, Some(c"apb_clk"))?; /// /// clk.prepare_enable()?; /// @@ -272,13 +271,12 @@ fn drop(&mut self) { /// device. The code functions correctly whether or not the clock is a= vailable. /// /// ``` - /// use kernel::c_str; /// use kernel::clk::{OptionalClk, Hertz}; /// use kernel::device::Device; /// use kernel::error::Result; /// /// fn configure_clk(dev: &Device) -> Result { - /// let clk =3D OptionalClk::get(dev, Some(c_str!("apb_clk")))?; + /// let clk =3D OptionalClk::get(dev, Some(c"apb_clk"))?; /// /// clk.prepare_enable()?; /// diff --git a/rust/kernel/configfs.rs b/rust/kernel/configfs.rs index ee83692fbb1e..9c99fee19a5c 100644 --- a/rust/kernel/configfs.rs +++ b/rust/kernel/configfs.rs @@ -21,7 +21,6 @@ //! //! ```ignore //! use kernel::alloc::flags; -//! use kernel::c_str; //! use kernel::configfs_attrs; //! use kernel::configfs; //! use kernel::new_mutex; @@ -50,7 +49,7 @@ //! //! try_pin_init!(Self { //! config <- configfs::Subsystem::new( -//! c_str!("rust_configfs"), item_type, Configuration::new= () +//! c"rust_configfs", item_type, Configuration::new() //! ), //! }) //! } @@ -66,7 +65,7 @@ //! impl Configuration { //! fn new() -> impl PinInit { //! try_pin_init!(Self { -//! message: c_str!("Hello World\n"), +//! message: c"Hello World\n", //! bar <- new_mutex!((KBox::new([0; PAGE_SIZE], flags::GFP_KE= RNEL)?, 0)), //! }) //! } @@ -1008,7 +1007,9 @@ macro_rules! configfs_attrs { static [< $data:upper _ $name:upper _ATTR >]: $crate::configfs::Attribute<$attr, $data, $data> = =3D unsafe { - $crate::configfs::Attribute::new(c_str!(::= core::stringify!($name))) + $crate::configfs::Attribute::new( + $crate::str_to_cstr!(::core::stringify= !($name)), + ) }; )* =20 diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs index e98fa609cbea..b53769e6cee5 100644 --- a/rust/kernel/cpufreq.rs +++ b/rust/kernel/cpufreq.rs @@ -841,7 +841,6 @@ fn register_em(_policy: &mut Policy) { /// ``` /// use kernel::{ /// cpufreq, -/// c_str, /// device::{Core, Device}, /// macros::vtable, /// of, platform, @@ -854,7 +853,7 @@ fn register_em(_policy: &mut Policy) { /// /// #[vtable] /// impl cpufreq::Driver for SampleDriver { -/// const NAME: &'static CStr =3D c_str!("cpufreq-sample"); +/// const NAME: &'static CStr =3D c"cpufreq-sample"; /// const FLAGS: u16 =3D cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpu= freq::flags::IS_COOLING_DEV; /// const BOOST_ENABLED: bool =3D true; /// diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs index 0f79a2ec9474..b1af2e29298a 100644 --- a/rust/kernel/devres.rs +++ b/rust/kernel/devres.rs @@ -45,7 +45,7 @@ struct DevresInner { /// # Example /// /// ```no_run -/// # use kernel::{bindings, c_str, device::{Bound, Device}, devres::Devre= s, io::{Io, IoRaw}}; +/// # use kernel::{bindings, device::{Bound, Device}, devres::Devres, io::= {Io, IoRaw}}; /// # use core::ops::Deref; /// /// // See also [`pci::Bar`] for a real example. diff --git a/rust/kernel/drm/ioctl.rs b/rust/kernel/drm/ioctl.rs index 445639404fb7..e67c9fe9cb91 100644 --- a/rust/kernel/drm/ioctl.rs +++ b/rust/kernel/drm/ioctl.rs @@ -153,7 +153,7 @@ macro_rules! declare_drm_ioctls { Some($cmd) }, flags: $flags, - name: $crate::c_str!(::core::stringify!($cmd)).as_char= _ptr(), + name: $crate::str_to_cstr!(::core::stringify!($cmd)).a= s_char_ptr(), } ),*]; ioctls diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs index 582ab648b14c..09fd3a27bcf0 100644 --- a/rust/kernel/firmware.rs +++ b/rust/kernel/firmware.rs @@ -51,13 +51,13 @@ fn request_nowarn() -> Self { /// # Examples /// /// ```no_run -/// # use kernel::{c_str, device::Device, firmware::Firmware}; +/// # use kernel::{device::Device, firmware::Firmware}; /// /// # fn no_run() -> Result<(), Error> { /// # // SAFETY: *NOT* safe, just for the example to get an `ARef`= instance /// # let dev =3D unsafe { Device::get_device(core::ptr::null_mut()) }; /// -/// let fw =3D Firmware::request(c_str!("path/to/firmware.bin"), &dev)?; +/// let fw =3D Firmware::request(c"path/to/firmware.bin", &dev)?; /// let blob =3D fw.data(); /// /// # Ok(()) @@ -203,7 +203,7 @@ macro_rules! module_firmware { ($($builder:tt)*) =3D> { const _: () =3D { const __MODULE_FIRMWARE_PREFIX: &'static $crate::str::CStr =3D= if cfg!(MODULE) { - $crate::c_str!("") + c"" } else { ::NAME }; diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs index 4927aa0b656e..2bab61910f1e 100644 --- a/rust/kernel/kunit.rs +++ b/rust/kernel/kunit.rs @@ -57,9 +57,10 @@ macro_rules! kunit_assert { break 'out; } =20 - static FILE: &'static $crate::str::CStr =3D $crate::c_str!($fi= le); + static FILE: &'static $crate::str::CStr =3D $file; static LINE: i32 =3D ::core::line!() as i32 - $diff; - static CONDITION: &'static $crate::str::CStr =3D $crate::c_str= !(stringify!($condition)); + static CONDITION: &'static $crate::str::CStr =3D + $crate::str_to_cstr!(stringify!($condition)); =20 // SAFETY: FFI call without safety requirements. let kunit_test =3D unsafe { $crate::bindings::kunit_get_curren= t_test() }; @@ -246,7 +247,7 @@ pub const fn kunit_case_null() -> kernel::bindings::kun= it_case { /// } /// /// static mut KUNIT_TEST_CASES: [kernel::bindings::kunit_case; 2] =3D [ -/// kernel::kunit::kunit_case(kernel::c_str!("name"), test_fn), +/// kernel::kunit::kunit_case(c"name", test_fn), /// kernel::kunit::kunit_case_null(), /// ]; /// kernel::kunit_unsafe_test_suite!(suite_name, KUNIT_TEST_CASES); diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs index 34239106bd27..5e654403c21b 100644 --- a/rust/kernel/net/phy.rs +++ b/rust/kernel/net/phy.rs @@ -781,7 +781,6 @@ const fn as_int(&self) -> u32 { /// /// ``` /// # mod module_phy_driver_sample { -/// use kernel::c_str; /// use kernel::net::phy::{self, DeviceId}; /// use kernel::prelude::*; /// @@ -800,7 +799,7 @@ const fn as_int(&self) -> u32 { /// /// #[vtable] /// impl phy::Driver for PhySample { -/// const NAME: &'static CStr =3D c_str!("PhySample"); +/// const NAME: &'static CStr =3D c"PhySample"; /// const PHY_DEVICE_ID: phy::DeviceId =3D phy::DeviceId::new_with_exa= ct_mask(0x00000001); /// } /// # } @@ -809,7 +808,6 @@ const fn as_int(&self) -> u32 { /// This expands to the following code: /// /// ```ignore -/// use kernel::c_str; /// use kernel::net::phy::{self, DeviceId}; /// use kernel::prelude::*; /// @@ -829,7 +827,7 @@ const fn as_int(&self) -> u32 { /// /// #[vtable] /// impl phy::Driver for PhySample { -/// const NAME: &'static CStr =3D c_str!("PhySample"); +/// const NAME: &'static CStr =3D c"PhySample"; /// const PHY_DEVICE_ID: phy::DeviceId =3D phy::DeviceId::new_with_exa= ct_mask(0x00000001); /// } /// diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 5b21fa517e55..338b8d7c65ee 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -123,7 +123,7 @@ macro_rules! module_platform_driver { /// # Example /// ///``` -/// # use kernel::{bindings, c_str, device::Core, of, platform}; +/// # use kernel::{bindings, device::Core, of, platform}; /// /// struct MyDriver; /// @@ -132,7 +132,7 @@ macro_rules! module_platform_driver { /// MODULE_OF_TABLE, /// ::IdInfo, /// [ -/// (of::DeviceId::new(c_str!("test,device")), ()) +/// (of::DeviceId::new(c"test,device"), ()) /// ] /// ); /// diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index e884ec1ce5c8..9908b09868bc 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -266,15 +266,14 @@ impl crate::fmt::Display for CStr { /// Formats printable ASCII characters, escaping the rest. /// /// ``` - /// # use kernel::c_str; /// # use kernel::prelude::fmt; /// # use kernel::str::CStr; /// # use kernel::str::CString; - /// let penguin =3D c_str!("=F0=9F=90=A7"); + /// let penguin =3D c"=F0=9F=90=A7"; /// let s =3D CString::try_from_fmt(fmt!("{}", penguin))?; /// assert_eq!(s.to_bytes_with_nul(), "\\xf0\\x9f\\x90\\xa7\0".as_byte= s()); /// - /// let ascii =3D c_str!("so \"cool\""); + /// let ascii =3D c"so \"cool\""; /// let s =3D CString::try_from_fmt(fmt!("{}", ascii))?; /// assert_eq!(s.to_bytes_with_nul(), "so \"cool\"\0".as_bytes()); /// # Ok::<(), kernel::error::Error>(()) @@ -364,19 +363,28 @@ fn as_ref(&self) -> &BStr { } } =20 -/// Creates a new [`CStr`] from a string literal. +/// Creates a new [`CStr`] at compile time. /// -/// The string literal should not contain any `NUL` bytes. +/// Rust supports C string literals since Rust 1.77, and they should be us= ed instead of this macro +/// where possible. This macro exists to allow static *non-literal* C stri= ngs to be created at +/// compile time. This is most often used in other macros. +/// +/// # Panics +/// +/// This macro panics if the operand contains an interior `NUL` byte. /// /// # Examples /// /// ``` -/// # use kernel::c_str; +/// # use kernel::str_to_cstr; /// # use kernel::str::CStr; -/// const MY_CSTR: &CStr =3D c_str!("My awesome CStr!"); +/// const MY_CSTR: &CStr =3D str_to_cstr!(concat!(file!(), ":", line!(), "= : My CStr!")); /// ``` #[macro_export] -macro_rules! c_str { +macro_rules! str_to_cstr { + // NB: we could write `($str:lit) =3D> compile_error!("use a C string = literal instead");` here but + // that would trigger when the literal is at the top of several macro = expansions. That would be + // too limiting to macro authors, so we rely on the name as a hint ins= tead. ($str:expr) =3D> {{ const S: &str =3D concat!($str, "\0"); const C: &$crate::str::CStr =3D match $crate::str::CStr::from_byte= s_with_nul(S.as_bytes()) { diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 36a719015583..e38629147f42 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -41,7 +41,6 @@ impl LockClassKey { /// /// # Example /// ``` - /// # use kernel::c_str; /// # use kernel::alloc::KBox; /// # use kernel::types::ForeignOwnable; /// # use kernel::sync::{LockClassKey, SpinLock}; @@ -53,7 +52,7 @@ impl LockClassKey { /// { /// stack_pin_init!(let num: SpinLock =3D SpinLock::new( /// 0, - /// c_str!("my_spinlock"), + /// c"my_spinlock", /// // SAFETY: `key_ptr` is returned by the above `into_foreig= n()`, whose /// // `from_foreign()` has not yet been called. /// unsafe { > as ForeignOwnable>::borr= ow(key_ptr) } @@ -106,9 +105,9 @@ macro_rules! static_lock_class { #[macro_export] macro_rules! optional_name { () =3D> { - $crate::c_str!(::core::concat!(::core::file!(), ":", ::core::line!= ())) + $crate::str_to_cstr!(::core::concat!(::core::file!(), ":", ::core:= :line!())) }; ($name:literal) =3D> { - $crate::c_str!($name) + $name }; } diff --git a/rust/kernel/sync/lock/global.rs b/rust/kernel/sync/lock/global= .rs index 79d0ef7fda86..9caa9b419f09 100644 --- a/rust/kernel/sync/lock/global.rs +++ b/rust/kernel/sync/lock/global.rs @@ -267,7 +267,8 @@ macro_rules! global_lock { $pub enum $name {} =20 impl $crate::sync::lock::GlobalLockBackend for $name { - const NAME: &'static $crate::str::CStr =3D $crate::c_str!(::co= re::stringify!($name)); + const NAME: &'static $crate::str::CStr =3D + $crate::str_to_cstr!(::core::stringify!($name)); type Item =3D $valuety; type Backend =3D $crate::global_lock_inner!(backend $kind); =20 diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index d092112d843f..dbec533fd31f 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -51,7 +51,7 @@ //! fn new(value: i32) -> Result> { //! Arc::pin_init(pin_init!(MyStruct { //! value, -//! work <- new_work!("MyStruct::work"), +//! work <- new_work!(c"MyStruct::work"), //! }), GFP_KERNEL) //! } //! } @@ -98,8 +98,8 @@ //! Arc::pin_init(pin_init!(MyStruct { //! value_1, //! value_2, -//! work_1 <- new_work!("MyStruct::work_1"), -//! work_2 <- new_work!("MyStruct::work_2"), +//! work_1 <- new_work!(c"MyStruct::work_1"), +//! work_2 <- new_work!(c"MyStruct::work_2"), //! }), GFP_KERNEL) //! } //! } @@ -215,7 +215,7 @@ pub fn try_spawn( func: T, ) -> Result<(), AllocError> { let init =3D pin_init!(ClosureWork { - work <- new_work!("Queue::try_spawn"), + work <- new_work!(c"Queue::try_spawn"), func: Some(func), }); =20 diff --git a/rust/macros/kunit.rs b/rust/macros/kunit.rs index 81d18149a0cc..c64df1a01b9d 100644 --- a/rust/macros/kunit.rs +++ b/rust/macros/kunit.rs @@ -89,8 +89,8 @@ pub(crate) fn kunit_tests(attr: TokenStream, ts: TokenStr= eam) -> TokenStream { // unsafe extern "C" fn kunit_rust_wrapper_bar(_test: *mut ::kernel::b= indings::kunit) { bar(); } // // static mut TEST_CASES: [::kernel::bindings::kunit_case; 3] =3D [ - // ::kernel::kunit::kunit_case(::kernel::c_str!("foo"), kunit_rust= _wrapper_foo), - // ::kernel::kunit::kunit_case(::kernel::c_str!("bar"), kunit_rust= _wrapper_bar), + // ::kernel::kunit::kunit_case(c"foo", kunit_rust_wrapper_foo), + // ::kernel::kunit::kunit_case(c"bar", kunit_rust_wrapper_bar), // ::kernel::kunit::kunit_case_null(), // ]; // @@ -109,7 +109,7 @@ pub(crate) fn kunit_tests(attr: TokenStream, ts: TokenS= tream) -> TokenStream { writeln!(kunit_macros, "{kunit_wrapper}").unwrap(); writeln!( test_cases, - " ::kernel::kunit::kunit_case(::kernel::c_str!(\"{test}\"),= {kunit_wrapper_fn_name})," + " ::kernel::kunit::kunit_case(c\"{test}\", {kunit_wrapper_f= n_name})," ) .unwrap(); writeln!( @@ -119,7 +119,7 @@ pub(crate) fn kunit_tests(attr: TokenStream, ts: TokenS= tream) -> TokenStream { #[allow(unused)] macro_rules! assert {{ ($cond:expr $(,)?) =3D> {{{{ - kernel::kunit_assert!("{test}", "{path}", 0, $cond); + kernel::kunit_assert!("{test}", c"{path}", 0, $cond); }}}} }} =20 @@ -127,7 +127,7 @@ macro_rules! assert {{ #[allow(unused)] macro_rules! assert_eq {{ ($left:expr, $right:expr $(,)?) =3D> {{{{ - kernel::kunit_assert_eq!("{test}", "{path}", 0, $left, $right); + kernel::kunit_assert_eq!("{test}", c"{path}", 0, $left, $right); }}}} }} "# diff --git a/rust/macros/module.rs b/rust/macros/module.rs index 2ddd2eeb2852..ec528cd86db5 100644 --- a/rust/macros/module.rs +++ b/rust/macros/module.rs @@ -234,7 +234,7 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream { type LocalModule =3D {type_}; =20 impl ::kernel::ModuleMetadata for {type_} {{ - const NAME: &'static ::kernel::str::CStr =3D ::kernel::c_s= tr!(\"{name}\"); + const NAME: &'static ::kernel::str::CStr =3D c\"{name}\"; }} =20 // Double nested modules, since then nobody can access the pub= lic items inside. diff --git a/samples/rust/rust_configfs.rs b/samples/rust/rust_configfs.rs index 02641dc06f25..4f362be5c7df 100644 --- a/samples/rust/rust_configfs.rs +++ b/samples/rust/rust_configfs.rs @@ -3,7 +3,6 @@ //! Rust configfs sample. =20 use kernel::alloc::flags; -use kernel::c_str; use kernel::configfs; use kernel::configfs_attrs; use kernel::new_mutex; @@ -35,7 +34,7 @@ struct Configuration { impl Configuration { fn new() -> impl PinInit { try_pin_init!(Self { - message: c_str!("Hello World\n"), + message: c"Hello World\n", bar <- new_mutex!((KBox::new([0; PAGE_SIZE], flags::GFP_KERNEL= )?, 0)), }) } @@ -61,7 +60,7 @@ fn init(_module: &'static ThisModule) -> impl PinInit { =20 try_pin_init!(Self { config <- configfs::Subsystem::new( - c_str!("rust_configfs"), item_type, Configuration::new() + c"rust_configfs", item_type, Configuration::new() ), }) } diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driv= er_auxiliary.rs index 3e15e6d002bb..0b38729bbab7 100644 --- a/samples/rust/rust_driver_auxiliary.rs +++ b/samples/rust/rust_driver_auxiliary.rs @@ -5,14 +5,14 @@ //! To make this driver probe, QEMU must be run with `-device pci-testdev`. =20 use kernel::{ - auxiliary, bindings, c_str, device::Core, driver, error::Error, pci, p= relude::*, str::CStr, + auxiliary, bindings, device::Core, driver, error::Error, pci, prelude:= :*, str::CStr, InPlaceModule, }; =20 use pin_init::PinInit; =20 const MODULE_NAME: &CStr =3D ::NAME; -const AUXILIARY_NAME: &CStr =3D c_str!("auxiliary"); +const AUXILIARY_NAME: &CStr =3D c"auxiliary"; =20 struct AuxiliaryDriver; =20 diff --git a/samples/rust/rust_driver_faux.rs b/samples/rust/rust_driver_fa= ux.rs index ecc9fd378cbd..23add3160693 100644 --- a/samples/rust/rust_driver_faux.rs +++ b/samples/rust/rust_driver_faux.rs @@ -2,7 +2,7 @@ =20 //! Rust faux device sample. =20 -use kernel::{c_str, faux, prelude::*, Module}; +use kernel::{faux, prelude::*, Module}; =20 module! { type: SampleModule, @@ -20,7 +20,7 @@ impl Module for SampleModule { fn init(_module: &'static ThisModule) -> Result { pr_info!("Initialising Rust Faux Device Sample\n"); =20 - let reg =3D faux::Registration::new(c_str!("rust-faux-sample-devic= e"), None)?; + let reg =3D faux::Registration::new(c"rust-faux-sample-device", No= ne)?; =20 dev_info!(reg.as_ref(), "Hello from faux device!\n"); =20 diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs index 15147e4401b2..4ba5fcd2b357 100644 --- a/samples/rust/rust_driver_pci.rs +++ b/samples/rust/rust_driver_pci.rs @@ -4,7 +4,7 @@ //! //! To make this driver probe, QEMU must be run with `-device pci-testdev`. =20 -use kernel::{bindings, c_str, device::Core, devres::Devres, pci, prelude::= *, types::ARef}; +use kernel::{bindings, device::Core, devres::Devres, pci, prelude::*, type= s::ARef}; =20 struct Regs; =20 @@ -73,7 +73,7 @@ fn probe(pdev: &pci::Device, info: &Self::IdInfo) -= > Result pdev.enable_device_mem()?; pdev.set_master(); =20 - let bar =3D pdev.iomap_region_sized::<{ Regs::END }>(0, c_str!("ru= st_driver_pci"))?; + let bar =3D pdev.iomap_region_sized::<{ Regs::END }>(0, c"rust_dri= ver_pci")?; =20 let drvdata =3D KBox::new( Self { diff --git a/samples/rust/rust_driver_platform.rs b/samples/rust/rust_drive= r_platform.rs index 8b42b3cfb363..e6487a970a59 100644 --- a/samples/rust/rust_driver_platform.rs +++ b/samples/rust/rust_driver_platform.rs @@ -2,7 +2,7 @@ =20 //! Rust Platform driver sample. =20 -use kernel::{c_str, device::Core, of, platform, prelude::*, types::ARef}; +use kernel::{device::Core, of, platform, prelude::*, types::ARef}; =20 struct SampleDriver { pdev: ARef, @@ -14,7 +14,7 @@ struct SampleDriver { OF_TABLE, MODULE_OF_TABLE, ::IdInfo, - [(of::DeviceId::new(c_str!("test,rust-device")), Info(42))] + [(of::DeviceId::new(c"test,rust-device"), Info(42))] ); =20 impl platform::Driver for SampleDriver { diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_devi= ce.rs index c881fd6dbd08..12b64296e912 100644 --- a/samples/rust/rust_misc_device.rs +++ b/samples/rust/rust_misc_device.rs @@ -98,7 +98,6 @@ use core::pin::Pin; =20 use kernel::{ - c_str, device::Device, fs::File, ioctl::{_IO, _IOC_SIZE, _IOR, _IOW}, @@ -133,7 +132,7 @@ fn init(_module: &'static ThisModule) -> impl PinInit { pr_info!("Initialising Rust Misc Device Sample\n"); =20 let options =3D MiscDeviceOptions { - name: c_str!("rust-misc-device"), + name: c"rust-misc-device", }; =20 try_pin_init!(Self { diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs index 507d36875196..0e86bdf1b5b1 100644 --- a/scripts/rustdoc_test_gen.rs +++ b/scripts/rustdoc_test_gen.rs @@ -173,7 +173,7 @@ pub extern "C" fn {kunit_name}(__kunit_test: *mut ::ker= nel::bindings::kunit) {{ macro_rules! assert {{ ($cond:expr $(,)?) =3D> {{{{ ::kernel::kunit_assert!( - "{kunit_name}", "{real_path}", __DOCTEST_ANCHOR - {line}, = $cond + "{kunit_name}", c"{real_path}", __DOCTEST_ANCHOR - {line},= $cond ); }}}} }} @@ -183,7 +183,7 @@ macro_rules! assert {{ macro_rules! assert_eq {{ ($left:expr, $right:expr $(,)?) =3D> {{{{ ::kernel::kunit_assert_eq!( - "{kunit_name}", "{real_path}", __DOCTEST_ANCHOR - {line}, = $left, $right + "{kunit_name}", c"{real_path}", __DOCTEST_ANCHOR - {line},= $left, $right ); }}}} }} --=20 2.50.0 From nobody Thu Oct 9 06:05:19 2025 Received: from mail-qt1-f176.google.com (mail-qt1-f176.google.com [209.85.160.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F0DD828CF71; Thu, 19 Jun 2025 15:06:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750345609; cv=none; b=aBj6LPv35SLQxCuTPsGMe9QdcbFsf7bMTEZijH8bCCNlu/N477Xyuis+gO20MZuFWrj06KGX3s5Usk4ftWWw3mHG+CiUBNwdpXSbkzBfPjoivtSVnqM5FHZybzE9+Vqoh3UFEt/QiM6uixRL8p4aluAM3d+dZzhk4oZy3qr/n00= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750345609; c=relaxed/simple; bh=lyshkepuNXBzM/AfGAS6FKh61q/DhI59C9wDKRcPAw4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AoDROOSyHyM5nyEqmIpxmAaJrvCXwWWizWCQ8/67Rp94dktb+CkkzIUw2Q2vrNtQswt4jMdiDiF7wcW8dBqrau+HTRUzyDD+htwMpX0k44wgu/F08kxsDxZGCKYzQAfIJaXVy9T2zHasYaAAtKBwZJJVkIAUgFd9Le/2cvE6Ye0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Pre6CVtr; arc=none smtp.client-ip=209.85.160.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Pre6CVtr" Received: by mail-qt1-f176.google.com with SMTP id d75a77b69052e-4a5840ec53dso10087971cf.0; Thu, 19 Jun 2025 08:06:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1750345605; x=1750950405; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=N+MLp/Wyw+FMmIoAUSP2P3WuAVxaRgs45Kjlyv6CyTI=; b=Pre6CVtrNiZ/hv6GC39NIaNCHZvZp4hl5xHpMDyY52a1V30TRKchhyYsG+ptLe3jg7 NIFp4RXwg6HdIJxaXvtwrh4dIKj7qWEAvTelsxqYKLxBWPD3FnG3cBXh7YiogNd4wyWZ ql4hNYvp7PQpZ4UYRzHd6bkXHn7rtba+qj0aeHgI/b7ERdPRdtIPUVID/FVmrKQbOUg4 pZp21FCzZMePDTO6ZY9+HB1zwm1IqgxVwXM9WhKuw0B18l7S+TyAKQZN4fOX9UrsSLv/ hEMJcFvLtD/HdPC6/eMYDdtxyvxP5VWCx2OnbDpVuWJ5PA21pMOoYfvTlDA11fVdDOIT T53w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750345605; x=1750950405; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=N+MLp/Wyw+FMmIoAUSP2P3WuAVxaRgs45Kjlyv6CyTI=; b=uWNeNVAj5dkbj5a42O1cQbX/JbVnp37mDe2JXMIvHqGvwENINQRZYd2mqTlU7F141g 5I+eaS9Wr83B49duxNUFG7EVEtlI7NurURb0SoMGFAfOxd/mLmejkFQl4XuwOMlp59+S bgdXi2gbg92anLRQWoWPleMolAy2McKpEXb/GNPRwHAJTV1m251G+R2jijborZ0kDsYm XDirarhUg799GiE4A5u9Y8+2rhswMgZyhDUAv6sB4fLl/oTNvgTviXtRW9GJDRfhj4Kr dpx8SH3mptzaqkDO4Z0bQU9z90Fvw86SzvS2doY3QYVjDtvCvBzR60QoC+2l7A69kX0P XTew== X-Forwarded-Encrypted: i=1; AJvYcCUBEfAOQX9I6lb6DwO/9HvHCYOBhORnbgX5Kc1Ih4YfbmY4n32agPefv8DrOb42vUdHlu8w8NItjz4=@vger.kernel.org, AJvYcCUOk2aPRgZUF/ZYaoq5eWvxiCCQYFnTXzBrzzUaZ+m58IvHBsX5FtT4bPT++QoOn0lFwHvBz2hZfPjc@vger.kernel.org, AJvYcCUSxeBqeQyPHQ2eEBgDzaTICnzhIzuE6ghfXrP/mqgOUS88FCuAUgM/QstXv3uZidkGRWtQxUzzvV1g@vger.kernel.org, AJvYcCUyRNhLwawehdas4vS9ToZPt32O+CVnzUn7VLtEKmbOHS2IlunihOL/EKuz9mEdAfSMelM5GRy2@vger.kernel.org, AJvYcCW0bWxpTrvSStqvzGMFKvhHsjPVTl88mdtoTB3V+9GNIwqbG5r5EOmpfdAcJzYm4Ni5fyhwt2PQhhkHpLbMw/eK@vger.kernel.org, AJvYcCWpgSLXNA7Wqcn65C3LXf1lXEeTEhAN6dK68lOLc1dc2Sjm+UGLpUnhtHQHrCUrVqIXVSKSiMgjRV3Ku78=@vger.kernel.org, AJvYcCWxvVnq6RzsM9EVrD3n0zAE7rxhHnwpR7Pbes6pxEcBq/sjPe5N/r3aKVuxAx41Etgw+J0V1+QtmJom@vger.kernel.org, AJvYcCXYxI8/3OIWTFxWXOjo/Xwa7RCcFm0oankAijLedVG+QGQdDseACWOu7y1avCDOtpdIvIdf7sAhLyoZV5TU@vger.kernel.org X-Gm-Message-State: AOJu0Yzxdh2MAeTHtC229MitVFLH5Oo0wlIyd8gxZU1hZ7WwxoWPxt64 hvcYcmzoZq6aprhLiHIQuHRuaPqKrIQrRemy5eQU0GM1vm2El+EHa9yG X-Gm-Gg: ASbGncssPRmQSF4pEpq2eN3kq14sZAihZajkoY0pwaFH5amV1a+1CCPmFh6lDhH6NsN 8jiu6+gncNON3mqc3FVsWcJYxhVk8f5QtyCDCCt3rGXSj7PjCZxg/sQgKbwfyx5lY2c1ov1Rj13 wZ+s0BvVSOB9mQgYtDuu5UcIK+NlolQGo7FVXDSluTZlle1FIEEYSqBcTsbmafz2jsNWiiPU0x6 zREtI3grklW9tKRVslvEMLQGm+utXOCXG7BxMFc1/2pvan/NtQIGABfXr9e3NySAQmpvZIm1Eei Zrl2ygkKCt61W9YYY6hts0uxzniVXaQQZFryTQdTvFaA/h0BTJuFTiIKq+sW0Mx/gW/hYvyT9mg M/t149BYHQA== X-Google-Smtp-Source: AGHT+IEIBl9XIMHrJ5og8oP/l3Yc1XPQQjJbdZ6bZEBoEIEuuRSD4EWvq6wtLdoVF2ZgNgXM1ksG3A== X-Received: by 2002:a05:622a:1890:b0:4a6:fa8e:50a8 with SMTP id d75a77b69052e-4a73c4fcea9mr360959781cf.2.1750345604456; Thu, 19 Jun 2025 08:06:44 -0700 (PDT) Received: from tamird-mac.local ([2600:4041:5be7:7c00:5c8a:fc6a:b57c:e57f]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-4a7785aaacdsm250531cf.39.2025.06.19.08.06.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Jun 2025 08:06:43 -0700 (PDT) From: Tamir Duberstein Date: Thu, 19 Jun 2025 11:06:29 -0400 Subject: [PATCH v12 5/5] rust: remove core::ffi::CStr reexport Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250619-cstr-core-v12-5-80c9c7b45900@gmail.com> References: <20250619-cstr-core-v12-0-80c9c7b45900@gmail.com> In-Reply-To: <20250619-cstr-core-v12-0-80c9c7b45900@gmail.com> To: Michal Rostecki , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Andreas Hindborg , Alice Ryhl , Trevor Gross , Brendan Higgins , David Gow , Rae Moar , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Greg Kroah-Hartman , "Rafael J. Wysocki" , Luis Chamberlain , Russ Weight , FUJITA Tomonori , Rob Herring , Saravana Kannan , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Bjorn Helgaas , Arnd Bergmann , Jens Axboe , Benno Lossin , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Dave Ertman , Ira Weiny , Leon Romanovsky , Breno Leitao , Viresh Kumar , Michael Turquette , Stephen Boyd Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, dri-devel@lists.freedesktop.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, llvm@lists.linux.dev, linux-pci@vger.kernel.org, nouveau@lists.freedesktop.org, linux-block@vger.kernel.org, linux-pm@vger.kernel.org, linux-clk@vger.kernel.org, Tamir Duberstein X-Mailer: b4 0.15-dev Clean up references to `kernel::str::CStr`. Signed-off-by: Tamir Duberstein Acked-by: Greg Kroah-Hartman Acked-by: Stephen Boyd Reviewed-by: Alice Ryhl --- drivers/gpu/drm/drm_panic_qr.rs | 3 ++- drivers/gpu/nova-core/firmware.rs | 2 +- drivers/gpu/nova-core/nova_core.rs | 2 +- drivers/net/phy/ax88796b_rust.rs | 1 + drivers/net/phy/qt2025.rs | 1 + rust/kernel/auxiliary.rs | 2 +- rust/kernel/clk.rs | 3 +-- rust/kernel/configfs.rs | 1 + rust/kernel/cpufreq.rs | 3 ++- rust/kernel/device.rs | 3 +-- rust/kernel/driver.rs | 4 ++-- rust/kernel/drm/driver.rs | 3 ++- rust/kernel/error.rs | 6 ++---- rust/kernel/faux.rs | 5 ++++- rust/kernel/firmware.rs | 15 ++++----------- rust/kernel/kunit.rs | 6 +++--- rust/kernel/lib.rs | 2 +- rust/kernel/miscdevice.rs | 3 +-- rust/kernel/net/phy.rs | 4 +++- rust/kernel/of.rs | 3 ++- rust/kernel/pci.rs | 2 +- rust/kernel/platform.rs | 2 +- rust/kernel/prelude.rs | 5 +---- rust/kernel/str.rs | 8 +++----- rust/kernel/sync/condvar.rs | 4 ++-- rust/kernel/sync/lock.rs | 4 ++-- rust/kernel/sync/lock/global.rs | 5 +++-- rust/kernel/sync/poll.rs | 1 + rust/kernel/workqueue.rs | 1 + rust/macros/module.rs | 2 +- samples/rust/rust_configfs.rs | 2 ++ samples/rust/rust_driver_auxiliary.rs | 5 +++-- 32 files changed, 57 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr= .rs index 01e8ba9e6de1..aa27c266213e 100644 --- a/drivers/gpu/drm/drm_panic_qr.rs +++ b/drivers/gpu/drm/drm_panic_qr.rs @@ -27,7 +27,8 @@ //! * //! * =20 -use kernel::{prelude::*, str::CStr}; +use core::ffi::CStr; +use kernel::prelude::*; =20 #[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)] struct Version(usize); diff --git a/drivers/gpu/nova-core/firmware.rs b/drivers/gpu/nova-core/firm= ware.rs index 4b8a38358a4f..562ad048ff99 100644 --- a/drivers/gpu/nova-core/firmware.rs +++ b/drivers/gpu/nova-core/firmware.rs @@ -66,7 +66,7 @@ const fn make_entry_chipset(self, chipset: &str) -> Self { } =20 pub(crate) const fn create( - module_name: &'static kernel::str::CStr, + module_name: &'static core::ffi::CStr, ) -> firmware::ModInfoBuilder { let mut this =3D Self(firmware::ModInfoBuilder::new(module_name)); let mut i =3D 0; diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nov= a_core.rs index 618632f0abcc..29b7ae8581e6 100644 --- a/drivers/gpu/nova-core/nova_core.rs +++ b/drivers/gpu/nova-core/nova_core.rs @@ -8,7 +8,7 @@ mod regs; mod util; =20 -pub(crate) const MODULE_NAME: &kernel::str::CStr =3D ::NAME; +pub(crate) const MODULE_NAME: &core::ffi::CStr =3D ::NAME; =20 kernel::module_pci_driver! { type: driver::NovaCore, diff --git a/drivers/net/phy/ax88796b_rust.rs b/drivers/net/phy/ax88796b_ru= st.rs index 2d24628a4e58..68b8e30ae296 100644 --- a/drivers/net/phy/ax88796b_rust.rs +++ b/drivers/net/phy/ax88796b_rust.rs @@ -4,6 +4,7 @@ //! Rust Asix PHYs driver //! //! C version of this driver: [`drivers/net/phy/ax88796b.c`](./ax88796b.c) +use core::ffi::CStr; use kernel::{ net::phy::{self, reg::C22, DeviceId, Driver}, prelude::*, diff --git a/drivers/net/phy/qt2025.rs b/drivers/net/phy/qt2025.rs index 9ccc75f70219..78ce2866f2b6 100644 --- a/drivers/net/phy/qt2025.rs +++ b/drivers/net/phy/qt2025.rs @@ -9,6 +9,7 @@ //! //! The QT2025 PHY integrates an Intel 8051 micro-controller. =20 +use core::ffi::CStr; use kernel::error::code; use kernel::firmware::Firmware; use kernel::net::phy::{ diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 89d961407adb..ff29077d9c2f 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -10,11 +10,11 @@ driver, error::{to_result, Result}, prelude::*, - str::CStr, types::{ForeignOwnable, Opaque}, ThisModule, }; use core::{ + ffi::CStr, marker::PhantomData, ptr::{addr_of_mut, NonNull}, }; diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs index c43a2aa154b6..bad49ecb30ed 100644 --- a/rust/kernel/clk.rs +++ b/rust/kernel/clk.rs @@ -78,10 +78,9 @@ mod common_clk { use crate::{ device::Device, error::{from_err_ptr, to_result, Result}, - prelude::*, }; =20 - use core::{ops::Deref, ptr}; + use core::{ffi::CStr, ops::Deref, ptr}; =20 /// A reference-counted clock. /// diff --git a/rust/kernel/configfs.rs b/rust/kernel/configfs.rs index 9c99fee19a5c..1eb46c6d5508 100644 --- a/rust/kernel/configfs.rs +++ b/rust/kernel/configfs.rs @@ -118,6 +118,7 @@ use crate::sync::ArcBorrow; use crate::types::Opaque; use core::cell::UnsafeCell; +use core::ffi::CStr; use core::marker::PhantomData; =20 /// A configfs subsystem. diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs index b53769e6cee5..ecc183de3133 100644 --- a/rust/kernel/cpufreq.rs +++ b/rust/kernel/cpufreq.rs @@ -26,6 +26,7 @@ =20 use core::{ cell::UnsafeCell, + ffi::CStr, marker::PhantomData, mem::MaybeUninit, ops::{Deref, DerefMut}, @@ -853,7 +854,7 @@ fn register_em(_policy: &mut Policy) { /// /// #[vtable] /// impl cpufreq::Driver for SampleDriver { -/// const NAME: &'static CStr =3D c"cpufreq-sample"; +/// const NAME: &'static core::ffi::CStr =3D c"cpufreq-sample"; /// const FLAGS: u16 =3D cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpu= freq::flags::IS_COOLING_DEV; /// const BOOST_ENABLED: bool =3D true; /// diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index d2b6c1ce02a5..ad5e60e96d98 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -6,10 +6,9 @@ =20 use crate::{ bindings, - str::CStr, types::{ARef, Opaque}, }; -use core::{fmt, marker::PhantomData, ptr}; +use core::{ffi::CStr, fmt, marker::PhantomData, ptr}; =20 #[cfg(CONFIG_PRINTK)] use crate::str::CStrExt as _; diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs index ec9166cedfa7..9926664d9ba2 100644 --- a/rust/kernel/driver.rs +++ b/rust/kernel/driver.rs @@ -6,8 +6,8 @@ //! register using the [`Registration`] class. =20 use crate::error::{Error, Result}; -use crate::{device, of, str::CStr, try_pin_init, types::Opaque, ThisModule= }; -use core::pin::Pin; +use crate::{device, of, try_pin_init, types::Opaque, ThisModule}; +use core::{ffi::CStr, pin::Pin}; use pin_init::{pin_data, pinned_drop, PinInit}; =20 /// The [`RegistrationOps`] trait serves as generic interface for subsyste= ms (e.g., PCI, Platform, diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs index acb638086131..4c30933051c7 100644 --- a/rust/kernel/drm/driver.rs +++ b/rust/kernel/drm/driver.rs @@ -10,11 +10,12 @@ drm, error::{to_result, Result}, prelude::*, - str::CStr, types::ARef, }; use macros::vtable; =20 +use core::ffi::CStr; + /// Driver use the GEM memory manager. This should be set for all modern d= rivers. pub(crate) const FEAT_GEM: u32 =3D bindings::drm_driver_feature_DRIVER_GEM; =20 diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index 933c048c04f1..b2b46d26f7b7 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -4,11 +4,9 @@ //! //! C header: [`include/uapi/asm-generic/errno-base.h`](srctree/include/ua= pi/asm-generic/errno-base.h) =20 -use crate::{ - alloc::{layout::LayoutError, AllocError}, - str::CStr, -}; +use crate::alloc::{layout::LayoutError, AllocError}; =20 +use core::ffi::CStr; use core::fmt; use core::num::NonZeroI32; use core::num::TryFromIntError; diff --git a/rust/kernel/faux.rs b/rust/kernel/faux.rs index 8a50fcd4c9bb..d9e5cd265101 100644 --- a/rust/kernel/faux.rs +++ b/rust/kernel/faux.rs @@ -7,7 +7,10 @@ //! C header: [`include/linux/device/faux.h`] =20 use crate::{bindings, device, error::code::*, prelude::*}; -use core::ptr::{addr_of_mut, null, null_mut, NonNull}; +use core::{ + ffi::CStr, + ptr::{addr_of_mut, null, null_mut, NonNull}, +}; =20 /// The registration of a faux device. /// diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs index 09fd3a27bcf0..4ba5e5589d7b 100644 --- a/rust/kernel/firmware.rs +++ b/rust/kernel/firmware.rs @@ -4,15 +4,8 @@ //! //! C header: [`include/linux/firmware.h`](srctree/include/linux/firmware.= h) =20 -use crate::{ - bindings, - device::Device, - error::Error, - error::Result, - ffi, - str::{CStr, CStrExt as _}, -}; -use core::ptr::NonNull; +use crate::{bindings, device::Device, error::Error, error::Result, ffi, st= r::CStrExt as _}; +use core::{ffi::CStr, ptr::NonNull}; =20 /// # Invariants /// @@ -168,7 +161,7 @@ unsafe impl Sync for Firmware {} /// const DIR: &'static str =3D "vendor/chip/"; /// const FILES: [&'static str; 3] =3D [ "foo", "bar", "baz" ]; /// -/// const fn create(module_name: &'static kernel::str::CStr) -> firmwa= re::ModInfoBuilder { +/// const fn create(module_name: &'static core::ffi::CStr) -> firmware= ::ModInfoBuilder { /// let mut builder =3D firmware::ModInfoBuilder::new(module_name); /// /// let mut i =3D 0; @@ -202,7 +195,7 @@ macro_rules! module_firmware { // this macro. Hence, we can neither use `expr` nor `ty`. ($($builder:tt)*) =3D> { const _: () =3D { - const __MODULE_FIRMWARE_PREFIX: &'static $crate::str::CStr =3D= if cfg!(MODULE) { + const __MODULE_FIRMWARE_PREFIX: &'static ::core::ffi::CStr =3D= if cfg!(MODULE) { c"" } else { ::NAME diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs index 2bab61910f1e..5504a6216d19 100644 --- a/rust/kernel/kunit.rs +++ b/rust/kernel/kunit.rs @@ -57,9 +57,9 @@ macro_rules! kunit_assert { break 'out; } =20 - static FILE: &'static $crate::str::CStr =3D $file; + static FILE: &'static ::core::ffi::CStr =3D $file; static LINE: i32 =3D ::core::line!() as i32 - $diff; - static CONDITION: &'static $crate::str::CStr =3D + static CONDITION: &'static ::core::ffi::CStr =3D $crate::str_to_cstr!(stringify!($condition)); =20 // SAFETY: FFI call without safety requirements. @@ -195,7 +195,7 @@ pub fn is_test_result_ok(t: impl TestResult) -> bool { /// Use [`kunit_case_null`] to generate such a delimiter. #[doc(hidden)] pub const fn kunit_case( - name: &'static kernel::str::CStr, + name: &'static core::ffi::CStr, run_case: unsafe extern "C" fn(*mut kernel::bindings::kunit), ) -> kernel::bindings::kunit_case { kernel::bindings::kunit_case { diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index aadcfaa5c759..3a7e935dd1fc 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -166,7 +166,7 @@ fn init(module: &'static ThisModule) -> impl pin_init::= PinInit u32 { /// /// ``` /// # mod module_phy_driver_sample { +/// use core::ffi::CStr; /// use kernel::net::phy::{self, DeviceId}; /// use kernel::prelude::*; /// @@ -808,6 +809,7 @@ const fn as_int(&self) -> u32 { /// This expands to the following code: /// /// ```ignore +/// use core::ffi::CStr; /// use kernel::net::phy::{self, DeviceId}; /// use kernel::prelude::*; /// diff --git a/rust/kernel/of.rs b/rust/kernel/of.rs index 12ea65df46de..087ac8e05551 100644 --- a/rust/kernel/of.rs +++ b/rust/kernel/of.rs @@ -2,7 +2,8 @@ =20 //! Device Tree / Open Firmware abstractions. =20 -use crate::{bindings, device_id::RawDeviceId, prelude::*}; +use crate::{bindings, device_id::RawDeviceId}; +use core::ffi::CStr; =20 /// IdTable type for OF drivers. pub type IdTable =3D &'static dyn kernel::device_id::IdTable; diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 8435f8132e38..86b5f666e22b 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -13,11 +13,11 @@ error::{to_result, Result}, io::Io, io::IoRaw, - str::CStr, types::{ARef, ForeignOwnable, Opaque}, ThisModule, }; use core::{ + ffi::CStr, marker::PhantomData, ops::Deref, ptr::{addr_of_mut, NonNull}, diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 338b8d7c65ee..ccf52274142a 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -9,12 +9,12 @@ error::{to_result, Result}, of, prelude::*, - str::CStr, types::{ForeignOwnable, Opaque}, ThisModule, }; =20 use core::{ + ffi::CStr, marker::PhantomData, ptr::{addr_of_mut, NonNull}, }; diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index 244b660fa835..3f7ca5a95160 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -40,10 +40,7 @@ =20 pub use super::error::{code::*, Error, Result}; =20 -pub use super::{ - str::{CStr, CStrExt as _}, - ThisModule, -}; +pub use super::{str::CStrExt as _, ThisModule}; =20 pub use super::init::InPlaceInit; =20 diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index 9908b09868bc..a64ce7cd8fc8 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -3,6 +3,7 @@ //! String representations. =20 use crate::alloc::{flags::*, AllocError, KVec}; +use core::ffi::CStr; use core::fmt::{self, Write}; use core::ops::{Deref, DerefMut, Index}; =20 @@ -175,8 +176,6 @@ macro_rules! b_str { }}; } =20 -pub use core::ffi::CStr; - /// Returns a C pointer to the string. // It is a free function rather than a method on an extension trait becaus= e: // @@ -267,7 +266,6 @@ impl crate::fmt::Display for CStr { /// /// ``` /// # use kernel::prelude::fmt; - /// # use kernel::str::CStr; /// # use kernel::str::CString; /// let penguin =3D c"=F0=9F=90=A7"; /// let s =3D CString::try_from_fmt(fmt!("{}", penguin))?; @@ -376,8 +374,8 @@ fn as_ref(&self) -> &BStr { /// # Examples /// /// ``` +/// # use core::ffi::CStr; /// # use kernel::str_to_cstr; -/// # use kernel::str::CStr; /// const MY_CSTR: &CStr =3D str_to_cstr!(concat!(file!(), ":", line!(), "= : My CStr!")); /// ``` #[macro_export] @@ -387,7 +385,7 @@ macro_rules! str_to_cstr { // too limiting to macro authors, so we rely on the name as a hint ins= tead. ($str:expr) =3D> {{ const S: &str =3D concat!($str, "\0"); - const C: &$crate::str::CStr =3D match $crate::str::CStr::from_byte= s_with_nul(S.as_bytes()) { + const C: &core::ffi::CStr =3D match core::ffi::CStr::from_bytes_wi= th_nul(S.as_bytes()) { Ok(v) =3D> v, Err(_) =3D> panic!("string contains interior NUL"), }; diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs index 0b6bc7f2878d..09bc35feb451 100644 --- a/rust/kernel/sync/condvar.rs +++ b/rust/kernel/sync/condvar.rs @@ -8,14 +8,14 @@ use super::{lock::Backend, lock::Guard, LockClassKey}; use crate::{ ffi::{c_int, c_long}, - str::{CStr, CStrExt as _}, + str::CStrExt as _, task::{ MAX_SCHEDULE_TIMEOUT, TASK_FREEZABLE, TASK_INTERRUPTIBLE, TASK_NOR= MAL, TASK_UNINTERRUPTIBLE, }, time::Jiffies, types::Opaque, }; -use core::{marker::PhantomPinned, pin::Pin, ptr}; +use core::{ffi::CStr, marker::PhantomPinned, pin::Pin, ptr}; use pin_init::{pin_data, pin_init, PinInit}; =20 /// Creates a [`CondVar`] initialiser with the given name and a newly-crea= ted lock class. diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index a777a22976e0..21deff0bb13b 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -7,10 +7,10 @@ =20 use super::LockClassKey; use crate::{ - str::{CStr, CStrExt as _}, + str::CStrExt as _, types::{NotThreadSafe, Opaque, ScopeGuard}, }; -use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin}; +use core::{cell::UnsafeCell, ffi::CStr, marker::PhantomPinned, pin::Pin}; use pin_init::{pin_data, pin_init, PinInit}; =20 pub mod mutex; diff --git a/rust/kernel/sync/lock/global.rs b/rust/kernel/sync/lock/global= .rs index 9caa9b419f09..ab5a3947fdd6 100644 --- a/rust/kernel/sync/lock/global.rs +++ b/rust/kernel/sync/lock/global.rs @@ -5,13 +5,14 @@ //! Support for defining statics containing locks. =20 use crate::{ - str::{CStr, CStrExt as _}, + str::CStrExt as _, sync::lock::{Backend, Guard, Lock}, sync::{LockClassKey, LockedBy}, types::Opaque, }; use core::{ cell::UnsafeCell, + ffi::CStr, marker::{PhantomData, PhantomPinned}, pin::Pin, }; @@ -267,7 +268,7 @@ macro_rules! global_lock { $pub enum $name {} =20 impl $crate::sync::lock::GlobalLockBackend for $name { - const NAME: &'static $crate::str::CStr =3D + const NAME: &'static ::core::ffi::CStr =3D $crate::str_to_cstr!(::core::stringify!($name)); type Item =3D $valuety; type Backend =3D $crate::global_lock_inner!(backend $kind); diff --git a/rust/kernel/sync/poll.rs b/rust/kernel/sync/poll.rs index d7e6e59e124b..bf2fb24d04ea 100644 --- a/rust/kernel/sync/poll.rs +++ b/rust/kernel/sync/poll.rs @@ -11,6 +11,7 @@ sync::{CondVar, LockClassKey}, types::Opaque, }; +use core::ffi::CStr; use core::ops::Deref; =20 /// Creates a [`PollCondVar`] initialiser with the given name and a newly-= created lock class. diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index dbec533fd31f..bb3f917204f8 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -135,6 +135,7 @@ =20 use crate::alloc::{AllocError, Flags}; use crate::{prelude::*, sync::Arc, sync::LockClassKey, types::Opaque}; +use core::ffi::CStr; use core::marker::PhantomData; =20 /// Creates a [`Work`] initialiser with the given name and a newly-created= lock class. diff --git a/rust/macros/module.rs b/rust/macros/module.rs index ec528cd86db5..5ed01f95db53 100644 --- a/rust/macros/module.rs +++ b/rust/macros/module.rs @@ -234,7 +234,7 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream { type LocalModule =3D {type_}; =20 impl ::kernel::ModuleMetadata for {type_} {{ - const NAME: &'static ::kernel::str::CStr =3D c\"{name}\"; + const NAME: &'static ::core::ffi::CStr =3D c\"{name}\"; }} =20 // Double nested modules, since then nobody can access the pub= lic items inside. diff --git a/samples/rust/rust_configfs.rs b/samples/rust/rust_configfs.rs index 4f362be5c7df..29514806bc27 100644 --- a/samples/rust/rust_configfs.rs +++ b/samples/rust/rust_configfs.rs @@ -10,6 +10,8 @@ use kernel::prelude::*; use kernel::sync::Mutex; =20 +use core::ffi::CStr; + module! { type: RustConfigfs, name: "rust_configfs", diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driv= er_auxiliary.rs index 0b38729bbab7..691df473d2fd 100644 --- a/samples/rust/rust_driver_auxiliary.rs +++ b/samples/rust/rust_driver_auxiliary.rs @@ -5,10 +5,11 @@ //! To make this driver probe, QEMU must be run with `-device pci-testdev`. =20 use kernel::{ - auxiliary, bindings, device::Core, driver, error::Error, pci, prelude:= :*, str::CStr, - InPlaceModule, + auxiliary, bindings, device::Core, driver, error::Error, pci, prelude:= :*, InPlaceModule, }; =20 +use core::ffi::CStr; + use pin_init::PinInit; =20 const MODULE_NAME: &CStr =3D ::NAME; --=20 2.50.0