< 返回版块

bigteech 发表于 2022-09-01 17:31

Tags:trait Any

struct Bar{
    a: i32
}

fn foo()  {
    use std::any::{Any, TypeId};
    let c = Bar { a: 1 };
    c.type_id();
}

Any是 impl 给 'static的,但是 c 不是 'static的,为什么还能调用 type_id呢?


Ext Link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&code=struct%20Bar%7B%0A%20%20%20%20a%3A%20i32%0A%7D%0A%0Afn%20foo()%20%20%7B%0A%20%20%20%20use%20std%3A%3Aany%3A%3A%7BAny%2C%20TypeId%7D%3B%0A%20%20%20%20let%20c%20%3D%20Bar%20%7B%20a%3A%201%20%7D%3B%0A%20%20%20%20c.type_id()%3B%0A%7D%0A%2F%2F%20Any%E6%98%AF%20impl%20%E7%BB%99%20'static%E7%9A%84%EF%BC%8C%E4%BD%86%E6%98%AF%20c%20%E4%B8%8D%E6%98%AF%20'static%E7%9A%84%EF%BC%8C%E4%B8%BA%E4%BB%80%E4%B9%88%E8%BF%98%E8%83%BD%E8%B0%83%E7%94%A8%20type_id%E5%91%A2%EF%BC%9F

评论区

写评论
Mike Tang 2022-09-01 21:36

苦瓜哥的链接,受益匪浅

苦瓜小仔 2022-09-01 20:19

类型没有“生命周期”。

类型有生命周期参数。

值有“生命周期”,引用也有“生命周期”,但这两个含义不同。

“生命周期”和“生命周期约束”就更不一样了。不会还有人没读过《生命周期的十个误区》这篇“必读”文章吧。


只要你记住了那篇文章的这句话:

if T: 'static then T can be a borrowed type with a 'static lifetime or an owned type

那么受 'static 约束的 T 有两种类型:

  • &'static T
  • 非引用类型(不含引用的类型、无生命周期参数的类型)

表示数据的拥有者 T 只要一直持有数据,就可以让数据一直有效。

Any trait 的定义和唯一实现为:

pub trait Any: 'static {
    fn type_id(&self) -> TypeId;
}

impl<T: 'static + ?Sized> Any for T {
    fn type_id(&self) -> TypeId {
        TypeId::of::<T>()
    }
}

翻译成文字就是,数据的拥有者通过 .type_id() 方法获取 TypeId。这个 TypeId 是数据的拥有者的。

所以“c.type_id()”获取的是 Bar 这个数据的拥有者的 TypeId。

变量 c 的类型是 Bar,通过 automatic referencing and dereferencing,得到 (&c).type_id(),此时 Bar 满足 'static 约束,成功调用,代码通过。

这里的自动引用和自动解引用方式找调用方法真的太基础了,它在 the book 介绍 method syntax 时就提到过。 但我觉得大部分人因为它的便利而忽略它的存在,导致完全不会思考调用方法时真正发生了什么,Rust 是如何找到调用的方法。

最后给一个例子,去理解为什么说“TypeId 是数据拥有者的”playground

作者 bigteech 2022-09-01 17:58

我好像有点明白了,'static 这个不是实例的生命周期,好像是类型的生命周期

1 共 3 条评论, 1 页