How to test a procedural macro from within the same crate


#1

Hi folks, I have a question. How would one test a procedural macro from within the same crate?

A procedural macro takes a proc_macro::TokenStream parameter. However, doing let foo: proc_macro::TokenStream = quote!{ 1 + 1 }.into() throws a massive error, as does "1 + 1".parse().unwrap():

thread 'tests::basic_test' panicked at 'proc_macro::__internal::with_sess() called before set_parse_sess()!', libproc_macro/lib.rs:1448:9
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
   1: std::sys_common::backtrace::print
   2: std::panicking::default_hook::{{closure}}
   3: std::panicking::default_hook
   4: std::panicking::rust_panic_with_hook
   5: std::panicking::begin_panic
   6: proc_macro::Span::call_site
   7: proc_macro2::imp::nightly_works::{{closure}}
             at /Users/robertbalicki/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-0.4.6/src/unstable.rs:33
   8: alloc::raw_vec::alloc_guard
             at /Users/travis/build/rust-lang/rust/src/libstd/panicking.rs:310
   9: __rust_maybe_catch_panic
  10: alloc::raw_vec::alloc_guard
             at /Users/travis/build/rust-lang/rust/src/libstd/panicking.rs:289
  11: core::ptr::swap_nonoverlapping_bytes
             at /Users/travis/build/rust-lang/rust/src/libstd/panic.rs:397
  12: <syntax::parse::token::DelimToken as core::clone::Clone>::clone
             at /Users/robertbalicki/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-0.4.6/src/unstable.rs:33
  13: proc_macro2::imp::nightly_works::{{closure}}
             at /Users/robertbalicki/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-0.4.6/src/unstable.rs:44
  14: proc_macro2::TokenStream::_new_stable
             at /Users/robertbalicki/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-0.4.6/src/lib.rs:107
  15: jsx_macro::tests::basic_test
             at jsx_macro/src/lib.rs:40
  16: jsx_macro::__test::TESTS::{{closure}}
             at jsx_macro/src/lib.rs:38
  17: core::ops::function::FnOnce::call_once
             at /Users/travis/build/rust-lang/rust/src/libcore/ops/function.rs:223
  18: <F as alloc::boxed::FnBox<A>>::call_box
  19: __rust_maybe_catch_panic
thread 'tests::basic_test' panicked at 'proc_macro::__internal::with_sess() called before set_parse_sess()!', libproc_macro/lib.rs:1448:9
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
   1: std::sys_common::backtrace::print
   2: std::panicking::default_hook::{{closure}}
   3: std::panicking::default_hook
   4: std::panicking::rust_panic_with_hook
   5: std::panicking::begin_panic
   6: proc_macro::__internal::with_sess
   7: <proc_macro::TokenStream as core::str::FromStr>::from_str
   8: core::str::<impl str>::chars
             at /Users/travis/build/rust-lang/rust/src/libcore/str/mod.rs:3792
   9: <proc_macro::TokenStream as core::clone::Clone>::clone
             at /Users/robertbalicki/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-0.4.6/src/unstable.rs:97
  10: <syntax::parse::token::DelimToken as core::clone::Clone>::clone
             at /Users/travis/build/rust-lang/rust/src/libcore/convert.rs:396
  11: <proc_macro::TokenStream as core::clone::Clone>::clone
             at /Users/robertbalicki/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-0.4.6/src/lib.rs:151
  12: <T as core::convert::Into<U>>::into
             at /Users/travis/build/rust-lang/rust/src/libcore/convert.rs:396
  13: jsx_macro::tests::basic_test
             at jsx_macro/src/lib.rs:40
  14: jsx_macro::__test::TESTS::{{closure}}
             at jsx_macro/src/lib.rs:38
  15: core::ops::function::FnOnce::call_once
             at /Users/travis/build/rust-lang/rust/src/libcore/ops/function.rs:223
  16: <F as alloc::boxed::FnBox<A>>::call_box
  17: __rust_maybe_catch_panic

I can create a TokenStream manually, or test from another crate in the same workspace. The latter seems okay, but then the crate will not be published along with its tests.

What is the best practice here?

Thank you!
-R