在有人將此標記為重復之前,我知道如何修復它(并且已經回答了),但我想了解為什么存在此限制,我在這里或 Rust 檔案中沒有找到答案。
例如,我寫了一些類似這樣的東西:
struct ItemList<T> {
items: Vec<T>
}
impl<T> ItemList<T> {
fn getFirstItem(&self) -> Link<T> { Link { position: 0 } }
}
struct Link<T> {
position: usize
}
impl<T> Link<T> {
fn getFromList<'a>(&self, list: &'a ItemList<T>) -> &'a T {
&list.items[self.position]
}
}
但是 rustc 拒絕了我的代碼并出現以下錯誤:
error[E0392]: parameter `T` is never used
--> src/main.rs:8:13
|
8 | struct Link<T> {
| ^ unused parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
= help: if you intended `T` to be a const parameter, use `const T: usize` instead
For more information about this error, try `rustc --explain E0392`.
為什么這是錯誤而不是警告?型別引數只會降低編譯期間的性能(如果我理解正確的話),那么為什么要強制洗掉它或使用 PhantomData 標記呢?它有一些我錯過的含義嗎?
uj5u.com熱心網友回復:
這是一個方差問題。
Rust 通過使用來確定型別引數的方差。如果不使用該型別,Rust 無法知道該型別的方差。
Rustonomicon有一章是關于方差的。
uj5u.com熱心網友回復:
除了@mcarton 所說的,這從一開始就不是這樣的:Rust 用于推斷未使用的泛型引數是雙變數的。這在 2014 年發生了變化(在 Rust 1.0 之前)。RFC中解釋了動機:
動機
今天,生命周期的方差推斷包括雙變數的概念——這基本上相當于不受約束。原則上,這可以有一些用處,但在實踐中,它往往是錯誤的載體。事實上,沒有已知的 Rust 代碼有意使用二元性(盡管似乎有很多是意外和錯誤地這樣做)。該 RFC 建議我們簡單地將雙方差的推斷結果作為錯誤。
作為出現這種情況的一個例子,想象一個
struct帶有“幻像”生命周期引數的 a,這意味著它本身的欄位中實際上沒有使用struct。這種型別的一個例子是Items向量迭代器:struct Items<'vec, T> { x: *mut T }這里的生命周期
'vec旨在表示被迭代的向量的生命周期,從而防止迭代器超過容器的壽命。但是,因為它根本沒有出現在 的主體中Items,所以編譯器目前會認為它與子型別無關。這意味著您可以從 a 轉換Items<'a, T>為 aItems<'static, T>,從而導致迭代器比它正在迭代的容器壽命更長。為了防止這種情況,
actual標準庫中迭代器的定義使用了標記型別。標記型別通知編譯器,雖然'vec看起來沒有被使用,但它應該像被使用一樣。例如,Items可能修改如下:struct Items<'vec, T> { x: *mut T, marker: marker::CovariantType<&'vec T>, }
CovariantType標記基本上通知編譯器它應該“好像”型別的參考是Items&'vec T的成員,即使它不是。這里的另一個等效選項是ContravariantLifetime.目前,用戶必須知道插入這些標記,否則會默默地得到錯誤的行為。該 RFC 將型別或生命周期引數在型別中的某處未(可傳遞地)使用是錯誤的。沒有其他任何改變。
代碼很舊(例如CovariantType并被ContravariantLifetime替換PhantomData),但這個概念仍然適用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/435082.html
