簡體   English   中英

為什么借用特征要求借用的類型作為參考?

[英]Why does the Borrow trait require the borrowed type to be a reference?

想象一下一些事件源,它產生表示為枚舉的事件。 當然,為了獲得最佳效率,此生產者是零拷貝,即它返回對其內部緩沖區的引用:

enum Variant<'a> {
    Nothing,
    SomeInt(u64),
    SomeBytes(&'a [u8])
}

impl Producer {
    fn next(&'a mut self) -> Variant<'a> { ... }
}

這對於不需要前瞻或回溯的消費者來說非常好,但有時需要保存一些事件序列。 因此,我們的Variant類型變為通用:

enum Variant<BytesT> {
    Nothing,
    SomeInt(u64),
    SomeBytes(BytesT)
}

type OwnedVariant = Variant<Vec<u8>>;
type BorrowedVariant<'a> = Variant<&'a [u8]>;

在這里,我們最終得到兩種具有“所有者 - 引用”關系的類型,它類似於對Vec<T> - &[T]String - &str 文檔建議內置特征BorrowToOwned提供除了微妙的細微差別之外所需的內容:

trait Borrow<Borrowed: ?Sized> {
    fn borrow(&self) -> &Borrowed;
    // this: -----------^
}

pub trait ToOwned {
    type Owned: Borrow<Self>;
    fn to_owned(&self) -> Self::Owned;
}

borrow結果必須是對某些東西引用 ,而BorrowedVariant<'a>顯然不是。 刪除此要求可以解決此問題(此處,名稱以alt為前綴,以強調這是一個替代接口):

trait AltBorrow<'a, AltBorrowed> {
    fn alt_borrow(&'a self) -> AltBorrowed;
}

trait AltToOwned<'a> {
    type AltOwned: AltBorrow<'a, Self>;
    fn alt_to_owned(&'a self) -> Self::AltOwned;
}

然后可以針對標准類型實現此特征,例如Vec

impl<'a, T> AltBorrow<'a, &'a [T]> for Vec<T> {
    fn alt_borrow(&'a self) -> &'a [T] {
        self.as_slice()
    }
}

impl<'a, T> AltToOwned<'a> for &'a [T]
    where T: Clone
{
    type AltOwned = Vec<T>;

    fn alt_to_owned(&'a self) -> Vec<T> {
        self.to_vec()
    }
}

以及有問題的Variant枚舉:

impl<'a> AltBorrow<'a, BorrowedVariant<'a>> for OwnedVariant {
    fn alt_borrow(&'a self) -> BorrowedVariant<'a> {
        match self {
            &Variant::Nothing => Variant::Nothing,
            &Variant::SomeInt(value) => Variant::SomeInt(value),
            &Variant::SomeBytes(ref value) => Variant::SomeBytes(value.alt_borrow()),
        }
    }
}

impl<'a> AltToOwned<'a> for BorrowedVariant<'a> {
    type AltOwned = OwnedVariant;

    fn alt_to_owned(&'a self) -> OwnedVariant {
        match self {
            &Variant::Nothing => Variant::Nothing,
            &Variant::SomeInt(value) => Variant::SomeInt(value),
            &Variant::SomeBytes(value) => Variant::SomeBytes(value.alt_to_owned()),
        }
    }
}

最后,問題:

  1. 我是否濫用了原始的Borrow / ToOwned概念? 我應該用別的東西來實現這個目標嗎?
  2. 如果沒有,那么為什么std::borrow當前不太通用的接口可能是首選的原因是什么?

這個例子在Rust游戲圍欄上

對#rust IRC有一些解釋

來自aturon

簡短的回答是:我們需要更高級別的(HKT)才能在這里做得更好; 不過,應該可以在以后順利“升級”到HKT

(這是一種在標准庫中出現的模式)

(將生命周期提升到特質水平是對HKT進行編碼的一種方式,但使使用該特征更加尷尬)

來自布魯斯

我喜歡你的問題。 這種特質的生命周期還沒有被IMO充分探索過,但現在借用檢查器中也存在一個已知的錯誤

暫無
暫無

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

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