jzimmerman
jzimmerman

Reputation: 74

Destructure rust enum without matching

What would be the correct way to simplify this strange code? There is no variant of AstNode that doesn't wrap around an inner structure.

impl<'a> Debug for AstNode<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            AstNode::Literal(inner) => inner.fmt(f),
            AstNode::Variable(inner) => inner.fmt(f),
            AstNode::Binary(inner) => inner.fmt(f),
            AstNode::Unary(inner) => inner.fmt(f),
            AstNode::Call(inner) => inner.fmt(f),
            AstNode::Function(inner) => inner.fmt(f),
            AstNode::If(inner) => inner.fmt(f),
            AstNode::While(inner) => inner.fmt(f),
            AstNode::Begin(inner) => inner.fmt(f),
            AstNode::Assign(inner) => inner.fmt(f),
            AstNode::NewGlobal(inner) => inner.fmt(f),
            AstNode::Error(inner) => inner.fmt(f),
            AstNode::TestAssert(inner) => inner.fmt(f),
            AstNode::TestExpect(inner) => inner.fmt(f),
        }
    }
}

Upvotes: 1

Views: 711

Answers (1)

Denis Bazhenov
Denis Bazhenov

Reputation: 9945

If the inner member is not dependent on enum variant there is no need to put it in enum. You can promote it up, so there will be no need to match it. Something along those lines:

struct AstNode(AstKind, InnerType);

enum AstKind {
  Literal,
  Variable,
  ...
}

then you can write:

impl<'a> Debug for AstNode<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.1.fmt(f)
    }
}

This type system explicitly states that InnerType and AstKind is independent. Which is your case If I understand correctly.

Upvotes: 2

Related Questions