來自於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

推薦閱讀:

相关文章