这是一个非常小的问题,我知道如何禁用警告,但仔细阅读它,我怀疑它可能表明我的宏可能做了一些不正确的事情.无论如何,我有一个用于有理数的 struct Rational:

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Rational {
    n: i128,
    d: i128,
}

impl Rational {
    pub fn new(n: i128, d: i128) -> Self {
        Rational { n, d }
    }
}

为了以一种可读的方式创建这些代码,我使用宏:

macro_rules! rat {
    ($whole: tt $n : tt / $d : tt) => {
        crate::rational::Rational::new($n + $whole * $d, $d)
    };
    ($n : tt / $d : tt) => {
        crate::rational::Rational::new($n, $d)
    };

    ($n : tt) => {
        crate::rational::Rational::new($n, 1)
    };
}

以及一些代码来测试和演示这一点:

    let x = 42;
    println!("{}", rat!(1));
    println!("{}", rat!(2 / 3));
    println!("{}", rat!(x));
    println!("{}", rat!(x / 2));
    println!("{}", rat!(2 / x));
    println!("{}", rat!(x 1/2));
    println!("{}", rat!(1 4/5));
    println!("{}", rat!((5 / 1) / 2)); //this line shows a warning

希望在这里你能(某种程度上)看到宏的意义--用一个普通的函数调用,像1/2这样的东西在被函数看到之前就会崩溃到0.(顺便说一句,我知道为了单一的有理数这样做是不值得的,但我认为这可能是为了快速解析更大的等式,比如equation!(1/2 x + 3 3/4 y + 24 z = 2 3/4 + 4 x).这只是迈向这一目标的一小步.)

不管怎样,实际的问题是:在最后一个例子中,它抱怨说5/1左右的括号是不必要的.然而,如果我删除它们(println!("{}", rat!(5 / 1 / 2));),宏会失败,并返回"在宏调用中没有规则需要这个令牌".)(顺便说一句,这个测试显然语法不好,我只是想确保它可以处理任意表达式.)

所以,有两个问题:

  1. 这是不是我在构建这些宏时风格不佳的结果?
  2. 有没有一种方法可以禁用这个警告,它不仅比通用的#![allow(unused_parens)]更具体,而且也不需要在每个调用点调用它?(我想知道是否可以以某种方式将Allow烘焙到宏本身,尽管我认为这没有意义.)

编辑:我发现问题不在于调用,而在于生成的代码--花括号对宏来说是必需的,Ruust认识到了这一点,但随后宏输出new((5/1), 2),其中花括号实际上是不必要的.我不确定处理这一问题的正确方式,尽管我看到了一些 Select .

推荐答案

这是不是我在构建这些宏时风格不佳的结果?

不,这看起来像是假阳性,又是#73068例.

有没有一种方法可以禁用这个警告,它不仅比通用的#![allow(unused_parens)]更具体,而且也不需要在每个调用点调用它?(我想知道是否可以以某种方式将Allow烘焙到宏本身,尽管我认为这没有意义.)

是的,您可以将其添加到宏调用中.试图天真地做到这一点是行不通的,因为表达式的属性是实验性的.但你可以把它变成一份声明:

macro_rules! rat {
    ($whole: tt $n : tt / $d : tt) => {{
        #[allow(unused_parens)]
        let v = crate::rational::Rational::new($n + $whole * $d, $d);
        v
    }};
    ($n : tt / $d : tt) => {{
        #[allow(unused_parens)]
        let v = crate::rational::Rational::new($n, $d);
        v
    }};
    ($n : tt) => {{
        #[allow(unused_parens)]
        let v = crate::rational::Rational::new($n, 1);
        v
    }};
}

请注意,这将禁用LINT,即使对于嵌套表达式也是如此,因此这可能不是您想要的.

Rust相关问答推荐

在‘await’点上使用‘std::同步::Mutex’是否总是会导致僵局?

有没有办法模仿对象安全克隆?

使用模块中的所有模块,但不包括特定模块

限制未使用的泛型导致编译错误

如何go 除铁 rust 中路径组件的第一项和最后一项?

当发送方分配给静态时,Tokio MPSC关闭通道

我如何使用AWS SDK for Rust获取我承担的角色的凭据?

什么时候使用FuturesOrdered?

什么是`&;[][..]`铁 rust 里的刻薄?

如何将生存期参数添加到框<>;具有dyn类型别名

Rust,如何从 Rc> 复制内部值并返回它?

Rust Option 的空显式泛型参数

Rust并发读写引起的死锁问题

str 和 String 的 Rust 生命周期

如何在 Rust 中将 bson::Bson 转换为 Vec

当我在 struct 中存储异步函数时,为什么它需要生命周期

隐式类型闭包的错误生命周期推断

覆盖类型的要求到底是什么?为什么单个元素元组满足它?

如何在宏中的多个参数上编写嵌套循环?

为什么一个整型变量赋值给另一个变量后仍然可以使用?