summaryrefslogtreecommitdiffstats
path: root/rust/syn/restriction.rs
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@kernel.org>2026-08-14 15:43:51 -0700
committerPaul E. McKenney <paulmck@kernel.org>2026-08-14 15:43:51 -0700
commit9cc63f8bcd560c760d0b12e15bba8f81c86237cf (patch)
tree3b5269b1bcf6714171754946367c51e0590f64da /rust/syn/restriction.rs
downloadlinux-stable-9cc63f8bcd560c760d0b12e15bba8f81c86237cf.tar.gz
linux-stable-9cc63f8bcd560c760d0b12e15bba8f81c86237cf.zip
Merge branches 'expcb.2026.07.24a', 'misc.2026.07.30a', 'rcu-tasks.2026.07.30a', 'srcu.2026.08.11a' and 'torture.2026.08.14a' into HEADgrafted
Changes: Make expedited grace periods expedite normal RCU callbacks Miscellaneous fixes: * Improve diagnostic output with character task states. * Mark accesses to inform KCSAN of concurrency design. * Move from kmalloc() to kmalloc_obj(). * Documentation updates. * Improve handling of RCU deferred quiescent states. * Clean up unused function arguments and structure fields. * Reduce show_rcu_gp_kthreads() stack space. Tasks RCU updates: * Clean up after SRCU re-implementation of Tasks Trace RCU. * Mark accesses to inform KCSAN of concurrency design. * Add ->lazy_timer status to diagnostic output. * Remove an unnecessary memory barrier. * Fix a data race, courtesy of KCSAN. * Documentation updates. * Convert cond_resched_tasks_rcu_qs() from macro to static inline function. SRCU updates: * Add Rust helpers for SRCU. * Avoid losing queued work at cleanup_srcu_struct() time. Torture-test updates: * Preparation work for immediate RCU priority deboosting. * Test RCU readers from real interrupt handlers (as opposed to softirq). * Simplify code through use of cpumask_next_wrap(). * Improve diagnostic output with character task states. * Add rcutorture.nwriters parameter to allow lightweight stall testing, and rcutorture.stall_only to make doing so easier. * Test an RCU Tasks Trace grace period implying an RCU grace period. * Make RCU Tasks Trace torturing track reader batches. * Fix a data race, courtesy of KCSAN. * Plug a shuffle_tmp_mask memory leak on kthread spawn failure.
Diffstat (limited to 'rust/syn/restriction.rs')
-rw-r--r--rust/syn/restriction.rs180
1 files changed, 180 insertions, 0 deletions
diff --git a/rust/syn/restriction.rs b/rust/syn/restriction.rs
new file mode 100644
index 000000000..b844f64c3
--- /dev/null
+++ b/rust/syn/restriction.rs
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+use crate::path::Path;
+use crate::token;
+
+ast_enum! {
+ /// The visibility level of an item: inherited or `pub` or
+ /// `pub(restricted)`.
+ ///
+ /// # Syntax tree enum
+ ///
+ /// This type is a [syntax tree enum].
+ ///
+ /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub enum Visibility {
+ /// A public visibility level: `pub`.
+ Public(Token![pub]),
+
+ /// A visibility level restricted to some path: `pub(self)` or
+ /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
+ Restricted(VisRestricted),
+
+ /// An inherited visibility, which usually means private.
+ Inherited,
+ }
+}
+
+ast_struct! {
+ /// A visibility level restricted to some path: `pub(self)` or
+ /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct VisRestricted {
+ pub pub_token: Token![pub],
+ pub paren_token: token::Paren,
+ pub in_token: Option<Token![in]>,
+ pub path: Box<Path>,
+ }
+}
+
+ast_enum! {
+ /// Unused, but reserved for RFC 3323 restrictions.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ #[non_exhaustive]
+ pub enum FieldMutability {
+ None,
+
+ // TODO: https://rust-lang.github.io/rfcs/3323-restrictions.html
+ //
+ // FieldMutability::Restricted(MutRestricted)
+ //
+ // pub struct MutRestricted {
+ // pub mut_token: Token![mut],
+ // pub paren_token: token::Paren,
+ // pub in_token: Option<Token![in]>,
+ // pub path: Box<Path>,
+ // }
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::error::Result;
+ use crate::ext::IdentExt as _;
+ use crate::ident::Ident;
+ use crate::parse::discouraged::Speculative as _;
+ use crate::parse::{Parse, ParseStream};
+ use crate::path::Path;
+ use crate::restriction::{VisRestricted, Visibility};
+ use crate::token;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Visibility {
+ fn parse(input: ParseStream) -> Result<Self> {
+ // Recognize an empty None-delimited group, as produced by a $:vis
+ // matcher that matched no tokens.
+ if input.peek(token::Group) {
+ let ahead = input.fork();
+ let group = crate::group::parse_group(&ahead)?;
+ if group.content.is_empty() {
+ input.advance_to(&ahead);
+ return Ok(Visibility::Inherited);
+ }
+ }
+
+ if input.peek(Token![pub]) {
+ Self::parse_pub(input)
+ } else {
+ Ok(Visibility::Inherited)
+ }
+ }
+ }
+
+ impl Visibility {
+ fn parse_pub(input: ParseStream) -> Result<Self> {
+ let pub_token = input.parse::<Token![pub]>()?;
+
+ if input.peek(token::Paren) {
+ let ahead = input.fork();
+
+ let content;
+ let paren_token = parenthesized!(content in ahead);
+ if content.peek(Token![crate])
+ || content.peek(Token![self])
+ || content.peek(Token![super])
+ {
+ let path = content.call(Ident::parse_any)?;
+
+ // Ensure there are no additional tokens within `content`.
+ // Without explicitly checking, we may misinterpret a tuple
+ // field as a restricted visibility, causing a parse error.
+ // e.g. `pub (crate::A, crate::B)` (Issue #720).
+ if content.is_empty() {
+ input.advance_to(&ahead);
+ return Ok(Visibility::Restricted(VisRestricted {
+ pub_token,
+ paren_token,
+ in_token: None,
+ path: Box::new(Path::from(path)),
+ }));
+ }
+ } else if content.peek(Token![in]) {
+ let in_token: Token![in] = content.parse()?;
+ let path = content.call(Path::parse_mod_style)?;
+
+ input.advance_to(&ahead);
+ return Ok(Visibility::Restricted(VisRestricted {
+ pub_token,
+ paren_token,
+ in_token: Some(in_token),
+ path: Box::new(path),
+ }));
+ }
+ }
+
+ Ok(Visibility::Public(pub_token))
+ }
+
+ #[cfg(feature = "full")]
+ pub(crate) fn is_some(&self) -> bool {
+ match self {
+ Visibility::Inherited => false,
+ _ => true,
+ }
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::path;
+ use crate::path::printing::PathStyle;
+ use crate::restriction::{VisRestricted, Visibility};
+ use proc_macro2::TokenStream;
+ use quote::ToTokens;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Visibility {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Visibility::Public(pub_token) => pub_token.to_tokens(tokens),
+ Visibility::Restricted(vis_restricted) => vis_restricted.to_tokens(tokens),
+ Visibility::Inherited => {}
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for VisRestricted {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.pub_token.to_tokens(tokens);
+ self.paren_token.surround(tokens, |tokens| {
+ // TODO: If we have a path which is not "self" or "super" or
+ // "crate", automatically add the "in" token.
+ self.in_token.to_tokens(tokens);
+ path::printing::print_path(tokens, &self.path, PathStyle::Mod);
+ });
+ }
+ }
+}