1
Fork 0

Box ExprKind::{Closure,MethodCall}, and QSelf in expressions, types, and patterns.

This commit is contained in:
Nicholas Nethercote 2022-09-08 10:52:51 +10:00
parent bebd57a960
commit 6b7ca2fcf2
37 changed files with 409 additions and 318 deletions

View file

@ -65,7 +65,7 @@ pub(super) fn dummy_arg(ident: Ident) -> Param {
pub(super) trait RecoverQPath: Sized + 'static {
const PATH_STYLE: PathStyle = PathStyle::Expr;
fn to_ty(&self) -> Option<P<Ty>>;
fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self;
fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self;
}
impl RecoverQPath for Ty {
@ -73,7 +73,7 @@ impl RecoverQPath for Ty {
fn to_ty(&self) -> Option<P<Ty>> {
Some(P(self.clone()))
}
fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self {
Self {
span: path.span,
kind: TyKind::Path(qself, path),
@ -87,7 +87,7 @@ impl RecoverQPath for Pat {
fn to_ty(&self) -> Option<P<Ty>> {
self.to_ty()
}
fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self {
Self {
span: path.span,
kind: PatKind::Path(qself, path),
@ -101,7 +101,7 @@ impl RecoverQPath for Expr {
fn to_ty(&self) -> Option<P<Ty>> {
self.to_ty()
}
fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self {
Self {
span: path.span,
kind: ExprKind::Path(qself, path),
@ -1437,7 +1437,7 @@ impl<'a> Parser<'a> {
});
let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`.
Ok(P(T::recovered(Some(QSelf { ty, path_span, position: 0 }), path)))
Ok(P(T::recovered(Some(P(QSelf { ty, path_span, position: 0 })), path)))
}
pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool {

View file

@ -840,7 +840,7 @@ impl<'a> Parser<'a> {
ExprKind::Index(_, _) => "indexing",
ExprKind::Try(_) => "`?`",
ExprKind::Field(_, _) => "a field access",
ExprKind::MethodCall(_, _, _, _) => "a method call",
ExprKind::MethodCall(_) => "a method call",
ExprKind::Call(_, _) => "a function call",
ExprKind::Await(_) => "`.await`",
ExprKind::Err => return Ok(with_postfix),
@ -1262,24 +1262,32 @@ impl<'a> Parser<'a> {
}
let fn_span_lo = self.token.span;
let mut segment = self.parse_path_segment(PathStyle::Expr, None)?;
self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(Delimiter::Parenthesis)]);
self.check_turbofish_missing_angle_brackets(&mut segment);
let mut seg = self.parse_path_segment(PathStyle::Expr, None)?;
self.check_trailing_angle_brackets(&seg, &[&token::OpenDelim(Delimiter::Parenthesis)]);
self.check_turbofish_missing_angle_brackets(&mut seg);
if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
// Method call `expr.f()`
let args = self.parse_paren_expr_seq()?;
let fn_span = fn_span_lo.to(self.prev_token.span);
let span = lo.to(self.prev_token.span);
Ok(self.mk_expr(span, ExprKind::MethodCall(segment, self_arg, args, fn_span)))
Ok(self.mk_expr(
span,
ExprKind::MethodCall(Box::new(ast::MethodCall {
seg,
receiver: self_arg,
args,
span: fn_span,
})),
))
} else {
// Field access `expr.f`
if let Some(args) = segment.args {
if let Some(args) = seg.args {
self.sess.emit_err(FieldExpressionWithGeneric(args.span()));
}
let span = lo.to(self.prev_token.span);
Ok(self.mk_expr(span, ExprKind::Field(self_arg, segment.ident)))
Ok(self.mk_expr(span, ExprKind::Field(self_arg, seg.ident)))
}
}
@ -1498,7 +1506,7 @@ impl<'a> Parser<'a> {
});
(lo.to(self.prev_token.span), ExprKind::MacCall(mac))
} else if self.check(&token::OpenDelim(Delimiter::Brace)) &&
let Some(expr) = self.maybe_parse_struct_expr(qself.as_ref(), &path) {
let Some(expr) = self.maybe_parse_struct_expr(&qself, &path) {
if qself.is_some() {
self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
}
@ -2049,9 +2057,9 @@ impl<'a> Parser<'a> {
};
let capture_clause = self.parse_capture_clause()?;
let decl = self.parse_fn_block_decl()?;
let fn_decl = self.parse_fn_block_decl()?;
let decl_hi = self.prev_token.span;
let mut body = match decl.output {
let mut body = match fn_decl.output {
FnRetTy::Default(_) => {
let restrictions = self.restrictions - Restrictions::STMT_EXPR;
self.parse_expr_res(restrictions, None)?
@ -2087,15 +2095,15 @@ impl<'a> Parser<'a> {
let closure = self.mk_expr(
lo.to(body.span),
ExprKind::Closure(
ExprKind::Closure(Box::new(ast::Closure {
binder,
capture_clause,
asyncness,
movability,
decl,
fn_decl,
body,
lo.to(decl_hi),
),
fn_decl_span: lo.to(decl_hi),
})),
);
// Disable recovery for closure body
@ -2800,7 +2808,7 @@ impl<'a> Parser<'a> {
fn maybe_parse_struct_expr(
&mut self,
qself: Option<&ast::QSelf>,
qself: &Option<P<ast::QSelf>>,
path: &ast::Path,
) -> Option<PResult<'a, P<Expr>>> {
let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
@ -2808,7 +2816,7 @@ impl<'a> Parser<'a> {
if let Err(err) = self.expect(&token::OpenDelim(Delimiter::Brace)) {
return Some(Err(err));
}
let expr = self.parse_struct_expr(qself.cloned(), path.clone(), true);
let expr = self.parse_struct_expr(qself.clone(), path.clone(), true);
if let (Ok(expr), false) = (&expr, struct_allowed) {
// This is a struct literal, but we don't can't accept them here.
self.sess.emit_err(StructLiteralNotAllowedHere {
@ -2939,7 +2947,7 @@ impl<'a> Parser<'a> {
/// Precondition: already parsed the '{'.
pub(super) fn parse_struct_expr(
&mut self,
qself: Option<ast::QSelf>,
qself: Option<P<ast::QSelf>>,
pth: ast::Path,
recover: bool,
) -> PResult<'a, P<Expr>> {

View file

@ -889,7 +889,7 @@ impl<'a> Parser<'a> {
}
/// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
fn parse_pat_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
fn parse_pat_struct(&mut self, qself: Option<P<QSelf>>, path: Path) -> PResult<'a, PatKind> {
if qself.is_some() {
// Feature gate the use of qualified paths in patterns
self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
@ -906,7 +906,11 @@ impl<'a> Parser<'a> {
}
/// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
fn parse_pat_tuple_struct(
&mut self,
qself: Option<P<QSelf>>,
path: Path,
) -> PResult<'a, PatKind> {
let (fields, _) = self.parse_paren_comma_seq(|p| {
p.parse_pat_allow_top_alt(
None,

View file

@ -48,7 +48,7 @@ impl<'a> Parser<'a> {
/// `<T as U>::a`
/// `<T as U>::F::a<S>` (without disambiguator)
/// `<T as U>::F::a::<S>` (with disambiguator)
pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, Path)> {
pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (P<QSelf>, Path)> {
let lo = self.prev_token.span;
let ty = self.parse_ty()?;
@ -77,7 +77,7 @@ impl<'a> Parser<'a> {
self.expect(&token::ModSep)?;
}
let qself = QSelf { ty, path_span, position: path.segments.len() };
let qself = P(QSelf { ty, path_span, position: path.segments.len() });
self.parse_path_segments(&mut path.segments, style, None)?;
Ok((