簡體   English   中英

為什么一致性規則會引發錯誤“類型參數必須用作某些本地類型的類型參數”?

[英]Why do the coherence rules raise the error “the type parameter must be used as the type parameter for some local type”?

為什么代碼示例1編譯但示例2給出了編譯錯誤?

例1:

use std::ops::Index;

struct Bounded {
    idx: usize,
}

impl Index<Bounded> for [i32; 4] {
    type Output = i32;

    fn index(&self, b: Bounded) -> &i32 {
        unsafe { self.get_unchecked(b.idx) }
    }
}

例2:

use std::ops::Index;

struct Bounded {
    idx: usize,
}

impl<T> Index<Bounded> for [T; 4] {
    type Output = T;

    fn index(&self, b: Bounded) -> &T {
        unsafe { self.get_unchecked(b.idx) }
    }
}
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`)
 --> src/main.rs:7:1
  |
7 | impl<T> Index<Bounded> for [T; 4] {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
  |
  = note: only traits defined in the current crate can be implemented for a type parameter

它確實歸結為“有一個很好的理由”,但好的理由並不是那么復雜。

這是問題所在。 想象一下,我有一個圖書館箱子:

// library.rs
pub struct Dog;
pub trait Speak {
    fn speak(&self);
}

還有兩個使用該庫箱的板條箱。

// bark.rs
extern crate library;
impl library::Speak for library::Dog {
    fn speak(&self) {
        println!("woof");
    }
}
// woof.rs
extern crate library;
impl library::Speak for library::Dog {
    fn speak(&self) {
        println!("bark");
    }
}

現在,出於某種原因,我想使用這兩個庫:

// main.rs
extern crate library;
extern crate woof;
extern crate bark;

fn main() {
   let rex = library::Dog;
   rex.speak();
}

該程序應該輸出什么? 有兩個同樣有效,難以區分的library::Speak實現library::Speak for library::Dog ; 沒有正確的答案。 更糟糕的是,如果我最初依賴於woof ,並且稍后添加了bark ,我的代碼將停止編譯,或者 - 更糟糕的是 - 開始透明地做錯事。 沖突的特質沖動是一件壞事™。

添加泛型時會變得更糟。 如果你有:

// barkgeneric.rs
extern crate library;
impl<T> library::Speak for T {
    fn speak(&self) {
        println!("woof");
    }
}
// woofgeneric.rs
extern crate library;
impl<T> library::Speak for T {
    fn speak(&self) {
        println!("bark");
    }
}

你現在有無數的沖突特質沖動。 哎呦。

為了避免這個問題,我們有了孤兒規則。 孤兒規則的想法是確保任何impl Trait for Type都有一個,只有一個,它可以被放置。 這樣,我們就不用擔心沖突了; 如果正確設置孤兒規則,它們應該是不可能的。

規則可以歸結為:當你impl的類型特征,無論是性狀或類型必須來自當前的箱子。 這使得我所有相互矛盾的例子都行不通。 woof.rs無法實現library::speak for library::Dog ,因為它們都不是來自它的箱子。

同樣,你也不能impl<T> Index<Bounded> for [T; 4]; impl<T> Index<Bounded> for [T; 4]; 因為[T; 4] [T; 4]並非來自你的箱子,而且rustc已經確定Index<Bounded>也不算來自你的箱子。

但是,它確實讓你的impl Index<Bounded> for [i32; 4] impl Index<Bounded> for [i32; 4]通過,因為在這種情況下, Index<Bounded>確實來自你。 這可能是一個錯誤,但它也可能只是預期的行為; 孤兒規則比我在這里所說的稍微復雜一些,並且它們可能以奇怪的方式進行交互。

有關更多細節,請參閱rustc --explain E0117rustc --explain E0210

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM