This feature requires is akin to Idea: Default method of comparing enum variants with data
Motivation
Almost all parsers operate on notion of token stream. For token stream it is useful to compare next token's type with expected type without advancing token stream while disregarding associated data:
pub enum Token {
Word(String),
Number(u16),
SpecialSymbol(char),
EndOfInput,
}
fn expect(self: &TokenStream, expected: Token) -> Result<(), TokenStreamError> ;
// first example
token_stream.expect(Token::Word); // don't care about data, just the type
// -------------------------------------------
// second example
// this token would be obtained from parsing
// it has both type information and associated data
let token = Token::Number(123);
// Token::Word only represents type of a token. Disregard data.
if token != Token::Word { // not interested in data
// notice `!=` not equals operator
// with pattern matching there is no way
// to do this without `else` clause
// `matches!()` won't work either
// ...
}
Both examples won't compile now. They require to instantiate Token::Word
with at least dummy data like Token::Word("")
.
The example can be generalized as: check type of data disregarding data itself. Modeling typed data with rust enums is the most straightforward way! Only the last bit is missing: check enum variant without constructing other instance of enum variant.
So the main usage is within parsers and weakly typed environments such as when building DSLs.
Alternatives
We could also use mem::discriminant
. But it also requires to instantiate enum variant with data supplied.
So currently there are several ways to accomplish the task:
- use pattern matching (requires a lot of boilerplate code)
if let Token::Word(_) = token_stream.peek() {
return Err(TokenStreamError::UnexpectedToken("word"));
}
if let Token::Number(_) = token_stream.peek() {
return Err(TokenStreamError::UnexpectedToken("number"))
}
- use macros to either generate the above code or to generate enum with same variants but without associated data:
enum TokenType {
Word,
Number,
SpecialSymbol,
EndOfInput
}
As you can see the problem is already solvable in user space but not without considerable hassle.
Solution
Allow to compare enum variants only by discriminant without constructing them:
fn expect(&self, expected: Discriminant<Token>) -> Result<(), TokenStreamError> {
mem::discriminant(self) == expected // expected is a variant of token without data supplied
}
let token = Token::Number(123);
// essentially next line should be possible
token.expect(mem::discriminant(Token::Word));
The proposal
Allow to obtain enum discriminant from enum variant constructor