cod*_*arm 3 generics traits rust const-generics
我正在尝试利用当前不稳定的功能,generic_const_exprs让我的库的用户知道他们生成的类型的结果尺寸。
我的用例要复杂得多,但我创建了一个带有可重现错误的最小示例。主要思想是,给定 aTensor<N>作为输入,我想输出 a Tensor<M>,其中M是{N + 1}。A是一个特质,它同时为和 forTensor<N>实现。这是代码:Constant<N>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);
}
Run Code Online (Sandbox Code Playgroud)
这是编译器错误:
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
Run Code Online (Sandbox Code Playgroud)
我已经没有办法解决这个问题了。我错过了什么,还是在目前的状态下这是不可能做到的generic_const_exprs?
感谢rust-lang Zulip 聊天@lcnr中的建议,我设法通过使用特征关联类型使其工作。这里的技巧是能够用一个表达式来表达我的界限。\xe2\x9d\xa4\xef\xb8\x8f
由此:
\nwhere\n X: Tensor<N> + ConvertTo<Y>,\n Y: Tensor<{ N + 1 }>,\nRun Code Online (Sandbox Code Playgroud)\n对此:
\nwhere\n X: Tensor + ConvertTo<{<X as Tensor>::N + 1}>,\nRun Code Online (Sandbox Code Playgroud)\n最初的示例不起作用,因为 Rust 独立评估每个特征边界。因此,它一方面试图断言这一点Constant<3>: ConvertTo<?>,另一方面又试图断言这一点?: Tensor<4>。只有同时考虑它们才有意义。
特征上的关联类型,允许必要的语法确实在单个表达式中具有所有边界,这是最终结果,可以完美编译:
\n#![allow(incomplete_features)]\n#![feature(generic_const_exprs)]\n#![feature(associated_type_bounds)]\n\nstruct Variable<const N: usize>;\nstruct Constant<const N: usize>;\n\ntrait Tensor {\n const N: usize;\n\n fn get_dim(&self) -> usize {\n Self::N\n }\n}\ntrait ConvertTo<const N: usize> {\n type To;\n \n fn convert(&self) -> Self::To;\n}\n\nimpl<const N: usize> Tensor for Variable<N> {\n const N: usize = N;\n}\nimpl<const N: usize> Tensor for Constant<N> {\n const N: usize = N;\n}\n\nimpl<const N: usize, const M: usize> ConvertTo<M> for Variable<N> {\n type To = Constant<M>;\n\n fn convert(&self) -> Self::To {\n Constant::<M>\n }\n}\n\nimpl<const N: usize, const M: usize> ConvertTo<M> for Constant<N> {\n type To = Variable<M>;\n \n fn convert(&self) -> Self::To {\n Variable::<M>\n }\n}\n\nfn convert_plus_one<X>(x: X) -> <X as ConvertTo<{<X as Tensor>::N + 1}>>::To\nwhere\n X: Tensor + ConvertTo<{<X as Tensor>::N + 1}>,\n{\n x.convert()\n}\n\nfn main() {\n let x = Constant::<3>;\n let y = convert_plus_one(x);\n assert_eq!(y.get_dim(), 4);\n}\nRun Code Online (Sandbox Code Playgroud)\n现在我可以休息了。
\n| 归档时间: |
|
| 查看次数: |
1981 次 |
| 最近记录: |