From 5d16aaf5334a6bb7cc509f73ed914cb185bdae4b Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Wed, 6 Nov 2024 00:41:39 +0100 Subject: [PATCH] rune: Move tests around and Send + Sync --- crates/rune/src/compile/names.rs | 29 +- crates/rune/src/compile/names/tests.rs | 22 + crates/rune/src/compile/v1/slots.rs | 194 +----- crates/rune/src/compile/v1/slots/tests.rs | 187 ++++++ crates/rune/src/internal_macros.rs | 10 + crates/rune/src/parse/lexer.rs | 661 +-------------------- crates/rune/src/parse/lexer/tests.rs | 654 ++++++++++++++++++++ crates/rune/src/runtime/function.rs | 25 +- crates/rune/src/runtime/runtime_context.rs | 2 + crates/rune/src/runtime/unit.rs | 2 + 10 files changed, 888 insertions(+), 898 deletions(-) create mode 100644 crates/rune/src/compile/names/tests.rs create mode 100644 crates/rune/src/compile/v1/slots/tests.rs create mode 100644 crates/rune/src/parse/lexer/tests.rs diff --git a/crates/rune/src/compile/names.rs b/crates/rune/src/compile/names.rs index f567ab343..930e4946f 100644 --- a/crates/rune/src/compile/names.rs +++ b/crates/rune/src/compile/names.rs @@ -1,3 +1,6 @@ +#[cfg(test)] +mod tests; + use core::mem::replace; use crate::alloc; @@ -113,29 +116,3 @@ impl TryClone for Node { }) } } - -#[cfg(test)] -mod tests { - use super::Names; - use crate::support::Result; - - #[test] - fn insert() -> Result<()> { - let mut names = Names::default(); - assert!(!names.contains(["test"])?); - assert!(!names.insert(["test"]).unwrap()); - assert!(names.contains(["test"])?); - assert!(names.insert(["test"]).unwrap()); - Ok(()) - } - - #[test] - fn contains() -> Result<()> { - let mut names = Names::default(); - assert!(!names.contains(["test"])?); - assert!(!names.insert(["test"]).unwrap()); - assert!(names.contains(["test"])?); - assert!(names.insert(["test"]).unwrap()); - Ok(()) - } -} diff --git a/crates/rune/src/compile/names/tests.rs b/crates/rune/src/compile/names/tests.rs new file mode 100644 index 000000000..846d34516 --- /dev/null +++ b/crates/rune/src/compile/names/tests.rs @@ -0,0 +1,22 @@ +use super::Names; +use crate::support::Result; + +#[test] +fn insert() -> Result<()> { + let mut names = Names::default(); + assert!(!names.contains(["test"])?); + assert!(!names.insert(["test"]).unwrap()); + assert!(names.contains(["test"])?); + assert!(names.insert(["test"]).unwrap()); + Ok(()) +} + +#[test] +fn contains() -> Result<()> { + let mut names = Names::default(); + assert!(!names.contains(["test"])?); + assert!(!names.insert(["test"]).unwrap()); + assert!(names.contains(["test"])?); + assert!(names.insert(["test"]).unwrap()); + Ok(()) +} diff --git a/crates/rune/src/compile/v1/slots.rs b/crates/rune/src/compile/v1/slots.rs index 878156b5d..b219ed6f1 100644 --- a/crates/rune/src/compile/v1/slots.rs +++ b/crates/rune/src/compile/v1/slots.rs @@ -2,6 +2,9 @@ #![allow(clippy::bool_assert_comparison)] +#[cfg(test)] +mod tests; + use core::fmt; use core::slice; @@ -151,194 +154,3 @@ impl Iterator for Iter<'_> { } } } - -#[cfg(test)] -mod tests { - use super::Slots; - - macro_rules! slab_eq { - ($slab:expr, $expected:expr) => {{ - let expected: &[usize] = &$expected[..]; - - if !$slab.iter().eq(expected.iter().copied()) { - panic!("{:?} != {:?}", $slab, expected); - } - }}; - } - - #[test] - fn iter() { - let mut slab = Slots::new(); - - assert_eq!(slab.insert(), Ok(0)); - assert_eq!(slab.insert(), Ok(1)); - assert_eq!(slab.insert(), Ok(2)); - assert_eq!(slab.insert(), Ok(3)); - assert_eq!(slab.insert(), Ok(4)); - slab_eq!(slab, [0, 1, 2, 3, 4]); - - assert_eq!(slab.remove(2), true); - slab_eq!(slab, [0, 1, 3, 4]); - - assert_eq!(slab.remove(3), true); - slab_eq!(slab, [0, 1, 4]); - - assert_eq!(slab.remove(0), true); - slab_eq!(slab, [1, 4]); - - assert_eq!(slab.remove(1), true); - slab_eq!(slab, [4]); - - assert_eq!(slab.remove(4), true); - slab_eq!(slab, []); - - assert_eq!(slab.insert(), Ok(0)); - } - - #[test] - fn insert() { - let mut slab = Slots::new(); - assert_eq!(slab.insert(), Ok(0)); - assert_eq!(slab.insert(), Ok(1)); - assert_eq!(slab.insert(), Ok(2)); - assert_eq!(slab.remove(1), true); - assert_eq!(slab.remove(1), false); - assert_eq!(slab.insert(), Ok(1)); - assert_eq!(slab.insert(), Ok(3)); - assert_eq!(slab.insert(), Ok(4)); - } - - #[test] - fn insert_boundary() { - let mut slab = Slots::new(); - - for n in 0..167 { - assert_eq!(slab.push(), Ok(n)); - } - - for n in 167..1024 { - assert_eq!(slab.insert(), Ok(n)); - } - - for n in 128..256 { - assert!(slab.remove(n)); - } - - assert_eq!(slab.push(), Ok(1024)); - assert_eq!(slab.push(), Ok(1025)); - - for n in (128..256).chain(1026..2047) { - assert_eq!(slab.insert(), Ok(n)); - } - - for n in 2047..3000 { - assert_eq!(slab.push(), Ok(n)); - } - } - - #[test] - fn push() { - let mut slab = Slots::new(); - assert_eq!(slab.insert(), Ok(0)); - assert_eq!(slab.push(), Ok(1)); - assert_eq!(slab.push(), Ok(2)); - assert_eq!(slab.remove(0), true); - assert_eq!(slab.remove(0), false); - assert_eq!(slab.insert(), Ok(0)); - assert_eq!(slab.insert(), Ok(3)); - assert_eq!(slab.remove(2), true); - assert_eq!(slab.remove(0), true); - assert_eq!(slab.insert(), Ok(0)); - assert_eq!(slab.insert(), Ok(2)); - assert_eq!(slab.insert(), Ok(4)); - assert_eq!(slab.push(), Ok(5)); - } - - #[test] - fn push_tail_hole() { - let mut slab = Slots::new(); - assert_eq!(slab.insert(), Ok(0)); - assert_eq!(slab.insert(), Ok(1)); - assert_eq!(slab.insert(), Ok(2)); - - assert_eq!(slab.remove(1), true); - assert_eq!(slab.remove(2), true); - assert_eq!(slab.remove(2), false); - - assert_eq!(slab.push(), Ok(1)); - assert_eq!(slab.push(), Ok(2)); - } - - #[test] - fn push_pop() { - let mut slab = Slots::new(); - assert_eq!(slab.insert(), Ok(0)); - assert_eq!(slab.insert(), Ok(1)); - assert_eq!(slab.insert(), Ok(2)); - assert_eq!(slab.remove(1), true); - - assert_eq!(slab.push(), Ok(3)); - assert_eq!(slab.push(), Ok(4)); - assert_eq!(slab.push(), Ok(5)); - assert_eq!(slab.insert(), Ok(1)); - - assert_eq!(slab.remove(2), true); - - assert_eq!(slab.remove(5), true); - assert_eq!(slab.remove(4), true); - assert_eq!(slab.remove(3), true); - assert_eq!(slab.remove(1), true); - assert_eq!(slab.remove(0), true); - assert_eq!(slab.remove(0), false); - } - - #[test] - fn bad_test() { - let mut slab = Slots::new(); - assert_eq!(slab.insert(), Ok(0)); - assert_eq!(slab.insert(), Ok(1)); - assert_eq!(slab.insert(), Ok(2)); - assert_eq!(slab.insert(), Ok(3)); - - assert_eq!(slab.remove(2), true); - assert_eq!(slab.remove(3), true); - - assert_eq!(slab.insert(), Ok(2)); - } - - #[test] - fn bug1() { - let mut slab = Slots::new(); - assert_eq!(slab.insert(), Ok(0)); - assert_eq!(slab.insert(), Ok(1)); - assert_eq!(slab.insert(), Ok(2)); - - assert_eq!(slab.remove(2), true); - assert_eq!(slab.remove(1), true); - - assert_eq!(slab.insert(), Ok(1)); - } - - #[test] - fn push_first() { - let mut slab = Slots::new(); - assert_eq!(slab.push(), Ok(0)); - assert_eq!(slab.insert(), Ok(1)); - assert_eq!(slab.push(), Ok(2)); - } - - #[test] - fn test_bug() { - let mut slab = Slots::new(); - assert_eq!(slab.insert(), Ok(0)); - assert_eq!(slab.remove(0), true); - assert_eq!(slab.push(), Ok(0)); - assert_eq!(slab.insert(), Ok(1)); - assert_eq!(slab.push(), Ok(2)); - assert_eq!(slab.remove(2), true); - assert_eq!(slab.insert(), Ok(2)); - assert_eq!(slab.remove(2), true); - assert_eq!(slab.remove(0), true); - assert_eq!(slab.remove(0), false); - } -} diff --git a/crates/rune/src/compile/v1/slots/tests.rs b/crates/rune/src/compile/v1/slots/tests.rs new file mode 100644 index 000000000..a3adf19da --- /dev/null +++ b/crates/rune/src/compile/v1/slots/tests.rs @@ -0,0 +1,187 @@ +use super::Slots; + +macro_rules! slab_eq { + ($slab:expr, $expected:expr) => {{ + let expected: &[usize] = &$expected[..]; + + if !$slab.iter().eq(expected.iter().copied()) { + panic!("{:?} != {:?}", $slab, expected); + } + }}; +} + +#[test] +fn iter() { + let mut slab = Slots::new(); + + assert_eq!(slab.insert(), Ok(0)); + assert_eq!(slab.insert(), Ok(1)); + assert_eq!(slab.insert(), Ok(2)); + assert_eq!(slab.insert(), Ok(3)); + assert_eq!(slab.insert(), Ok(4)); + slab_eq!(slab, [0, 1, 2, 3, 4]); + + assert_eq!(slab.remove(2), true); + slab_eq!(slab, [0, 1, 3, 4]); + + assert_eq!(slab.remove(3), true); + slab_eq!(slab, [0, 1, 4]); + + assert_eq!(slab.remove(0), true); + slab_eq!(slab, [1, 4]); + + assert_eq!(slab.remove(1), true); + slab_eq!(slab, [4]); + + assert_eq!(slab.remove(4), true); + slab_eq!(slab, []); + + assert_eq!(slab.insert(), Ok(0)); +} + +#[test] +fn insert() { + let mut slab = Slots::new(); + assert_eq!(slab.insert(), Ok(0)); + assert_eq!(slab.insert(), Ok(1)); + assert_eq!(slab.insert(), Ok(2)); + assert_eq!(slab.remove(1), true); + assert_eq!(slab.remove(1), false); + assert_eq!(slab.insert(), Ok(1)); + assert_eq!(slab.insert(), Ok(3)); + assert_eq!(slab.insert(), Ok(4)); +} + +#[test] +fn insert_boundary() { + let mut slab = Slots::new(); + + for n in 0..167 { + assert_eq!(slab.push(), Ok(n)); + } + + for n in 167..1024 { + assert_eq!(slab.insert(), Ok(n)); + } + + for n in 128..256 { + assert!(slab.remove(n)); + } + + assert_eq!(slab.push(), Ok(1024)); + assert_eq!(slab.push(), Ok(1025)); + + for n in (128..256).chain(1026..2047) { + assert_eq!(slab.insert(), Ok(n)); + } + + for n in 2047..3000 { + assert_eq!(slab.push(), Ok(n)); + } +} + +#[test] +fn push() { + let mut slab = Slots::new(); + assert_eq!(slab.insert(), Ok(0)); + assert_eq!(slab.push(), Ok(1)); + assert_eq!(slab.push(), Ok(2)); + assert_eq!(slab.remove(0), true); + assert_eq!(slab.remove(0), false); + assert_eq!(slab.insert(), Ok(0)); + assert_eq!(slab.insert(), Ok(3)); + assert_eq!(slab.remove(2), true); + assert_eq!(slab.remove(0), true); + assert_eq!(slab.insert(), Ok(0)); + assert_eq!(slab.insert(), Ok(2)); + assert_eq!(slab.insert(), Ok(4)); + assert_eq!(slab.push(), Ok(5)); +} + +#[test] +fn push_tail_hole() { + let mut slab = Slots::new(); + assert_eq!(slab.insert(), Ok(0)); + assert_eq!(slab.insert(), Ok(1)); + assert_eq!(slab.insert(), Ok(2)); + + assert_eq!(slab.remove(1), true); + assert_eq!(slab.remove(2), true); + assert_eq!(slab.remove(2), false); + + assert_eq!(slab.push(), Ok(1)); + assert_eq!(slab.push(), Ok(2)); +} + +#[test] +fn push_pop() { + let mut slab = Slots::new(); + assert_eq!(slab.insert(), Ok(0)); + assert_eq!(slab.insert(), Ok(1)); + assert_eq!(slab.insert(), Ok(2)); + assert_eq!(slab.remove(1), true); + + assert_eq!(slab.push(), Ok(3)); + assert_eq!(slab.push(), Ok(4)); + assert_eq!(slab.push(), Ok(5)); + assert_eq!(slab.insert(), Ok(1)); + + assert_eq!(slab.remove(2), true); + + assert_eq!(slab.remove(5), true); + assert_eq!(slab.remove(4), true); + assert_eq!(slab.remove(3), true); + assert_eq!(slab.remove(1), true); + assert_eq!(slab.remove(0), true); + assert_eq!(slab.remove(0), false); +} + +#[test] +fn bad_test() { + let mut slab = Slots::new(); + assert_eq!(slab.insert(), Ok(0)); + assert_eq!(slab.insert(), Ok(1)); + assert_eq!(slab.insert(), Ok(2)); + assert_eq!(slab.insert(), Ok(3)); + + assert_eq!(slab.remove(2), true); + assert_eq!(slab.remove(3), true); + + assert_eq!(slab.insert(), Ok(2)); +} + +#[test] +fn bug1() { + let mut slab = Slots::new(); + assert_eq!(slab.insert(), Ok(0)); + assert_eq!(slab.insert(), Ok(1)); + assert_eq!(slab.insert(), Ok(2)); + + assert_eq!(slab.remove(2), true); + assert_eq!(slab.remove(1), true); + + assert_eq!(slab.insert(), Ok(1)); +} + +#[test] +fn push_first() { + let mut slab = Slots::new(); + assert_eq!(slab.push(), Ok(0)); + assert_eq!(slab.insert(), Ok(1)); + assert_eq!(slab.push(), Ok(2)); +} + +#[test] +fn test_bug() { + let mut slab = Slots::new(); + assert_eq!(slab.insert(), Ok(0)); + assert_eq!(slab.remove(0), true); + assert_eq!(slab.push(), Ok(0)); + assert_eq!(slab.insert(), Ok(1)); + assert_eq!(slab.push(), Ok(2)); + assert_eq!(slab.remove(2), true); + assert_eq!(slab.insert(), Ok(2)); + assert_eq!(slab.remove(2), true); + assert_eq!(slab.remove(0), true); + assert_eq!(slab.remove(0), false); +} diff --git a/crates/rune/src/internal_macros.rs b/crates/rune/src/internal_macros.rs index 195127b3c..439a8fd16 100644 --- a/crates/rune/src/internal_macros.rs +++ b/crates/rune/src/internal_macros.rs @@ -52,3 +52,13 @@ macro_rules! cfg_std { )* } } + +macro_rules! assert_impl { + ($ty:ty: $first_trait:ident $(+ $rest_trait:ident)*) => { + #[cfg(test)] + const _: () = const { + const fn assert_traits() where T: $first_trait $(+ $rest_trait)* {} + assert_traits::<$ty>(); + }; + }; +} diff --git a/crates/rune/src/parse/lexer.rs b/crates/rune/src/parse/lexer.rs index e4b2dd220..f324a68a7 100644 --- a/crates/rune/src/parse/lexer.rs +++ b/crates/rune/src/parse/lexer.rs @@ -1,3 +1,6 @@ +#[cfg(test)] +mod tests; + use core::fmt; use core::mem::take; @@ -1079,661 +1082,3 @@ impl fmt::Display for LexerMode { Ok(()) } } - -#[cfg(test)] -mod tests { - use super::Lexer; - use crate::{ast, SourceId}; - - macro_rules! test_lexer { - ($source:expr $(, $pat:pat)* $(,)?) => {{ - let mut it = Lexer::new($source, SourceId::empty(), false); - - #[allow(unused_assignments)] - { - let mut n = 0; - - $( - match it.next().unwrap().expect("expected token") { - $pat => (), - #[allow(unreachable_patterns)] - other => { - panic!("\nGot bad token #{}.\nExpected: `{}`\nBut got: {:?}", n, stringify!($pat), other); - } - } - - n += 1; - )* - } - - assert_eq!(it.next().unwrap(), None); - }} - } - - #[test] - fn test_number_literals() { - test_lexer! { - "(10)", - ast::Token { - span: span!(0, 1), - kind: ast::Kind::Open(ast::Delimiter::Parenthesis), - }, - ast::Token { - span: span!(1, 3), - kind: ast::Kind::Number(ast::NumberSource::Text(ast::NumberText { - source_id: SourceId::EMPTY, - is_fractional: false, - base: ast::NumberBase::Decimal, - number: span!(1, 3), - suffix: span!(3, 3), - })), - }, - ast::Token { - span: span!(3, 4), - kind: ast::Kind::Close(ast::Delimiter::Parenthesis), - }, - }; - - test_lexer! { - "(10.)", - _, - ast::Token { - span: span!(1, 4), - kind: ast::Kind::Number(ast::NumberSource::Text(ast::NumberText { - source_id: SourceId::EMPTY, - is_fractional: true, - base: ast::NumberBase::Decimal, - number: span!(1, 4), - suffix: span!(4, 4), - })), - }, - _, - }; - } - - #[test] - fn test_char_literal() { - test_lexer! { - "'a'", - ast::Token { - span: span!(0, 3), - kind: ast::Kind::Char(ast::CopySource::Text(SourceId::EMPTY)), - } - }; - - test_lexer! { - "'\\u{abcd}'", - ast::Token { - span: span!(0, 10), - kind: ast::Kind::Char(ast::CopySource::Text(SourceId::EMPTY)), - } - }; - } - - #[test] - fn test_label() { - test_lexer! { - "'asdf 'a' \"foo bar\"", - ast::Token { - span: span!(0, 5), - kind: ast::Kind::Label(ast::LitSource::Text(SourceId::EMPTY)), - }, - ast::Token { - span: span!(5, 6), - kind: ast::Kind::Whitespace, - }, - ast::Token { - span: span!(6, 9), - kind: ast::Kind::Char(ast::CopySource::Text(SourceId::EMPTY)), - }, - ast::Token { - span: span!(9, 10), - kind: ast::Kind::Whitespace, - }, - ast::Token { - span: span!(10, 19), - kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { source_id: SourceId::EMPTY, escaped: false, wrapped: true })), - } - }; - } - - #[test] - fn test_operators() { - test_lexer! { - "+ += - -= * *= / /=", - ast::Token { - span: span!(0, 1), - kind: ast::Kind::Plus, - }, - ast::Token { - span: span!(1, 2), - kind: ast::Kind::Whitespace, - }, - ast::Token { - span: span!(2, 4), - kind: ast::Kind::PlusEq, - }, - ast::Token { - span: span!(4, 5), - kind: ast::Kind::Whitespace, - }, - ast::Token { - span: span!(5, 6), - kind: ast::Kind::Dash, - }, - ast::Token { - span: span!(6, 7), - kind: ast::Kind::Whitespace, - }, - ast::Token { - span: span!(7, 9), - kind: ast::Kind::DashEq, - }, - ast::Token { - span: span!(9, 10), - kind: ast::Kind::Whitespace, - }, - ast::Token { - span: span!(10, 11), - kind: ast::Kind::Star, - }, - ast::Token { - span: span!(11, 12), - kind: ast::Kind::Whitespace, - }, - ast::Token { - span: span!(12, 14), - kind: ast::Kind::StarEq, - }, - ast::Token { - span: span!(14, 15), - kind: ast::Kind::Whitespace, - }, - ast::Token { - span: span!(15, 16), - kind: ast::Kind::Div, - }, - ast::Token { - span: span!(16, 17), - kind: ast::Kind::Whitespace, - }, - ast::Token { - span: span!(17, 19), - kind: ast::Kind::SlashEq, - } - }; - } - - #[test] - fn test_idents() { - test_lexer! { - "a.checked_div(10)", - ast::Token { - span: span!(0, 1), - kind: ast::Kind::Ident(ast::LitSource::Text(SourceId::EMPTY)), - }, - ast::Token { - span: span!(1, 2), - kind: ast::Kind::Dot, - }, - ast::Token { - span: span!(2, 13), - kind: ast::Kind::Ident(ast::LitSource::Text(SourceId::EMPTY)), - }, - ast::Token { - span: span!(13, 14), - kind: ast::Kind::Open(ast::Delimiter::Parenthesis), - }, - ast::Token { - span: span!(14, 16), - kind: ast::Kind::Number(ast::NumberSource::Text(ast::NumberText { - source_id: SourceId::EMPTY, - is_fractional: false, - base: ast::NumberBase::Decimal, - number: span!(14, 16), - suffix: span!(16, 16), - })), - }, - ast::Token { - span: span!(16, 17), - kind: ast::Kind::Close(ast::Delimiter::Parenthesis), - }, - }; - } - - #[test] - fn test_doc_strings() { - test_lexer! { - "//! inner\n/// \"quoted\"", - ast::Token { - kind: K![#], - span: span!(0, 9) - }, - ast::Token { - kind: K![!], - span: span!(0, 9) - }, - ast::Token { - kind: K!['['], - span: span!(0, 9) - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Doc)), - span: span!(0, 9) - }, - ast::Token { - kind: K![=], - span: span!(0, 9) - }, - ast::Token { - kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { - source_id: SourceId::EMPTY, - escaped: false, - wrapped: false, - })), - span: span!(3, 9) - }, - ast::Token { - kind: K![']'], - span: span!(0, 9) - }, - ast::Token { - kind: ast::Kind::Whitespace, - span: span!(9, 10) - }, - ast::Token { - kind: K![#], - span: span!(10, 22) - }, - ast::Token { - kind: K!['['], - span: span!(10, 22) - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Doc)), - span: span!(10, 22) - }, - ast::Token { - kind: K![=], - span: span!(10, 22) - }, - ast::Token { - kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { - source_id: SourceId::EMPTY, - escaped: false, - wrapped: false, - })), - span: span!(13, 22) - }, - ast::Token { - kind: K![']'], - span: span!(10, 22) - }, - }; - } - - #[test] - fn test_multiline_docstring() { - test_lexer! { - // /*! - // * inner docstr - // */ - // /** - // * docstr - // */ - "/*!\n * inner docstr\n */\n/**\n * docstr\n */", - ast::Token { - kind: K![#], - span: span!(0, 23) - }, - ast::Token { - kind: K![!], - span: span!(0, 23) - }, - ast::Token { - kind: K!['['], - span: span!(0, 23) - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Doc)), - span: span!(0, 23) - }, - ast::Token { - kind: K![=], - span: span!(0, 23) - }, - ast::Token { - kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { - source_id: SourceId::EMPTY, - escaped: false, - wrapped: false, - })), - span: span!(3, 21) - }, - ast::Token { - kind: K![']'], - span: span!(0, 23) - }, - ast::Token { - kind: ast::Kind::Whitespace, - span: span!(23, 24) - }, - ast::Token { - kind: K![#], - span: span!(24, 41) - }, - ast::Token { - kind: K!['['], - span: span!(24, 41) - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Doc)), - span: span!(24, 41) - }, - ast::Token { - kind: K![=], - span: span!(24, 41) - }, - ast::Token { - kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { - source_id: SourceId::EMPTY, - escaped: false, - wrapped: false, - })), - span: span!(27, 39) - }, - ast::Token { - kind: K![']'], - span: span!(24, 41) - }, - }; - } - - #[test] - fn test_comment_separators() { - test_lexer! { - "///////////////////////////////////\n\ - /*********************************/\n\ - /**********************************\n\ - * *\n\ - ***********************************/", - ast::Token { - kind: ast::Kind::Comment, - span: span!(0, 35) - }, - ast::Token { - kind: ast::Kind::Whitespace, - span: span!(35, 36) - }, - ast::Token { - kind: ast::Kind::MultilineComment(true), - span: span!(36, 71) - }, - ast::Token { - kind: ast::Kind::Whitespace, - span: span!(71, 72) - }, - ast::Token { - kind: ast::Kind::MultilineComment(true), - span: span!(72, 180) - }, - }; - } - - #[test] - fn test_template_literals() { - test_lexer! { - "`foo ${bar} \\` baz`", - ast::Token { - kind: ast::Kind::Open(ast::Delimiter::Empty), - span: span!(0, 1), - }, - ast::Token { - kind: K![#], - span: span!(0, 1), - }, - ast::Token { - kind: K!['['], - span: span!(0, 1), - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::BuiltIn)), - span: span!(0, 1), - }, - ast::Token { - kind: K!['('], - span: span!(0, 1), - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Literal)), - span: span!(0, 1), - }, - ast::Token { - kind: K![')'], - span: span!(0, 1), - }, - ast::Token { - kind: K![']'], - span: span!(0, 1), - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Template)), - span: span!(0, 1), - }, - ast::Token { - kind: ast::Kind::Bang, - span: span!(0, 1), - }, - ast::Token { - kind: K!['('], - span: span!(0, 1), - }, - ast::Token { - kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { - source_id: SourceId::EMPTY, - escaped: false, - wrapped: false, - })), - span: span!(1, 5), - }, - ast::Token { - kind: ast::Kind::Comma, - span: span!(5, 7), - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::Text(SourceId::EMPTY)), - span: span!(7, 10), - }, - ast::Token { - kind: ast::Kind::Comma, - span: span!(11, 18), - }, - ast::Token { - kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { - source_id: SourceId::EMPTY, - escaped: true, - wrapped: false, - })), - span: span!(11, 18), - }, - ast::Token { - kind: K![')'], - span: span!(18, 19), - }, - ast::Token { - kind: ast::Kind::Close(ast::Delimiter::Empty), - span: span!(18, 19), - }, - }; - } - - #[test] - fn test_template_literals_multi() { - test_lexer! { - "`foo ${bar} ${baz}`", - ast::Token { - kind: ast::Kind::Open(ast::Delimiter::Empty), - span: span!(0, 1), - }, - ast::Token { - kind: K![#], - span: span!(0, 1), - }, - ast::Token { - kind: K!['['], - span: span!(0, 1), - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::BuiltIn)), - span: span!(0, 1), - }, - ast::Token { - kind: K!['('], - span: span!(0, 1), - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Literal)), - span: span!(0, 1), - }, - ast::Token { - kind: K![')'], - span: span!(0, 1), - }, - ast::Token { - kind: K![']'], - span: span!(0, 1), - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Template)), - span: span!(0, 1), - }, - ast::Token { - kind: ast::Kind::Bang, - span: span!(0, 1), - }, - ast::Token { - kind: K!['('], - span: span!(0, 1), - }, - ast::Token { - kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { - source_id: SourceId::EMPTY, - escaped: false, - wrapped: false, - })), - span: span!(1, 5), - }, - ast::Token { - kind: ast::Kind::Comma, - span: span!(5, 7), - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::Text(SourceId::EMPTY)), - span: span!(7, 10), - }, - ast::Token { - kind: ast::Kind::Comma, - span: span!(11, 12), - }, - ast::Token { - kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { - source_id: SourceId::EMPTY, - escaped: false, - wrapped: false, - })), - span: span!(11, 12), - }, - ast::Token { - kind: ast::Kind::Comma, - span: span!(12, 14), - }, - ast::Token { - kind: ast::Kind::Ident(ast::LitSource::Text(SourceId::EMPTY)), - span: span!(14, 17), - }, - ast::Token { - kind: K![')'], - span: span!(18, 19), - }, - ast::Token { - kind: ast::Kind::Close(ast::Delimiter::Empty), - span: span!(18, 19), - }, - }; - } - - #[test] - fn test_literals() { - test_lexer! { - r#"b"""#, - ast::Token { - span: span!(0, 3), - kind: ast::Kind::ByteStr(ast::StrSource::Text(ast::StrText { - source_id: SourceId::EMPTY, - escaped: false, - wrapped: true, - })), - }, - }; - - test_lexer! { - r#"b"hello world""#, - ast::Token { - span: span!(0, 14), - kind: ast::Kind::ByteStr(ast::StrSource::Text(ast::StrText { - source_id: SourceId::EMPTY, - escaped: false, - wrapped: true, - })), - }, - }; - - test_lexer! { - "b'\\\\''", - ast::Token { - span: span!(0, 6), - kind: ast::Kind::Byte(ast::CopySource::Text(SourceId::EMPTY)), - }, - }; - - test_lexer! { - "'label 'a' b'a'", - ast::Token { - span: span!(0, 6), - kind: ast::Kind::Label(ast::LitSource::Text(SourceId::EMPTY)), - }, - ast::Token { - span: span!(6, 7), - kind: ast::Kind::Whitespace, - }, - ast::Token { - span: span!(7, 10), - kind: ast::Kind::Char(ast::CopySource::Text(SourceId::EMPTY)), - }, - ast::Token { - span: span!(10, 11), - kind: ast::Kind::Whitespace, - }, - ast::Token { - span: span!(11, 15), - kind: ast::Kind::Byte(ast::CopySource::Text(SourceId::EMPTY)), - }, - }; - - test_lexer! { - "b'a'", - ast::Token { - span: span!(0, 4), - kind: ast::Kind::Byte(ast::CopySource::Text(SourceId::EMPTY)), - }, - }; - - test_lexer! { - "b'\\n'", - ast::Token { - span: span!(0, 5), - kind: ast::Kind::Byte(ast::CopySource::Text(SourceId::EMPTY)), - }, - }; - } -} diff --git a/crates/rune/src/parse/lexer/tests.rs b/crates/rune/src/parse/lexer/tests.rs new file mode 100644 index 000000000..a88b20dd8 --- /dev/null +++ b/crates/rune/src/parse/lexer/tests.rs @@ -0,0 +1,654 @@ +use super::Lexer; +use crate::{ast, SourceId}; + +macro_rules! test_lexer { + ($source:expr $(, $pat:pat)* $(,)?) => {{ + let mut it = Lexer::new($source, SourceId::empty(), false); + + #[allow(unused_assignments)] + { + let mut n = 0; + + $( + match it.next().unwrap().expect("expected token") { + $pat => (), + #[allow(unreachable_patterns)] + other => { + panic!("\nGot bad token #{}.\nExpected: `{}`\nBut got: {:?}", n, stringify!($pat), other); + } + } + + n += 1; + )* + } + + assert_eq!(it.next().unwrap(), None); + }} +} + +#[test] +fn test_number_literals() { + test_lexer! { + "(10)", + ast::Token { + span: span!(0, 1), + kind: ast::Kind::Open(ast::Delimiter::Parenthesis), + }, + ast::Token { + span: span!(1, 3), + kind: ast::Kind::Number(ast::NumberSource::Text(ast::NumberText { + source_id: SourceId::EMPTY, + is_fractional: false, + base: ast::NumberBase::Decimal, + number: span!(1, 3), + suffix: span!(3, 3), + })), + }, + ast::Token { + span: span!(3, 4), + kind: ast::Kind::Close(ast::Delimiter::Parenthesis), + }, + }; + + test_lexer! { + "(10.)", + _, + ast::Token { + span: span!(1, 4), + kind: ast::Kind::Number(ast::NumberSource::Text(ast::NumberText { + source_id: SourceId::EMPTY, + is_fractional: true, + base: ast::NumberBase::Decimal, + number: span!(1, 4), + suffix: span!(4, 4), + })), + }, + _, + }; +} + +#[test] +fn test_char_literal() { + test_lexer! { + "'a'", + ast::Token { + span: span!(0, 3), + kind: ast::Kind::Char(ast::CopySource::Text(SourceId::EMPTY)), + } + }; + + test_lexer! { + "'\\u{abcd}'", + ast::Token { + span: span!(0, 10), + kind: ast::Kind::Char(ast::CopySource::Text(SourceId::EMPTY)), + } + }; +} + +#[test] +fn test_label() { + test_lexer! { + "'asdf 'a' \"foo bar\"", + ast::Token { + span: span!(0, 5), + kind: ast::Kind::Label(ast::LitSource::Text(SourceId::EMPTY)), + }, + ast::Token { + span: span!(5, 6), + kind: ast::Kind::Whitespace, + }, + ast::Token { + span: span!(6, 9), + kind: ast::Kind::Char(ast::CopySource::Text(SourceId::EMPTY)), + }, + ast::Token { + span: span!(9, 10), + kind: ast::Kind::Whitespace, + }, + ast::Token { + span: span!(10, 19), + kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { source_id: SourceId::EMPTY, escaped: false, wrapped: true })), + } + }; +} + +#[test] +fn test_operators() { + test_lexer! { + "+ += - -= * *= / /=", + ast::Token { + span: span!(0, 1), + kind: ast::Kind::Plus, + }, + ast::Token { + span: span!(1, 2), + kind: ast::Kind::Whitespace, + }, + ast::Token { + span: span!(2, 4), + kind: ast::Kind::PlusEq, + }, + ast::Token { + span: span!(4, 5), + kind: ast::Kind::Whitespace, + }, + ast::Token { + span: span!(5, 6), + kind: ast::Kind::Dash, + }, + ast::Token { + span: span!(6, 7), + kind: ast::Kind::Whitespace, + }, + ast::Token { + span: span!(7, 9), + kind: ast::Kind::DashEq, + }, + ast::Token { + span: span!(9, 10), + kind: ast::Kind::Whitespace, + }, + ast::Token { + span: span!(10, 11), + kind: ast::Kind::Star, + }, + ast::Token { + span: span!(11, 12), + kind: ast::Kind::Whitespace, + }, + ast::Token { + span: span!(12, 14), + kind: ast::Kind::StarEq, + }, + ast::Token { + span: span!(14, 15), + kind: ast::Kind::Whitespace, + }, + ast::Token { + span: span!(15, 16), + kind: ast::Kind::Div, + }, + ast::Token { + span: span!(16, 17), + kind: ast::Kind::Whitespace, + }, + ast::Token { + span: span!(17, 19), + kind: ast::Kind::SlashEq, + } + }; +} + +#[test] +fn test_idents() { + test_lexer! { + "a.checked_div(10)", + ast::Token { + span: span!(0, 1), + kind: ast::Kind::Ident(ast::LitSource::Text(SourceId::EMPTY)), + }, + ast::Token { + span: span!(1, 2), + kind: ast::Kind::Dot, + }, + ast::Token { + span: span!(2, 13), + kind: ast::Kind::Ident(ast::LitSource::Text(SourceId::EMPTY)), + }, + ast::Token { + span: span!(13, 14), + kind: ast::Kind::Open(ast::Delimiter::Parenthesis), + }, + ast::Token { + span: span!(14, 16), + kind: ast::Kind::Number(ast::NumberSource::Text(ast::NumberText { + source_id: SourceId::EMPTY, + is_fractional: false, + base: ast::NumberBase::Decimal, + number: span!(14, 16), + suffix: span!(16, 16), + })), + }, + ast::Token { + span: span!(16, 17), + kind: ast::Kind::Close(ast::Delimiter::Parenthesis), + }, + }; +} + +#[test] +fn test_doc_strings() { + test_lexer! { + "//! inner\n/// \"quoted\"", + ast::Token { + kind: K![#], + span: span!(0, 9) + }, + ast::Token { + kind: K![!], + span: span!(0, 9) + }, + ast::Token { + kind: K!['['], + span: span!(0, 9) + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Doc)), + span: span!(0, 9) + }, + ast::Token { + kind: K![=], + span: span!(0, 9) + }, + ast::Token { + kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { + source_id: SourceId::EMPTY, + escaped: false, + wrapped: false, + })), + span: span!(3, 9) + }, + ast::Token { + kind: K![']'], + span: span!(0, 9) + }, + ast::Token { + kind: ast::Kind::Whitespace, + span: span!(9, 10) + }, + ast::Token { + kind: K![#], + span: span!(10, 22) + }, + ast::Token { + kind: K!['['], + span: span!(10, 22) + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Doc)), + span: span!(10, 22) + }, + ast::Token { + kind: K![=], + span: span!(10, 22) + }, + ast::Token { + kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { + source_id: SourceId::EMPTY, + escaped: false, + wrapped: false, + })), + span: span!(13, 22) + }, + ast::Token { + kind: K![']'], + span: span!(10, 22) + }, + }; +} + +#[test] +fn test_multiline_docstring() { + test_lexer! { + // /*! + // * inner docstr + // */ + // /** + // * docstr + // */ + "/*!\n * inner docstr\n */\n/**\n * docstr\n */", + ast::Token { + kind: K![#], + span: span!(0, 23) + }, + ast::Token { + kind: K![!], + span: span!(0, 23) + }, + ast::Token { + kind: K!['['], + span: span!(0, 23) + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Doc)), + span: span!(0, 23) + }, + ast::Token { + kind: K![=], + span: span!(0, 23) + }, + ast::Token { + kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { + source_id: SourceId::EMPTY, + escaped: false, + wrapped: false, + })), + span: span!(3, 21) + }, + ast::Token { + kind: K![']'], + span: span!(0, 23) + }, + ast::Token { + kind: ast::Kind::Whitespace, + span: span!(23, 24) + }, + ast::Token { + kind: K![#], + span: span!(24, 41) + }, + ast::Token { + kind: K!['['], + span: span!(24, 41) + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Doc)), + span: span!(24, 41) + }, + ast::Token { + kind: K![=], + span: span!(24, 41) + }, + ast::Token { + kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { + source_id: SourceId::EMPTY, + escaped: false, + wrapped: false, + })), + span: span!(27, 39) + }, + ast::Token { + kind: K![']'], + span: span!(24, 41) + }, + }; +} + +#[test] +fn test_comment_separators() { + test_lexer! { + "///////////////////////////////////\n\ + /*********************************/\n\ + /**********************************\n\ + * *\n\ + ***********************************/", + ast::Token { + kind: ast::Kind::Comment, + span: span!(0, 35) + }, + ast::Token { + kind: ast::Kind::Whitespace, + span: span!(35, 36) + }, + ast::Token { + kind: ast::Kind::MultilineComment(true), + span: span!(36, 71) + }, + ast::Token { + kind: ast::Kind::Whitespace, + span: span!(71, 72) + }, + ast::Token { + kind: ast::Kind::MultilineComment(true), + span: span!(72, 180) + }, + }; +} + +#[test] +fn test_template_literals() { + test_lexer! { + "`foo ${bar} \\` baz`", + ast::Token { + kind: ast::Kind::Open(ast::Delimiter::Empty), + span: span!(0, 1), + }, + ast::Token { + kind: K![#], + span: span!(0, 1), + }, + ast::Token { + kind: K!['['], + span: span!(0, 1), + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::BuiltIn)), + span: span!(0, 1), + }, + ast::Token { + kind: K!['('], + span: span!(0, 1), + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Literal)), + span: span!(0, 1), + }, + ast::Token { + kind: K![')'], + span: span!(0, 1), + }, + ast::Token { + kind: K![']'], + span: span!(0, 1), + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Template)), + span: span!(0, 1), + }, + ast::Token { + kind: ast::Kind::Bang, + span: span!(0, 1), + }, + ast::Token { + kind: K!['('], + span: span!(0, 1), + }, + ast::Token { + kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { + source_id: SourceId::EMPTY, + escaped: false, + wrapped: false, + })), + span: span!(1, 5), + }, + ast::Token { + kind: ast::Kind::Comma, + span: span!(5, 7), + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::Text(SourceId::EMPTY)), + span: span!(7, 10), + }, + ast::Token { + kind: ast::Kind::Comma, + span: span!(11, 18), + }, + ast::Token { + kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { + source_id: SourceId::EMPTY, + escaped: true, + wrapped: false, + })), + span: span!(11, 18), + }, + ast::Token { + kind: K![')'], + span: span!(18, 19), + }, + ast::Token { + kind: ast::Kind::Close(ast::Delimiter::Empty), + span: span!(18, 19), + }, + }; +} + +#[test] +fn test_template_literals_multi() { + test_lexer! { + "`foo ${bar} ${baz}`", + ast::Token { + kind: ast::Kind::Open(ast::Delimiter::Empty), + span: span!(0, 1), + }, + ast::Token { + kind: K![#], + span: span!(0, 1), + }, + ast::Token { + kind: K!['['], + span: span!(0, 1), + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::BuiltIn)), + span: span!(0, 1), + }, + ast::Token { + kind: K!['('], + span: span!(0, 1), + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Literal)), + span: span!(0, 1), + }, + ast::Token { + kind: K![')'], + span: span!(0, 1), + }, + ast::Token { + kind: K![']'], + span: span!(0, 1), + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::BuiltIn(ast::BuiltIn::Template)), + span: span!(0, 1), + }, + ast::Token { + kind: ast::Kind::Bang, + span: span!(0, 1), + }, + ast::Token { + kind: K!['('], + span: span!(0, 1), + }, + ast::Token { + kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { + source_id: SourceId::EMPTY, + escaped: false, + wrapped: false, + })), + span: span!(1, 5), + }, + ast::Token { + kind: ast::Kind::Comma, + span: span!(5, 7), + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::Text(SourceId::EMPTY)), + span: span!(7, 10), + }, + ast::Token { + kind: ast::Kind::Comma, + span: span!(11, 12), + }, + ast::Token { + kind: ast::Kind::Str(ast::StrSource::Text(ast::StrText { + source_id: SourceId::EMPTY, + escaped: false, + wrapped: false, + })), + span: span!(11, 12), + }, + ast::Token { + kind: ast::Kind::Comma, + span: span!(12, 14), + }, + ast::Token { + kind: ast::Kind::Ident(ast::LitSource::Text(SourceId::EMPTY)), + span: span!(14, 17), + }, + ast::Token { + kind: K![')'], + span: span!(18, 19), + }, + ast::Token { + kind: ast::Kind::Close(ast::Delimiter::Empty), + span: span!(18, 19), + }, + }; +} + +#[test] +fn test_literals() { + test_lexer! { + r#"b"""#, + ast::Token { + span: span!(0, 3), + kind: ast::Kind::ByteStr(ast::StrSource::Text(ast::StrText { + source_id: SourceId::EMPTY, + escaped: false, + wrapped: true, + })), + }, + }; + + test_lexer! { + r#"b"hello world""#, + ast::Token { + span: span!(0, 14), + kind: ast::Kind::ByteStr(ast::StrSource::Text(ast::StrText { + source_id: SourceId::EMPTY, + escaped: false, + wrapped: true, + })), + }, + }; + + test_lexer! { + "b'\\\\''", + ast::Token { + span: span!(0, 6), + kind: ast::Kind::Byte(ast::CopySource::Text(SourceId::EMPTY)), + }, + }; + + test_lexer! { + "'label 'a' b'a'", + ast::Token { + span: span!(0, 6), + kind: ast::Kind::Label(ast::LitSource::Text(SourceId::EMPTY)), + }, + ast::Token { + span: span!(6, 7), + kind: ast::Kind::Whitespace, + }, + ast::Token { + span: span!(7, 10), + kind: ast::Kind::Char(ast::CopySource::Text(SourceId::EMPTY)), + }, + ast::Token { + span: span!(10, 11), + kind: ast::Kind::Whitespace, + }, + ast::Token { + span: span!(11, 15), + kind: ast::Kind::Byte(ast::CopySource::Text(SourceId::EMPTY)), + }, + }; + + test_lexer! { + "b'a'", + ast::Token { + span: span!(0, 4), + kind: ast::Kind::Byte(ast::CopySource::Text(SourceId::EMPTY)), + }, + }; + + test_lexer! { + "b'\\n'", + ast::Token { + span: span!(0, 5), + kind: ast::Kind::Byte(ast::CopySource::Text(SourceId::EMPTY)), + }, + }; +} diff --git a/crates/rune/src/runtime/function.rs b/crates/rune/src/runtime/function.rs index d64218332..6c35f371c 100644 --- a/crates/rune/src/runtime/function.rs +++ b/crates/rune/src/runtime/function.rs @@ -397,6 +397,8 @@ impl Function { #[repr(transparent)] pub struct SyncFunction(FunctionImpl); +assert_impl!(SyncFunction: Send + Sync); + impl SyncFunction { /// Perform an asynchronous call over the function which also implements /// [Send]. @@ -972,26 +974,3 @@ fn check_args(actual: usize, expected: usize) -> VmResult<()> { VmResult::Ok(()) } - -#[cfg(test)] -mod tests { - use super::SyncFunction; - - fn assert_send() - where - T: Send, - { - } - - fn assert_sync() - where - T: Sync, - { - } - - #[test] - fn assert_send_sync() { - assert_send::(); - assert_sync::(); - } -} diff --git a/crates/rune/src/runtime/runtime_context.rs b/crates/rune/src/runtime/runtime_context.rs index bbed74515..f1a47cc60 100644 --- a/crates/rune/src/runtime/runtime_context.rs +++ b/crates/rune/src/runtime/runtime_context.rs @@ -28,6 +28,8 @@ pub struct RuntimeContext { construct: hash::Map>, } +assert_impl!(RuntimeContext: Send + Sync); + impl RuntimeContext { pub(crate) fn new( functions: hash::Map>, diff --git a/crates/rune/src/runtime/unit.rs b/crates/rune/src/runtime/unit.rs index 6e97ddd29..f89cc6597 100644 --- a/crates/rune/src/runtime/unit.rs +++ b/crates/rune/src/runtime/unit.rs @@ -48,6 +48,8 @@ pub struct Unit { debug: Option>, } +assert_impl!(Unit: Send + Sync); + /// Instructions from a single source file. #[derive(Debug, TryClone, Default, Serialize, Deserialize)] #[serde(rename = "Unit")]