这是一个最小的example代表我遇到的问题类型。
use core::fmt::Debug;
pub trait Config {
type A: Debug;
}
#[derive(Debug)]
pub struct Info<T: Config> {
pub field: T::A,
}
pub struct Conf;
impl Config for Conf {
type A = i128;
}
fn main() {
let s = Info::<Conf> {
field: 123
};
dbg!(s);
}
我正在使用的框架 (Substrate) 使用
Config
特性的概念,它聚合了模块(托盘)的所有泛型类型。
问题是,尝试
#[derive(Debug)]
一个只使用对象的关联类型T
实现Config
的结构仍然需要T
实现Debug
本身。
error[E0277]: `Conf` doesn't implement `Debug`
--> src/main.rs:22:5
|
22 | dbg!(s);
| ^^^^^^^ `Conf` cannot be formatted using `{:?}`
|
= help: the trait `Debug` is not implemented for `Conf`
= note: add `#[derive(Debug)]` to `Conf` or manually `impl Debug for Conf`
此外,我无法控制
Conf
对象的实现。无论如何,我不想打印任何关于Conf
对象本身的东西。
有没有办法让
#[derive(Debug)]
为Info
忽略T
?
不幸的是,不是今天。您必须手动实施
Debug
:
impl<T: Config> fmt::Debug for Info<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Info").field("field", &self.field).finish()
}
}
有一个目的是让创建所谓的“完美派生”成为可能:根据需要而不是通用参数派生边界。例如参见这个 lang 团队设计会议提案。但是现在什么都没有。
derive_where
板条箱可用于实现此目的:
#[derive_where(Clone, Debug)]
pub struct Info<T: Config> {
pub field: T::A,
}