我创建了一个特性,用于从某些值转换为我需要的类型。对于许多类型,该转换已经包含在From/Into中,但不是我想要的所有类型。我以为我可以利用这一点,但很快就得到了一个错误“上游板条箱可能会添加一个新的特征实现”。
(操场上的精简示例)
pub trait Cookable {
fn cook(self) -> (String, Vec<i8>);
}
impl<T: Into<Vec<i8>>> Cookable for T {
fn cook(self) -> (String, Vec<i8>) {
(String::from("simple"), self.into())
}
}
impl Cookable for &str {
fn cook(self) -> (String, Vec<i8>) {
(String::from("smelly"), vec![self.len()])
}
}
Run Code Online (Sandbox Code Playgroud)
这会触发以下错误:
pub trait Cookable {
fn cook(self) -> (String, Vec<i8>);
}
impl<T: Into<Vec<i8>>> Cookable for T {
fn cook(self) -> (String, Vec<i8>) {
(String::from("simple"), self.into())
}
}
impl Cookable for &str {
fn cook(self) -> (String, Vec<i8>) {
(String::from("smelly"), vec![self.len()])
}
}
Run Code Online (Sandbox Code Playgroud)
我担心解决此错误的唯一方法是为已经具有Into.
根据 Shepmaster 列出的问题的答案,我提出了以下解决方法,这似乎可以完成我的任务。它是“使用宏来紧凑地完成实现一堆结构的特征的所有样板”的实现:
extern crate jni;
use jni::objects::{JObject, JValue};
use jni::JNIEnv;
pub trait ConvertRustToJValue<'a> {
fn into_jvalue(self, je: &JNIEnv<'a>) -> JValue<'a>;
}
macro_rules! impl_convert_rust_to_jvalue {
( $($t:ty),* ) => {
$( impl<'a> ConvertRustToJValue<'a> for $t
{
fn into_jvalue(self, _je:&JNIEnv) -> JValue<'a>
{
self.into()
}
}) *
}
}
impl_convert_rust_to_jvalue! { i8, i16, i32, i64 }
Run Code Online (Sandbox Code Playgroud)
这不是您可以“解决”的问题。这是编译器强加的限制,以防止将来对依赖项的更改巧妙地更改代码的行为。
现在,您通过实现具体类型而不是使用泛型和特征来避免错误。宏是减少必须执行的键盘输入量的一种方法。
将来,某种形式的专业化也可能有助于解决这个问题。然而,这恰好是专业化不稳定的原因。可以使用这种类型的专业化仅使用安全代码来创建不健全的 Rust。正在研究一种简化形式的专业化,但它故意避开基于特征的专业化能力,仅适用于具体类型。
也可以看看:
| 归档时间: |
|
| 查看次数: |
571 次 |
| 最近记录: |