There are a number of questions on this site about pattern matching Box<>
, and it currently can't be done on stable Rust (one, two, three etc.). But those questions are all about single levels of box. I have a deeply nested Box/Enum tree. Basically I want to do this:
match node {
ConstantExpression::ConstantPrimary(Box(ConstantPrimary::PrimaryLiteral(Box(
PrimaryLiteral::Number(Box(Number::IntegralNumber(Box(
IntegralNumber::DecimalNumber(Box(DecimalNumber::UnsignedNumber(unsigned_number))),
)))),
)))) => Some(unsigned_number),
_ => None,
};
Is there a way to do this on stable Rust that isn't extremely verbose?
(Edit: This is not a duplicate of this question; I already know you can't do it using match
. I was asking for an alternative way to do it.)
The problem of matching against boxes aside, there isn't really any redundant information in your pattern. You have to mention each enum variant at least once to specify what you want. The best you can do to make the pattern less unwieldy is doing one level at a time:
pub fn extract_unsigned_number(node: ConstantExpression) -> Option<UnsignedNumber> {
let ConstantExpression::ConstantPrimary(constant_primary) = node else { return None };
let ConstantPrimary::PrimaryLiteral(primary_literal) = *constant_primary else { return None };
let PrimaryLiteral::Number(number) = *primary_literal else { return None };
let Number::IntegralNumber(integral_number) = *number else { return None };
let IntegralNumber::DecimalNumber(decimal_number) = *integral_number else { return None };
let DecimalNumber::UnsignedNumber(unsigned_number) = *decimal_number else { return None };
Some(*unsigned_number)
}
You could make this slightly less repetitive with a declarative macro, but the code will become more obscure, so I'd personally just use this code as it is.