/// Parses an expression, forcing tokens to be collected
pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P<Expr>> {
- // If we have outer attributes, then the call to `collect_tokens_trailing_token`
- // will be made for us.
- if matches!(self.token.kind, TokenKind::Pound | TokenKind::DocComment(..)) {
- self.parse_expr()
- } else {
- // If we don't have outer attributes, then we need to ensure
- // that collection happens by using `collect_tokens_no_attrs`.
- // Expression don't support custom inner attributes, so `parse_expr`
- // will never try to collect tokens if we don't have outer attributes.
- self.collect_tokens_no_attrs(|this| this.parse_expr())
- }
+ self.collect_tokens_no_attrs(|this| this.parse_expr())
}
pub fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
self.parse_closure_expr(attrs)
} else if self.check(&token::OpenDelim(token::Bracket)) {
self.parse_array_or_repeat_expr(attrs)
- } else if self.eat_lt() {
- let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
- Ok(self.mk_expr(lo.to(path.span), ExprKind::Path(Some(qself), path), attrs))
} else if self.check_path() {
self.parse_path_start_expr(attrs)
} else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
}
fn parse_path_start_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
- let path = self.parse_path(PathStyle::Expr)?;
+ let (qself, path) = if self.eat_lt() {
+ let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
+ (Some(qself), path)
+ } else {
+ (None, self.parse_path(PathStyle::Expr)?)
+ };
let lo = path.span;
// `!`, as an operator, is prefix, so we know this isn't that.
let (hi, kind) = if self.eat(&token::Not) {
// MACRO INVOCATION expression
+ if qself.is_some() {
+ self.struct_span_err(path.span, "macros cannot use qualified paths").emit();
+ }
let mac = MacCall {
path,
args: self.parse_mac_args()?,
};
(self.prev_token.span, ExprKind::MacCall(mac))
} else if self.check(&token::OpenDelim(token::Brace)) {
- if let Some(expr) = self.maybe_parse_struct_expr(&path, &attrs) {
+ if let Some(expr) = self.maybe_parse_struct_expr(qself.as_ref(), &path, &attrs) {
+ if qself.is_some() {
+ self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
+ }
return expr;
} else {
- (path.span, ExprKind::Path(None, path))
+ (path.span, ExprKind::Path(qself, path))
}
} else {
- (path.span, ExprKind::Path(None, path))
+ (path.span, ExprKind::Path(qself, path))
};
let expr = self.mk_expr(lo.to(hi), kind, attrs);
fn maybe_parse_struct_expr(
&mut self,
+ qself: Option<&ast::QSelf>,
path: &ast::Path,
attrs: &AttrVec,
) -> Option<PResult<'a, P<Expr>>> {
if let Err(err) = self.expect(&token::OpenDelim(token::Brace)) {
return Some(Err(err));
}
- let expr = self.parse_struct_expr(path.clone(), attrs.clone(), true);
+ let expr = self.parse_struct_expr(qself.cloned(), path.clone(), attrs.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.error_struct_lit_not_allowed_here(path.span, expr.span);
/// Precondition: already parsed the '{'.
pub(super) fn parse_struct_expr(
&mut self,
+ qself: Option<ast::QSelf>,
pth: ast::Path,
attrs: AttrVec,
recover: bool,
let expr = if recover_async {
ExprKind::Err
} else {
- ExprKind::Struct(P(ast::StructExpr { path: pth, fields, rest: base }))
+ ExprKind::Struct(P(ast::StructExpr { qself, path: pth, fields, rest: base }))
};
Ok(self.mk_expr(span, expr, attrs))
}