#macro #compile-time #lint #issue #checked #check #unimplemented

incomplete

提供 incomplete!(),unimplemented!() 的编译时检查版本

4个版本

使用旧的Rust 2015

0.1.3 2018年12月4日
0.1.2 2017年2月23日
0.1.1 2017年2月23日
0.1.0 2017年2月23日

#1686 in Rust模式

MIT/Apache

11KB

incomplete

Crates.io Documentation

此crate提供 incomplete!(),它是 unimplemented!() 的编译时检查版本。

关于此宏的动机和讨论可以在 rust-internals 线程中找到,以及 RFC问题。以下是一些重复的内容。

我们都熟悉并喜爱 unimplemented!() 宏,用于跟踪我们尚未着手的事情。然而,它仅在遇到特定的代码路径时进行运行时检查。这在许多情况下都很好,例如对于你尚未预料到需要处理的边缘情况。但是,当你从头开始编写新代码(特别是当移植时)、重构大量代码或构建全新的功能时,你通常会有一些尚未实现的代码段,但你 知道 你将不得不实现它们。

此宏的基本动机是引入一个结构,指示一段代码 需要 填充(即,程序在存在时不应编译),但开发人员希望推迟到以后编写。

例如,考虑一个需要将所有 FooBar 替换为 Baz 的重构。大多数转换都很直接,但一些需要更深入的改变(例如,Baz 需要一些在特定代码段中不可直接获得的其他值)。你可能首先完成翻译所有 FooBar,然后再处理边缘情况。

通常情况下,开发者可能会添加一个 // TODO 注释,或者一个 unimplemented!() 语句。然而,这种方法有一些缺点。特别是,这两种方法仍然允许代码在存在的情况下编译。因此,在“第一次遍历”之后,开发者必须 记住 同时 grep 所有 unimplemented()// TODO并且 过滤掉任何与问题重构无关的)。

这个 crate 实现的宏提供了一种方式,告诉编译器“在未实现时不要让代码编译”,同时运行类型检查和借用检查,这样你就可以在同时完成其他代码段。

理想情况下,这个宏会有自己的编译器 lint,使得生成的错误直接表示“所需代码段未完成”。然而,直到 RFC 问题 1911 有所进展,这个 crate 通过“滥用”另一个 lint 并将其变成一个致命警告来解决这个问题。结果基本上符合预期:它只有在所有编译器遍历都成功完成之后才会出错,它可以作为一个语句或表达式来评估。

示例

#[macro_use] extern crate incomplete;
fn foo() -> bool {
    incomplete!()
}
fn main() {
    foo();
}

产生

 error: value assigned to `incomplete` is never read
 --> src/main.rs:5:5
  |
5 |     incomplete!()
  |     ^^^^^^^^^^^^^
  |

注意事项

截至编写本文时,稳定的编译器在 incomplete!() 被使用时只会产生 警告,而不是 错误。这是因为它没有正确解释语句上编译器指令的使用。在 nightly 上这个问题已经被修复。

此外,这个宏在幕后“滥用”了一个现有的 Rust 编译器 lint。由于编译器坚持告诉你每个 lint 警告转换成错误的来源,不幸的是,你也会收到类似的消息

note: lint level defined here
 --> src/main.rs:5:13
  |
5 |     let x = incomplete!(bool);
  |             ^^^^^^^^^^^^^^^^^
  = note: this error originates in a macro outside of the current crate

没有运行时依赖