Skip to content
This repository was archived by the owner on Apr 2, 2026. It is now read-only.

Commit eb3a92f

Browse files
committed
Make send/sync the default for crate abstractions
1 parent 456c489 commit eb3a92f

6 files changed

Lines changed: 42 additions & 36 deletions

File tree

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ extension = []
4040
sync = ["spin"]
4141

4242
# Enable Pratt parsing combinator
43-
pratt = ["unstable"]
43+
pratt = []
4444

4545
# Allow the use of unstable features (aka features where the API is not settled)
4646
unstable = []
@@ -66,7 +66,7 @@ docsrs = []
6666
# An alias of all features that work with the stable compiler.
6767
# Do not use this feature, its removal is not considered a breaking change and its behaviour may change.
6868
# If you're working on chumsky and you're adding a feature that does not require nightly support, please add it to this list.
69-
_test_stable = ["std", "stacker", "memoization", "extension", "sync"]
69+
_test_stable = ["std", "stacker", "memoization", "extension", "sync", "pratt"]
7070

7171
[package.metadata.docs.rs]
7272
all-features = true

src/lib.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ pub mod prelude {
8989
use crate::input::InputOwn;
9090
use alloc::{
9191
boxed::Box,
92-
rc::{self, Rc},
9392
string::String,
93+
sync::{Arc, Weak},
9494
vec,
9595
vec::Vec,
9696
};
@@ -157,9 +157,10 @@ impl<T> Unpin for EmptyPhantom<T> {}
157157
impl<T> core::panic::UnwindSafe for EmptyPhantom<T> {}
158158
impl<T> core::panic::RefUnwindSafe for EmptyPhantom<T> {}
159159

160-
pub(crate) type DynParser<'src, 'b, I, O, E> = dyn Parser<'src, I, O, E> + 'b;
160+
pub(crate) type DynParser<'src, 'b, I, O, E> = dyn Parser<'src, I, O, E> + Send + Sync + 'b;
161161
#[cfg(feature = "pratt")]
162-
pub(crate) type DynOperator<'src, 'b, I, O, E> = dyn pratt::Operator<'src, I, O, E> + 'b;
162+
pub(crate) type DynOperator<'src, 'b, I, O, E> =
163+
dyn pratt::Operator<'src, I, O, E> + Send + Sync + 'b;
163164

164165
/// Labels corresponding to a variety of patterns.
165166
#[derive(Clone, Debug, PartialEq)]
@@ -2201,10 +2202,10 @@ pub trait Parser<'src, I: Input<'src>, O, E: ParserExtra<'src, I> = extra::Defau
22012202
///
22022203
fn boxed<'b>(self) -> Boxed<'src, 'b, I, O, E>
22032204
where
2204-
Self: Sized + 'b,
2205+
Self: Sized + Send + Sync + 'b,
22052206
{
22062207
Boxed {
2207-
inner: Rc::new(self),
2208+
inner: Arc::new(self),
22082209
}
22092210
}
22102211

@@ -2795,12 +2796,11 @@ where
27952796

27962797
/// See [`Parser::boxed`].
27972798
///
2798-
/// Due to current implementation details, the inner value is not, in fact, a [`Box`], but is an [`Rc`] to facilitate
2799-
/// efficient cloning. This is likely to change in the future. Unlike [`Box`], [`Rc`] has no size guarantees: although
2799+
/// Due to current implementation details, the inner value is not, in fact, a [`Box`], but is an [`Arc`] to facilitate
2800+
/// efficient cloning. This is likely to change in the future. Unlike [`Box`], [`Arc`] has no size guarantees: although
28002801
/// it is *currently* the same size as a raw pointer.
2801-
// TODO: Don't use an Rc (why?)
28022802
pub struct Boxed<'src, 'b, I: Input<'src>, O, E: ParserExtra<'src, I> = extra::Default> {
2803-
inner: Rc<DynParser<'src, 'b, I, O, E>>,
2803+
inner: Arc<DynParser<'src, 'b, I, O, E>>,
28042804
}
28052805

28062806
impl<'src, I: Input<'src>, O, E: ParserExtra<'src, I>> Clone for Boxed<'src, '_, I, O, E> {

src/pratt.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,9 @@ where
205205
/// Box this operator, allowing it to be used via dynamic dispatch.
206206
fn boxed<'a>(self) -> Boxed<'src, 'a, I, O, E>
207207
where
208-
Self: Sized + 'a,
208+
Self: Sized + Send + Sync + 'a,
209209
{
210-
Boxed(Rc::new(self))
210+
Boxed(Arc::new(self))
211211
}
212212

213213
#[doc(hidden)]
@@ -317,7 +317,7 @@ where
317317
}
318318

319319
/// A boxed pratt parser operator. See [`Operator`].
320-
pub struct Boxed<'src, 'a, I, O, E = extra::Default>(Rc<DynOperator<'src, 'a, I, O, E>>);
320+
pub struct Boxed<'src, 'a, I, O, E = extra::Default>(Arc<DynOperator<'src, 'a, I, O, E>>);
321321

322322
impl<I, O, E> Clone for Boxed<'_, '_, I, O, E> {
323323
fn clone(&self) -> Self {

src/recovery.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,10 @@ pub fn nested_delimiters<'src, 'parse, I, O, E, F, const N: usize>(
239239
) -> impl Parser<'src, I, O, E> + Clone + 'parse
240240
where
241241
I: ValueInput<'src>,
242-
I::Token: PartialEq + Clone,
242+
I::Token: PartialEq + Clone + Send + Sync,
243243
E: extra::ParserExtra<'src, I> + 'parse,
244244
'src: 'parse,
245-
F: Fn(I::Span) -> O + Clone + 'parse,
245+
F: Fn(I::Span) -> O + Clone + Send + Sync + 'parse,
246246
{
247247
// TODO: Does this actually work? TESTS!
248248
#[allow(clippy::tuple_array_conversions)]

src/recursive.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ impl<T> OnceCell<T> {
3737

3838
// TODO: Ensure that this doesn't produce leaks
3939
enum RecursiveInner<T: ?Sized> {
40-
Owned(Rc<T>),
41-
Unowned(rc::Weak<T>),
40+
Owned(Arc<T>),
41+
Unowned(Weak<T>),
4242
}
4343

4444
/// Type for recursive parsers that are defined through a call to `recursive`, and as such
@@ -100,7 +100,7 @@ impl<'src, 'b, I: Input<'src>, O, E: ParserExtra<'src, I>> Recursive<Indirect<'s
100100
/// ```
101101
pub fn declare() -> Self {
102102
Recursive {
103-
inner: RecursiveInner::Owned(Rc::new(Indirect {
103+
inner: RecursiveInner::Owned(Arc::new(Indirect {
104104
inner: OnceCell::new(),
105105
})),
106106
}
@@ -109,7 +109,7 @@ impl<'src, 'b, I: Input<'src>, O, E: ParserExtra<'src, I>> Recursive<Indirect<'s
109109
/// Defines the parser after declaring it, allowing it to be used for parsing.
110110
// INFO: Clone bound not actually needed, but good to be safe for future compat
111111
#[track_caller]
112-
pub fn define<P: Parser<'src, I, O, E> + Clone + 'b>(&mut self, parser: P) {
112+
pub fn define<P: Parser<'src, I, O, E> + Clone + Send + Sync + 'b>(&mut self, parser: P) {
113113
let location = *Location::caller();
114114
self.parser()
115115
.inner
@@ -122,7 +122,7 @@ impl<'src, 'b, I: Input<'src>, O, E: ParserExtra<'src, I>> Recursive<Indirect<'s
122122

123123
impl<P: ?Sized> Recursive<P> {
124124
#[inline]
125-
fn parser(&self) -> Rc<P> {
125+
fn parser(&self) -> Arc<P> {
126126
match &self.inner {
127127
RecursiveInner::Owned(x) => x.clone(),
128128
RecursiveInner::Unowned(x) => x
@@ -243,11 +243,11 @@ pub fn recursive<'src, 'b, I, O, E, A, F>(f: F) -> Recursive<Direct<'src, 'b, I,
243243
where
244244
I: Input<'src>,
245245
E: ParserExtra<'src, I>,
246-
A: Parser<'src, I, O, E> + Clone + 'b,
246+
A: Parser<'src, I, O, E> + Clone + Send + Sync + 'b,
247247
F: FnOnce(Recursive<Direct<'src, 'b, I, O, E>>) -> A,
248248
{
249-
let rc = Rc::new_cyclic(|rc| {
250-
let rc: rc::Weak<DynParser<'src, 'b, I, O, E>> = rc.clone() as _;
249+
let rc = Arc::new_cyclic(|rc| {
250+
let rc: Weak<DynParser<'src, 'b, I, O, E>> = rc.clone() as _;
251251
let parser = Recursive {
252252
inner: RecursiveInner::Unowned(rc.clone()),
253253
};

src/text.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,8 @@ where
251251
/// // ...including none at all!
252252
/// assert_eq!(whitespace.parse("").into_result(), Ok(()));
253253
/// ```
254-
pub fn whitespace<'src, I, E>() -> Repeated<impl Parser<'src, I, (), E> + Copy, (), I, E>
254+
pub fn whitespace<'src, I, E>(
255+
) -> Repeated<impl Parser<'src, I, (), E> + Copy + Send + Sync, (), I, E>
255256
where
256257
I: StrInput<'src>,
257258
I::Token: Char + 'src,
@@ -287,7 +288,8 @@ where
287288
/// // ... but not newlines
288289
/// assert!(inline_whitespace.at_least(1).parse("\n\r").has_errors());
289290
/// ```
290-
pub fn inline_whitespace<'src, I, E>() -> Repeated<impl Parser<'src, I, (), E> + Copy, (), I, E>
291+
pub fn inline_whitespace<'src, I, E>(
292+
) -> Repeated<impl Parser<'src, I, (), E> + Copy + Send + Sync, (), I, E>
291293
where
292294
I: StrInput<'src>,
293295
I::Token: Char + 'src,
@@ -335,7 +337,7 @@ where
335337
/// assert_eq!(newline.parse("\u{2029}").into_result(), Ok(()));
336338
/// ```
337339
#[must_use]
338-
pub fn newline<'src, I, E>() -> impl Parser<'src, I, (), E> + Copy
340+
pub fn newline<'src, I, E>() -> impl Parser<'src, I, (), E> + Copy + Send + Sync
339341
where
340342
I: StrInput<'src>,
341343
I::Token: Char + 'src,
@@ -398,7 +400,7 @@ where
398400
#[must_use]
399401
pub fn digits<'src, I, E>(
400402
radix: u32,
401-
) -> Repeated<impl Parser<'src, I, <I as Input<'src>>::Token, E> + Copy, I::Token, I, E>
403+
) -> Repeated<impl Parser<'src, I, <I as Input<'src>>::Token, E> + Copy + Send + Sync, I::Token, I, E>
402404
where
403405
I: StrInput<'src>,
404406
I::Token: Char + 'src,
@@ -446,10 +448,12 @@ where
446448
/// ```
447449
///
448450
#[must_use]
449-
pub fn int<'src, I, E>(radix: u32) -> impl Parser<'src, I, <I as SliceInput<'src>>::Slice, E> + Copy
451+
pub fn int<'src, I, E>(
452+
radix: u32,
453+
) -> impl Parser<'src, I, <I as SliceInput<'src>>::Slice, E> + Copy + Send + Sync
450454
where
451455
I: StrInput<'src>,
452-
I::Token: Char + 'src,
456+
I::Token: Char + Send + Sync + 'src,
453457
E: ParserExtra<'src, I>,
454458
E::Error:
455459
LabelError<'src, I, TextExpected<'src, I>> + LabelError<'src, I, MaybeRef<'src, I::Token>>,
@@ -486,7 +490,8 @@ pub mod ascii {
486490
/// An identifier is defined as an ASCII alphabetic character or an underscore followed by any number of alphanumeric
487491
/// characters or underscores. The regex pattern for it is `[a-zA-Z_][a-zA-Z0-9_]*`.
488492
#[must_use]
489-
pub fn ident<'src, I, E>() -> impl Parser<'src, I, <I as SliceInput<'src>>::Slice, E> + Copy
493+
pub fn ident<'src, I, E>(
494+
) -> impl Parser<'src, I, <I as SliceInput<'src>>::Slice, E> + Copy + Send + Sync
490495
where
491496
I: StrInput<'src>,
492497
I::Token: Char + 'src,
@@ -539,12 +544,12 @@ pub mod ascii {
539544
#[track_caller]
540545
pub fn keyword<'src, I, S, E>(
541546
keyword: S,
542-
) -> impl Parser<'src, I, <I as SliceInput<'src>>::Slice, E> + Clone + 'src
547+
) -> impl Parser<'src, I, <I as SliceInput<'src>>::Slice, E> + Clone + Send + Sync + 'src
543548
where
544549
I: StrInput<'src>,
545550
I::Slice: PartialEq,
546551
I::Token: Char + fmt::Debug + 'src,
547-
S: PartialEq<I::Slice> + Clone + 'src,
552+
S: PartialEq<I::Slice> + Clone + Send + Sync + 'src,
548553
E: ParserExtra<'src, I> + 'src,
549554
E::Error: LabelError<'src, I, TextExpected<'src, I>> + LabelError<'src, I, S>,
550555
{
@@ -981,7 +986,8 @@ pub mod unicode {
981986
///
982987
/// An identifier is defined as per "Default Identifiers" in [Unicode Standard Annex #31](https://www.unicode.org/reports/tr31/).
983988
#[must_use]
984-
pub fn ident<'src, I, E>() -> impl Parser<'src, I, <I as SliceInput<'src>>::Slice, E> + Copy
989+
pub fn ident<'src, I, E>(
990+
) -> impl Parser<'src, I, <I as SliceInput<'src>>::Slice, E> + Copy + Send + Sync
985991
where
986992
I: StrInput<'src>,
987993
I::Token: Char + 'src,
@@ -1028,12 +1034,12 @@ pub mod unicode {
10281034
#[track_caller]
10291035
pub fn keyword<'src, I, S, E>(
10301036
keyword: S,
1031-
) -> impl Parser<'src, I, <I as SliceInput<'src>>::Slice, E> + Clone + 'src
1037+
) -> impl Parser<'src, I, <I as SliceInput<'src>>::Slice, E> + Clone + Send + Sync + 'src
10321038
where
10331039
I: StrInput<'src>,
10341040
I::Slice: PartialEq,
10351041
I::Token: Char + fmt::Debug + 'src,
1036-
S: PartialEq<I::Slice> + Clone + 'src,
1042+
S: PartialEq<I::Slice> + Clone + Send + Sync + 'src,
10371043
E: ParserExtra<'src, I> + 'src,
10381044
E::Error: LabelError<'src, I, TextExpected<'src, I>> + LabelError<'src, I, S>,
10391045
{

0 commit comments

Comments
 (0)