Rollup merge of #46827 - petrochenkov:assocrecov2, r=estebank
syntax: Follow-up to the incorrect qpath recovery PR cc https://github.com/rust-lang/rust/pull/46788 Add tests checking that "priority" of qpath recovery is higher than priority of unary and binary operators Fix regressed parsing of paths with fn-like generic arguments r? @estebank
This commit is contained in:
commit
2917ac6b59
8 changed files with 165 additions and 70 deletions
|
@ -169,11 +169,49 @@ enum PrevTokenKind {
|
|||
Other,
|
||||
}
|
||||
|
||||
pub(crate) trait RecoverQPath: Sized {
|
||||
trait RecoverQPath: Sized {
|
||||
const PATH_STYLE: PathStyle = PathStyle::Expr;
|
||||
fn to_ty(&self) -> Option<P<Ty>>;
|
||||
fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self;
|
||||
fn to_string(&self) -> String;
|
||||
const PATH_STYLE: PathStyle = PathStyle::Expr;
|
||||
}
|
||||
|
||||
impl RecoverQPath for Ty {
|
||||
const PATH_STYLE: PathStyle = PathStyle::Type;
|
||||
fn to_ty(&self) -> Option<P<Ty>> {
|
||||
Some(P(self.clone()))
|
||||
}
|
||||
fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self {
|
||||
Self { span: path.span, node: TyKind::Path(qself, path), id: self.id }
|
||||
}
|
||||
fn to_string(&self) -> String {
|
||||
pprust::ty_to_string(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl RecoverQPath for Pat {
|
||||
fn to_ty(&self) -> Option<P<Ty>> {
|
||||
self.to_ty()
|
||||
}
|
||||
fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self {
|
||||
Self { span: path.span, node: PatKind::Path(qself, path), id: self.id }
|
||||
}
|
||||
fn to_string(&self) -> String {
|
||||
pprust::pat_to_string(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl RecoverQPath for Expr {
|
||||
fn to_ty(&self) -> Option<P<Ty>> {
|
||||
self.to_ty()
|
||||
}
|
||||
fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self {
|
||||
Self { span: path.span, node: ExprKind::Path(qself, path),
|
||||
id: self.id, attrs: self.attrs.clone() }
|
||||
}
|
||||
fn to_string(&self) -> String {
|
||||
pprust::expr_to_string(self)
|
||||
}
|
||||
}
|
||||
|
||||
/* ident is handled by common.rs */
|
||||
|
@ -1432,7 +1470,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
// Parse a type
|
||||
pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
|
||||
self.parse_ty_common(true)
|
||||
self.parse_ty_common(true, true)
|
||||
}
|
||||
|
||||
/// Parse a type in restricted contexts where `+` is not permitted.
|
||||
|
@ -1441,10 +1479,11 @@ impl<'a> Parser<'a> {
|
|||
/// Example 2: `value1 as TYPE + value2`
|
||||
/// `+` is prohibited to avoid interactions with expression grammar.
|
||||
fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
|
||||
self.parse_ty_common(false)
|
||||
self.parse_ty_common(false, true)
|
||||
}
|
||||
|
||||
fn parse_ty_common(&mut self, allow_plus: bool) -> PResult<'a, P<Ty>> {
|
||||
fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool)
|
||||
-> PResult<'a, P<Ty>> {
|
||||
maybe_whole!(self, NtTy, |x| x);
|
||||
|
||||
let lo = self.span;
|
||||
|
@ -1577,7 +1616,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
// Try to recover from use of `+` with incorrect priority.
|
||||
self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
|
||||
let ty = self.maybe_recover_from_bad_qpath(ty)?;
|
||||
let ty = self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)?;
|
||||
|
||||
Ok(P(ty))
|
||||
}
|
||||
|
@ -1633,9 +1672,10 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
// Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`.
|
||||
fn maybe_recover_from_bad_qpath<T: RecoverQPath>(&mut self, base: T) -> PResult<'a, T> {
|
||||
fn maybe_recover_from_bad_qpath<T: RecoverQPath>(&mut self, base: T, allow_recovery: bool)
|
||||
-> PResult<'a, T> {
|
||||
// Do not add `::` to expected tokens.
|
||||
if self.token != token::ModSep {
|
||||
if !allow_recovery || self.token != token::ModSep {
|
||||
return Ok(base);
|
||||
}
|
||||
let ty = match base.to_ty() {
|
||||
|
@ -1969,7 +2009,7 @@ impl<'a> Parser<'a> {
|
|||
|p| p.parse_ty())?;
|
||||
self.bump(); // `)`
|
||||
let output = if self.eat(&token::RArrow) {
|
||||
Some(self.parse_ty_no_plus()?)
|
||||
Some(self.parse_ty_common(false, false)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -2376,7 +2416,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
let expr = Expr { node: ex, span: lo.to(hi), id: ast::DUMMY_NODE_ID, attrs };
|
||||
let expr = self.maybe_recover_from_bad_qpath(expr)?;
|
||||
let expr = self.maybe_recover_from_bad_qpath(expr, true)?;
|
||||
|
||||
return Ok(P(expr));
|
||||
}
|
||||
|
@ -3743,7 +3783,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
let pat = Pat { node: pat, span: lo.to(self.prev_span), id: ast::DUMMY_NODE_ID };
|
||||
let pat = self.maybe_recover_from_bad_qpath(pat)?;
|
||||
let pat = self.maybe_recover_from_bad_qpath(pat, true)?;
|
||||
|
||||
Ok(P(pat))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue