什么是内置`#[main]`属性?

14 program-entry-point entry-point rust rust-macros

我一直#[tokio::main]在我的一个程序中使用该宏。不合格的导入使用后main,遇到了意想不到的错误。

use tokio::main;

#[main]
async fn main() {}
Run Code Online (Sandbox Code Playgroud)
error[E0659]: `main` is ambiguous
 --> src/main.rs:3:3
  |
3 | #[main]
  |   ^^^^ ambiguous name
  |
  = note: ambiguous because of a name conflict with a builtin attribute
  = note: `main` could refer to a built-in attribute
Run Code Online (Sandbox Code Playgroud)

我一直在搜索文档,但找不到#[main]任何地方描述的这个内置属性。Rust 参考包含内置属性的索引。该索引不包含#[main],但它包含名为 的属性#[no_main]

我对存储库进行了搜索rustlang/rust,发现了一些似乎相关的代码,但它似乎使用了一对名为#[start]和 的宏#[rustc_main],而没有提及其#[main]本身。(这两个宏似乎都不能在稳定版上使用,会#[start]发出一个错误,表明它不稳定,并#[rustc_main]发出一个错误,表明它仅供编译器内部使用。)

我从名称中猜测它是为了将不同的函数标记为入口点而不是main,但它似乎也没有这样做:

error[E0659]: `main` is ambiguous
 --> src/main.rs:3:3
  |
3 | #[main]
  |   ^^^^ ambiguous name
  |
  = note: ambiguous because of a name conflict with a builtin attribute
  = note: `main` could refer to a built-in attribute
Run Code Online (Sandbox Code Playgroud)

Rust Analyzer 没有提供太多功能:

显示 Rust 分析器对 #[main] 属性的上下文帮助的屏幕截图,没有任何详细信息

#[main]除了与我的导入冲突之外,内置属性还有什么作用?

mca*_*ton 12

#[main]是一个古老的、不稳定的属性,在 1.53.0 中大部分已从语言中删除。然而,删除过程中漏掉了一行,结果如您所见:该属性没有任何效果,但它可以在稳定的 Rust 上使用而不会出现错误,并且与名为 的导入属性发生冲突main。这是一个错误,而不是预期的行为。自和 起已修复。您的示例现在可以毫无错误地运行。nightly-2022-02-101.59.0-beta.8use tokio::main;#[main]

在被删除之前,unstable#[main]被用来指定程序的入口点。Alex Crichton 在GitHub 上的 2016 年评论中描述了它的行为和相关属性:

啊,是的,我们有三个入口点。我..认为这就是他们的工作方式:

  • 首先, ,和#[start]的接收者。这实际上是符号(或者编译器中生成的符号所调用的符号)。int argcchar **argvmain
  • 接下来,有#[lang = "start"]. 如果#[start]板条箱图中不存在,则编译器会生成一个main调用此函数的函数。该函数接收 argc/argv 以及第三个参数,该参数是指向该函数的函数指针#[main](下面定义)。重要的是,#[lang = "start"]可以位于图书馆中。例如,它位于标准库 (libstd) 中。
  • 最后,#[main]可执行文件的主函数。#[lang = "start"]不传递任何参数并由(如果决定)调用。标准库使用它来初始化自身,然后调用 Rust 程序。如果未指定,则默认位于fn main顶部。

所以回答你的问题,这与#[start]. 为了回答您的其他(可能尚未提出)问题,是的,我们有太多的入口点。

  • 有趣的是,根据[此评论](https://github.com/rust-lang/rust/pull/84062#issuecomment-825038275),冲突不应再出现。但确实如此。 (3认同)