Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

设计约束

跨 StructError 的 From 转换:orphan rule 限制

问题

跨层错误转换(StructError<ParseReason>StructError<OrderReason>)需要调用 .conv_err()

#![allow(unused)]
fn main() {
// 期望但不能实现
fn place_order() -> Result<OrderDraft, StructError<OrderReason>> {
    let draft = parse_order()?;  // 期望自动 From<ParseError> → OrderError
    Ok(draft)
}

// 实际需要显式调用
fn place_order() -> Result<OrderDraft, StructError<OrderReason>> {
    let draft = parse_order().conv_err()?;  // 显式转换
    Ok(draft)
}
}

原因

Rust 的 orphan rule 不允许从下游 crate 中实现 From<Foreign<Local>> for Foreign<Local2>

#![allow(unused)]
fn main() {
// 这行代码在用户 crate 中展开
impl From<orion_error::StructError<UserLocalReason>>   // Foreign<Local>
    for orion_error::StructError<UserLocalReason2>      // Foreign<Local2>
}
  • From = 标准库 trait(外来)
  • StructError = orion-error 的类型(外来)
  • 即使 LocalReasonLocalReason2 是本地类型

Orphan rule 要求 trait 或 self type 至少有一个本地锚点,但这里 From 是外来 trait,StructError<_> 也是外来类型。 即使 LocalReasonLocalReason2 是本地类型,From<StructError<Local>> for StructError<Local2> 仍然不能在下游 crate 里实现。

已经尝试过的方案

方案结果
下游 crate 直接 impl From<StructError<A>> for StructError<B>❌ orphan rule
derive 属性 upcast_from(SubReason) 在目标类型上❌ orphan rule
derive 属性 upcast_to(MainReason) 在源类型上❌ orphan rule
? 自动触发跨 reason 转换❌ 不能靠 From 达成
newtype struct AppError(StructError<T>)✅ 可行,但所有 API 返回类型都需要改

结论

.conv_err() 是唯一的路径。 newtype 可以绕过 orphan rule,但代价太大——为了省一次显式调用而把所有函数返回类型包一层,收益远低于成本。 Rust 的 orphan rule 是生态兼容性的核心保证,短期内不会为此放宽。