我如何解决“上游板条箱可能会添加新的特征实现”错误?

Mut*_*Bob 8 traits rust

我创建了一个特性,用于从某些值转换为我需要的类型。对于许多类型,该转换已经包含在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.

Mut*_*Bob 6

根据 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)


She*_*ter 5

这不是您可以“解决”的问题。这是编译器强加的限制,以防止将来对依赖项的更改巧妙地更改代码的行为。

现在,您通过实现具体类型而不是使用泛型和特征来避免错误。宏是减少必须执行的键盘输入量的一种方法。

将来,某种形式的专业化也可能有助于解决这个问题。然而,这恰好是专业化不稳定的原因。可以使用这种类型的专业化仅使用安全代码来创建不健全的 Rust。正在研究一种简化形式的专业化,但它故意避开基于特征的专业化能力,仅适用于具体类型。

也可以看看:

  • 如果这是一个可能的未来问题,那么当这确实是一个问题时,为什么编译器将来不会失败呢?既然还没有冲突,为什么现在就必须失败呢?既然无论如何它都会在稍后编译时失败,那么早点失败有什么好处呢?只是想知道你是否知道原因。谢谢! (13认同)