我正在嘗試利用當前不穩定的功能generic_const_exprs來讓我的庫的用戶知道他們生成的型別的結果維度。
我的用例要復雜得多,但我創建了一個帶有可重現錯誤的最小示例。主要思想是,給定 aTensor<N>作為輸入,我想輸出 a Tensor<M>,其中M是{N 1}。ATensor<N>是一個特征,它在 forConstant<N>和 for中都實作了Variable<M>。這是代碼:
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
struct Variable<const N: usize>;
struct Constant<const N: usize>;
trait Tensor<const N: usize> {
fn get_dim(&self) -> usize {
N
}
}
trait ConvertTo<Y> {
fn convert(&self) -> Y;
}
impl<const N: usize> Tensor<N> for Variable<N> {}
impl<const N: usize> Tensor<N> for Constant<N> {}
impl<const N: usize, const M: usize> ConvertTo<Constant<M>> for Variable<N> {
fn convert(&self) -> Constant<M> {
Constant::<M>
}
}
impl<const N: usize, const M: usize> ConvertTo<Variable<M>> for Constant<N> {
fn convert(&self) -> Variable<M> {
Variable::<M>
}
}
fn convert_plus_one<const N: usize, X, Y>(x: X) -> Y
where
X: Tensor<N> ConvertTo<Y>,
Y: Tensor<{ N 1 }>,
{
x.convert()
}
fn main() {
let x = Constant::<3>;
let y = convert_plus_one(x);
// At this point the compiler should know that y is a Variable<N> with N = 4
// and it implements Tensor<4>, because Tensor<N> is implemented for Variable<N>
assert_eq!(y.get_dim(), 4);
}
這是編譯器錯誤:
Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `Variable<{_: usize}>: Tensor<{ N 1 }>` is not satisfied
--> src/main.rs:41:13
|
41 | let y = convert_plus_one(x);
| ^^^^^^^^^^^^^^^^ the trait `Tensor<{ N 1 }>` is not implemented for `Variable<{_: usize}>`
|
= help: the trait `Tensor<N>` is implemented for `Variable<N>`
note: required by a bound in `convert_plus_one`
--> src/main.rs:34:8
|
31 | fn convert_plus_one<const N: usize, X, Y>(x: X) -> Y
| ---------------- required by a bound in this
...
34 | Y: Tensor<{ N 1 }>,
| ^^^^^^^^^^^^^^^^^ required by this bound in `convert_plus_one`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error
我已經沒有關于如何解決這個問題的想法了。我錯過了什么,還是在目前的狀態下這是不可能的generic_const_exprs?
鏈接到 Rust 游樂場
uj5u.com熱心網友回復:
感謝rust-lang Zulip 聊天@lcnr中的建議,我設法通過使用trait associated types使其作業。這里的訣竅是能夠用一個運算式來表達我的界限。??
由此:
where
X: Tensor<N> ConvertTo<Y>,
Y: Tensor<{ N 1 }>,
對此:
where
X: Tensor ConvertTo<{<X as Tensor>::N 1}>,
原始示例不起作用,因為 Rust 獨立評估每個 trait 系結。所以一方面它試圖斷言,Constant<3>: ConvertTo<?>另一方面?: Tensor<4>。只有同時考慮它們才有意義。
特征上的關聯型別允許必要的語法在單個運算式中確實具有所有邊界,這是最終結果,它可以完美編譯:
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
#![feature(associated_type_bounds)]
struct Variable<const N: usize>;
struct Constant<const N: usize>;
trait Tensor {
const N: usize;
fn get_dim(&self) -> usize {
Self::N
}
}
trait ConvertTo<const N: usize> {
type To;
fn convert(&self) -> Self::To;
}
impl<const N: usize> Tensor for Variable<N> {
const N: usize = N;
}
impl<const N: usize> Tensor for Constant<N> {
const N: usize = N;
}
impl<const N: usize, const M: usize> ConvertTo<M> for Variable<N> {
type To = Constant<M>;
fn convert(&self) -> Self::To {
Constant::<M>
}
}
impl<const N: usize, const M: usize> ConvertTo<M> for Constant<N> {
type To = Variable<M>;
fn convert(&self) -> Self::To {
Variable::<M>
}
}
fn convert_plus_one<X>(x: X) -> <X as ConvertTo<{<X as Tensor>::N 1}>>::To
where
X: Tensor ConvertTo<{<X as Tensor>::N 1}>,
{
x.convert()
}
fn main() {
let x = Constant::<3>;
let y = convert_plus_one(x);
assert_eq!(y.get_dim(), 4);
}
現在我可以休息了。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/495752.html
上一篇:是否可以在Rust中使用const泛型實體化新型別?
下一篇:為什么T[keyofT]的<TextendsRecord<number,X>>和<TextendsRecord<string,X>>的行為不同?
