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

@ -718,10 +718,10 @@ pub enum PatKind {
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
/// The `bool` is `true` in the presence of a `..`.
Struct(Option<QSelf>, Path, Vec<PatField>, /* recovered */ bool),
Struct(Option<P<QSelf>>, Path, Vec<PatField>, /* recovered */ bool),
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
TupleStruct(Option<QSelf>, Path, Vec<P<Pat>>),
TupleStruct(Option<P<QSelf>>, Path, Vec<P<Pat>>),
/// An or-pattern `A | B | C`.
/// Invariant: `pats.len() >= 2`.
@ -731,7 +731,7 @@ pub enum PatKind {
/// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants
/// or associated constants. Qualified path patterns `<A>::B::C`/`<A as Trait>::B::C` can
/// only legally refer to associated constants.
Path(Option<QSelf>, Path),
Path(Option<P<QSelf>>, Path),
/// A tuple pattern (`(a, b)`).
Tuple(Vec<P<Pat>>),
@ -1272,6 +1272,18 @@ impl Expr {
}
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Closure {
pub binder: ClosureBinder,
pub capture_clause: CaptureBy,
pub asyncness: Async,
pub movability: Movability,
pub fn_decl: P<FnDecl>,
pub body: P<Expr>,
/// The span of the argument block `|...|`.
pub fn_decl_span: Span,
}
/// Limit types of a range (inclusive or exclusive)
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)]
pub enum RangeLimits {
@ -1281,6 +1293,20 @@ pub enum RangeLimits {
Closed,
}
/// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`).
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct MethodCall {
/// The method name and its generic arguments, e.g. `foo::<Bar, Baz>`.
pub seg: PathSegment,
/// The receiver, e.g. `x`.
pub receiver: P<Expr>,
/// The arguments, e.g. `a, b, c`.
pub args: Vec<P<Expr>>,
/// The span of the function, without the dot and receiver e.g. `foo::<Bar,
/// Baz>(a, b, c)`.
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum StructRest {
/// `..x`.
@ -1293,7 +1319,7 @@ pub enum StructRest {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct StructExpr {
pub qself: Option<QSelf>,
pub qself: Option<P<QSelf>>,
pub path: Path,
pub fields: Vec<ExprField>,
pub rest: StructRest,
@ -1314,17 +1340,8 @@ pub enum ExprKind {
/// This also represents calling the constructor of
/// tuple-like ADTs such as tuple structs and enum variants.
Call(P<Expr>, Vec<P<Expr>>),
/// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`)
///
/// The `PathSegment` represents the method name and its generic arguments
/// (within the angle brackets).
/// The standalone `Expr` is the receiver expression.
/// The vector of `Expr` is the arguments.
/// `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, x, [a, b, c, d])`.
/// This `Span` is the span of the function, without the dot and receiver
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
MethodCall(PathSegment, P<Expr>, Vec<P<Expr>>, Span),
/// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`).
MethodCall(Box<MethodCall>),
/// A tuple (e.g., `(a, b, c, d)`).
Tup(Vec<P<Expr>>),
/// A binary operation (e.g., `a + b`, `a * b`).
@ -1363,9 +1380,7 @@ pub enum ExprKind {
/// A `match` block.
Match(P<Expr>, Vec<Arm>),
/// A closure (e.g., `move |a, b, c| a + b + c`).
///
/// The final span is the span of the argument block `|...|`.
Closure(ClosureBinder, CaptureBy, Async, Movability, P<FnDecl>, P<Expr>, Span),
Closure(Box<Closure>),
/// A block (`'label: { ... }`).
Block(P<Block>, Option<Label>),
/// An async block (`async move { ... }`).
@ -1403,7 +1418,7 @@ pub enum ExprKind {
/// parameters (e.g., `foo::bar::<baz>`).
///
/// Optionally "qualified" (e.g., `<Vec<T> as SomeTrait>::SomeType`).
Path(Option<QSelf>, Path),
Path(Option<P<QSelf>>, Path),
/// A referencing operation (`&a`, `&mut a`, `&raw const a` or `&raw mut a`).
AddrOf(BorrowKind, Mutability, P<Expr>),
@ -2006,7 +2021,7 @@ pub enum TyKind {
/// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
///
/// Type parameters are stored in the `Path` itself.
Path(Option<QSelf>, Path),
Path(Option<P<QSelf>>, Path),
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
TraitObject(GenericBounds, TraitObjectSyntax),
@ -2138,7 +2153,7 @@ impl InlineAsmTemplatePiece {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct InlineAsmSym {
pub id: NodeId,
pub qself: Option<QSelf>,
pub qself: Option<P<QSelf>>,
pub path: Path,
}
@ -3031,8 +3046,8 @@ mod size_asserts {
static_assert_size!(AssocItemKind, 32);
static_assert_size!(Attribute, 32);
static_assert_size!(Block, 48);
static_assert_size!(Expr, 104);
static_assert_size!(ExprKind, 72);
static_assert_size!(Expr, 88);
static_assert_size!(ExprKind, 56);
static_assert_size!(Fn, 184);
static_assert_size!(ForeignItem, 96);
static_assert_size!(ForeignItemKind, 24);
@ -3046,13 +3061,13 @@ mod size_asserts {
static_assert_size!(LitKind, 24);
static_assert_size!(Local, 72);
static_assert_size!(Param, 40);
static_assert_size!(Pat, 120);
static_assert_size!(Pat, 104);
static_assert_size!(Path, 40);
static_assert_size!(PathSegment, 24);
static_assert_size!(PatKind, 96);
static_assert_size!(PatKind, 80);
static_assert_size!(Stmt, 32);
static_assert_size!(StmtKind, 16);
static_assert_size!(Ty, 96);
static_assert_size!(TyKind, 72);
static_assert_size!(Ty, 80);
static_assert_size!(TyKind, 56);
// tidy-alphabetical-end
}

View file

@ -194,7 +194,7 @@ pub trait MutVisitor: Sized {
noop_visit_path(p, self);
}
fn visit_qself(&mut self, qs: &mut Option<QSelf>) {
fn visit_qself(&mut self, qs: &mut Option<P<QSelf>>) {
noop_visit_qself(qs, self);
}
@ -529,8 +529,9 @@ pub fn noop_visit_path<T: MutVisitor>(Path { segments, span, tokens }: &mut Path
visit_lazy_tts(tokens, vis);
}
pub fn noop_visit_qself<T: MutVisitor>(qself: &mut Option<QSelf>, vis: &mut T) {
visit_opt(qself, |QSelf { ty, path_span, position: _ }| {
pub fn noop_visit_qself<T: MutVisitor>(qself: &mut Option<P<QSelf>>, vis: &mut T) {
visit_opt(qself, |qself| {
let QSelf { ty, path_span, position: _ } = &mut **qself;
vis.visit_ty(ty);
vis.visit_span(path_span);
})
@ -1303,12 +1304,17 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_expr(f);
visit_exprs(args, vis);
}
ExprKind::MethodCall(PathSegment { ident, id, args }, receiver, exprs, span) => {
ExprKind::MethodCall(box MethodCall {
seg: PathSegment { ident, id, args: seg_args },
receiver,
args: call_args,
span,
}) => {
vis.visit_ident(ident);
vis.visit_id(id);
visit_opt(args, |args| vis.visit_generic_args(args));
visit_opt(seg_args, |args| vis.visit_generic_args(args));
vis.visit_method_receiver_expr(receiver);
visit_exprs(exprs, vis);
visit_exprs(call_args, vis);
vis.visit_span(span);
}
ExprKind::Binary(_binop, lhs, rhs) => {
@ -1353,12 +1359,20 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_expr(expr);
arms.flat_map_in_place(|arm| vis.flat_map_arm(arm));
}
ExprKind::Closure(binder, _capture_by, asyncness, _movability, decl, body, span) => {
ExprKind::Closure(box Closure {
binder,
capture_clause: _,
asyncness,
movability: _,
fn_decl,
body,
fn_decl_span,
}) => {
vis.visit_closure_binder(binder);
vis.visit_asyncness(asyncness);
vis.visit_fn_decl(decl);
vis.visit_fn_decl(fn_decl);
vis.visit_expr(body);
vis.visit_span(span);
vis.visit_span(fn_decl_span);
}
ExprKind::Block(blk, label) => {
vis.visit_block(blk);

View file

@ -36,7 +36,6 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
| Binary(_, _, e)
| Box(e)
| Break(_, Some(e))
| Closure(.., e, _)
| Let(_, e, _)
| Range(_, Some(e), _)
| Ret(Some(e))
@ -44,6 +43,9 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
| Yield(Some(e)) => {
expr = e;
}
Closure(closure) => {
expr = &closure.body;
}
Async(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
| TryBlock(..) | While(..) => break Some(expr),
_ => break None,

View file

@ -396,7 +396,7 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
contains_exterior_struct_lit(&x)
}
ast::ExprKind::MethodCall(_, ref receiver, _, _) => {
ast::ExprKind::MethodCall(box ast::MethodCall { ref receiver, .. }) => {
// X { y: 1 }.bar(...)
contains_exterior_struct_lit(&receiver)
}

View file

@ -798,10 +798,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr(callee_expression);
walk_list!(visitor, visit_expr, arguments);
}
ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _span) => {
visitor.visit_path_segment(segment);
ExprKind::MethodCall(box MethodCall { ref seg, ref receiver, ref args, span: _ }) => {
visitor.visit_path_segment(seg);
visitor.visit_expr(receiver);
walk_list!(visitor, visit_expr, arguments);
walk_list!(visitor, visit_expr, args);
}
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
visitor.visit_expr(left_expression);
@ -842,8 +842,16 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr(subexpression);
walk_list!(visitor, visit_arm, arms);
}
ExprKind::Closure(ref binder, _, _, _, ref decl, ref body, _decl_span) => {
visitor.visit_fn(FnKind::Closure(binder, decl, body), expression.span, expression.id)
ExprKind::Closure(box Closure {
ref binder,
capture_clause: _,
asyncness: _,
movability: _,
ref fn_decl,
ref body,
fn_decl_span: _,
}) => {
visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), expression.span, expression.id)
}
ExprKind::Block(ref block, ref opt_label) => {
walk_list!(visitor, visit_label, opt_label);

View file

@ -61,7 +61,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ExprKind::Call(f, self.lower_exprs(args))
}
}
ExprKind::MethodCall(ref seg, ref receiver, ref args, span) => {
ExprKind::MethodCall(box MethodCall { ref seg, ref receiver, ref args, span }) => {
let hir_seg = self.arena.alloc(self.lower_path_segment(
e.span,
seg,
@ -172,22 +172,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
};
self.lower_expr_await(dot_await_span, expr)
}
ExprKind::Closure(
ExprKind::Closure(box Closure {
ref binder,
capture_clause,
asyncness,
movability,
ref decl,
ref fn_decl,
ref body,
fn_decl_span,
) => {
}) => {
if let Async::Yes { closure_id, .. } = asyncness {
self.lower_expr_async_closure(
binder,
capture_clause,
e.id,
closure_id,
decl,
fn_decl,
body,
fn_decl_span,
)
@ -197,7 +197,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
capture_clause,
e.id,
movability,
decl,
fn_decl,
body,
fn_decl_span,
)
@ -1077,7 +1077,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn extract_tuple_struct_path<'a>(
&mut self,
expr: &'a Expr,
) -> Option<(&'a Option<QSelf>, &'a Path)> {
) -> Option<(&'a Option<AstP<QSelf>>, &'a Path)> {
if let ExprKind::Path(qself, path) = &expr.kind {
// Does the path resolve to something disallowed in a tuple struct/variant pattern?
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
@ -1097,7 +1097,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn extract_unit_struct_path<'a>(
&mut self,
expr: &'a Expr,
) -> Option<(&'a Option<QSelf>, &'a Path)> {
) -> Option<(&'a Option<AstP<QSelf>>, &'a Path)> {
if let ExprKind::Path(qself, path) = &expr.kind {
// Does the path resolve to something disallowed in a unit struct/variant pattern?
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {

View file

@ -1207,7 +1207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_path_ty(
&mut self,
t: &Ty,
qself: &Option<QSelf>,
qself: &Option<ptr::P<QSelf>>,
path: &Path,
param_mode: ParamMode,
itctx: &ImplTraitContext,

View file

@ -19,7 +19,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pub(crate) fn lower_qpath(
&mut self,
id: NodeId,
qself: &Option<QSelf>,
qself: &Option<ptr::P<QSelf>>,
p: &Path,
param_mode: ParamMode,
itctx: &ImplTraitContext,

View file

@ -121,7 +121,7 @@ impl<'a> State<'a> {
fn print_expr_struct(
&mut self,
qself: &Option<ast::QSelf>,
qself: &Option<P<ast::QSelf>>,
path: &ast::Path,
fields: &[ast::ExprField],
rest: &ast::StructRest,
@ -307,8 +307,13 @@ impl<'a> State<'a> {
ast::ExprKind::Call(ref func, ref args) => {
self.print_expr_call(func, &args);
}
ast::ExprKind::MethodCall(ref segment, ref receiver, ref args, _) => {
self.print_expr_method_call(segment, &receiver, &args);
ast::ExprKind::MethodCall(box ast::MethodCall {
ref seg,
ref receiver,
ref args,
..
}) => {
self.print_expr_method_call(seg, &receiver, &args);
}
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
self.print_expr_binary(op, lhs, rhs);
@ -396,21 +401,21 @@ impl<'a> State<'a> {
let empty = attrs.is_empty() && arms.is_empty();
self.bclose(expr.span, empty);
}
ast::ExprKind::Closure(
ast::ExprKind::Closure(box ast::Closure {
ref binder,
capture_clause,
asyncness,
movability,
ref decl,
ref fn_decl,
ref body,
_,
) => {
fn_decl_span: _,
}) => {
self.print_closure_binder(binder);
self.print_movability(movability);
self.print_asyncness(asyncness);
self.print_capture_clause(capture_clause);
self.print_fn_params_and_ret(decl, true);
self.print_fn_params_and_ret(fn_decl, true);
self.space();
self.print_expr(body);
self.end(); // need to close a box

View file

@ -3,8 +3,8 @@ use rustc_ast::{
ptr::P,
token,
tokenstream::{DelimSpan, TokenStream, TokenTree},
BinOpKind, BorrowKind, Expr, ExprKind, ItemKind, MacArgs, MacCall, MacDelimiter, Mutability,
Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeKind, DUMMY_NODE_ID,
BinOpKind, BorrowKind, Expr, ExprKind, ItemKind, MacArgs, MacCall, MacDelimiter, MethodCall,
Mutability, Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeKind, DUMMY_NODE_ID,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
@ -242,9 +242,9 @@ impl<'cx, 'a> Context<'cx, 'a> {
self.manage_cond_expr(prefix);
self.manage_cond_expr(suffix);
}
ExprKind::MethodCall(_, _,ref mut local_exprs, _) => {
for local_expr in local_exprs.iter_mut() {
self.manage_cond_expr(local_expr);
ExprKind::MethodCall(ref mut call) => {
for arg in call.args.iter_mut() {
self.manage_cond_expr(arg);
}
}
ExprKind::Path(_, Path { ref segments, .. }) if let &[ref path_segment] = &segments[..] => {
@ -296,7 +296,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
| ExprKind::Block(_, _)
| ExprKind::Box(_)
| ExprKind::Break(_, _)
| ExprKind::Closure(_, _, _, _, _, _, _)
| ExprKind::Closure(_)
| ExprKind::ConstBlock(_)
| ExprKind::Continue(_)
| ExprKind::Err
@ -442,12 +442,12 @@ fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
fn expr_method_call(
cx: &ExtCtxt<'_>,
path: PathSegment,
seg: PathSegment,
receiver: P<Expr>,
args: Vec<P<Expr>>,
span: Span,
) -> P<Expr> {
cx.expr(span, ExprKind::MethodCall(path, receiver, args, span))
cx.expr(span, ExprKind::MethodCall(Box::new(MethodCall { seg, receiver, args, span })))
}
fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {

View file

@ -532,15 +532,15 @@ impl<'a> ExtCtxt<'a> {
// here, but that's not entirely clear.
self.expr(
span,
ast::ExprKind::Closure(
ast::ClosureBinder::NotPresent,
ast::CaptureBy::Ref,
ast::Async::No,
ast::Movability::Movable,
ast::ExprKind::Closure(Box::new(ast::Closure {
binder: ast::ClosureBinder::NotPresent,
capture_clause: ast::CaptureBy::Ref,
asyncness: ast::Async::No,
movability: ast::Movability::Movable,
fn_decl,
body,
span,
),
fn_decl_span: span,
})),
)
}

View file

@ -212,7 +212,10 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
// Explicitly check for lints associated with 'closure_id', since
// it does not have a corresponding AST node
match e.kind {
ast::ExprKind::Closure(_, _, ast::Async::Yes { closure_id, .. }, ..)
ast::ExprKind::Closure(box ast::Closure {
asyncness: ast::Async::Yes { closure_id, .. },
..
})
| ast::ExprKind::Async(_, closure_id, ..) => self.check_id(closure_id),
_ => {}
}

View file

@ -653,7 +653,7 @@ trait UnusedDelimLint {
ref call_or_other => {
let (args_to_check, ctx) = match *call_or_other {
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
MethodCall(_, _, ref args, _) => (&args[..], UnusedDelimsCtx::MethodArg),
MethodCall(ref call) => (&call.args[..], UnusedDelimsCtx::MethodArg),
// actual catch-all arm
_ => {
return;

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((

View file

@ -262,11 +262,11 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
fn visit_expr(&mut self, expr: &'a Expr) {
let parent_def = match expr.kind {
ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id),
ExprKind::Closure(_, _, asyncness, ..) => {
ExprKind::Closure(ref closure) => {
// Async closures desugar to closures inside of closures, so
// we must create two defs.
let closure_def = self.create_def(expr.id, DefPathData::ClosureExpr, expr.span);
match asyncness {
match closure.asyncness {
Async::Yes { closure_id, .. } => {
self.create_def(closure_id, DefPathData::ClosureExpr, expr.span)
}

View file

@ -648,7 +648,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
}
TyKind::Path(ref qself, ref path) => {
self.diagnostic_metadata.current_type_path = Some(ty);
self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
self.smart_resolve_path(ty.id, &qself, path, PathSource::Type);
// Check whether we should interpret this as a bare trait object.
if qself.is_none()
@ -749,7 +749,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
this.visit_generic_params(&tref.bound_generic_params, false);
this.smart_resolve_path(
tref.trait_ref.ref_id,
None,
&None,
&tref.trait_ref.path,
PathSource::Trait(AliasPossibility::Maybe),
);
@ -978,7 +978,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|this| {
this.smart_resolve_path(
ty.id,
qself.as_ref(),
qself,
path,
PathSource::Expr(None),
);
@ -1138,12 +1138,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
self.with_rib(ValueNS, InlineAsmSymRibKind, |this| {
this.with_rib(TypeNS, InlineAsmSymRibKind, |this| {
this.with_label_rib(InlineAsmSymRibKind, |this| {
this.smart_resolve_path(
sym.id,
sym.qself.as_ref(),
&sym.path,
PathSource::Expr(None),
);
this.smart_resolve_path(sym.id, &sym.qself, &sym.path, PathSource::Expr(None));
visit::walk_inline_asm_sym(this, sym);
});
})
@ -2571,7 +2566,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.diagnostic_metadata.currently_processing_impl_trait =
Some((trait_ref.clone(), self_type.clone()));
let res = self.smart_resolve_path_fragment(
None,
&None,
&path,
PathSource::Trait(AliasPossibility::No),
Finalize::new(trait_ref.ref_id, trait_ref.path.span),
@ -3094,7 +3089,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
PatKind::TupleStruct(ref qself, ref path, ref sub_patterns) => {
self.smart_resolve_path(
pat.id,
qself.as_ref(),
qself,
path,
PathSource::TupleStruct(
pat.span,
@ -3103,10 +3098,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
);
}
PatKind::Path(ref qself, ref path) => {
self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat);
self.smart_resolve_path(pat.id, qself, path, PathSource::Pat);
}
PatKind::Struct(ref qself, ref path, ..) => {
self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Struct);
self.smart_resolve_path(pat.id, qself, path, PathSource::Struct);
}
PatKind::Or(ref ps) => {
// Add a new set of bindings to the stack. `Or` here records that when a
@ -3299,7 +3294,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
fn smart_resolve_path(
&mut self,
id: NodeId,
qself: Option<&QSelf>,
qself: &Option<P<QSelf>>,
path: &Path,
source: PathSource<'ast>,
) {
@ -3313,7 +3308,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
fn smart_resolve_path_fragment(
&mut self,
qself: Option<&QSelf>,
qself: &Option<P<QSelf>>,
path: &[Segment],
source: PathSource<'ast>,
finalize: Finalize,
@ -3534,7 +3529,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// Resolve in alternative namespaces if resolution in the primary namespace fails.
fn resolve_qpath_anywhere(
&mut self,
qself: Option<&QSelf>,
qself: &Option<P<QSelf>>,
path: &[Segment],
primary_ns: Namespace,
span: Span,
@ -3578,7 +3573,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
/// Handles paths that may refer to associated items.
fn resolve_qpath(
&mut self,
qself: Option<&QSelf>,
qself: &Option<P<QSelf>>,
path: &[Segment],
ns: Namespace,
finalize: Finalize,
@ -3608,7 +3603,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// but with `qself` set to `None`.
let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
let partial_res = self.smart_resolve_path_fragment(
None,
&None,
&path[..=qself.position],
PathSource::TraitItem(ns),
Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span),
@ -3791,12 +3786,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// Next, resolve the node.
match expr.kind {
ExprKind::Path(ref qself, ref path) => {
self.smart_resolve_path(expr.id, qself.as_ref(), path, PathSource::Expr(parent));
self.smart_resolve_path(expr.id, qself, path, PathSource::Expr(parent));
visit::walk_expr(self, expr);
}
ExprKind::Struct(ref se) => {
self.smart_resolve_path(expr.id, se.qself.as_ref(), &se.path, PathSource::Struct);
self.smart_resolve_path(expr.id, &se.qself, &se.path, PathSource::Struct);
visit::walk_expr(self, expr);
}
@ -3866,12 +3861,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ExprKind::Field(ref subexpression, _) => {
self.resolve_expr(subexpression, Some(expr));
}
ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _) => {
ExprKind::MethodCall(box MethodCall { ref seg, ref receiver, ref args, .. }) => {
self.resolve_expr(receiver, Some(expr));
for argument in arguments {
self.resolve_expr(argument, None);
for arg in args {
self.resolve_expr(arg, None);
}
self.visit_path_segment(segment);
self.visit_path_segment(seg);
}
ExprKind::Call(ref callee, ref arguments) => {
@ -3913,7 +3908,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to
// resolve the arguments within the proper scopes so that usages of them inside the
// closure are detected as upvars rather than normal closure arg usages.
ExprKind::Closure(_, _, Async::Yes { .. }, _, ref fn_decl, ref body, _span) => {
ExprKind::Closure(box ast::Closure {
asyncness: Async::Yes { .. },
ref fn_decl,
ref body,
..
}) => {
self.with_rib(ValueNS, NormalRibKind, |this| {
this.with_label_rib(ClosureOrAsyncRibKind, |this| {
// Resolve arguments:
@ -3933,7 +3933,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
});
}
// For closures, ClosureOrAsyncRibKind is added in visit_fn
ExprKind::Closure(ClosureBinder::For { ref generic_params, span }, ..) => {
ExprKind::Closure(box ast::Closure {
binder: ClosureBinder::For { ref generic_params, span },
..
}) => {
self.with_generic_param_rib(
&generic_params,
NormalRibKind,
@ -3990,9 +3993,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let traits = self.traits_in_scope(ident, ValueNS);
self.r.trait_map.insert(expr.id, traits);
}
ExprKind::MethodCall(ref segment, ..) => {
ExprKind::MethodCall(ref call) => {
debug!("(recording candidate traits for expr) recording traits for {}", expr.id);
let traits = self.traits_in_scope(segment.ident, ValueNS);
let traits = self.traits_in_scope(call.seg.ident, ValueNS);
self.r.trait_map.insert(expr.id, traits);
}
_ => {

View file

@ -8,7 +8,7 @@ use crate::{PathResult, PathSource, Segment};
use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt};
use rustc_ast::{
self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind,
NodeId, Path, Ty, TyKind, DUMMY_NODE_ID,
MethodCall, NodeId, Path, Ty, TyKind, DUMMY_NODE_ID,
};
use rustc_ast_pretty::pprust::path_segment_to_string;
use rustc_data_structures::fx::FxHashSet;
@ -1022,11 +1022,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
};
// Confirm that the target is an associated type.
let (ty, position, path) = if let ast::TyKind::Path(
Some(ast::QSelf { ty, position, .. }),
path,
) = &bounded_ty.kind
{
let (ty, position, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
// use this to verify that ident is a type param.
let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
return false;
@ -1037,7 +1033,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
) {
return false;
}
(ty, position, path)
(&qself.ty, qself.position, path)
} else {
return false;
};
@ -1073,12 +1069,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.source_map()
.span_to_snippet(ty.span) // Account for `<&'a T as Foo>::Bar`.
.unwrap_or_else(|_| constrain_ident.to_string()),
path.segments[..*position]
path.segments[..position]
.iter()
.map(|segment| path_segment_to_string(segment))
.collect::<Vec<_>>()
.join("::"),
path.segments[*position..]
path.segments[position..]
.iter()
.map(|segment| path_segment_to_string(segment))
.collect::<Vec<_>>()
@ -1170,7 +1166,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let (lhs_span, rhs_span) = match &expr.kind {
ExprKind::Field(base, ident) => (base.span, ident.span),
ExprKind::MethodCall(_, receiver, _, span) => (receiver.span, *span),
ExprKind::MethodCall(box MethodCall { receiver, span, .. }) => {
(receiver.span, *span)
}
_ => return false,
};