生命周期是类型的一部分吗?

Lou*_*inn 2 types language-lawyer rust

各种文档,例如类型参考,没有详细讨论类型和生命周期之间的关系。这让我想知道生命周期是否是类型本身的一部分,或者它们是否只是在单态化发生之前被删除的编译器提示。

给出以下示例:

fn example<'a, 'b>(a: &'a str, b: &'b str) {
    struct Foo<T> {
        t: T,
    }

    let bar = Foo { t: a };
    let baz = Foo { t: b };
}
Run Code Online (Sandbox Code Playgroud)

bar两者baz都是同一类型,但生命周期被擦除(即Foo<&str>)并共享一个单态副本,或者它们是两种不同的类型Foo<&'a str>,并且Foo<&'b str>生命周期是该类型的一部分?

作为旁注:类型推断算法是否在任何地方记录了T在每种情况下如何接收其最终类型?

Sil*_*olo 5

这里有几个不同的问题。对于值,每种类型都会被删除。Rust 编译为本机,并且在本机架构上,Foo所有其他类型只是一个字节序列。没有像 Java 那样的反射可以恢复部分类型。

泛型函数会带来单态化问题。具体来说,

fn foo<T>(x: T) -> T {
  x
}
Run Code Online (Sandbox Code Playgroud)

该函数将为每个 生成不同的(本机)函数T,因此foo(0 as i32)foo("ABC")实际上调用不同的函数。从这个意义上说,生命周期在单态化发生之前就被删除了,所以如果我们有一个如下所示的函数

fn foo<'a, T>(x: &'a T) -> &'a T {
  x
}
Run Code Online (Sandbox Code Playgroud)

那么只有不同的T参数才会产生不同的功能。如果只是生命周期不同,则不会生成新函数。

  • @LouisQuinn 您可以阅读 [`rustc`](https://rustc-dev-guide.rust-lang.org/overview.html) (定义 Rust 的权威实现)及其工作原理。在指南中,它描述了当代码转换为中级中间表示(MIR)时评估借用检查(以及因此的生命周期),然后在进行代码生成时不考虑借用检查。LLVM 不知道 Rust 生命周期,此时引用只是指针。所以是的,生命周期可以说是在单态化之前被擦除的编译器提示。 (2认同)