通过使用 AsRef<T> 在 Rust 中解包枚举来重载它?

Overloading AsRef<T> by using it to unwrap enums in Rust?

我正在使用 AsRef<T>AsMut<T> 来公开枚举中的包装值。谁能告诉我这是否是反模式?我遇到了 ,它让我相信 Deref 是个坏主意,但我不确定下面的方法。

pub enum Node {
    Stmt(Statement),
    Expr(Expression),
}

impl AsMut<Expression> for Node {
    fn as_mut(&mut self) -> &mut Expression {
        match self {
            Node::Stmt(_) => panic!("fatal: expected Expression"),
            Node::Expr(e) => e,
        }
    }
}

impl AsMut<Expression> for Box<Node> {
    fn as_mut(&mut self) -> &mut Expression {
        (**self).as_mut()
    }
}

impl AsMut<Expression> for Expression {
    fn as_mut(&mut self) -> &mut Expression {
        self
    }
}

fn check_binop<T: AsMut<Expression>>(
    &mut self,
    sym: Symbol,
    lhs: &mut T,
    rhs: &mut T,
    ty: &mut Option<Type>,
) -> Result<Type, String> {
    let lhs = lhs.as_mut();
    let rhs = rhs.as_mut();
    ...
}

我正在考虑制作我自己的特征(AsExpr<T>AsExprMut<T>),它们只是 AsRef<T>AsMut<T> 的重新实现。功能上没有什么不同,但我认为它会更清楚。

我强烈建议你不要这样做,特别是考虑到 AsRefAsMut 的文档用粗体表示:

Note: This trait must not fail.

而且我肯定会认为恐慌是失败的。这不是 anti-pattern ,因为它通过实施这些特征违反了你 opt-into 的合同。您应该考虑返回一个 Option<&mut Expression> 而不是通过 AsRef/AsMut,或者像您提到的那样创建您自己的特征。