Rust 中的“可选特征绑定”功能

tow*_*120 6 rust

我想要一些类似功能绑定的可选特征。ifT实现该类型的地方 - 做一些事情。

fn test<T: Eq + ?Debug>(a:T, b:T){
    if a!=b{
        println!("Not equal!");
        if (T impl Debug){
            println!("{:?} != {:?}", a, b);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Fil*_*ues 3

正如@user4815162342 评论的那样,使用专业化,这是可能的。

我将提供与他们在评论中指定的方法略有不同的方法,以保持与if ... { ... }原始代码中相同的设置。

这个想法是拥有一个AsMaybeDebug具有关联 type 的特征Debug,它总是实现Debug一个从 到 的&Self函数Option<&Self::Debug>

trait AsMaybeDebug {
    type Debug: Debug;
    fn as_maybe_debug(&self) -> Option<&Self::Debug>;
}
Run Code Online (Sandbox Code Playgroud)

之后,我们为 all 创建一个默认的 impl T,调试类型为!never 类型,并且始终返回None

impl<T> AsMaybeDebug for T {
    default type Debug = !;
    default fn as_maybe_debug(&self) -> Option<&Self::Debug> {
        None
    }
}
Run Code Online (Sandbox Code Playgroud)

Debug您可以选择始终实现但仍返回 的任何类型,而不是 never 类型None

之后我们专门T: Debug返回Self

impl<T: Debug> AsMaybeDebug for T {
    type Debug = Self;
    fn as_maybe_debug(&self) -> Option<&Self::Debug> {
        Some(self)
    }
}
Run Code Online (Sandbox Code Playgroud)

最后test我们只需调用as_maybe_debug并检查是否T: Debug

impl<T: Debug> AsMaybeDebug for T {
    type Debug = Self;
    fn as_maybe_debug(&self) -> Option<&Self::Debug> {
        Some(self)
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在游乐场中检查它是否有效,以及生成的程序集是否test_non_debug没有任何调试调用,只有对std::io::_print.

不幸的是,调用后无法检索原始内容ab内部内容。ifas_maybe_debug

这是由于<Self as AsMaybeDebug>::Debug无法转换回Self. 这个问题可以修复,但并不容易,因为它需要标准库的更新。

要求AsMaybeDebug::Debug: AsRef<Self>不起作用有两个原因:

    1. 目前还没有impl<T> AsRef<T> for T,我认为这是由于专业化仍然不完整。
    1. 目前还没有impl<T> AsRef<T> for !。不确定这个实现是否可以在专业化的情况下实现,但这是必需的。

另外,虽然可能specialization不健全,但我相信该特征及其隐含不能用于不健全,您需要一个特定的设置才能从中生成不健全,而这是所缺乏的。