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

时间:2015-03-10 04:56:10

标签: rust

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

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

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

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

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


更新:正如Reem建议的那样,将0作为$to传递会导致问题。一个例子(Playpen Example):

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

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

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

1 个答案:

答案 0 :(得分: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(|| { &[] })

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

使用宏需要的东西:

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

您不需要使用宏的东西:

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