How are we able to pass type as an argument instead of turbofish to syn::parse::ParseBuffer::peek
?
Methods are generally called like input.parse::<Token![;]>()
. We pass types as generics but peek expects them as input.peek(Token![;])
.
I wanted to know because if I create a type alias to Token![;]
like type TokenAlias = Token![;]
and use it like input.peek(TokenAlias)
,
I get the error:
expected value, found type alias `TokenAlias` can't use a type alias as a constructor
which would have made sense if Token![;]
was also not allowed.
Why do I get this error when I use type alias?
Code with TokenAlias
:
// COMPILE ERROR: expected value, found type alias `TokenAlias` can't use a type alias as a constructor
type TokenAlias = Token![;];
impl Parse for PathSegments {
fn parse(input: ParseStream) -> Result<Self> {
let mut segments = Punctuated::new();
let first = parse_until(input, TokenAlias)?;
segments.push_value(syn::parse2(first)?);
while input.peek(TokenAlias) {
segments.push_punct(input.parse()?);
let next = parse_until(input, TokenAlias)?;
segments.push_value(syn::parse2(next)?);
}
Ok(PathSegments { segments })
}
}
Code with Token![;]
:
// BUILDS SUCCESSFULLY
impl Parse for PathSegments {
fn parse(input: ParseStream) -> Result<Self> {
let mut segments = Punctuated::new();
let first = parse_until(input, Token![;])?;
segments.push_value(syn::parse2(first)?);
while input.peek(Token![;]) {
segments.push_punct(input.parse()?);
let next = parse_until(input, Token![;])?;
segments.push_value(syn::parse2(next)?);
}
Ok(PathSegments { segments })
}
}
Following is the source code of peek
from syn
:
pub fn peek<T: Peek>(&self, token: T) -> bool {
let _ = token;
T::Token::peek(self.cursor())
}
The peek
function accepts a token value, not a type.
The reason it accepts Token[;]
is that it expands to an identifier that is the name of a type, but also of a global function hidden from docs! Your type alias refers to the type, and attempting to construct a value using constructor syntax for unit-like structs makes the compiler complain that such syntax doesn't work for type aliases. (And even if it did, Semi
is not a unit-like struct, so it wouldn't work for that type in particular.)