about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-11-18 16:56:12 +0000
committerbors <bors@rust-lang.org>2022-11-18 16:56:12 +0000
commit70fe5f08fffd16dc20506f7d140e47b074f77964 (patch)
treeecd74afdbcaec5b26090a88115a860b202986dc6
parentfd3bfb35511cbcff59ce1454d3db627b576d7e92 (diff)
parent67d5cc0462f33773f042dc3c5ec9bd710095b1b4 (diff)
downloadrust-70fe5f08fffd16dc20506f7d140e47b074f77964.tar.gz
rust-70fe5f08fffd16dc20506f7d140e47b074f77964.zip
Auto merge of #101562 - nnethercote:shrink-ast-Expr-harder, r=petrochenkov
Shrink `ast::Expr` harder

r? `@ghost`
-rw-r--r--Cargo.lock3
-rw-r--r--compiler/rustc_ast/src/ast.rs81
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs7
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs32
-rw-r--r--compiler/rustc_ast/src/util/classify.rs4
-rw-r--r--compiler/rustc_ast/src/util/parser.rs2
-rw-r--r--compiler/rustc_ast/src/visit.rs18
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs16
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs21
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs16
-rw-r--r--compiler/rustc_expand/Cargo.toml15
-rw-r--r--compiler/rustc_expand/src/build.rs19
-rw-r--r--compiler/rustc_expand/src/placeholders.rs8
-rw-r--r--compiler/rustc_lint/src/early.rs5
-rw-r--r--compiler/rustc_lint/src/unused.rs2
-rw-r--r--compiler/rustc_parse/Cargo.toml7
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs29
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs42
-rw-r--r--compiler/rustc_parse/src/parser/item.rs7
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs8
-rw-r--r--compiler/rustc_parse/src/parser/path.rs13
-rw-r--r--compiler/rustc_resolve/Cargo.toml7
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs4
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs3
-rw-r--r--compiler/rustc_resolve/src/late.rs59
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs24
-rw-r--r--src/test/ui-fulldeps/pprust-expr-roundtrip.rs34
-rw-r--r--src/test/ui/stats/hir-stats.stderr204
-rw-r--r--src/tools/clippy/clippy_lints/src/double_parens.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/option_env_unwrap.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/precedence.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_closure_call.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_rounding.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs32
-rw-r--r--src/tools/rustfmt/src/attr.rs6
-rw-r--r--src/tools/rustfmt/src/chains.rs12
-rw-r--r--src/tools/rustfmt/src/closures.rs30
-rw-r--r--src/tools/rustfmt/src/expr.rs26
-rw-r--r--src/tools/rustfmt/src/patterns.rs9
-rw-r--r--src/tools/rustfmt/src/types.rs8
-rw-r--r--src/tools/rustfmt/src/utils.rs2
46 files changed, 486 insertions, 383 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c867bb4ceaa..e1359b9e9e4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3476,6 +3476,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "smallvec",
+ "thin-vec",
  "tracing",
 ]
 
@@ -3916,6 +3917,7 @@ dependencies = [
  "rustc_macros",
  "rustc_session",
  "rustc_span",
+ "thin-vec",
  "tracing",
  "unicode-normalization",
  "unicode-width",
@@ -4051,6 +4053,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "smallvec",
+ "thin-vec",
  "tracing",
 ]
 
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 5d9d0a5feca..e6b72bd58c5 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -36,7 +36,7 @@ use rustc_span::{Span, DUMMY_SP};
 use std::convert::TryFrom;
 use std::fmt;
 use std::mem;
-use thin_vec::ThinVec;
+use thin_vec::{thin_vec, ThinVec};
 
 /// A "Label" is an identifier of some point in sources,
 /// e.g. in the following code:
@@ -90,7 +90,7 @@ pub struct Path {
     pub span: Span,
     /// The segments in the path: the things separated by `::`.
     /// Global paths begin with `kw::PathRoot`.
-    pub segments: Vec<PathSegment>,
+    pub segments: ThinVec<PathSegment>,
     pub tokens: Option<LazyAttrTokenStream>,
 }
 
@@ -114,7 +114,7 @@ impl Path {
     // Convert a span and an identifier to the corresponding
     // one-segment path.
     pub fn from_ident(ident: Ident) -> Path {
-        Path { segments: vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None }
+        Path { segments: thin_vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None }
     }
 
     pub fn is_global(&self) -> bool {
@@ -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,28 +3046,28 @@ 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, 72);
+    static_assert_size!(ExprKind, 40);
     static_assert_size!(Fn, 184);
     static_assert_size!(ForeignItem, 96);
     static_assert_size!(ForeignItemKind, 24);
     static_assert_size!(GenericArg, 24);
-    static_assert_size!(GenericBound, 88);
+    static_assert_size!(GenericBound, 72);
     static_assert_size!(Generics, 72);
-    static_assert_size!(Impl, 200);
+    static_assert_size!(Impl, 184);
     static_assert_size!(Item, 184);
     static_assert_size!(ItemKind, 112);
     static_assert_size!(Lit, 48);
     static_assert_size!(LitKind, 24);
     static_assert_size!(Local, 72);
     static_assert_size!(Param, 40);
-    static_assert_size!(Pat, 120);
-    static_assert_size!(Path, 40);
+    static_assert_size!(Pat, 88);
+    static_assert_size!(Path, 24);
     static_assert_size!(PathSegment, 24);
-    static_assert_size!(PatKind, 96);
+    static_assert_size!(PatKind, 64);
     static_assert_size!(Stmt, 32);
     static_assert_size!(StmtKind, 16);
-    static_assert_size!(Ty, 96);
-    static_assert_size!(TyKind, 72);
+    static_assert_size!(Ty, 64);
+    static_assert_size!(TyKind, 40);
     // tidy-alphabetical-end
 }
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 07f982b7e86..09b08d5059c 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -10,19 +10,18 @@ use crate::token::{self, CommentKind, Delimiter, Token};
 use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
 use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
 use crate::util::comments;
-
 use rustc_data_structures::sync::WorkerLocal;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_span::source_map::BytePos;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
-
 use std::cell::Cell;
 use std::iter;
 #[cfg(debug_assertions)]
 use std::ops::BitXor;
 #[cfg(debug_assertions)]
 use std::sync::atomic::{AtomicU32, Ordering};
+use thin_vec::thin_vec;
 
 pub struct MarkedAttrs(GrowableBitSet<AttrId>);
 
@@ -471,12 +470,12 @@ impl MetaItem {
                         tokens.peek()
                     {
                         tokens.next();
-                        vec![PathSegment::from_ident(Ident::new(name, span))]
+                        thin_vec![PathSegment::from_ident(Ident::new(name, span))]
                     } else {
                         break 'arm Path::from_ident(Ident::new(name, span));
                     }
                 } else {
-                    vec![PathSegment::path_root(span)]
+                    thin_vec![PathSegment::path_root(span)]
                 };
                 loop {
                     if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) =
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 3ab8267263d..ece4cb5556b 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -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);
diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs
index 6ea3db6d303..fbb4cf43a95 100644
--- a/compiler/rustc_ast/src/util/classify.rs
+++ b/compiler/rustc_ast/src/util/classify.rs
@@ -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,
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index b40ad6f700e..30c55dffb18 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -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)
         }
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index da0545ce80c..ad5a2116c42 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -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);
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 01716859a9d..eaa5a38388a 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -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,
                         )
@@ -1105,7 +1105,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) {
@@ -1125,7 +1125,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) {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 77c5ed6036e..05022c1a14c 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -19,8 +19,8 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{Span, Symbol};
 use rustc_target::spec::abi;
 use smallvec::{smallvec, SmallVec};
-
 use std::iter;
+use thin_vec::ThinVec;
 
 pub(super) struct ItemLowerer<'a, 'hir> {
     pub(super) tcx: TyCtxt<'hir>,
@@ -242,7 +242,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(orig_name),
             ItemKind::Use(ref use_tree) => {
                 // Start with an empty prefix.
-                let prefix = Path { segments: vec![], span: use_tree.span, tokens: None };
+                let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None };
 
                 self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
             }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index ecc2578dd2a..e1703b0b02b 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1208,7 +1208,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,
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index c6955741fd4..83d459d899b 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -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,
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 86f1d6bfecd..1da40d2302e 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -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
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index f72cd14bea0..4b57bdfbc8f 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -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> {
diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml
index 4ee7b6c42bb..192f54171ce 100644
--- a/compiler/rustc_expand/Cargo.toml
+++ b/compiler/rustc_expand/Cargo.toml
@@ -8,20 +8,21 @@ build = false
 doctest = false
 
 [dependencies]
-rustc_serialize = { path = "../rustc_serialize" }
-tracing = "0.1"
-rustc_span = { path = "../rustc_span" }
-rustc_ast_pretty = { path = "../rustc_ast_pretty" }
+crossbeam-channel = "0.5.0"
 rustc_ast_passes = { path = "../rustc_ast_passes" }
+rustc_ast = { path = "../rustc_ast" }
+rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
+rustc_lexer = { path = "../rustc_lexer" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_macros = { path = "../rustc_macros" }
-rustc_lexer = { path = "../rustc_lexer" }
 rustc_parse = { path = "../rustc_parse" }
+rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-rustc_ast = { path = "../rustc_ast" }
-crossbeam-channel = "0.5.0"
+thin-vec = "0.2.8"
+tracing = "0.1"
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 8aa72e142f8..e17cba1478a 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -1,13 +1,12 @@
 use crate::base::ExtCtxt;
-
 use rustc_ast::attr;
 use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp};
 use rustc_data_structures::sync::Lrc;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-
 use rustc_span::Span;
+use thin_vec::ThinVec;
 
 impl<'a> ExtCtxt<'a> {
     pub fn path(&self, span: Span, strs: Vec<Ident>) -> ast::Path {
@@ -28,7 +27,7 @@ impl<'a> ExtCtxt<'a> {
     ) -> ast::Path {
         assert!(!idents.is_empty());
         let add_root = global && !idents[0].is_path_segment_keyword();
-        let mut segments = Vec::with_capacity(idents.len() + add_root as usize);
+        let mut segments = ThinVec::with_capacity(idents.len() + add_root as usize);
         if add_root {
             segments.push(ast::PathSegment::path_root(span));
         }
@@ -532,15 +531,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,
+            })),
         )
     }
 
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index faaf3b3fea5..97b1871028e 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -1,14 +1,12 @@
 use crate::expand::{AstFragment, AstFragmentKind};
-
 use rustc_ast as ast;
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_span::source_map::DUMMY_SP;
 use rustc_span::symbol::Ident;
-
 use smallvec::{smallvec, SmallVec};
-
-use rustc_data_structures::fx::FxHashMap;
+use thin_vec::ThinVec;
 
 pub fn placeholder(
     kind: AstFragmentKind,
@@ -17,7 +15,7 @@ pub fn placeholder(
 ) -> AstFragment {
     fn mac_placeholder() -> P<ast::MacCall> {
         P(ast::MacCall {
-            path: ast::Path { span: DUMMY_SP, segments: Vec::new(), tokens: None },
+            path: ast::Path { span: DUMMY_SP, segments: ThinVec::new(), tokens: None },
             args: P(ast::MacArgs::Empty),
             prior_type_ascription: None,
         })
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index aee870dd29d..fc760ee3b8f 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -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),
             _ => {}
         }
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 9ae34013ecb..50f9cb0b56f 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -651,7 +651,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;
diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml
index a5c94e16403..dbcfb390333 100644
--- a/compiler/rustc_parse/Cargo.toml
+++ b/compiler/rustc_parse/Cargo.toml
@@ -7,15 +7,16 @@ edition = "2021"
 
 [dependencies]
 bitflags = "1.0"
-tracing = "0.1"
+rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_macros = { path = "../rustc_macros" }
-rustc_errors = { path = "../rustc_errors" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-rustc_ast = { path = "../rustc_ast" }
+thin-vec = "0.2.8"
+tracing = "0.1"
 unicode-normalization = "0.1.11"
 unicode-width = "0.1.4"
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 0bbe073fe2a..350b270cc3d 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -18,6 +18,7 @@ use crate::errors::{
 };
 
 use crate::lexer::UnmatchedBrace;
+use crate::parser;
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind};
@@ -37,11 +38,10 @@ use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{Span, SpanSnippetError, DUMMY_SP};
-use std::ops::{Deref, DerefMut};
-
 use std::mem::take;
-
-use crate::parser;
+use std::ops::{Deref, DerefMut};
+use thin_vec::{thin_vec, ThinVec};
+use tracing::{debug, trace};
 
 /// Creates a placeholder argument.
 pub(super) fn dummy_arg(ident: Ident) -> Param {
@@ -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),
@@ -638,8 +638,11 @@ impl<'a> Parser<'a> {
             //     field: value,
             // }
             let mut snapshot = self.create_snapshot_for_diagnostic();
-            let path =
-                Path { segments: vec![], span: self.prev_token.span.shrink_to_lo(), tokens: None };
+            let path = Path {
+                segments: ThinVec::new(),
+                span: self.prev_token.span.shrink_to_lo(),
+                tokens: None,
+            };
             let struct_expr = snapshot.parse_struct_expr(None, path, false);
             let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No);
             return Some(match (struct_expr, block_tail) {
@@ -1426,7 +1429,7 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, P<T>> {
         self.expect(&token::ModSep)?;
 
-        let mut path = ast::Path { segments: Vec::new(), span: DUMMY_SP, tokens: None };
+        let mut path = ast::Path { segments: ThinVec::new(), span: DUMMY_SP, tokens: None };
         self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?;
         path.span = ty_span.to(self.prev_token.span);
 
@@ -1437,7 +1440,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 {
@@ -2434,7 +2437,7 @@ impl<'a> Parser<'a> {
                                             None,
                                             Path {
                                                 span: new_span,
-                                                segments: vec![
+                                                segments: thin_vec![
                                                     PathSegment::from_ident(*old_ident),
                                                     PathSegment::from_ident(*ident),
                                                 ],
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index c9629ea49e0..413c58f1bff 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -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>> {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 494f0cf56a8..e5f58ca3894 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -3,7 +3,6 @@ use crate::errors::{DocCommentDoesNotDocumentAnything, UseEmptyBlockNotSemi};
 use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
-
 use rustc_ast::ast::*;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, TokenKind};
@@ -22,9 +21,10 @@ use rustc_span::lev_distance::lev_distance;
 use rustc_span::source_map::{self, Span};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::DUMMY_SP;
-
 use std::convert::TryFrom;
 use std::mem;
+use thin_vec::ThinVec;
+use tracing::debug;
 
 impl<'a> Parser<'a> {
     /// Parses a source module as a crate. This is the main entry point for the parser.
@@ -972,7 +972,8 @@ impl<'a> Parser<'a> {
     fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
         let lo = self.token.span;
 
-        let mut prefix = ast::Path { segments: Vec::new(), span: lo.shrink_to_lo(), tokens: None };
+        let mut prefix =
+            ast::Path { segments: ThinVec::new(), span: lo.shrink_to_lo(), tokens: None };
         let kind = if self.check(&token::OpenDelim(Delimiter::Brace))
             || self.check(&token::BinOp(token::Star))
             || self.is_import_coupler()
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index b3af37a5f70..0e202645a39 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -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,
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index d46565dea89..2d432e3f5bd 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -11,8 +11,9 @@ use rustc_ast::{
 use rustc_errors::{pluralize, Applicability, PResult};
 use rustc_span::source_map::{BytePos, Span};
 use rustc_span::symbol::{kw, sym, Ident};
-
 use std::mem;
+use thin_vec::ThinVec;
+use tracing::debug;
 
 /// Specifies how to parse a path.
 #[derive(Copy, Clone, PartialEq)]
@@ -48,7 +49,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()?;
 
@@ -63,7 +64,7 @@ impl<'a> Parser<'a> {
             path_span = path_lo.to(self.prev_token.span);
         } else {
             path_span = self.token.span.to(self.token.span);
-            path = ast::Path { segments: Vec::new(), span: path_span, tokens: None };
+            path = ast::Path { segments: ThinVec::new(), span: path_span, tokens: None };
         }
 
         // See doc comment for `unmatched_angle_bracket_count`.
@@ -77,7 +78,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((
@@ -179,7 +180,7 @@ impl<'a> Parser<'a> {
         }
 
         let lo = self.token.span;
-        let mut segments = Vec::new();
+        let mut segments = ThinVec::new();
         let mod_sep_ctxt = self.token.span.ctxt();
         if self.eat(&token::ModSep) {
             segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
@@ -191,7 +192,7 @@ impl<'a> Parser<'a> {
 
     pub(super) fn parse_path_segments(
         &mut self,
-        segments: &mut Vec<PathSegment>,
+        segments: &mut ThinVec<PathSegment>,
         style: PathStyle,
         ty_generics: Option<&Generics>,
     ) -> PResult<'a, ()> {
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index d66db1d7a0d..b97f4560c37 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -7,10 +7,8 @@ edition = "2021"
 
 [dependencies]
 bitflags = "1.2.1"
-tracing = "0.1"
-rustc_ast = { path = "../rustc_ast" }
 rustc_arena = { path = "../rustc_arena" }
-rustc_middle = { path = "../rustc_middle" }
+rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
@@ -20,7 +18,10 @@ rustc_feature = { path = "../rustc_feature" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_metadata = { path = "../rustc_metadata" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_query_system = { path = "../rustc_query_system" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+thin-vec = "0.2.8"
+tracing = "0.1"
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index d36e0f61d91..b1cee06849d 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -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)
                     }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index a12918b2979..5482e1ccefa 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -25,6 +25,7 @@ use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Span, SyntaxContext};
+use thin_vec::ThinVec;
 
 use crate::imports::{Import, ImportKind, ImportResolver};
 use crate::late::{PatternSource, Rib};
@@ -1295,7 +1296,7 @@ impl<'a> Resolver<'a> {
     {
         let mut candidates = Vec::new();
         let mut seen_modules = FxHashSet::default();
-        let mut worklist = vec![(start_module, Vec::<ast::PathSegment>::new(), true)];
+        let mut worklist = vec![(start_module, ThinVec::<ast::PathSegment>::new(), true)];
         let mut worklist_via_import = vec![];
 
         while let Some((in_module, path_segments, accessible)) = match worklist.pop() {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index ede67813883..1b0879cf79e 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -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);
             }
             _ => {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 95eff92ef5e..e0c927dd1e7 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -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;
@@ -33,6 +33,8 @@ use rustc_span::{BytePos, Span};
 use std::iter;
 use std::ops::Deref;
 
+use thin_vec::ThinVec;
+
 type Res = def::Res<ast::NodeId>;
 
 /// A field or associated item from self type suggested in case of resolution failure.
@@ -78,7 +80,7 @@ fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, Str
     let path_len = suggestion.path.segments.len();
     let enum_path = ast::Path {
         span: suggestion.path.span,
-        segments: suggestion.path.segments[0..path_len - 1].to_vec(),
+        segments: suggestion.path.segments[0..path_len - 1].iter().cloned().collect(),
         tokens: None,
     };
     let enum_path_string = path_names_to_string(&enum_path);
@@ -1022,11 +1024,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 +1035,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
             ) {
                 return false;
             }
-            (ty, position, path)
+            (&qself.ty, qself.position, path)
         } else {
             return false;
         };
@@ -1073,12 +1071,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 +1168,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,
             };
 
@@ -1833,7 +1833,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
     fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> {
         let mut result = None;
         let mut seen_modules = FxHashSet::default();
-        let mut worklist = vec![(self.r.graph_root, Vec::new())];
+        let mut worklist = vec![(self.r.graph_root, ThinVec::new())];
 
         while let Some((in_module, path_segments)) = worklist.pop() {
             // abort if the module is already found
diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
index 117b798710c..d6dc179da7f 100644
--- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -25,6 +25,7 @@ extern crate rustc_data_structures;
 extern crate rustc_parse;
 extern crate rustc_session;
 extern crate rustc_span;
+extern crate thin_vec;
 
 use rustc_ast::mut_visit::{self, visit_clobber, MutVisitor};
 use rustc_ast::ptr::P;
@@ -35,6 +36,7 @@ use rustc_session::parse::ParseSess;
 use rustc_span::source_map::FilePathMapping;
 use rustc_span::source_map::{FileName, Spanned, DUMMY_SP};
 use rustc_span::symbol::Ident;
+use thin_vec::thin_vec;
 
 fn parse_expr(ps: &ParseSess, src: &str) -> Option<P<Expr>> {
     let src_as_string = src.to_string();
@@ -51,7 +53,7 @@ fn expr(kind: ExprKind) -> P<Expr> {
 
 fn make_x() -> P<Expr> {
     let seg = PathSegment::from_ident(Ident::from_str("x"));
-    let path = Path { segments: vec![seg], span: DUMMY_SP, tokens: None };
+    let path = Path { segments: thin_vec![seg], span: DUMMY_SP, tokens: None };
     expr(ExprKind::Path(None, path))
 }
 
@@ -73,11 +75,15 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
             2 => {
                 let seg = PathSegment::from_ident(Ident::from_str("x"));
                 iter_exprs(depth - 1, &mut |e| {
-                    g(ExprKind::MethodCall(seg.clone(), e, vec![make_x()], DUMMY_SP))
-                });
+                    g(ExprKind::MethodCall(Box::new(MethodCall {
+                        seg: seg.clone(), receiver: e, args: vec![make_x()], span: DUMMY_SP
+                    }))
+                )});
                 iter_exprs(depth - 1, &mut |e| {
-                    g(ExprKind::MethodCall(seg.clone(), make_x(), vec![e], DUMMY_SP))
-                });
+                    g(ExprKind::MethodCall(Box::new(MethodCall {
+                        seg: seg.clone(), receiver: make_x(), args: vec![e], span: DUMMY_SP
+                    }))
+                )});
             }
             3..=8 => {
                 let op = Spanned {
@@ -112,15 +118,15 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
             11 => {
                 let decl = P(FnDecl { inputs: vec![], output: FnRetTy::Default(DUMMY_SP) });
                 iter_exprs(depth - 1, &mut |e| {
-                    g(ExprKind::Closure(
-                        ClosureBinder::NotPresent,
-                        CaptureBy::Value,
-                        Async::No,
-                        Movability::Movable,
-                        decl.clone(),
-                        e,
-                        DUMMY_SP,
-                    ))
+                    g(ExprKind::Closure(Box::new(Closure {
+                        binder: ClosureBinder::NotPresent,
+                        capture_clause: CaptureBy::Value,
+                        asyncness: Async::No,
+                        movability: Movability::Movable,
+                        fn_decl: decl.clone(),
+                        body: e,
+                        fn_decl_span: DUMMY_SP,
+                    })))
                 });
             }
             12 => {
diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr
index 9cadd59c3dc..297245f0198 100644
--- a/src/test/ui/stats/hir-stats.stderr
+++ b/src/test/ui/stats/hir-stats.stderr
@@ -2,118 +2,118 @@ ast-stats-1 PRE EXPANSION AST STATS
 ast-stats-1 Name                Accumulated Size         Count     Item Size
 ast-stats-1 ----------------------------------------------------------------
 ast-stats-1 ExprField                 48 ( 0.6%)             1            48
-ast-stats-1 Crate                     56 ( 0.7%)             1            56
-ast-stats-1 Attribute                 64 ( 0.8%)             2            32
+ast-stats-1 Crate                     56 ( 0.8%)             1            56
+ast-stats-1 Attribute                 64 ( 0.9%)             2            32
 ast-stats-1 - Normal                    32 ( 0.4%)             1
 ast-stats-1 - DocComment                32 ( 0.4%)             1
-ast-stats-1 GenericArgs               64 ( 0.8%)             1            64
-ast-stats-1 - AngleBracketed            64 ( 0.8%)             1
-ast-stats-1 Local                     72 ( 0.9%)             1            72
-ast-stats-1 WherePredicate            72 ( 0.9%)             1            72
-ast-stats-1 - BoundPredicate            72 ( 0.9%)             1
-ast-stats-1 Arm                       96 ( 1.1%)             2            48
-ast-stats-1 ForeignItem               96 ( 1.1%)             1            96
-ast-stats-1 - Fn                        96 ( 1.1%)             1
-ast-stats-1 FieldDef                 160 ( 1.9%)             2            80
-ast-stats-1 Stmt                     160 ( 1.9%)             5            32
+ast-stats-1 GenericArgs               64 ( 0.9%)             1            64
+ast-stats-1 - AngleBracketed            64 ( 0.9%)             1
+ast-stats-1 Local                     72 ( 1.0%)             1            72
+ast-stats-1 WherePredicate            72 ( 1.0%)             1            72
+ast-stats-1 - BoundPredicate            72 ( 1.0%)             1
+ast-stats-1 Arm                       96 ( 1.3%)             2            48
+ast-stats-1 ForeignItem               96 ( 1.3%)             1            96
+ast-stats-1 - Fn                        96 ( 1.3%)             1
+ast-stats-1 FieldDef                 160 ( 2.2%)             2            80
+ast-stats-1 Stmt                     160 ( 2.2%)             5            32
 ast-stats-1 - Local                     32 ( 0.4%)             1
 ast-stats-1 - MacCall                   32 ( 0.4%)             1
-ast-stats-1 - Expr                      96 ( 1.1%)             3
-ast-stats-1 Param                    160 ( 1.9%)             4            40
-ast-stats-1 FnDecl                   200 ( 2.4%)             5            40
-ast-stats-1 Variant                  240 ( 2.9%)             2           120
-ast-stats-1 Block                    288 ( 3.4%)             6            48
-ast-stats-1 GenericBound             352 ( 4.2%)             4            88
-ast-stats-1 - Trait                    352 ( 4.2%)             4
-ast-stats-1 AssocItem                416 ( 4.9%)             4           104
-ast-stats-1 - Type                     208 ( 2.5%)             2
-ast-stats-1 - Fn                       208 ( 2.5%)             2
-ast-stats-1 GenericParam             480 ( 5.7%)             5            96
-ast-stats-1 PathSegment              720 ( 8.6%)            30            24
-ast-stats-1 Expr                     832 ( 9.9%)             8           104
-ast-stats-1 - Path                     104 ( 1.2%)             1
-ast-stats-1 - Match                    104 ( 1.2%)             1
-ast-stats-1 - Struct                   104 ( 1.2%)             1
-ast-stats-1 - Lit                      208 ( 2.5%)             2
-ast-stats-1 - Block                    312 ( 3.7%)             3
-ast-stats-1 Pat                      840 (10.0%)             7           120
-ast-stats-1 - Struct                   120 ( 1.4%)             1
-ast-stats-1 - Wild                     120 ( 1.4%)             1
-ast-stats-1 - Ident                    600 ( 7.1%)             5
-ast-stats-1 Ty                     1_344 (16.0%)            14            96
-ast-stats-1 - Rptr                      96 ( 1.1%)             1
-ast-stats-1 - Ptr                       96 ( 1.1%)             1
-ast-stats-1 - ImplicitSelf             192 ( 2.3%)             2
-ast-stats-1 - Path                     960 (11.4%)            10
-ast-stats-1 Item                   1_656 (19.7%)             9           184
-ast-stats-1 - Trait                    184 ( 2.2%)             1
-ast-stats-1 - Enum                     184 ( 2.2%)             1
-ast-stats-1 - ForeignMod               184 ( 2.2%)             1
-ast-stats-1 - Impl                     184 ( 2.2%)             1
-ast-stats-1 - Fn                       368 ( 4.4%)             2
-ast-stats-1 - Use                      552 ( 6.6%)             3
+ast-stats-1 - Expr                      96 ( 1.3%)             3
+ast-stats-1 Param                    160 ( 2.2%)             4            40
+ast-stats-1 FnDecl                   200 ( 2.7%)             5            40
+ast-stats-1 Variant                  240 ( 3.2%)             2           120
+ast-stats-1 GenericBound             288 ( 3.9%)             4            72
+ast-stats-1 - Trait                    288 ( 3.9%)             4
+ast-stats-1 Block                    288 ( 3.9%)             6            48
+ast-stats-1 AssocItem                416 ( 5.6%)             4           104
+ast-stats-1 - Type                     208 ( 2.8%)             2
+ast-stats-1 - Fn                       208 ( 2.8%)             2
+ast-stats-1 GenericParam             480 ( 6.5%)             5            96
+ast-stats-1 Expr                     576 ( 7.8%)             8            72
+ast-stats-1 - Path                      72 ( 1.0%)             1
+ast-stats-1 - Match                     72 ( 1.0%)             1
+ast-stats-1 - Struct                    72 ( 1.0%)             1
+ast-stats-1 - Lit                      144 ( 1.9%)             2
+ast-stats-1 - Block                    216 ( 2.9%)             3
+ast-stats-1 Pat                      616 ( 8.3%)             7            88
+ast-stats-1 - Struct                    88 ( 1.2%)             1
+ast-stats-1 - Wild                      88 ( 1.2%)             1
+ast-stats-1 - Ident                    440 ( 5.9%)             5
+ast-stats-1 PathSegment              720 ( 9.7%)            30            24
+ast-stats-1 Ty                       896 (12.1%)            14            64
+ast-stats-1 - Rptr                      64 ( 0.9%)             1
+ast-stats-1 - Ptr                       64 ( 0.9%)             1
+ast-stats-1 - ImplicitSelf             128 ( 1.7%)             2
+ast-stats-1 - Path                     640 ( 8.6%)            10
+ast-stats-1 Item                   1_656 (22.3%)             9           184
+ast-stats-1 - Trait                    184 ( 2.5%)             1
+ast-stats-1 - Enum                     184 ( 2.5%)             1
+ast-stats-1 - ForeignMod               184 ( 2.5%)             1
+ast-stats-1 - Impl                     184 ( 2.5%)             1
+ast-stats-1 - Fn                       368 ( 5.0%)             2
+ast-stats-1 - Use                      552 ( 7.4%)             3
 ast-stats-1 ----------------------------------------------------------------
-ast-stats-1 Total                  8_416
+ast-stats-1 Total                  7_424
 ast-stats-1
 ast-stats-2 POST EXPANSION AST STATS
 ast-stats-2 Name                Accumulated Size         Count     Item Size
 ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 ExprField                 48 ( 0.5%)             1            48
-ast-stats-2 Crate                     56 ( 0.6%)             1            56
-ast-stats-2 GenericArgs               64 ( 0.7%)             1            64
-ast-stats-2 - AngleBracketed            64 ( 0.7%)             1
-ast-stats-2 Local                     72 ( 0.8%)             1            72
-ast-stats-2 WherePredicate            72 ( 0.8%)             1            72
-ast-stats-2 - BoundPredicate            72 ( 0.8%)             1
-ast-stats-2 Arm                       96 ( 1.0%)             2            48
-ast-stats-2 ForeignItem               96 ( 1.0%)             1            96
-ast-stats-2 - Fn                        96 ( 1.0%)             1
-ast-stats-2 InlineAsm                120 ( 1.3%)             1           120
-ast-stats-2 Attribute                128 ( 1.4%)             4            32
-ast-stats-2 - DocComment                32 ( 0.3%)             1
-ast-stats-2 - Normal                    96 ( 1.0%)             3
-ast-stats-2 FieldDef                 160 ( 1.7%)             2            80
-ast-stats-2 Stmt                     160 ( 1.7%)             5            32
-ast-stats-2 - Local                     32 ( 0.3%)             1
-ast-stats-2 - Semi                      32 ( 0.3%)             1
-ast-stats-2 - Expr                      96 ( 1.0%)             3
-ast-stats-2 Param                    160 ( 1.7%)             4            40
-ast-stats-2 FnDecl                   200 ( 2.2%)             5            40
-ast-stats-2 Variant                  240 ( 2.6%)             2           120
-ast-stats-2 Block                    288 ( 3.1%)             6            48
-ast-stats-2 GenericBound             352 ( 3.8%)             4            88
-ast-stats-2 - Trait                    352 ( 3.8%)             4
-ast-stats-2 AssocItem                416 ( 4.5%)             4           104
-ast-stats-2 - Type                     208 ( 2.3%)             2
-ast-stats-2 - Fn                       208 ( 2.3%)             2
-ast-stats-2 GenericParam             480 ( 5.2%)             5            96
-ast-stats-2 PathSegment              792 ( 8.7%)            33            24
-ast-stats-2 Pat                      840 ( 9.2%)             7           120
-ast-stats-2 - Struct                   120 ( 1.3%)             1
-ast-stats-2 - Wild                     120 ( 1.3%)             1
-ast-stats-2 - Ident                    600 ( 6.6%)             5
-ast-stats-2 Expr                     936 (10.2%)             9           104
-ast-stats-2 - Path                     104 ( 1.1%)             1
-ast-stats-2 - Match                    104 ( 1.1%)             1
-ast-stats-2 - Struct                   104 ( 1.1%)             1
-ast-stats-2 - InlineAsm                104 ( 1.1%)             1
-ast-stats-2 - Lit                      208 ( 2.3%)             2
-ast-stats-2 - Block                    312 ( 3.4%)             3
-ast-stats-2 Ty                     1_344 (14.7%)            14            96
-ast-stats-2 - Rptr                      96 ( 1.0%)             1
-ast-stats-2 - Ptr                       96 ( 1.0%)             1
-ast-stats-2 - ImplicitSelf             192 ( 2.1%)             2
-ast-stats-2 - Path                     960 (10.5%)            10
-ast-stats-2 Item                   2_024 (22.1%)            11           184
-ast-stats-2 - Trait                    184 ( 2.0%)             1
-ast-stats-2 - Enum                     184 ( 2.0%)             1
-ast-stats-2 - ExternCrate              184 ( 2.0%)             1
-ast-stats-2 - ForeignMod               184 ( 2.0%)             1
-ast-stats-2 - Impl                     184 ( 2.0%)             1
-ast-stats-2 - Fn                       368 ( 4.0%)             2
-ast-stats-2 - Use                      736 ( 8.0%)             4
+ast-stats-2 ExprField                 48 ( 0.6%)             1            48
+ast-stats-2 Crate                     56 ( 0.7%)             1            56
+ast-stats-2 GenericArgs               64 ( 0.8%)             1            64
+ast-stats-2 - AngleBracketed            64 ( 0.8%)             1
+ast-stats-2 Local                     72 ( 0.9%)             1            72
+ast-stats-2 WherePredicate            72 ( 0.9%)             1            72
+ast-stats-2 - BoundPredicate            72 ( 0.9%)             1
+ast-stats-2 Arm                       96 ( 1.2%)             2            48
+ast-stats-2 ForeignItem               96 ( 1.2%)             1            96
+ast-stats-2 - Fn                        96 ( 1.2%)             1
+ast-stats-2 InlineAsm                120 ( 1.5%)             1           120
+ast-stats-2 Attribute                128 ( 1.6%)             4            32
+ast-stats-2 - DocComment                32 ( 0.4%)             1
+ast-stats-2 - Normal                    96 ( 1.2%)             3
+ast-stats-2 FieldDef                 160 ( 2.0%)             2            80
+ast-stats-2 Stmt                     160 ( 2.0%)             5            32
+ast-stats-2 - Local                     32 ( 0.4%)             1
+ast-stats-2 - Semi                      32 ( 0.4%)             1
+ast-stats-2 - Expr                      96 ( 1.2%)             3
+ast-stats-2 Param                    160 ( 2.0%)             4            40
+ast-stats-2 FnDecl                   200 ( 2.5%)             5            40
+ast-stats-2 Variant                  240 ( 3.0%)             2           120
+ast-stats-2 GenericBound             288 ( 3.5%)             4            72
+ast-stats-2 - Trait                    288 ( 3.5%)             4
+ast-stats-2 Block                    288 ( 3.5%)             6            48
+ast-stats-2 AssocItem                416 ( 5.1%)             4           104
+ast-stats-2 - Type                     208 ( 2.6%)             2
+ast-stats-2 - Fn                       208 ( 2.6%)             2
+ast-stats-2 GenericParam             480 ( 5.9%)             5            96
+ast-stats-2 Pat                      616 ( 7.6%)             7            88
+ast-stats-2 - Struct                    88 ( 1.1%)             1
+ast-stats-2 - Wild                      88 ( 1.1%)             1
+ast-stats-2 - Ident                    440 ( 5.4%)             5
+ast-stats-2 Expr                     648 ( 8.0%)             9            72
+ast-stats-2 - Path                      72 ( 0.9%)             1
+ast-stats-2 - Match                     72 ( 0.9%)             1
+ast-stats-2 - Struct                    72 ( 0.9%)             1
+ast-stats-2 - InlineAsm                 72 ( 0.9%)             1
+ast-stats-2 - Lit                      144 ( 1.8%)             2
+ast-stats-2 - Block                    216 ( 2.7%)             3
+ast-stats-2 PathSegment              792 ( 9.8%)            33            24
+ast-stats-2 Ty                       896 (11.0%)            14            64
+ast-stats-2 - Rptr                      64 ( 0.8%)             1
+ast-stats-2 - Ptr                       64 ( 0.8%)             1
+ast-stats-2 - ImplicitSelf             128 ( 1.6%)             2
+ast-stats-2 - Path                     640 ( 7.9%)            10
+ast-stats-2 Item                   2_024 (24.9%)            11           184
+ast-stats-2 - Trait                    184 ( 2.3%)             1
+ast-stats-2 - Enum                     184 ( 2.3%)             1
+ast-stats-2 - ExternCrate              184 ( 2.3%)             1
+ast-stats-2 - ForeignMod               184 ( 2.3%)             1
+ast-stats-2 - Impl                     184 ( 2.3%)             1
+ast-stats-2 - Fn                       368 ( 4.5%)             2
+ast-stats-2 - Use                      736 ( 9.1%)             4
 ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 Total                  9_144
+ast-stats-2 Total                  8_120
 ast-stats-2
 hir-stats HIR STATS
 hir-stats Name                Accumulated Size         Count     Item Size
diff --git a/src/tools/clippy/clippy_lints/src/double_parens.rs b/src/tools/clippy/clippy_lints/src/double_parens.rs
index 0f1d701865e..29425b2e554 100644
--- a/src/tools/clippy/clippy_lints/src/double_parens.rs
+++ b/src/tools/clippy/clippy_lints/src/double_parens.rs
@@ -61,10 +61,10 @@ impl EarlyLintPass for DoubleParens {
                     }
                 }
             },
-            ExprKind::MethodCall(_, _, ref params, _) => {
-                if let [ref param] = params[..] {
-                    if let ExprKind::Paren(_) = param.kind {
-                        span_lint(cx, DOUBLE_PARENS, param.span, msg);
+            ExprKind::MethodCall(ref call) => {
+                if let [ref arg] = call.args[..] {
+                    if let ExprKind::Paren(_) = arg.kind {
+                        span_lint(cx, DOUBLE_PARENS, arg.span, msg);
                     }
                 }
             },
diff --git a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
index d9ee031c9f9..377bddeaa5f 100644
--- a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::is_direct_expn_of;
 use if_chain::if_chain;
-use rustc_ast::ast::{Expr, ExprKind};
+use rustc_ast::ast::{Expr, ExprKind, MethodCall};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
@@ -37,8 +37,8 @@ declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]);
 impl EarlyLintPass for OptionEnvUnwrap {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
         if_chain! {
-            if let ExprKind::MethodCall(path_segment, receiver, _, _) = &expr.kind;
-            if matches!(path_segment.ident.name, sym::expect | sym::unwrap);
+            if let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &expr.kind;
+            if matches!(seg.ident.name, sym::expect | sym::unwrap);
             if let ExprKind::Call(caller, _) = &receiver.kind;
             if is_direct_expn_of(caller.span, "option_env").is_some();
             then {
diff --git a/src/tools/clippy/clippy_lints/src/precedence.rs b/src/tools/clippy/clippy_lints/src/precedence.rs
index bee4a33fb4a..057b7e30642 100644
--- a/src/tools/clippy/clippy_lints/src/precedence.rs
+++ b/src/tools/clippy/clippy_lints/src/precedence.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use if_chain::if_chain;
-use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp};
+use rustc_ast::ast::{BinOpKind, Expr, ExprKind, MethodCall, UnOp};
 use rustc_ast::token;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
@@ -110,11 +110,11 @@ impl EarlyLintPass for Precedence {
             let mut arg = operand;
 
             let mut all_odd = true;
-            while let ExprKind::MethodCall(path_segment, receiver, _, _) = &arg.kind {
-                let path_segment_str = path_segment.ident.name.as_str();
+            while let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &arg.kind {
+                let seg_str = seg.ident.name.as_str();
                 all_odd &= ALLOWED_ODD_FUNCTIONS
                     .iter()
-                    .any(|odd_function| **odd_function == *path_segment_str);
+                    .any(|odd_function| **odd_function == *seg_str);
                 arg = receiver;
             }
 
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index 74eea6de4bb..4cbe9597c53 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -69,10 +69,10 @@ impl EarlyLintPass for RedundantClosureCall {
         if_chain! {
             if let ast::ExprKind::Call(ref paren, _) = expr.kind;
             if let ast::ExprKind::Paren(ref closure) = paren.kind;
-            if let ast::ExprKind::Closure(_, _, ref r#async, _, ref decl, ref block, _) = closure.kind;
+            if let ast::ExprKind::Closure(box ast::Closure { ref asyncness, ref fn_decl, ref body, .. }) = closure.kind;
             then {
                 let mut visitor = ReturnVisitor::new();
-                visitor.visit_expr(block);
+                visitor.visit_expr(body);
                 if !visitor.found_return {
                     span_lint_and_then(
                         cx,
@@ -80,13 +80,13 @@ impl EarlyLintPass for RedundantClosureCall {
                         expr.span,
                         "try not to call a closure in the expression where it is declared",
                         |diag| {
-                            if decl.inputs.is_empty() {
+                            if fn_decl.inputs.is_empty() {
                                 let app = Applicability::MachineApplicable;
-                                let mut hint = Sugg::ast(cx, block, "..");
+                                let mut hint = Sugg::ast(cx, body, "..");
 
-                                if r#async.is_async() {
+                                if asyncness.is_async() {
                                     // `async x` is a syntax error, so it becomes `async { x }`
-                                    if !matches!(block.kind, ast::ExprKind::Block(_, _)) {
+                                    if !matches!(body.kind, ast::ExprKind::Block(_, _)) {
                                         hint = hint.blockify();
                                     }
 
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
index eef9bdc7849..78e83880e1a 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
@@ -580,7 +580,7 @@ fn ident_difference_expr_with_base_location(
         | (Await(_), Await(_))
         | (Async(_, _, _), Async(_, _, _))
         | (Block(_, _), Block(_, _))
-        | (Closure(_, _, _, _, _, _, _), Closure(_, _, _, _, _, _, _))
+        | (Closure(_), Closure(_))
         | (Match(_, _), Match(_, _))
         | (Loop(_, _), Loop(_, _))
         | (ForLoop(_, _, _, _), ForLoop(_, _, _, _))
@@ -593,7 +593,7 @@ fn ident_difference_expr_with_base_location(
         | (Unary(_, _), Unary(_, _))
         | (Binary(_, _, _), Binary(_, _, _))
         | (Tup(_), Tup(_))
-        | (MethodCall(_, _, _, _), MethodCall(_, _, _, _))
+        | (MethodCall(_), MethodCall(_))
         | (Call(_, _), Call(_, _))
         | (ConstBlock(_), ConstBlock(_))
         | (Array(_), Array(_))
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index b305dae7608..bb6fb38e969 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -292,7 +292,7 @@ fn transform_with_focus_on_idx(alternatives: &mut Vec<P<Pat>>, focus_idx: usize)
 /// So when we fixate on some `ident_k: pat_k`, we try to find `ident_k` in the other pattern
 /// and check that all `fp_i` where `i ∈ ((0...n) \ k)` between two patterns are equal.
 fn extend_with_struct_pat(
-    qself1: &Option<ast::QSelf>,
+    qself1: &Option<P<ast::QSelf>>,
     path1: &ast::Path,
     fps1: &mut [ast::PatField],
     rest1: bool,
diff --git a/src/tools/clippy/clippy_lints/src/unused_rounding.rs b/src/tools/clippy/clippy_lints/src/unused_rounding.rs
index 3c1998d0237..5ab351bc29c 100644
--- a/src/tools/clippy/clippy_lints/src/unused_rounding.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_rounding.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use rustc_ast::ast::{Expr, ExprKind};
+use rustc_ast::ast::{Expr, ExprKind, MethodCall};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -30,8 +30,8 @@ declare_clippy_lint! {
 declare_lint_pass!(UnusedRounding => [UNUSED_ROUNDING]);
 
 fn is_useless_rounding(expr: &Expr) -> Option<(&str, String)> {
-    if let ExprKind::MethodCall(name_ident, receiver, _, _) = &expr.kind
-        && let method_name = name_ident.ident.name.as_str()
+    if let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &expr.kind
+        && let method_name = seg.ident.name.as_str()
         && (method_name == "ceil" || method_name == "round" || method_name == "floor")
         && let ExprKind::Lit(token_lit) = &receiver.kind
         && token_lit.is_semantic_float() {
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 73d1ba727c8..23aed4b5ba2 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -75,11 +75,11 @@ pub fn eq_field_pat(l: &PatField, r: &PatField) -> bool {
         && over(&l.attrs, &r.attrs, eq_attr)
 }
 
-pub fn eq_qself(l: &QSelf, r: &QSelf) -> bool {
+pub fn eq_qself(l: &P<QSelf>, r: &P<QSelf>) -> bool {
     l.position == r.position && eq_ty(&l.ty, &r.ty)
 }
 
-pub fn eq_maybe_qself(l: &Option<QSelf>, r: &Option<QSelf>) -> bool {
+pub fn eq_maybe_qself(l: &Option<P<QSelf>>, r: &Option<P<QSelf>>) -> bool {
     match (l, r) {
         (Some(l), Some(r)) => eq_qself(l, r),
         (None, None) => true,
@@ -147,8 +147,11 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         (Array(l), Array(r)) | (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
         (Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
         (Call(lc, la), Call(rc, ra)) => eq_expr(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
-        (MethodCall(lc, ls, la, _), MethodCall(rc, rs, ra, _)) => {
-            eq_path_seg(lc, rc) && eq_expr(ls, rs) && over(la, ra, |l, r| eq_expr(l, r))
+        (
+            MethodCall(box ast::MethodCall { seg: ls, receiver: lr, args: la, .. }),
+            MethodCall(box ast::MethodCall { seg: rs, receiver: rr, args: ra, .. })
+        ) => {
+            eq_path_seg(ls, rs) && eq_expr(lr, rr) && over(la, ra, |l, r| eq_expr(l, r))
         },
         (Binary(lo, ll, lr), Binary(ro, rl, rr)) => lo.node == ro.node && eq_expr(ll, rl) && eq_expr(lr, rr),
         (Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r),
@@ -170,7 +173,26 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         (AssignOp(lo, lp, lv), AssignOp(ro, rp, rv)) => lo.node == ro.node && eq_expr(lp, rp) && eq_expr(lv, rv),
         (Field(lp, lf), Field(rp, rf)) => eq_id(*lf, *rf) && eq_expr(lp, rp),
         (Match(ls, la), Match(rs, ra)) => eq_expr(ls, rs) && over(la, ra, eq_arm),
-        (Closure(lb, lc, la, lm, lf, le, _), Closure(rb, rc, ra, rm, rf, re, _)) => {
+        (
+            Closure(box ast::Closure {
+                binder: lb,
+                capture_clause: lc,
+                asyncness: la,
+                movability: lm,
+                fn_decl: lf,
+                body: le,
+                ..
+            }),
+            Closure(box ast::Closure {
+                binder: rb,
+                capture_clause: rc,
+                asyncness: ra,
+                movability: rm,
+                fn_decl: rf,
+                body: re,
+                ..
+            })
+        ) => {
             eq_closure_binder(lb, rb)
                 && lc == rc
                 && la.is_async() == ra.is_async()
diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs
index ccc2fd0d5f5..23f55db773e 100644
--- a/src/tools/rustfmt/src/attr.rs
+++ b/src/tools/rustfmt/src/attr.rs
@@ -290,10 +290,10 @@ impl Rewrite for ast::MetaItem {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         Some(match self.kind {
             ast::MetaItemKind::Word => {
-                rewrite_path(context, PathContext::Type, None, &self.path, shape)?
+                rewrite_path(context, PathContext::Type, &None, &self.path, shape)?
             }
             ast::MetaItemKind::List(ref list) => {
-                let path = rewrite_path(context, PathContext::Type, None, &self.path, shape)?;
+                let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?;
                 let has_trailing_comma = crate::expr::span_ends_with_comma(context, self.span);
                 overflow::rewrite_with_parens(
                     context,
@@ -311,7 +311,7 @@ impl Rewrite for ast::MetaItem {
                 )?
             }
             ast::MetaItemKind::NameValue(ref literal) => {
-                let path = rewrite_path(context, PathContext::Type, None, &self.path, shape)?;
+                let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?;
                 // 3 = ` = `
                 let lit_shape = shape.shrink_left(path.len() + 3)?;
                 // `rewrite_literal` returns `None` when `literal` exceeds max
diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs
index fcc02eca429..a1a73cf4bd5 100644
--- a/src/tools/rustfmt/src/chains.rs
+++ b/src/tools/rustfmt/src/chains.rs
@@ -145,8 +145,8 @@ impl ChainItemKind {
 
     fn from_ast(context: &RewriteContext<'_>, expr: &ast::Expr) -> (ChainItemKind, Span) {
         let (kind, span) = match expr.kind {
-            ast::ExprKind::MethodCall(ref segment, ref receiver, ref expressions, _) => {
-                let types = if let Some(ref generic_args) = segment.args {
+            ast::ExprKind::MethodCall(ref call) => {
+                let types = if let Some(ref generic_args) = call.seg.args {
                     if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args {
                         data.args
                             .iter()
@@ -163,8 +163,8 @@ impl ChainItemKind {
                 } else {
                     vec![]
                 };
-                let span = mk_sp(receiver.span.hi(), expr.span.hi());
-                let kind = ChainItemKind::MethodCall(segment.clone(), types, expressions.clone());
+                let span = mk_sp(call.receiver.span.hi(), expr.span.hi());
+                let kind = ChainItemKind::MethodCall(call.seg.clone(), types, call.args.clone());
                 (kind, span)
             }
             ast::ExprKind::Field(ref nested, field) => {
@@ -400,9 +400,7 @@ impl Chain {
     // is a try! macro, we'll convert it to shorthand when the option is set.
     fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext<'_>) -> Option<ast::Expr> {
         match expr.kind {
-            ast::ExprKind::MethodCall(_, ref receiver, _, _) => {
-                Some(Self::convert_try(&receiver, context))
-            }
+            ast::ExprKind::MethodCall(ref call) => Some(Self::convert_try(&call.receiver, context)),
             ast::ExprKind::Field(ref subexpr, _)
             | ast::ExprKind::Try(ref subexpr)
             | ast::ExprKind::Await(ref subexpr) => Some(Self::convert_try(subexpr, context)),
diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs
index 88a6bebb68c..423c3a997f5 100644
--- a/src/tools/rustfmt/src/closures.rs
+++ b/src/tools/rustfmt/src/closures.rs
@@ -326,16 +326,16 @@ pub(crate) fn rewrite_last_closure(
     expr: &ast::Expr,
     shape: Shape,
 ) -> Option<String> {
-    if let ast::ExprKind::Closure(
-        ref binder,
-        capture,
-        ref is_async,
-        movability,
-        ref fn_decl,
-        ref body,
-        _,
-    ) = expr.kind
-    {
+    if let ast::ExprKind::Closure(ref closure) = expr.kind {
+        let ast::Closure {
+            ref binder,
+            capture_clause,
+            ref asyncness,
+            movability,
+            ref fn_decl,
+            ref body,
+            fn_decl_span: _,
+        } = **closure;
         let body = match body.kind {
             ast::ExprKind::Block(ref block, _)
                 if !is_unsafe_block(block)
@@ -347,7 +347,15 @@ pub(crate) fn rewrite_last_closure(
             _ => body,
         };
         let (prefix, extra_offset) = rewrite_closure_fn_decl(
-            binder, capture, is_async, movability, fn_decl, body, expr.span, context, shape,
+            binder,
+            capture_clause,
+            asyncness,
+            movability,
+            fn_decl,
+            body,
+            expr.span,
+            context,
+            shape,
         )?;
         // If the closure goes multi line before its body, do not overflow the closure.
         if prefix.contains('\n') {
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index b4f1a178dbf..aba1c484bf1 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -116,7 +116,7 @@ pub(crate) fn format_expr(
             rewrite_struct_lit(
                 context,
                 path,
-                qself.as_ref(),
+                qself,
                 fields,
                 rest,
                 &expr.attrs,
@@ -169,7 +169,7 @@ pub(crate) fn format_expr(
             rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs)
         }
         ast::ExprKind::Path(ref qself, ref path) => {
-            rewrite_path(context, PathContext::Expr, qself.as_ref(), path, shape)
+            rewrite_path(context, PathContext::Expr, qself, path, shape)
         }
         ast::ExprKind::Assign(ref lhs, ref rhs, _) => {
             rewrite_assignment(context, lhs, rhs, None, shape)
@@ -203,16 +203,16 @@ pub(crate) fn format_expr(
                 Some("yield".to_string())
             }
         }
-        ast::ExprKind::Closure(
-            ref binder,
-            capture,
-            ref is_async,
-            movability,
-            ref fn_decl,
-            ref body,
-            _,
-        ) => closures::rewrite_closure(
-            binder, capture, is_async, movability, fn_decl, body, expr.span, context, shape,
+        ast::ExprKind::Closure(ref cl) => closures::rewrite_closure(
+            &cl.binder,
+            cl.capture_clause,
+            &cl.asyncness,
+            cl.movability,
+            &cl.fn_decl,
+            &cl.body,
+            expr.span,
+            context,
+            shape,
         ),
         ast::ExprKind::Try(..)
         | ast::ExprKind::Field(..)
@@ -1537,7 +1537,7 @@ fn struct_lit_can_be_aligned(fields: &[ast::ExprField], has_base: bool) -> bool
 fn rewrite_struct_lit<'a>(
     context: &RewriteContext<'_>,
     path: &ast::Path,
-    qself: Option<&ast::QSelf>,
+    qself: &Option<ptr::P<ast::QSelf>>,
     fields: &'a [ast::ExprField],
     struct_rest: &ast::StructRest,
     attrs: &[ast::Attribute],
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index e2fe92b28f2..3f335172590 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -227,11 +227,10 @@ impl Rewrite for Pat {
             }
             PatKind::Tuple(ref items) => rewrite_tuple_pat(items, None, self.span, context, shape),
             PatKind::Path(ref q_self, ref path) => {
-                rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape)
+                rewrite_path(context, PathContext::Expr, q_self, path, shape)
             }
             PatKind::TupleStruct(ref q_self, ref path, ref pat_vec) => {
-                let path_str =
-                    rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape)?;
+                let path_str = rewrite_path(context, PathContext::Expr, q_self, path, shape)?;
                 rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape)
             }
             PatKind::Lit(ref expr) => expr.rewrite(context, shape),
@@ -271,7 +270,7 @@ impl Rewrite for Pat {
 }
 
 fn rewrite_struct_pat(
-    qself: &Option<ast::QSelf>,
+    qself: &Option<ptr::P<ast::QSelf>>,
     path: &ast::Path,
     fields: &[ast::PatField],
     ellipsis: bool,
@@ -281,7 +280,7 @@ fn rewrite_struct_pat(
 ) -> Option<String> {
     // 2 =  ` {`
     let path_shape = shape.sub_width(2)?;
-    let path_str = rewrite_path(context, PathContext::Expr, qself.as_ref(), path, path_shape)?;
+    let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape)?;
 
     if fields.is_empty() && !ellipsis {
         return Some(format!("{} {{}}", path_str));
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 2627886db10..d5177a2057b 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -38,11 +38,11 @@ pub(crate) enum PathContext {
 pub(crate) fn rewrite_path(
     context: &RewriteContext<'_>,
     path_context: PathContext,
-    qself: Option<&ast::QSelf>,
+    qself: &Option<ptr::P<ast::QSelf>>,
     path: &ast::Path,
     shape: Shape,
 ) -> Option<String> {
-    let skip_count = qself.map_or(0, |x| x.position);
+    let skip_count = qself.as_ref().map_or(0, |x| x.position);
 
     let mut result = if path.is_global() && qself.is_none() && path_context != PathContext::Import {
         "::".to_owned()
@@ -655,7 +655,7 @@ impl Rewrite for ast::PolyTraitRef {
 
 impl Rewrite for ast::TraitRef {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        rewrite_path(context, PathContext::Type, None, &self.path, shape)
+        rewrite_path(context, PathContext::Type, &None, &self.path, shape)
     }
 }
 
@@ -800,7 +800,7 @@ impl Rewrite for ast::Ty {
                 rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1)
             }
             ast::TyKind::Path(ref q_self, ref path) => {
-                rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape)
+                rewrite_path(context, PathContext::Type, q_self, path, shape)
             }
             ast::TyKind::Array(ref ty, ref repeats) => rewrite_pair(
                 &**ty,
diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs
index c47b3b314dd..136a2c7fce2 100644
--- a/src/tools/rustfmt/src/utils.rs
+++ b/src/tools/rustfmt/src/utils.rs
@@ -479,9 +479,9 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr
         | ast::ExprKind::Binary(_, _, ref expr)
         | ast::ExprKind::Index(_, ref expr)
         | ast::ExprKind::Unary(_, ref expr)
-        | ast::ExprKind::Closure(_, _, _, _, _, ref expr, _)
         | ast::ExprKind::Try(ref expr)
         | ast::ExprKind::Yield(Some(ref expr)) => is_block_expr(context, expr, repr),
+        ast::ExprKind::Closure(ref closure) => is_block_expr(context, &closure.body, repr),
         // This can only be a string lit
         ast::ExprKind::Lit(_) => {
             repr.contains('\n') && trimmed_last_line_width(repr) <= context.config.tab_spaces()