avatar Nihil

Nichts Hsu

  • 首页
  • 子域
  • 分类
  • 标签
  • 归档
  • 关于
首页 于 Rust 1.76 稳定的 trait upcasting coercion
文章

于 Rust 1.76 稳定的 trait upcasting coercion

发表于 2024/01/16
作者 Nichts Hsu
2 分钟阅读

由于在 Rust 1.76 发布前夕,trait upcasting coercion 突然发现了健全性问题,因此该特性已被取消稳定,目前还没有下一步的稳定计划。

先提出一个问题,在 Rust 中如何把一个 &dyn MyTrait 转换为 &MyStruct?

1
2
3
4
5
6
7
8
9
10
11
trait MyTrait {}

struct Foo;
struct Bar;

impl MyTrait for Foo {}
impl MyTrait for Bar {}

fn rtti(obj: &dyn MyTrait) {
    // How to convert `obj` to `&Foo` or `&Bar`
}

很自然地,我们可以想到借助 Any,rust 在 dyn Any 类型上实现了 is() 和 downcast_ref() 可以很好地帮助我们在运行时获取类型信息。

然而,在 Rust 1.75.0 及之前,想要从 &dyn MyTrait 中获取 &dyn Any 并不是一件简单的事情,你需要在 MyTrait 中专门添加一个方法 as_any() 将自身转换为 &dyn Any,并且不厌其烦地在每一个 impl MyTrait for S 中复制粘贴一份其实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
use std::any::Any;

trait MyTrait {
    fn as_any(&self) -> &dyn Any;
}

struct Foo;
struct Bar;

impl MyTrait for Foo {
    fn as_any(&self) -> &dyn Any {
        self
    }
}
impl MyTrait for Bar {
    fn as_any(&self) -> &dyn Any {
        self
    }
}

fn rtti(obj: &dyn MyTrait) {
    let any = obj.as_any();
    if any.is::<Foo>() {
        let _ref: &Foo = any.downcast_ref().unwrap();
    } else if any.is::<Bar>() {
        let _ref: &Bar = any.downcast_ref().unwrap();
    }
}

而在 Rust 1.76.0 中,trait upcasting coercion 迎来了稳定。什么是 trait upcasting coercion 呢?简单的说,对于 trait A: B,可以直接将 &dyn A 强制为 &dyn B,这意味着,我们只需要让 trait MyTrait: Any,即可实现从 &dyn MyTrait 到 &dyn Any 的转换了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use std::any::Any;

trait MyTrait: Any {}

struct Foo;
struct Bar;

impl MyTrait for Foo {}
impl MyTrait for Bar {}

fn rtti(obj: &dyn MyTrait) {
    let any = obj as &dyn Any;
    if any.is::<Foo>() {
        let _ref: &Foo = any.downcast_ref().unwrap();
    } else if any.is::<Bar>() {
        let _ref: &Bar = any.downcast_ref().unwrap();
    }
}
教程, Rust
rust 编程语言
本文由作者按照 CC BY 4.0 进行授权
分享

最近更新

  • 『I Wanna』 Best Bye To 2016
  • [译] Rust 中的内联
  • [Rust] 幽灵索引类型与匿名结构体
  • [C++] 深入了解左值与右值
  • Android.bp 中启用 openmp
外部链接
  • 996.icu
  •  此博客的 Github 仓库
  •  Olimi 的个人博客

相关文章

2023/12/22

于 Rust 1.75 稳定的 RPITIT 与 AFIT

RPIT 在说 RPITIT 和 AFIT 之前,我们需要首先了解 RPIT,即:Return Position impl Trait。该特性又被称为 Abstract Return Types,简单来说,就是允许在函数的返回值类型中使用 impl Trait 的形式替代具体类型,例如: fn test_rpit() -&gt; impl Iterator&lt;Item = i32&g...

2021/06/07

Rust 中的闭包递归与 Y 组合子

λ 函数递归 λ 函数也即匿名函数,在 Rust 中体现为闭包(Closure)。在一些语言中,你可以简单地在 λ 函数内调用自己实现递归,例如在 JavaScript 中实现一个阶乘: fact = n =&gt; { if (n == 0) return 1; else return n * fact(n - 1); } console.log(fact(5)) //...

2021/04/24

Rust 中函数与闭包与 Fn Traits 探讨

闭包 闭包,或者又名匿名函数,lambda 函数,它在官方文档中被定义为可以捕获环境的匿名函数。通常,闭包的定义具有以下的形式: let closure_name = |arg1: type1, arg2: type2| -&gt; return_type { // closure body } 在闭包定义中,可以省略参数的类型和返回值类型,Rust 将通过第一次调用该闭包时...

[译] 改变 Rust 的规则

从另一个视角看 Rust HRTBs

© 2024 Nichts Hsu. 保留部分权利。

本站采用 Jekyll 主题 Chirpy

热门标签

编程语言 教程 rust c++ android c++20 usb 翻译 linux qt

发现新版本的内容。