在宏中处理与类型相关的警告的最佳策略是什么?

uru*_*ubi 2 rust

我已经定义了一个宏来优雅地处理越界切片.以下是宏的定义:

macro_rules! slice_or_else {
    ($array: expr, $to:expr, $err: block) => ({
        if $to <= $array.len() {
            &$array[..$to]
        }
        else $err
    })
}
Run Code Online (Sandbox Code Playgroud)

当我使用它编译一个函数时,编译器会抱怨

warning: comparison is useless due to type limits, #[warn(unused_comparisons)] on by default
Run Code Online (Sandbox Code Playgroud)

尽管使用比较确定请求的切片是否有效,以及宏是否通过测试.我错过了什么吗?可以为宏关闭这些警告吗?


更新:看来,通过0$to引起该问题,如雷姆建议.一个例子(围栏示例):

fn main() {
    let a: [u8; 4] = [0, 1, 2, 3];
    assert!(slice_or_else!(a, 0, {return;}).len() == 0);
}
Run Code Online (Sandbox Code Playgroud)

我正在使用宏,因为我希望能够影响调用函数的流程.

由于警告是合理的,处理此用例的最佳策略是什么?绑定$to到临时变量?明确地投射它?

ree*_*eem 5

如果你使用这个$to设置为宏,0那么rustc会抱怨,0 <= X因为我们正在使用usize,因为它是无符号的.请注意,&x[..0]永远不会触发越界错误.

在相关的说明中,这是编写此代码的更惯用的方法:

fn slice_opt<T>(buf: &[T], ind: usize) -> Option<&[T]> {
     if ind <= buf.len() {
         Some(&buf[..ind])
     } else {
         None
     }
}

// Usage site                 // $err
slice_opt(x).unwrap_or_else(|| { &[] })
Run Code Online (Sandbox Code Playgroud)

除非必须使用宏,否则不应使用宏.

使用宏需要的东西:

  • 新语法
  • 从封闭范围返回/中断/继续
  • 检查代码生成
  • 一些微妙的类型技巧(只借用一个类型的一个字段,&c.)

你不需要使用宏的东西:

  • 任何可能成为函数的东西(使用函数)
  • 内联(使用#[inline])
  • polymorphism/generics(使用实际泛型)

  • "新的控制流结构"是使用宏的完全合理的理由.它确保`return` /`continue` /`break`将从用户传递到控制流结构的代码中起作用,而闭包则不然. (2认同)