Skip to content

Commit 813afcc

Browse files
committed
Optimize parse_fn_arg_or_variadic for less lookahead on erroneous receiver
1 parent c172150 commit 813afcc

File tree

1 file changed

+61
-40
lines changed

1 file changed

+61
-40
lines changed

src/item.rs

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,8 +1607,9 @@ pub(crate) mod parsing {
16071607
allow_variadic: bool,
16081608
) -> Result<FnArgOrVariadic> {
16091609
let ahead = input.fork();
1610-
if let Ok(mut receiver) = ahead.parse::<Receiver>() {
1610+
if let Ok((reference, mutability, self_token)) = parse_receiver_begin(&ahead) {
16111611
input.advance_to(&ahead);
1612+
let mut receiver = parse_rest_of_receiver(reference, mutability, self_token, input)?;
16121613
receiver.attrs = attrs;
16131614
return Ok(FnArgOrVariadic::FnArg(FnArg::Receiver(receiver)));
16141615
}
@@ -1654,48 +1655,68 @@ pub(crate) mod parsing {
16541655
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
16551656
impl Parse for Receiver {
16561657
fn parse(input: ParseStream) -> Result<Self> {
1657-
let reference = if input.peek(Token![&]) {
1658-
let ampersand: Token![&] = input.parse()?;
1659-
let lifetime: Option<Lifetime> = input.parse()?;
1660-
Some((ampersand, lifetime))
1661-
} else {
1662-
None
1663-
};
1664-
let mutability: Option<Token![mut]> = input.parse()?;
1665-
let self_token: Token![self] = input.parse()?;
1666-
let colon_token: Option<Token![:]> = if reference.is_some() {
1667-
None
1668-
} else {
1669-
input.parse()?
1670-
};
1671-
let ty: Type = if colon_token.is_some() {
1672-
input.parse()?
1673-
} else {
1674-
let mut ty = Type::Path(TypePath {
1675-
qself: None,
1676-
path: Path::from(Ident::new("Self", self_token.span)),
1677-
});
1678-
if let Some((ampersand, lifetime)) = reference.as_ref() {
1679-
ty = Type::Reference(TypeReference {
1680-
and_token: Token![&](ampersand.span),
1681-
lifetime: lifetime.clone(),
1682-
mutability: mutability.as_ref().map(|m| Token![mut](m.span)),
1683-
elem: Box::new(ty),
1684-
});
1685-
}
1686-
ty
1687-
};
1688-
Ok(Receiver {
1689-
attrs: Vec::new(),
1690-
reference,
1691-
mutability,
1692-
self_token,
1693-
colon_token,
1694-
ty: Box::new(ty),
1695-
})
1658+
let (reference, mutability, self_token) = parse_receiver_begin(input)?;
1659+
parse_rest_of_receiver(reference, mutability, self_token, input)
16961660
}
16971661
}
16981662

1663+
fn parse_receiver_begin(
1664+
input: ParseStream,
1665+
) -> Result<(
1666+
Option<(Token![&], Option<Lifetime>)>,
1667+
Option<Token![mut]>,
1668+
Token![self],
1669+
)> {
1670+
let reference = if input.peek(Token![&]) {
1671+
let ampersand: Token![&] = input.parse()?;
1672+
let lifetime: Option<Lifetime> = input.parse()?;
1673+
Some((ampersand, lifetime))
1674+
} else {
1675+
None
1676+
};
1677+
let mutability: Option<Token![mut]> = input.parse()?;
1678+
let self_token: Token![self] = input.parse()?;
1679+
Ok((reference, mutability, self_token))
1680+
}
1681+
1682+
fn parse_rest_of_receiver(
1683+
reference: Option<(Token![&], Option<Lifetime>)>,
1684+
mutability: Option<Token![mut]>,
1685+
self_token: Token![self],
1686+
input: ParseStream,
1687+
) -> Result<Receiver> {
1688+
let colon_token: Option<Token![:]> = if reference.is_some() {
1689+
None
1690+
} else {
1691+
input.parse()?
1692+
};
1693+
let ty: Type = if colon_token.is_some() {
1694+
input.parse()?
1695+
} else {
1696+
let mut ty = Type::Path(TypePath {
1697+
qself: None,
1698+
path: Path::from(Ident::new("Self", self_token.span)),
1699+
});
1700+
if let Some((ampersand, lifetime)) = reference.as_ref() {
1701+
ty = Type::Reference(TypeReference {
1702+
and_token: Token![&](ampersand.span),
1703+
lifetime: lifetime.clone(),
1704+
mutability: mutability.as_ref().map(|m| Token![mut](m.span)),
1705+
elem: Box::new(ty),
1706+
});
1707+
}
1708+
ty
1709+
};
1710+
Ok(Receiver {
1711+
attrs: Vec::new(),
1712+
reference,
1713+
mutability,
1714+
self_token,
1715+
colon_token,
1716+
ty: Box::new(ty),
1717+
})
1718+
}
1719+
16991720
fn parse_fn_args(
17001721
input: ParseStream,
17011722
) -> Result<(Punctuated<FnArg, Token![,]>, Option<Variadic>)> {

0 commit comments

Comments
 (0)