如何在Rust宏中使用ty
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Rust宏中使用ty相关的知识,希望对你有一定的参考价值。
我试图编写一个通用的解决方案,为单元测试Rust代码提供夹具。我想出了一个宏,它允许用户定义设置和拆卸方法。这是我到目前为止的解决方案:
struct FooTestFixture {
pub name : String
}
impl FooTestFixture {
fn setup() -> FooTestFixture {
FooTestFixture { name: String::from("Initialised") }
}
}
fn teardown(fixture : &mut FooTestFixture) {
fixture.name = "".to_string();
}
macro_rules! unit_test {
($name:ident $fixt:ident $expr:expr) => (
#[test]
fn $name() {
let mut $fixt : FooTestFixture = FooTestFixture::setup();
$expr;
teardown(&mut $fixt);
}
)
}
unit_test! (heap_foo_fixture_should_be_initialised_using_macro f {
assert_eq!(f.name, "Initialised");
});
这有效。唯一的问题是,宏unit_test不是通用的,并且绑定到夹具名称FooTestFixture。这意味着每个测试模块都需要为每个测试夹具重新定义这个宏,这是不理想的。我希望能够做的是引入一个类型变量并在宏扩展中使用该类型。深入研究宏我发现有一个'ty'项,代表一种类型,我想我能做到这一点......
macro_rules! unit_test {
($name:ident $fixt:ident $ftype:ty $expr:expr) => (
#[test]
fn $name() {
let mut $fixt : $ftype = $ftype::setup();
$expr;
teardown(&mut $fixt);
}
)
}
unit_test! (heap_foo_fixture_should_be_initialised_using_macro FooTestFixture f {
assert_eq!(f.name, "Initialised");
});
但是,这不起作用并导致以下错误:
src tests heap_fixture_with_new.rs:48:40:48:50错误:
$ftype:ty
之后是$expr:expr
,ty
片段不允许src tests heap_fixture_with_new.rs:48($ name:ident $ fixt:ident $ ftype :ty $ expr:expr)=>(
如您所见,在宏定义中,我用$ ftype替换了对FooTestFixture的引用。
我正在努力实现的目标是什么?这几乎就像我希望宏是通用的,允许你传入一个类型,在宏定义中使用。
ty
不能直接跟随expr
。它必须是followed by a specific set of tokens:
=>
,
=
|
;
:
>
[
{
as
where
在expr
,stmt
,path
和pat
之后存在类似的限制。这是在RFC 550中引入future-proof potential change in Rust syntax的。
要修复它,您需要更改宏模式,例如
macro_rules! unit_test {
($name:ident $fixt:ident<$ftype:ty> $expr:expr) => (
// ^ ^ followed by '>' is OK
unit_test! (test_name fixture_name<FooTestFixture> f {
// ^ ^
好吧,我意识到我毕竟不需要ty
。我可以将类型指定为ident
参数,以便以下工作:
macro_rules! unit_test {
($name:ident $fixt:ident $ftype:ident $expr:expr) => (
#[test]
fn $name() {
let mut $fixt = $ftype::setup();
$expr;
teardown(&mut $fixt);
}
)
}
unit_test! (foo_fixture_should_be_initialised_using_generic_macro f FooTestFixture {
assert_eq!(f.name, "Initialised");
});
以上是关于如何在Rust宏中使用ty的主要内容,如果未能解决你的问题,请参考以下文章