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

What is the built-in `#[main]` attribute?

我一直在我的一个程序中使用 #[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] 属性的描述。 The Rust Reference contains an index of built-in attributes. The index doesn't include #[main], though it does include an attribute named #[no_main].

我搜索了 rustlang/rust 存储库,找到了 some code that seems related,但它似乎使用了一对名为 #[start]#[rustc_main] 的宏,没有提到 #[main] 本身。 (这些宏似乎都不能在稳定版上使用,#[start] 会发出不稳定的错误,#[rustc_main] 会发出仅供编译器内部使用的错误。)

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

#[main]
fn something_else() {
    println!("this does not run");
}

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

Rust 分析器没有提供太多:


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

#[main] 是从 nightly-2022-02-101.59.0-beta.8 开始的一个旧的、不稳定的属性 that was mostly removed from the language in 1.53.0. However, the removal missed one line, with the result you see: the attribute had no effect, but it could be used on stable Rust without an error, and conflicted with imported attributes named main. This was a bug, not intended behaviour. It has been fixeduse tokio::main;#[main] 的示例现在可以 运行 而不会出错。

在删除之前,不稳定的 #[main] 用于指定程序的入口点。 Alex Crichton 在 a 2016 comment on GitHub:

中描述了它的行为和相关属性

Ah yes, we've got three entry points. I.. think this is how they work:

  • First, #[start], the receiver of int argc and char **argv. This is literally the symbol main (or what is called by that symbol generated in the compiler).
  • Next, there's #[lang = "start"]. If no #[start] exists in the crate graph then the compiler generates a main function that calls this. This functions receives argc/argv along with a third argument that is a function pointer to the #[main] function (defined below). Importantly, #[lang = "start"] can be located in a library. For example it's located in the standard library (libstd).
  • Finally, #[main], the main function for an executable. This is passed no arguments and is called by #[lang = "start"] (if it decides to). The standard library uses this to initialize itself and then call the Rust program. This, if not specified, defaults to fn main at the top.

So to answer your question, this isn't the same as #[start]. To answer your other (possibly not yet asked) question, yes we have too many entry points.