来自于RustFest 2018 大会上Alex Crichton 和 David Tolnay两位大佬的轻演讲主题:Rust Quiz

- rust-quiz源码- 在线练习和解答

- 视频

不得不说,两位大佬出的题非常具有迷惑性,一不留神就落入了陷阱。

Quiz 15:

下面这段代码输出什么?

trait Trait {
fn f(&self);
}

impl Trait for u32 {
fn f(&self) {
print!("1");
}
}

impl<a> Trait for &a i32 {
fn f(&self) {
print!("2");
}
}

fn main() {
let x = &0;
x.f();
}

输出结果: 1

解读

考察要点:

  1. trait实现
  2. T&a T的区别
  3. 类型推断
  4. 自动加引用

其实Quiz 15和Quiz 5的考察点是相似的。主要是考察T&T有啥区别呢?虽然这里是u32&』a i32

  • T, 是一个泛型参数,代表任何一个具体的类型。
  • &T,实际上等价于&a T,代表某个引用类型。注意这里的a也是一个泛型参数,并不是指具体的类型。

main函数中直接使用了let x = &0;&0实际上是一个包含了具体生命周期参数实例的具体类型&a 0。所以,&0实际上会被推断为一个具体的T类型的实例u32

这和impl Trait for ...的定义顺序无关。不妨把impl<a> Trait for &a i32 { ... }impl Trait for u32 { ... }的顺序交换,输出结果照样不变。

此时在u32f方法实现中self&u32

所以,x.f()会输出1

如果把impl Trait for u32 {}实现注释掉。则 x.f()会输出2

trait Trait {
fn f(&self);
}

impl<a> Trait for &a i32 {
fn f(&self) {
print!("2");
}
}

fn main() {
let x = &0;
x.f();
}

在这个代码中,f方法中的self会被自动加引用为&&0

点此查看 Rust Quiz 15

推荐阅读:

相关文章