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

14

我在我的一个程序中使用了#[tokio::main]宏。在导入main并未经修饰地使用它后,我遇到了一个意外的错误。

use tokio::main;

#[main]
async fn 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

我一直在查阅文档,但是我找不到任何关于内置的#[main]属性的描述。Rust参考手册包含内置属性的索引。该索引不包括#[main],但它包括一个名为#[no_main]的属性
我搜索了rustlang/rust代码库,并找到一些相关的代码,但它似乎使用了一对名为#[start]#[rustc_main]的宏,没有提及#[main]本身。(这两个宏似乎都不能在稳定版中使用,#[start]会发出一个错误,表示它是不稳定的,而#[rustc_main]则会发出一个错误,表示它只是编译器内部使用的。)
从名称上猜测,它可能是用来标记一个不同的函数作为入口点而不是main,但它似乎也不是这样做的:
#[main]
fn something_else() {
    println!("this does not run");
}

fn main() {
    println!("this runs");
}

Rust Analyzer没有太多可提供的功能:

a screenshot showing Rust Analyzer's contextual help for the #[main] attribute, devoid of any details

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

1个回答

12

#[main] 是 Rust 编程语言在 1.53.0 版本中被移除的旧版不稳定属性但是已经从该语言中大部分删除。但是,这个移除漏掉了一行代码,导致它仍可以在稳定版本的 Rust 中使用而不出错,但并没有起到任何作用,并且可能与命名为main的导入属性冲突。这是一个错误,不是预期的行为。这个问题已经在nightly-2022-02-10和1.59.0-beta.8中得到修复,现在您可以无误地运行带有 use tokio::main;#[main] 的示例程序。

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

啊,是的,我们有三个入口点。我认为是这样工作的:

  • 首先是 #[start],接收 int argcchar **argv。这实际上就是符号 main(或者编译器生成的叫做该符号的内容)。
  • 然后是 #[lang = "start"]。如果在 crate 图中不存在 #[start],则编译器将生成一个调用此函数的main函数。此函数接收 argc/argv 以及第三个参数,即指向 #[main] 函数的函数指针(定义如下)。重要的是,#[lang = "start"] 可以位于库中。例如,它位于标准库(libstd)中。
  • 最后是 #[main],可执行程序的主函数。它不接收任何参数,并且由 #[lang = "start"] 调用(如果决定这样做)。标准库使用它来初始化自身,然后调用 Rust 程序。如果未指定,则默认为顶部的 fn main

因此回答您的问题,这与 #[start] 不同。回答您可能尚未提出的其他问题,是的,我们有太多入口点了。


3
有趣的是,根据这条评论,应该不再出现冲突。但实际上还是有。 - peterulb
1
@peterulb 可能是因为这个吗?从编译器中完全删除 main 属性 #93753 - mhutter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接