]> git.lizzy.rs Git - rust.git/commitdiff
lowering: refactor into item.rs
authorMazdak Farrokhzad <twingoow@gmail.com>
Sat, 10 Aug 2019 18:13:12 +0000 (20:13 +0200)
committerMazdak Farrokhzad <twingoow@gmail.com>
Sat, 10 Aug 2019 18:24:43 +0000 (20:24 +0200)
src/librustc/hir/lowering.rs
src/librustc/hir/lowering/expr.rs
src/librustc/hir/lowering/item.rs [new file with mode: 0644]

index bf3a24de81b358e9ed946715e4cf39d1094ea86f..9a4cf4c36cc7f4867f19c740994e94110094f76c 100644 (file)
@@ -33,6 +33,7 @@
 //! in the HIR, especially for multiple identifiers.
 
 mod expr;
+mod item;
 
 use crate::dep_graph::DepGraph;
 use crate::hir::{self, ParamName};
@@ -55,7 +56,7 @@
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_data_structures::sync::Lrc;
 
-use std::collections::{BTreeSet, BTreeMap};
+use std::collections::BTreeMap;
 use std::mem;
 use smallvec::SmallVec;
 use syntax::attr;
@@ -563,90 +564,11 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
             }
         }
 
-        struct ItemLowerer<'tcx, 'interner> {
-            lctx: &'tcx mut LoweringContext<'interner>,
-        }
-
-        impl<'tcx, 'interner> ItemLowerer<'tcx, 'interner> {
-            fn with_trait_impl_ref<F>(&mut self, trait_impl_ref: &Option<TraitRef>, f: F)
-            where
-                F: FnOnce(&mut Self),
-            {
-                let old = self.lctx.is_in_trait_impl;
-                self.lctx.is_in_trait_impl = if let &None = trait_impl_ref {
-                    false
-                } else {
-                    true
-                };
-                f(self);
-                self.lctx.is_in_trait_impl = old;
-            }
-        }
-
-        impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> {
-            fn visit_mod(&mut self, m: &'tcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
-                self.lctx.modules.insert(n, hir::ModuleItems {
-                    items: BTreeSet::new(),
-                    trait_items: BTreeSet::new(),
-                    impl_items: BTreeSet::new(),
-                });
-
-                let old = self.lctx.current_module;
-                self.lctx.current_module = n;
-                visit::walk_mod(self, m);
-                self.lctx.current_module = old;
-            }
-
-            fn visit_item(&mut self, item: &'tcx Item) {
-                let mut item_hir_id = None;
-                self.lctx.with_hir_id_owner(item.id, |lctx| {
-                    if let Some(hir_item) = lctx.lower_item(item) {
-                        item_hir_id = Some(hir_item.hir_id);
-                        lctx.insert_item(hir_item);
-                    }
-                });
-
-                if let Some(hir_id) = item_hir_id {
-                    self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
-                        let this = &mut ItemLowerer { lctx: this };
-                        if let ItemKind::Impl(.., ref opt_trait_ref, _, _) = item.node {
-                            this.with_trait_impl_ref(opt_trait_ref, |this| {
-                                visit::walk_item(this, item)
-                            });
-                        } else {
-                            visit::walk_item(this, item);
-                        }
-                    });
-                }
-            }
-
-            fn visit_trait_item(&mut self, item: &'tcx TraitItem) {
-                self.lctx.with_hir_id_owner(item.id, |lctx| {
-                    let hir_item = lctx.lower_trait_item(item);
-                    let id = hir::TraitItemId { hir_id: hir_item.hir_id };
-                    lctx.trait_items.insert(id, hir_item);
-                    lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id);
-                });
-
-                visit::walk_trait_item(self, item);
-            }
-
-            fn visit_impl_item(&mut self, item: &'tcx ImplItem) {
-                self.lctx.with_hir_id_owner(item.id, |lctx| {
-                    let hir_item = lctx.lower_impl_item(item);
-                    let id = hir::ImplItemId { hir_id: hir_item.hir_id };
-                    lctx.impl_items.insert(id, hir_item);
-                    lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id);
-                });
-                visit::walk_impl_item(self, item);
-            }
-        }
-
         self.lower_node_id(CRATE_NODE_ID);
         debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == hir::CRATE_HIR_ID);
 
         visit::walk_crate(&mut MiscCollector { lctx: &mut self, hir_id_owner: None }, c);
-        visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c);
+        visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
 
         let module = self.lower_mod(&c.module);
         let attrs = self.lower_attrs(&c.attrs);
@@ -785,57 +707,6 @@ fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> hi
         })
     }
 
-    fn generator_movability_for_fn(
-        &mut self,
-        decl: &ast::FnDecl,
-        fn_decl_span: Span,
-        generator_kind: Option<hir::GeneratorKind>,
-        movability: Movability,
-    ) -> Option<hir::GeneratorMovability> {
-        match generator_kind {
-            Some(hir::GeneratorKind::Gen) =>  {
-                if !decl.inputs.is_empty() {
-                    span_err!(
-                        self.sess,
-                        fn_decl_span,
-                        E0628,
-                        "generators cannot have explicit arguments"
-                    );
-                    self.sess.abort_if_errors();
-                }
-                Some(match movability {
-                    Movability::Movable => hir::GeneratorMovability::Movable,
-                    Movability::Static => hir::GeneratorMovability::Static,
-                })
-            },
-            Some(hir::GeneratorKind::Async) => {
-                bug!("non-`async` closure body turned `async` during lowering");
-            },
-            None => {
-                if movability == Movability::Static {
-                    span_err!(
-                        self.sess,
-                        fn_decl_span,
-                        E0697,
-                        "closures cannot be static"
-                    );
-                }
-                None
-            },
-        }
-    }
-
-    fn record_body(&mut self, arguments: HirVec<hir::Arg>, value: hir::Expr) -> hir::BodyId {
-        let body = hir::Body {
-            generator_kind: self.generator_kind,
-            arguments,
-            value,
-        };
-        let id = body.id();
-        self.bodies.insert(id, body);
-        id
-    }
-
     fn next_id(&mut self) -> hir::HirId {
         self.lower_node_id(self.sess.next_node_id())
     }
@@ -1039,38 +910,6 @@ fn with_in_scope_lifetime_defs<T, F>(&mut self, params: &[GenericParam], f: F) -
         res
     }
 
-    // Same as the method above, but accepts `hir::GenericParam`s
-    // instead of `ast::GenericParam`s.
-    // This should only be used with generics that have already had their
-    // in-band lifetimes added. In practice, this means that this function is
-    // only used when lowering a child item of a trait or impl.
-    fn with_parent_item_lifetime_defs<T, F>(&mut self,
-        parent_hir_id: hir::HirId,
-        f: F
-    ) -> T where
-        F: FnOnce(&mut LoweringContext<'_>) -> T,
-    {
-        let old_len = self.in_scope_lifetimes.len();
-
-        let parent_generics = match self.items.get(&parent_hir_id).unwrap().node {
-            hir::ItemKind::Impl(_, _, _, ref generics, ..)
-            | hir::ItemKind::Trait(_, _, ref generics, ..) => {
-                &generics.params[..]
-            }
-            _ => &[],
-        };
-        let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind {
-            hir::GenericParamKind::Lifetime { .. } => Some(param.name.ident().modern()),
-            _ => None,
-        });
-        self.in_scope_lifetimes.extend(lt_def_names);
-
-        let res = f(self);
-
-        self.in_scope_lifetimes.truncate(old_len);
-        res
-    }
-
     /// Appends in-band lifetime defs and argument-position `impl
     /// Trait` defs to the existing set of generics.
     ///
@@ -1151,39 +990,6 @@ fn with_catch_scope<T, F>(&mut self, catch_id: NodeId, f: F) -> T
         result
     }
 
-    fn lower_body(
-        &mut self,
-        f: impl FnOnce(&mut LoweringContext<'_>) -> (HirVec<hir::Arg>, hir::Expr),
-    ) -> hir::BodyId {
-        let prev_gen_kind = self.generator_kind.take();
-        let (arguments, result) = f(self);
-        let body_id = self.record_body(arguments, result);
-        self.generator_kind = prev_gen_kind;
-        body_id
-    }
-
-    fn lower_fn_body(
-        &mut self,
-        decl: &FnDecl,
-        body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
-    ) -> hir::BodyId {
-        self.lower_body(|this| (
-            decl.inputs.iter().map(|x| this.lower_arg(x)).collect(),
-            body(this),
-        ))
-    }
-
-    fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
-        self.lower_fn_body(decl, |this| {
-            let body = this.lower_block(body, false);
-            this.expr_block(body, ThinVec::new())
-        })
-    }
-
-    fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId {
-        self.lower_body(|this| (hir_vec![], this.lower_expr(expr)))
-    }
-
     fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
     where
         F: FnOnce(&mut LoweringContext<'_>) -> T,
@@ -1894,36 +1700,6 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
         )
     }
 
-    fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
-        hir::ForeignMod {
-            abi: fm.abi,
-            items: fm.items
-                .iter()
-                .map(|x| self.lower_foreign_item(x))
-                .collect(),
-        }
-    }
-
-    fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> {
-        P(hir::GlobalAsm {
-            asm: ga.asm,
-            ctxt: ga.ctxt,
-        })
-    }
-
-    fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
-        Spanned {
-            node: hir::VariantKind {
-                ident: v.node.ident,
-                id: self.lower_node_id(v.node.id),
-                attrs: self.lower_attrs(&v.node.attrs),
-                data: self.lower_variant_data(&v.node.data),
-                disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
-            },
-            span: v.span,
-        }
-    }
-
     fn lower_qpath(
         &mut self,
         id: NodeId,
@@ -2857,169 +2633,6 @@ fn lower_generic_param(&mut self,
         }
     }
 
-    fn lower_generics(
-        &mut self,
-        generics: &Generics,
-        itctx: ImplTraitContext<'_>)
-        -> hir::Generics
-    {
-        // Collect `?Trait` bounds in where clause and move them to parameter definitions.
-        // FIXME: this could probably be done with less rightward drift. It also looks like two
-        // control paths where `report_error` is called are the only paths that advance to after the
-        // match statement, so the error reporting could probably just be moved there.
-        let mut add_bounds: NodeMap<Vec<_>> = Default::default();
-        for pred in &generics.where_clause.predicates {
-            if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
-                'next_bound: for bound in &bound_pred.bounds {
-                    if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound {
-                        let report_error = |this: &mut Self| {
-                            this.diagnostic().span_err(
-                                bound_pred.bounded_ty.span,
-                                "`?Trait` bounds are only permitted at the \
-                                 point where a type parameter is declared",
-                            );
-                        };
-                        // Check if the where clause type is a plain type parameter.
-                        match bound_pred.bounded_ty.node {
-                            TyKind::Path(None, ref path)
-                                if path.segments.len() == 1
-                                    && bound_pred.bound_generic_params.is_empty() =>
-                            {
-                                if let Some(Res::Def(DefKind::TyParam, def_id)) = self.resolver
-                                    .get_partial_res(bound_pred.bounded_ty.id)
-                                    .map(|d| d.base_res())
-                                {
-                                    if let Some(node_id) =
-                                        self.resolver.definitions().as_local_node_id(def_id)
-                                    {
-                                        for param in &generics.params {
-                                            match param.kind {
-                                                GenericParamKind::Type { .. } => {
-                                                    if node_id == param.id {
-                                                        add_bounds.entry(param.id)
-                                                            .or_default()
-                                                            .push(bound.clone());
-                                                        continue 'next_bound;
-                                                    }
-                                                }
-                                                _ => {}
-                                            }
-                                        }
-                                    }
-                                }
-                                report_error(self)
-                            }
-                            _ => report_error(self),
-                        }
-                    }
-                }
-            }
-        }
-
-        hir::Generics {
-            params: self.lower_generic_params(&generics.params, &add_bounds, itctx),
-            where_clause: self.lower_where_clause(&generics.where_clause),
-            span: generics.span,
-        }
-    }
-
-    fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause {
-        self.with_anonymous_lifetime_mode(
-            AnonymousLifetimeMode::ReportError,
-            |this| {
-                hir::WhereClause {
-                    predicates: wc.predicates
-                        .iter()
-                        .map(|predicate| this.lower_where_predicate(predicate))
-                        .collect(),
-                    span: wc.span,
-                }
-            },
-        )
-    }
-
-    fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate {
-        match *pred {
-            WherePredicate::BoundPredicate(WhereBoundPredicate {
-                ref bound_generic_params,
-                ref bounded_ty,
-                ref bounds,
-                span,
-            }) => {
-                self.with_in_scope_lifetime_defs(
-                    &bound_generic_params,
-                    |this| {
-                        hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
-                            bound_generic_params: this.lower_generic_params(
-                                bound_generic_params,
-                                &NodeMap::default(),
-                                ImplTraitContext::disallowed(),
-                            ),
-                            bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
-                            bounds: bounds
-                                .iter()
-                                .filter_map(|bound| match *bound {
-                                    // Ignore `?Trait` bounds.
-                                    // They were copied into type parameters already.
-                                    GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
-                                    _ => Some(this.lower_param_bound(
-                                        bound,
-                                        ImplTraitContext::disallowed(),
-                                    )),
-                                })
-                                .collect(),
-                            span,
-                        })
-                    },
-                )
-            }
-            WherePredicate::RegionPredicate(WhereRegionPredicate {
-                ref lifetime,
-                ref bounds,
-                span,
-            }) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
-                span,
-                lifetime: self.lower_lifetime(lifetime),
-                bounds: self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
-            }),
-            WherePredicate::EqPredicate(WhereEqPredicate {
-                id,
-                ref lhs_ty,
-                ref rhs_ty,
-                span,
-            }) => {
-                hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
-                    hir_id: self.lower_node_id(id),
-                    lhs_ty: self.lower_ty(lhs_ty, ImplTraitContext::disallowed()),
-                    rhs_ty: self.lower_ty(rhs_ty, ImplTraitContext::disallowed()),
-                    span,
-                })
-            },
-        }
-    }
-
-    fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
-        match *vdata {
-            VariantData::Struct(ref fields, recovered) => hir::VariantData::Struct(
-                fields.iter().enumerate().map(|f| self.lower_struct_field(f)).collect(),
-                recovered,
-            ),
-            VariantData::Tuple(ref fields, id) => {
-                hir::VariantData::Tuple(
-                    fields
-                        .iter()
-                        .enumerate()
-                        .map(|f| self.lower_struct_field(f))
-                        .collect(),
-                    self.lower_node_id(id),
-                )
-            },
-            VariantData::Unit(id) => {
-                hir::VariantData::Unit(self.lower_node_id(id))
-            },
-        }
-    }
-
     fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext<'_>) -> hir::TraitRef {
         let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
             hir::QPath::Resolved(None, path) => path,
@@ -3053,33 +2666,6 @@ fn lower_poly_trait_ref(
         }
     }
 
-    fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField {
-        let ty = if let TyKind::Path(ref qself, ref path) = f.ty.node {
-            let t = self.lower_path_ty(
-                &f.ty,
-                qself,
-                path,
-                ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124)
-                ImplTraitContext::disallowed()
-            );
-            P(t)
-        } else {
-            self.lower_ty(&f.ty, ImplTraitContext::disallowed())
-        };
-        hir::StructField {
-            span: f.span,
-            hir_id: self.lower_node_id(f.id),
-            ident: match f.ident {
-                Some(ident) => ident,
-                // FIXME(jseyfried): positional field hygiene.
-                None => Ident::new(sym::integer(index), f.span),
-            },
-            vis: self.lower_visibility(&f.vis, None),
-            ty,
-            attrs: self.lower_attrs(&f.attrs),
-        }
-    }
-
     fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_>) -> hir::MutTy {
         hir::MutTy {
             ty: self.lower_ty(&mt.ty, itctx),
@@ -3126,950 +2712,6 @@ fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
         self.lower_block_with_stmts(b, targeted_by_break, vec![])
     }
 
-    fn lower_maybe_async_body(
-        &mut self,
-        decl: &FnDecl,
-        asyncness: IsAsync,
-        body: &Block,
-    ) -> hir::BodyId {
-        let closure_id = match asyncness {
-            IsAsync::Async { closure_id, .. } => closure_id,
-            IsAsync::NotAsync => return self.lower_fn_body_block(decl, body),
-        };
-
-        self.lower_body(|this| {
-            let mut arguments: Vec<hir::Arg> = Vec::new();
-            let mut statements: Vec<hir::Stmt> = Vec::new();
-
-            // Async function arguments are lowered into the closure body so that they are
-            // captured and so that the drop order matches the equivalent non-async functions.
-            //
-            // from:
-            //
-            //     async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
-            //       async move {
-            //       }
-            //     }
-            //
-            // into:
-            //
-            //     fn foo(__arg0: <ty>, __arg1: <ty>, __arg2: <ty>) {
-            //       async move {
-            //         let __arg2 = __arg2;
-            //         let <pattern> = __arg2;
-            //         let __arg1 = __arg1;
-            //         let <pattern> = __arg1;
-            //         let __arg0 = __arg0;
-            //         let <pattern> = __arg0;
-            //       }
-            //     }
-            //
-            // If `<pattern>` is a simple ident, then it is lowered to a single
-            // `let <pattern> = <pattern>;` statement as an optimization.
-            for (index, argument) in decl.inputs.iter().enumerate() {
-                let argument = this.lower_arg(argument);
-                let span = argument.pat.span;
-
-                // Check if this is a binding pattern, if so, we can optimize and avoid adding a
-                // `let <pat> = __argN;` statement. In this case, we do not rename the argument.
-                let (ident, is_simple_argument) = match argument.pat.node {
-                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _) =>
-                        (ident, true),
-                    _ => {
-                        // Replace the ident for bindings that aren't simple.
-                        let name = format!("__arg{}", index);
-                        let ident = Ident::from_str(&name);
-
-                        (ident, false)
-                    },
-                };
-
-                let desugared_span =
-                    this.mark_span_with_reason(DesugaringKind::Async, span, None);
-
-                // Construct an argument representing `__argN: <ty>` to replace the argument of the
-                // async function.
-                //
-                // If this is the simple case, this argument will end up being the same as the
-                // original argument, but with a different pattern id.
-                let mut stmt_attrs = ThinVec::new();
-                stmt_attrs.extend(argument.attrs.iter().cloned());
-                let (new_argument_pat, new_argument_id) = this.pat_ident(desugared_span, ident);
-                let new_argument = hir::Arg {
-                    attrs: argument.attrs,
-                    hir_id: argument.hir_id,
-                    pat: new_argument_pat,
-                    span: argument.span,
-                };
-
-
-                if is_simple_argument {
-                    // If this is the simple case, then we only insert one statement that is
-                    // `let <pat> = <pat>;`. We re-use the original argument's pattern so that
-                    // `HirId`s are densely assigned.
-                    let expr = this.expr_ident(desugared_span, ident, new_argument_id);
-                    let stmt = this.stmt_let_pat(
-                        stmt_attrs,
-                        desugared_span,
-                        Some(P(expr)),
-                        argument.pat,
-                        hir::LocalSource::AsyncFn
-                    );
-                    statements.push(stmt);
-                } else {
-                    // If this is not the simple case, then we construct two statements:
-                    //
-                    // ```
-                    // let __argN = __argN;
-                    // let <pat> = __argN;
-                    // ```
-                    //
-                    // The first statement moves the argument into the closure and thus ensures
-                    // that the drop order is correct.
-                    //
-                    // The second statement creates the bindings that the user wrote.
-
-                    // Construct the `let mut __argN = __argN;` statement. It must be a mut binding
-                    // because the user may have specified a `ref mut` binding in the next
-                    // statement.
-                    let (move_pat, move_id) = this.pat_ident_binding_mode(
-                        desugared_span, ident, hir::BindingAnnotation::Mutable);
-                    let move_expr = this.expr_ident(desugared_span, ident, new_argument_id);
-                    let move_stmt = this.stmt_let_pat(
-                        ThinVec::new(),
-                        desugared_span,
-                        Some(P(move_expr)),
-                        move_pat,
-                        hir::LocalSource::AsyncFn
-                    );
-
-                    // Construct the `let <pat> = __argN;` statement. We re-use the original
-                    // argument's pattern so that `HirId`s are densely assigned.
-                    let pattern_expr = this.expr_ident(desugared_span, ident, move_id);
-                    let pattern_stmt = this.stmt_let_pat(
-                        stmt_attrs,
-                        desugared_span,
-                        Some(P(pattern_expr)),
-                        argument.pat,
-                        hir::LocalSource::AsyncFn
-                    );
-
-                    statements.push(move_stmt);
-                    statements.push(pattern_stmt);
-                };
-
-                arguments.push(new_argument);
-            }
-
-            let async_expr = this.make_async_expr(
-                CaptureBy::Value, closure_id, None, body.span,
-                |this| {
-                    let body = this.lower_block_with_stmts(body, false, statements);
-                    this.expr_block(body, ThinVec::new())
-                });
-            (HirVec::from(arguments), this.expr(body.span, async_expr, ThinVec::new()))
-        })
-    }
-
-    fn lower_item_kind(
-        &mut self,
-        id: NodeId,
-        ident: &mut Ident,
-        attrs: &hir::HirVec<Attribute>,
-        vis: &mut hir::Visibility,
-        i: &ItemKind,
-    ) -> hir::ItemKind {
-        match *i {
-            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,
-                };
-
-                self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs)
-            }
-            ItemKind::Static(ref t, m, ref e) => {
-                hir::ItemKind::Static(
-                    self.lower_ty(
-                        t,
-                        if self.sess.features_untracked().impl_trait_in_bindings {
-                            ImplTraitContext::OpaqueTy(None)
-                        } else {
-                            ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
-                        }
-                    ),
-                    self.lower_mutability(m),
-                    self.lower_const_body(e),
-                )
-            }
-            ItemKind::Const(ref t, ref e) => {
-                hir::ItemKind::Const(
-                    self.lower_ty(
-                        t,
-                        if self.sess.features_untracked().impl_trait_in_bindings {
-                            ImplTraitContext::OpaqueTy(None)
-                        } else {
-                            ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
-                        }
-                    ),
-                    self.lower_const_body(e)
-                )
-            }
-            ItemKind::Fn(ref decl, header, ref generics, ref body) => {
-                let fn_def_id = self.resolver.definitions().local_def_id(id);
-                self.with_new_scopes(|this| {
-                    this.current_item = Some(ident.span);
-
-                    // Note: we don't need to change the return type from `T` to
-                    // `impl Future<Output = T>` here because lower_body
-                    // only cares about the input argument patterns in the function
-                    // declaration (decl), not the return types.
-                    let body_id = this.lower_maybe_async_body(&decl, header.asyncness.node, body);
-
-                    let (generics, fn_decl) = this.add_in_band_defs(
-                        generics,
-                        fn_def_id,
-                        AnonymousLifetimeMode::PassThrough,
-                        |this, idty| this.lower_fn_decl(
-                            &decl,
-                            Some((fn_def_id, idty)),
-                            true,
-                            header.asyncness.node.opt_return_id()
-                        ),
-                    );
-
-                    hir::ItemKind::Fn(
-                        fn_decl,
-                        this.lower_fn_header(header),
-                        generics,
-                        body_id,
-                    )
-                })
-            }
-            ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
-            ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
-            ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
-            ItemKind::TyAlias(ref t, ref generics) => hir::ItemKind::TyAlias(
-                self.lower_ty(t, ImplTraitContext::disallowed()),
-                self.lower_generics(generics, ImplTraitContext::disallowed()),
-            ),
-            ItemKind::OpaqueTy(ref b, ref generics) => hir::ItemKind::OpaqueTy(
-                hir::OpaqueTy {
-                    generics: self.lower_generics(generics,
-                        ImplTraitContext::OpaqueTy(None)),
-                    bounds: self.lower_param_bounds(b,
-                        ImplTraitContext::OpaqueTy(None)),
-                    impl_trait_fn: None,
-                    origin: hir::OpaqueTyOrigin::TypeAlias,
-                },
-            ),
-            ItemKind::Enum(ref enum_definition, ref generics) => {
-                hir::ItemKind::Enum(
-                    hir::EnumDef {
-                        variants: enum_definition
-                            .variants
-                            .iter()
-                            .map(|x| self.lower_variant(x))
-                            .collect(),
-                    },
-                    self.lower_generics(generics, ImplTraitContext::disallowed()),
-                )
-            },
-            ItemKind::Struct(ref struct_def, ref generics) => {
-                let struct_def = self.lower_variant_data(struct_def);
-                hir::ItemKind::Struct(
-                    struct_def,
-                    self.lower_generics(generics, ImplTraitContext::disallowed()),
-                )
-            }
-            ItemKind::Union(ref vdata, ref generics) => {
-                let vdata = self.lower_variant_data(vdata);
-                hir::ItemKind::Union(
-                    vdata,
-                    self.lower_generics(generics, ImplTraitContext::disallowed()),
-                )
-            }
-            ItemKind::Impl(
-                unsafety,
-                polarity,
-                defaultness,
-                ref ast_generics,
-                ref trait_ref,
-                ref ty,
-                ref impl_items,
-            ) => {
-                let def_id = self.resolver.definitions().local_def_id(id);
-
-                // Lower the "impl header" first. This ordering is important
-                // for in-band lifetimes! Consider `'a` here:
-                //
-                //     impl Foo<'a> for u32 {
-                //         fn method(&'a self) { .. }
-                //     }
-                //
-                // Because we start by lowering the `Foo<'a> for u32`
-                // part, we will add `'a` to the list of generics on
-                // the impl. When we then encounter it later in the
-                // method, it will not be considered an in-band
-                // lifetime to be added, but rather a reference to a
-                // parent lifetime.
-                let lowered_trait_impl_id = self.lower_node_id(id);
-                let (generics, (trait_ref, lowered_ty)) = self.add_in_band_defs(
-                    ast_generics,
-                    def_id,
-                    AnonymousLifetimeMode::CreateParameter,
-                    |this, _| {
-                        let trait_ref = trait_ref.as_ref().map(|trait_ref| {
-                            this.lower_trait_ref(trait_ref, ImplTraitContext::disallowed())
-                        });
-
-                        if let Some(ref trait_ref) = trait_ref {
-                            if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res {
-                                this.trait_impls.entry(def_id).or_default().push(
-                                    lowered_trait_impl_id);
-                            }
-                        }
-
-                        let lowered_ty = this.lower_ty(ty, ImplTraitContext::disallowed());
-
-                        (trait_ref, lowered_ty)
-                    },
-                );
-
-                let new_impl_items = self.with_in_scope_lifetime_defs(
-                    &ast_generics.params,
-                    |this| {
-                        impl_items
-                            .iter()
-                            .map(|item| this.lower_impl_item_ref(item))
-                            .collect()
-                    },
-                );
-
-                hir::ItemKind::Impl(
-                    self.lower_unsafety(unsafety),
-                    self.lower_impl_polarity(polarity),
-                    self.lower_defaultness(defaultness, true /* [1] */),
-                    generics,
-                    trait_ref,
-                    lowered_ty,
-                    new_impl_items,
-                )
-            }
-            ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
-                let bounds = self.lower_param_bounds(bounds, ImplTraitContext::disallowed());
-                let items = items
-                    .iter()
-                    .map(|item| self.lower_trait_item_ref(item))
-                    .collect();
-                hir::ItemKind::Trait(
-                    self.lower_is_auto(is_auto),
-                    self.lower_unsafety(unsafety),
-                    self.lower_generics(generics, ImplTraitContext::disallowed()),
-                    bounds,
-                    items,
-                )
-            }
-            ItemKind::TraitAlias(ref generics, ref bounds) => hir::ItemKind::TraitAlias(
-                self.lower_generics(generics, ImplTraitContext::disallowed()),
-                self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
-            ),
-            ItemKind::MacroDef(..)
-            | ItemKind::Mac(..) => bug!("`TyMac` should have been expanded by now"),
-        }
-
-        // [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to
-        //     not cause an assertion failure inside the `lower_defaultness` function.
-    }
-
-    fn lower_use_tree(
-        &mut self,
-        tree: &UseTree,
-        prefix: &Path,
-        id: NodeId,
-        vis: &mut hir::Visibility,
-        ident: &mut Ident,
-        attrs: &hir::HirVec<Attribute>,
-    ) -> hir::ItemKind {
-        debug!("lower_use_tree(tree={:?})", tree);
-        debug!("lower_use_tree: vis = {:?}", vis);
-
-        let path = &tree.prefix;
-        let segments = prefix
-            .segments
-            .iter()
-            .chain(path.segments.iter())
-            .cloned()
-            .collect();
-
-        match tree.kind {
-            UseTreeKind::Simple(rename, id1, id2) => {
-                *ident = tree.ident();
-
-                // First, apply the prefix to the path.
-                let mut path = Path {
-                    segments,
-                    span: path.span,
-                };
-
-                // Correctly resolve `self` imports.
-                if path.segments.len() > 1
-                    && path.segments.last().unwrap().ident.name == kw::SelfLower
-                {
-                    let _ = path.segments.pop();
-                    if rename.is_none() {
-                        *ident = path.segments.last().unwrap().ident;
-                    }
-                }
-
-                let mut resolutions = self.expect_full_res_from_use(id);
-                // We want to return *something* from this function, so hold onto the first item
-                // for later.
-                let ret_res = self.lower_res(resolutions.next().unwrap_or(Res::Err));
-
-                // Here, we are looping over namespaces, if they exist for the definition
-                // being imported. We only handle type and value namespaces because we
-                // won't be dealing with macros in the rest of the compiler.
-                // Essentially a single `use` which imports two names is desugared into
-                // two imports.
-                for (res, &new_node_id) in resolutions.zip([id1, id2].iter()) {
-                    let ident = *ident;
-                    let mut path = path.clone();
-                    for seg in &mut path.segments {
-                        seg.id = self.sess.next_node_id();
-                    }
-                    let span = path.span;
-
-                    self.with_hir_id_owner(new_node_id, |this| {
-                        let new_id = this.lower_node_id(new_node_id);
-                        let res = this.lower_res(res);
-                        let path =
-                            this.lower_path_extra(res, &path, ParamMode::Explicit, None);
-                        let item = hir::ItemKind::Use(P(path), hir::UseKind::Single);
-                        let vis = this.rebuild_vis(&vis);
-
-                        this.insert_item(
-                            hir::Item {
-                                hir_id: new_id,
-                                ident,
-                                attrs: attrs.into_iter().cloned().collect(),
-                                node: item,
-                                vis,
-                                span,
-                            },
-                        );
-                    });
-                }
-
-                let path =
-                    P(self.lower_path_extra(ret_res, &path, ParamMode::Explicit, None));
-                hir::ItemKind::Use(path, hir::UseKind::Single)
-            }
-            UseTreeKind::Glob => {
-                let path = P(self.lower_path(
-                    id,
-                    &Path {
-                        segments,
-                        span: path.span,
-                    },
-                    ParamMode::Explicit,
-                ));
-                hir::ItemKind::Use(path, hir::UseKind::Glob)
-            }
-            UseTreeKind::Nested(ref trees) => {
-                // Nested imports are desugared into simple imports.
-                // So, if we start with
-                //
-                // ```
-                // pub(x) use foo::{a, b};
-                // ```
-                //
-                // we will create three items:
-                //
-                // ```
-                // pub(x) use foo::a;
-                // pub(x) use foo::b;
-                // pub(x) use foo::{}; // <-- this is called the `ListStem`
-                // ```
-                //
-                // The first two are produced by recursively invoking
-                // `lower_use_tree` (and indeed there may be things
-                // like `use foo::{a::{b, c}}` and so forth).  They
-                // wind up being directly added to
-                // `self.items`. However, the structure of this
-                // function also requires us to return one item, and
-                // for that we return the `{}` import (called the
-                // `ListStem`).
-
-                let prefix = Path {
-                    segments,
-                    span: prefix.span.to(path.span),
-                };
-
-                // Add all the nested `PathListItem`s to the HIR.
-                for &(ref use_tree, id) in trees {
-                    let new_hir_id = self.lower_node_id(id);
-
-                    let mut prefix = prefix.clone();
-
-                    // Give the segments new node-ids since they are being cloned.
-                    for seg in &mut prefix.segments {
-                        seg.id = self.sess.next_node_id();
-                    }
-
-                    // Each `use` import is an item and thus are owners of the
-                    // names in the path. Up to this point the nested import is
-                    // the current owner, since we want each desugared import to
-                    // own its own names, we have to adjust the owner before
-                    // lowering the rest of the import.
-                    self.with_hir_id_owner(id, |this| {
-                        let mut vis = this.rebuild_vis(&vis);
-                        let mut ident = *ident;
-
-                        let item = this.lower_use_tree(use_tree,
-                                                       &prefix,
-                                                       id,
-                                                       &mut vis,
-                                                       &mut ident,
-                                                       attrs);
-
-                        this.insert_item(
-                            hir::Item {
-                                hir_id: new_hir_id,
-                                ident,
-                                attrs: attrs.into_iter().cloned().collect(),
-                                node: item,
-                                vis,
-                                span: use_tree.span,
-                            },
-                        );
-                    });
-                }
-
-                // Subtle and a bit hacky: we lower the privacy level
-                // of the list stem to "private" most of the time, but
-                // not for "restricted" paths. The key thing is that
-                // we don't want it to stay as `pub` (with no caveats)
-                // because that affects rustdoc and also the lints
-                // about `pub` items. But we can't *always* make it
-                // private -- particularly not for restricted paths --
-                // because it contains node-ids that would then be
-                // unused, failing the check that HirIds are "densely
-                // assigned".
-                match vis.node {
-                    hir::VisibilityKind::Public |
-                    hir::VisibilityKind::Crate(_) |
-                    hir::VisibilityKind::Inherited => {
-                        *vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited);
-                    }
-                    hir::VisibilityKind::Restricted { .. } => {
-                        // Do nothing here, as described in the comment on the match.
-                    }
-                }
-
-                let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err);
-                let res = self.lower_res(res);
-                let path = P(self.lower_path_extra(res, &prefix, ParamMode::Explicit, None));
-                hir::ItemKind::Use(path, hir::UseKind::ListStem)
-            }
-        }
-    }
-
-    /// Paths like the visibility path in `pub(super) use foo::{bar, baz}` are repeated
-    /// many times in the HIR tree; for each occurrence, we need to assign distinct
-    /// `NodeId`s. (See, e.g., #56128.)
-    fn rebuild_use_path(&mut self, path: &hir::Path) -> hir::Path {
-        debug!("rebuild_use_path(path = {:?})", path);
-        let segments = path.segments.iter().map(|seg| hir::PathSegment {
-            ident: seg.ident,
-            hir_id: seg.hir_id.map(|_| self.next_id()),
-            res: seg.res,
-            args: None,
-            infer_args: seg.infer_args,
-        }).collect();
-        hir::Path {
-            span: path.span,
-            res: path.res,
-            segments,
-        }
-    }
-
-    fn rebuild_vis(&mut self, vis: &hir::Visibility) -> hir::Visibility {
-        let vis_kind = match vis.node {
-            hir::VisibilityKind::Public => hir::VisibilityKind::Public,
-            hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
-            hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
-            hir::VisibilityKind::Restricted { ref path, hir_id: _ } => {
-                hir::VisibilityKind::Restricted {
-                    path: P(self.rebuild_use_path(path)),
-                    hir_id: self.next_id(),
-                }
-            }
-        };
-        respan(vis.span, vis_kind)
-    }
-
-    fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
-        let trait_item_def_id = self.resolver.definitions().local_def_id(i.id);
-
-        let (generics, node) = match i.node {
-            TraitItemKind::Const(ref ty, ref default) => (
-                self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
-                hir::TraitItemKind::Const(
-                    self.lower_ty(ty, ImplTraitContext::disallowed()),
-                    default
-                        .as_ref()
-                        .map(|x| self.lower_const_body(x)),
-                ),
-            ),
-            TraitItemKind::Method(ref sig, None) => {
-                let names = self.lower_fn_args_to_names(&sig.decl);
-                let (generics, sig) = self.lower_method_sig(
-                    &i.generics,
-                    sig,
-                    trait_item_def_id,
-                    false,
-                    None,
-                );
-                (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names)))
-            }
-            TraitItemKind::Method(ref sig, Some(ref body)) => {
-                let body_id = self.lower_fn_body_block(&sig.decl, body);
-                let (generics, sig) = self.lower_method_sig(
-                    &i.generics,
-                    sig,
-                    trait_item_def_id,
-                    false,
-                    None,
-                );
-                (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id)))
-            }
-            TraitItemKind::Type(ref bounds, ref default) => {
-                let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed());
-                let node = hir::TraitItemKind::Type(
-                    self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
-                    default
-                        .as_ref()
-                        .map(|x| self.lower_ty(x, ImplTraitContext::disallowed())),
-                );
-
-                (generics, node)
-            },
-            TraitItemKind::Macro(..) => bug!("macro item shouldn't exist at this point"),
-        };
-
-        hir::TraitItem {
-            hir_id: self.lower_node_id(i.id),
-            ident: i.ident,
-            attrs: self.lower_attrs(&i.attrs),
-            generics,
-            node,
-            span: i.span,
-        }
-    }
-
-    fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef {
-        let (kind, has_default) = match i.node {
-            TraitItemKind::Const(_, ref default) => {
-                (hir::AssocItemKind::Const, default.is_some())
-            }
-            TraitItemKind::Type(_, ref default) => {
-                (hir::AssocItemKind::Type, default.is_some())
-            }
-            TraitItemKind::Method(ref sig, ref default) => (
-                hir::AssocItemKind::Method {
-                    has_self: sig.decl.has_self(),
-                },
-                default.is_some(),
-            ),
-            TraitItemKind::Macro(..) => unimplemented!(),
-        };
-        hir::TraitItemRef {
-            id: hir::TraitItemId { hir_id: self.lower_node_id(i.id) },
-            ident: i.ident,
-            span: i.span,
-            defaultness: self.lower_defaultness(Defaultness::Default, has_default),
-            kind,
-        }
-    }
-
-    fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
-        let impl_item_def_id = self.resolver.definitions().local_def_id(i.id);
-
-        let (generics, node) = match i.node {
-            ImplItemKind::Const(ref ty, ref expr) => (
-                self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
-                hir::ImplItemKind::Const(
-                    self.lower_ty(ty, ImplTraitContext::disallowed()),
-                    self.lower_const_body(expr),
-                ),
-            ),
-            ImplItemKind::Method(ref sig, ref body) => {
-                self.current_item = Some(i.span);
-                let body_id = self.lower_maybe_async_body(
-                    &sig.decl, sig.header.asyncness.node, body
-                );
-                let impl_trait_return_allow = !self.is_in_trait_impl;
-                let (generics, sig) = self.lower_method_sig(
-                    &i.generics,
-                    sig,
-                    impl_item_def_id,
-                    impl_trait_return_allow,
-                    sig.header.asyncness.node.opt_return_id(),
-                );
-
-                (generics, hir::ImplItemKind::Method(sig, body_id))
-            }
-            ImplItemKind::TyAlias(ref ty) => (
-                self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
-                hir::ImplItemKind::TyAlias(self.lower_ty(ty, ImplTraitContext::disallowed())),
-            ),
-            ImplItemKind::OpaqueTy(ref bounds) => (
-                self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
-                hir::ImplItemKind::OpaqueTy(
-                    self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
-                ),
-            ),
-            ImplItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"),
-        };
-
-        hir::ImplItem {
-            hir_id: self.lower_node_id(i.id),
-            ident: i.ident,
-            attrs: self.lower_attrs(&i.attrs),
-            generics,
-            vis: self.lower_visibility(&i.vis, None),
-            defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
-            node,
-            span: i.span,
-        }
-
-        // [1] since `default impl` is not yet implemented, this is always true in impls
-    }
-
-    fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
-        hir::ImplItemRef {
-            id: hir::ImplItemId { hir_id: self.lower_node_id(i.id) },
-            ident: i.ident,
-            span: i.span,
-            vis: self.lower_visibility(&i.vis, Some(i.id)),
-            defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
-            kind: match i.node {
-                ImplItemKind::Const(..) => hir::AssocItemKind::Const,
-                ImplItemKind::TyAlias(..) => hir::AssocItemKind::Type,
-                ImplItemKind::OpaqueTy(..) => hir::AssocItemKind::OpaqueTy,
-                ImplItemKind::Method(ref sig, _) => hir::AssocItemKind::Method {
-                    has_self: sig.decl.has_self(),
-                },
-                ImplItemKind::Macro(..) => unimplemented!(),
-            },
-        }
-
-        // [1] since `default impl` is not yet implemented, this is always true in impls
-    }
-
-    fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
-        hir::Mod {
-            inner: m.inner,
-            item_ids: m.items.iter().flat_map(|x| self.lower_item_id(x)).collect(),
-        }
-    }
-
-    fn lower_item_id(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
-        let node_ids = match i.node {
-            ItemKind::Use(ref use_tree) => {
-                let mut vec = smallvec![i.id];
-                self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
-                vec
-            }
-            ItemKind::MacroDef(..) => SmallVec::new(),
-            ItemKind::Fn(..) |
-            ItemKind::Impl(.., None, _, _) => smallvec![i.id],
-            ItemKind::Static(ref ty, ..) => {
-                let mut ids = smallvec![i.id];
-                if self.sess.features_untracked().impl_trait_in_bindings {
-                    let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
-                    visitor.visit_ty(ty);
-                }
-                ids
-            },
-            ItemKind::Const(ref ty, ..) => {
-                let mut ids = smallvec![i.id];
-                if self.sess.features_untracked().impl_trait_in_bindings {
-                    let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
-                    visitor.visit_ty(ty);
-                }
-                ids
-            },
-            _ => smallvec![i.id],
-        };
-
-        node_ids.into_iter().map(|node_id| hir::ItemId {
-            id: self.allocate_hir_id_counter(node_id)
-        }).collect()
-    }
-
-    fn lower_item_id_use_tree(&mut self,
-                              tree: &UseTree,
-                              base_id: NodeId,
-                              vec: &mut SmallVec<[NodeId; 1]>)
-    {
-        match tree.kind {
-            UseTreeKind::Nested(ref nested_vec) => for &(ref nested, id) in nested_vec {
-                vec.push(id);
-                self.lower_item_id_use_tree(nested, id, vec);
-            },
-            UseTreeKind::Glob => {}
-            UseTreeKind::Simple(_, id1, id2) => {
-                for (_, &id) in self.expect_full_res_from_use(base_id)
-                                    .skip(1)
-                                    .zip([id1, id2].iter())
-                {
-                    vec.push(id);
-                }
-            },
-        }
-    }
-
-    pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
-        let mut ident = i.ident;
-        let mut vis = self.lower_visibility(&i.vis, None);
-        let mut attrs = self.lower_attrs_extendable(&i.attrs);
-        if self.resolver.has_derives(i.id, SpecialDerives::PARTIAL_EQ | SpecialDerives::EQ) {
-            // Add `#[structural_match]` if the item derived both `PartialEq` and `Eq`.
-            let ident = Ident::new(sym::structural_match, i.span);
-            attrs.push(attr::mk_attr_outer(attr::mk_word_item(ident)));
-        }
-        let attrs = attrs.into();
-
-        if let ItemKind::MacroDef(ref def) = i.node {
-            if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) {
-                let body = self.lower_token_stream(def.stream());
-                let hir_id = self.lower_node_id(i.id);
-                self.exported_macros.push(hir::MacroDef {
-                    name: ident.name,
-                    vis,
-                    attrs,
-                    hir_id,
-                    span: i.span,
-                    body,
-                    legacy: def.legacy,
-                });
-            } else {
-                self.non_exported_macro_attrs.extend(attrs.into_iter());
-            }
-            return None;
-        }
-
-        let node = self.lower_item_kind(i.id, &mut ident, &attrs, &mut vis, &i.node);
-
-        Some(hir::Item {
-            hir_id: self.lower_node_id(i.id),
-            ident,
-            attrs,
-            node,
-            vis,
-            span: i.span,
-        })
-    }
-
-    fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
-        let def_id = self.resolver.definitions().local_def_id(i.id);
-        hir::ForeignItem {
-            hir_id: self.lower_node_id(i.id),
-            ident: i.ident,
-            attrs: self.lower_attrs(&i.attrs),
-            node: match i.node {
-                ForeignItemKind::Fn(ref fdec, ref generics) => {
-                    let (generics, (fn_dec, fn_args)) = self.add_in_band_defs(
-                        generics,
-                        def_id,
-                        AnonymousLifetimeMode::PassThrough,
-                        |this, _| {
-                            (
-                                // Disallow impl Trait in foreign items
-                                this.lower_fn_decl(fdec, None, false, None),
-                                this.lower_fn_args_to_names(fdec),
-                            )
-                        },
-                    );
-
-                    hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
-                }
-                ForeignItemKind::Static(ref t, m) => {
-                    hir::ForeignItemKind::Static(
-                        self.lower_ty(t, ImplTraitContext::disallowed()), self.lower_mutability(m))
-                }
-                ForeignItemKind::Ty => hir::ForeignItemKind::Type,
-                ForeignItemKind::Macro(_) => panic!("shouldn't exist here"),
-            },
-            vis: self.lower_visibility(&i.vis, None),
-            span: i.span,
-        }
-    }
-
-    fn lower_method_sig(
-        &mut self,
-        generics: &Generics,
-        sig: &MethodSig,
-        fn_def_id: DefId,
-        impl_trait_return_allow: bool,
-        is_async: Option<NodeId>,
-    ) -> (hir::Generics, hir::MethodSig) {
-        let header = self.lower_fn_header(sig.header);
-        let (generics, decl) = self.add_in_band_defs(
-            generics,
-            fn_def_id,
-            AnonymousLifetimeMode::PassThrough,
-            |this, idty| this.lower_fn_decl(
-                &sig.decl,
-                Some((fn_def_id, idty)),
-                impl_trait_return_allow,
-                is_async,
-            ),
-        );
-        (generics, hir::MethodSig { header, decl })
-    }
-
-    fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto {
-        match a {
-            IsAuto::Yes => hir::IsAuto::Yes,
-            IsAuto::No => hir::IsAuto::No,
-        }
-    }
-
-    fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
-        hir::FnHeader {
-            unsafety: self.lower_unsafety(h.unsafety),
-            asyncness: self.lower_asyncness(h.asyncness.node),
-            constness: self.lower_constness(h.constness),
-            abi: h.abi,
-        }
-    }
-
-    fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
-        match u {
-            Unsafety::Unsafe => hir::Unsafety::Unsafe,
-            Unsafety::Normal => hir::Unsafety::Normal,
-        }
-    }
-
-    fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
-        match c.node {
-            Constness::Const => hir::Constness::Const,
-            Constness::NotConst => hir::Constness::NotConst,
-        }
-    }
-
-    fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {
-        match a {
-            IsAsync::Async { .. } => hir::IsAsync::Async,
-            IsAsync::NotAsync => hir::IsAsync::NotAsync,
-        }
-    }
-
     fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
         let node = match p.node {
             PatKind::Wild => hir::PatKind::Wild,
@@ -4370,55 +3012,6 @@ fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause {
         }
     }
 
-    /// If an `explicit_owner` is given, this method allocates the `HirId` in
-    /// the address space of that item instead of the item currently being
-    /// lowered. This can happen during `lower_impl_item_ref()` where we need to
-    /// lower a `Visibility` value although we haven't lowered the owning
-    /// `ImplItem` in question yet.
-    fn lower_visibility(
-        &mut self,
-        v: &Visibility,
-        explicit_owner: Option<NodeId>,
-    ) -> hir::Visibility {
-        let node = match v.node {
-            VisibilityKind::Public => hir::VisibilityKind::Public,
-            VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
-            VisibilityKind::Restricted { ref path, id } => {
-                debug!("lower_visibility: restricted path id = {:?}", id);
-                let lowered_id = if let Some(owner) = explicit_owner {
-                    self.lower_node_id_with_owner(id, owner)
-                } else {
-                    self.lower_node_id(id)
-                };
-                let res = self.expect_full_res(id);
-                let res = self.lower_res(res);
-                hir::VisibilityKind::Restricted {
-                    path: P(self.lower_path_extra(
-                        res,
-                        path,
-                        ParamMode::Explicit,
-                        explicit_owner,
-                    )),
-                    hir_id: lowered_id,
-                }
-            },
-            VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
-        };
-        respan(v.span, node)
-    }
-
-    fn lower_defaultness(&self, d: Defaultness, has_value: bool) -> hir::Defaultness {
-        match d {
-            Defaultness::Default => hir::Defaultness::Default {
-                has_value: has_value,
-            },
-            Defaultness::Final => {
-                assert!(has_value);
-                hir::Defaultness::Final
-            }
-        }
-    }
-
     fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
         match *b {
             BlockCheckMode::Default => hir::DefaultBlock,
@@ -4442,13 +3035,6 @@ fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource {
         }
     }
 
-    fn lower_impl_polarity(&mut self, i: ImplPolarity) -> hir::ImplPolarity {
-        match i {
-            ImplPolarity::Positive => hir::ImplPolarity::Positive,
-            ImplPolarity::Negative => hir::ImplPolarity::Negative,
-        }
-    }
-
     fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
         match f {
             TraitBoundModifier::None => hir::TraitBoundModifier::None,
index c76d714ffb4c9eeb43847df463fdc80f6d4ed024..96887ed85ae4cad1ad8277e9ca63651e37c2554f 100644 (file)
@@ -700,6 +700,46 @@ fn lower_expr_closure(
         })
     }
 
+    fn generator_movability_for_fn(
+        &mut self,
+        decl: &ast::FnDecl,
+        fn_decl_span: Span,
+        generator_kind: Option<hir::GeneratorKind>,
+        movability: Movability,
+    ) -> Option<hir::GeneratorMovability> {
+        match generator_kind {
+            Some(hir::GeneratorKind::Gen) =>  {
+                if !decl.inputs.is_empty() {
+                    span_err!(
+                        self.sess,
+                        fn_decl_span,
+                        E0628,
+                        "generators cannot have explicit arguments"
+                    );
+                    self.sess.abort_if_errors();
+                }
+                Some(match movability {
+                    Movability::Movable => hir::GeneratorMovability::Movable,
+                    Movability::Static => hir::GeneratorMovability::Static,
+                })
+            },
+            Some(hir::GeneratorKind::Async) => {
+                bug!("non-`async` closure body turned `async` during lowering");
+            },
+            None => {
+                if movability == Movability::Static {
+                    span_err!(
+                        self.sess,
+                        fn_decl_span,
+                        E0697,
+                        "closures cannot be static"
+                    );
+                }
+                None
+            },
+        }
+    }
+
     fn lower_expr_async_closure(
         &mut self,
         capture_clause: CaptureBy,
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
new file mode 100644 (file)
index 0000000..819fbf7
--- /dev/null
@@ -0,0 +1,1401 @@
+use super::LoweringContext;
+use super::ImplTraitContext;
+use super::ImplTraitPosition;
+use super::ImplTraitTypeIdVisitor;
+use super::AnonymousLifetimeMode;
+use super::ParamMode;
+
+use crate::hir::{self, HirVec};
+use crate::hir::ptr::P;
+use crate::hir::def_id::DefId;
+use crate::hir::def::{Res, DefKind};
+use crate::util::nodemap::NodeMap;
+
+use rustc_data_structures::thin_vec::ThinVec;
+
+use std::collections::BTreeSet;
+use smallvec::SmallVec;
+use syntax::attr;
+use syntax::ast::*;
+use syntax::visit::{self, Visitor};
+use syntax::ext::base::SpecialDerives;
+use syntax::source_map::{respan, DesugaringKind, Spanned};
+use syntax::symbol::{kw, sym};
+use syntax_pos::Span;
+
+pub(super) struct ItemLowerer<'tcx, 'interner> {
+    pub(super) lctx: &'tcx mut LoweringContext<'interner>,
+}
+
+impl<'tcx, 'interner> ItemLowerer<'tcx, 'interner> {
+    fn with_trait_impl_ref<F>(&mut self, trait_impl_ref: &Option<TraitRef>, f: F)
+    where
+        F: FnOnce(&mut Self),
+    {
+        let old = self.lctx.is_in_trait_impl;
+        self.lctx.is_in_trait_impl = if let &None = trait_impl_ref {
+            false
+        } else {
+            true
+        };
+        f(self);
+        self.lctx.is_in_trait_impl = old;
+    }
+}
+
+impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> {
+    fn visit_mod(&mut self, m: &'tcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
+        self.lctx.modules.insert(n, hir::ModuleItems {
+            items: BTreeSet::new(),
+            trait_items: BTreeSet::new(),
+            impl_items: BTreeSet::new(),
+        });
+
+        let old = self.lctx.current_module;
+        self.lctx.current_module = n;
+        visit::walk_mod(self, m);
+        self.lctx.current_module = old;
+    }
+
+    fn visit_item(&mut self, item: &'tcx Item) {
+        let mut item_hir_id = None;
+        self.lctx.with_hir_id_owner(item.id, |lctx| {
+            if let Some(hir_item) = lctx.lower_item(item) {
+                item_hir_id = Some(hir_item.hir_id);
+                lctx.insert_item(hir_item);
+            }
+        });
+
+        if let Some(hir_id) = item_hir_id {
+            self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
+                let this = &mut ItemLowerer { lctx: this };
+                if let ItemKind::Impl(.., ref opt_trait_ref, _, _) = item.node {
+                    this.with_trait_impl_ref(opt_trait_ref, |this| {
+                        visit::walk_item(this, item)
+                    });
+                } else {
+                    visit::walk_item(this, item);
+                }
+            });
+        }
+    }
+
+    fn visit_trait_item(&mut self, item: &'tcx TraitItem) {
+        self.lctx.with_hir_id_owner(item.id, |lctx| {
+            let hir_item = lctx.lower_trait_item(item);
+            let id = hir::TraitItemId { hir_id: hir_item.hir_id };
+            lctx.trait_items.insert(id, hir_item);
+            lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id);
+        });
+
+        visit::walk_trait_item(self, item);
+    }
+
+    fn visit_impl_item(&mut self, item: &'tcx ImplItem) {
+        self.lctx.with_hir_id_owner(item.id, |lctx| {
+            let hir_item = lctx.lower_impl_item(item);
+            let id = hir::ImplItemId { hir_id: hir_item.hir_id };
+            lctx.impl_items.insert(id, hir_item);
+            lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id);
+        });
+        visit::walk_impl_item(self, item);
+    }
+}
+
+impl LoweringContext<'_> {
+    // Same as the method above, but accepts `hir::GenericParam`s
+    // instead of `ast::GenericParam`s.
+    // This should only be used with generics that have already had their
+    // in-band lifetimes added. In practice, this means that this function is
+    // only used when lowering a child item of a trait or impl.
+    fn with_parent_item_lifetime_defs<T>(
+        &mut self,
+        parent_hir_id: hir::HirId,
+        f: impl FnOnce(&mut LoweringContext<'_>) -> T,
+    ) -> T {
+        let old_len = self.in_scope_lifetimes.len();
+
+        let parent_generics = match self.items.get(&parent_hir_id).unwrap().node {
+            hir::ItemKind::Impl(_, _, _, ref generics, ..)
+            | hir::ItemKind::Trait(_, _, ref generics, ..) => {
+                &generics.params[..]
+            }
+            _ => &[],
+        };
+        let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind {
+            hir::GenericParamKind::Lifetime { .. } => Some(param.name.ident().modern()),
+            _ => None,
+        });
+        self.in_scope_lifetimes.extend(lt_def_names);
+
+        let res = f(self);
+
+        self.in_scope_lifetimes.truncate(old_len);
+        res
+    }
+
+    pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
+        hir::Mod {
+            inner: m.inner,
+            item_ids: m.items.iter().flat_map(|x| self.lower_item_id(x)).collect(),
+        }
+    }
+
+    pub(super) fn lower_item_id(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
+        let node_ids = match i.node {
+            ItemKind::Use(ref use_tree) => {
+                let mut vec = smallvec![i.id];
+                self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
+                vec
+            }
+            ItemKind::MacroDef(..) => SmallVec::new(),
+            ItemKind::Fn(..) |
+            ItemKind::Impl(.., None, _, _) => smallvec![i.id],
+            ItemKind::Static(ref ty, ..) => {
+                let mut ids = smallvec![i.id];
+                if self.sess.features_untracked().impl_trait_in_bindings {
+                    let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
+                    visitor.visit_ty(ty);
+                }
+                ids
+            },
+            ItemKind::Const(ref ty, ..) => {
+                let mut ids = smallvec![i.id];
+                if self.sess.features_untracked().impl_trait_in_bindings {
+                    let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
+                    visitor.visit_ty(ty);
+                }
+                ids
+            },
+            _ => smallvec![i.id],
+        };
+
+        node_ids.into_iter().map(|node_id| hir::ItemId {
+            id: self.allocate_hir_id_counter(node_id)
+        }).collect()
+    }
+
+    fn lower_item_id_use_tree(
+        &mut self,
+        tree: &UseTree,
+        base_id: NodeId,
+        vec: &mut SmallVec<[NodeId; 1]>
+    ) {
+        match tree.kind {
+            UseTreeKind::Nested(ref nested_vec) => for &(ref nested, id) in nested_vec {
+                vec.push(id);
+                self.lower_item_id_use_tree(nested, id, vec);
+            },
+            UseTreeKind::Glob => {}
+            UseTreeKind::Simple(_, id1, id2) => {
+                for (_, &id) in self.expect_full_res_from_use(base_id)
+                                    .skip(1)
+                                    .zip([id1, id2].iter())
+                {
+                    vec.push(id);
+                }
+            },
+        }
+    }
+
+    pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
+        let mut ident = i.ident;
+        let mut vis = self.lower_visibility(&i.vis, None);
+        let mut attrs = self.lower_attrs_extendable(&i.attrs);
+        if self.resolver.has_derives(i.id, SpecialDerives::PARTIAL_EQ | SpecialDerives::EQ) {
+            // Add `#[structural_match]` if the item derived both `PartialEq` and `Eq`.
+            let ident = Ident::new(sym::structural_match, i.span);
+            attrs.push(attr::mk_attr_outer(attr::mk_word_item(ident)));
+        }
+        let attrs = attrs.into();
+
+        if let ItemKind::MacroDef(ref def) = i.node {
+            if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) {
+                let body = self.lower_token_stream(def.stream());
+                let hir_id = self.lower_node_id(i.id);
+                self.exported_macros.push(hir::MacroDef {
+                    name: ident.name,
+                    vis,
+                    attrs,
+                    hir_id,
+                    span: i.span,
+                    body,
+                    legacy: def.legacy,
+                });
+            } else {
+                self.non_exported_macro_attrs.extend(attrs.into_iter());
+            }
+            return None;
+        }
+
+        let node = self.lower_item_kind(i.id, &mut ident, &attrs, &mut vis, &i.node);
+
+        Some(hir::Item {
+            hir_id: self.lower_node_id(i.id),
+            ident,
+            attrs,
+            node,
+            vis,
+            span: i.span,
+        })
+    }
+
+    fn lower_item_kind(
+        &mut self,
+        id: NodeId,
+        ident: &mut Ident,
+        attrs: &hir::HirVec<Attribute>,
+        vis: &mut hir::Visibility,
+        i: &ItemKind,
+    ) -> hir::ItemKind {
+        match *i {
+            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,
+                };
+
+                self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs)
+            }
+            ItemKind::Static(ref t, m, ref e) => {
+                hir::ItemKind::Static(
+                    self.lower_ty(
+                        t,
+                        if self.sess.features_untracked().impl_trait_in_bindings {
+                            ImplTraitContext::OpaqueTy(None)
+                        } else {
+                            ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
+                        }
+                    ),
+                    self.lower_mutability(m),
+                    self.lower_const_body(e),
+                )
+            }
+            ItemKind::Const(ref t, ref e) => {
+                hir::ItemKind::Const(
+                    self.lower_ty(
+                        t,
+                        if self.sess.features_untracked().impl_trait_in_bindings {
+                            ImplTraitContext::OpaqueTy(None)
+                        } else {
+                            ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
+                        }
+                    ),
+                    self.lower_const_body(e)
+                )
+            }
+            ItemKind::Fn(ref decl, header, ref generics, ref body) => {
+                let fn_def_id = self.resolver.definitions().local_def_id(id);
+                self.with_new_scopes(|this| {
+                    this.current_item = Some(ident.span);
+
+                    // Note: we don't need to change the return type from `T` to
+                    // `impl Future<Output = T>` here because lower_body
+                    // only cares about the input argument patterns in the function
+                    // declaration (decl), not the return types.
+                    let body_id = this.lower_maybe_async_body(&decl, header.asyncness.node, body);
+
+                    let (generics, fn_decl) = this.add_in_band_defs(
+                        generics,
+                        fn_def_id,
+                        AnonymousLifetimeMode::PassThrough,
+                        |this, idty| this.lower_fn_decl(
+                            &decl,
+                            Some((fn_def_id, idty)),
+                            true,
+                            header.asyncness.node.opt_return_id()
+                        ),
+                    );
+
+                    hir::ItemKind::Fn(
+                        fn_decl,
+                        this.lower_fn_header(header),
+                        generics,
+                        body_id,
+                    )
+                })
+            }
+            ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
+            ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
+            ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
+            ItemKind::TyAlias(ref t, ref generics) => hir::ItemKind::TyAlias(
+                self.lower_ty(t, ImplTraitContext::disallowed()),
+                self.lower_generics(generics, ImplTraitContext::disallowed()),
+            ),
+            ItemKind::OpaqueTy(ref b, ref generics) => hir::ItemKind::OpaqueTy(
+                hir::OpaqueTy {
+                    generics: self.lower_generics(generics,
+                        ImplTraitContext::OpaqueTy(None)),
+                    bounds: self.lower_param_bounds(b,
+                        ImplTraitContext::OpaqueTy(None)),
+                    impl_trait_fn: None,
+                    origin: hir::OpaqueTyOrigin::TypeAlias,
+                },
+            ),
+            ItemKind::Enum(ref enum_definition, ref generics) => {
+                hir::ItemKind::Enum(
+                    hir::EnumDef {
+                        variants: enum_definition
+                            .variants
+                            .iter()
+                            .map(|x| self.lower_variant(x))
+                            .collect(),
+                    },
+                    self.lower_generics(generics, ImplTraitContext::disallowed()),
+                )
+            },
+            ItemKind::Struct(ref struct_def, ref generics) => {
+                let struct_def = self.lower_variant_data(struct_def);
+                hir::ItemKind::Struct(
+                    struct_def,
+                    self.lower_generics(generics, ImplTraitContext::disallowed()),
+                )
+            }
+            ItemKind::Union(ref vdata, ref generics) => {
+                let vdata = self.lower_variant_data(vdata);
+                hir::ItemKind::Union(
+                    vdata,
+                    self.lower_generics(generics, ImplTraitContext::disallowed()),
+                )
+            }
+            ItemKind::Impl(
+                unsafety,
+                polarity,
+                defaultness,
+                ref ast_generics,
+                ref trait_ref,
+                ref ty,
+                ref impl_items,
+            ) => {
+                let def_id = self.resolver.definitions().local_def_id(id);
+
+                // Lower the "impl header" first. This ordering is important
+                // for in-band lifetimes! Consider `'a` here:
+                //
+                //     impl Foo<'a> for u32 {
+                //         fn method(&'a self) { .. }
+                //     }
+                //
+                // Because we start by lowering the `Foo<'a> for u32`
+                // part, we will add `'a` to the list of generics on
+                // the impl. When we then encounter it later in the
+                // method, it will not be considered an in-band
+                // lifetime to be added, but rather a reference to a
+                // parent lifetime.
+                let lowered_trait_impl_id = self.lower_node_id(id);
+                let (generics, (trait_ref, lowered_ty)) = self.add_in_band_defs(
+                    ast_generics,
+                    def_id,
+                    AnonymousLifetimeMode::CreateParameter,
+                    |this, _| {
+                        let trait_ref = trait_ref.as_ref().map(|trait_ref| {
+                            this.lower_trait_ref(trait_ref, ImplTraitContext::disallowed())
+                        });
+
+                        if let Some(ref trait_ref) = trait_ref {
+                            if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res {
+                                this.trait_impls.entry(def_id).or_default().push(
+                                    lowered_trait_impl_id);
+                            }
+                        }
+
+                        let lowered_ty = this.lower_ty(ty, ImplTraitContext::disallowed());
+
+                        (trait_ref, lowered_ty)
+                    },
+                );
+
+                let new_impl_items = self.with_in_scope_lifetime_defs(
+                    &ast_generics.params,
+                    |this| {
+                        impl_items
+                            .iter()
+                            .map(|item| this.lower_impl_item_ref(item))
+                            .collect()
+                    },
+                );
+
+                hir::ItemKind::Impl(
+                    self.lower_unsafety(unsafety),
+                    self.lower_impl_polarity(polarity),
+                    self.lower_defaultness(defaultness, true /* [1] */),
+                    generics,
+                    trait_ref,
+                    lowered_ty,
+                    new_impl_items,
+                )
+            }
+            ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
+                let bounds = self.lower_param_bounds(bounds, ImplTraitContext::disallowed());
+                let items = items
+                    .iter()
+                    .map(|item| self.lower_trait_item_ref(item))
+                    .collect();
+                hir::ItemKind::Trait(
+                    self.lower_is_auto(is_auto),
+                    self.lower_unsafety(unsafety),
+                    self.lower_generics(generics, ImplTraitContext::disallowed()),
+                    bounds,
+                    items,
+                )
+            }
+            ItemKind::TraitAlias(ref generics, ref bounds) => hir::ItemKind::TraitAlias(
+                self.lower_generics(generics, ImplTraitContext::disallowed()),
+                self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
+            ),
+            ItemKind::MacroDef(..)
+            | ItemKind::Mac(..) => bug!("`TyMac` should have been expanded by now"),
+        }
+
+        // [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to
+        //     not cause an assertion failure inside the `lower_defaultness` function.
+    }
+
+    fn lower_use_tree(
+        &mut self,
+        tree: &UseTree,
+        prefix: &Path,
+        id: NodeId,
+        vis: &mut hir::Visibility,
+        ident: &mut Ident,
+        attrs: &hir::HirVec<Attribute>,
+    ) -> hir::ItemKind {
+        debug!("lower_use_tree(tree={:?})", tree);
+        debug!("lower_use_tree: vis = {:?}", vis);
+
+        let path = &tree.prefix;
+        let segments = prefix
+            .segments
+            .iter()
+            .chain(path.segments.iter())
+            .cloned()
+            .collect();
+
+        match tree.kind {
+            UseTreeKind::Simple(rename, id1, id2) => {
+                *ident = tree.ident();
+
+                // First, apply the prefix to the path.
+                let mut path = Path {
+                    segments,
+                    span: path.span,
+                };
+
+                // Correctly resolve `self` imports.
+                if path.segments.len() > 1
+                    && path.segments.last().unwrap().ident.name == kw::SelfLower
+                {
+                    let _ = path.segments.pop();
+                    if rename.is_none() {
+                        *ident = path.segments.last().unwrap().ident;
+                    }
+                }
+
+                let mut resolutions = self.expect_full_res_from_use(id);
+                // We want to return *something* from this function, so hold onto the first item
+                // for later.
+                let ret_res = self.lower_res(resolutions.next().unwrap_or(Res::Err));
+
+                // Here, we are looping over namespaces, if they exist for the definition
+                // being imported. We only handle type and value namespaces because we
+                // won't be dealing with macros in the rest of the compiler.
+                // Essentially a single `use` which imports two names is desugared into
+                // two imports.
+                for (res, &new_node_id) in resolutions.zip([id1, id2].iter()) {
+                    let ident = *ident;
+                    let mut path = path.clone();
+                    for seg in &mut path.segments {
+                        seg.id = self.sess.next_node_id();
+                    }
+                    let span = path.span;
+
+                    self.with_hir_id_owner(new_node_id, |this| {
+                        let new_id = this.lower_node_id(new_node_id);
+                        let res = this.lower_res(res);
+                        let path =
+                            this.lower_path_extra(res, &path, ParamMode::Explicit, None);
+                        let item = hir::ItemKind::Use(P(path), hir::UseKind::Single);
+                        let vis = this.rebuild_vis(&vis);
+
+                        this.insert_item(
+                            hir::Item {
+                                hir_id: new_id,
+                                ident,
+                                attrs: attrs.into_iter().cloned().collect(),
+                                node: item,
+                                vis,
+                                span,
+                            },
+                        );
+                    });
+                }
+
+                let path =
+                    P(self.lower_path_extra(ret_res, &path, ParamMode::Explicit, None));
+                hir::ItemKind::Use(path, hir::UseKind::Single)
+            }
+            UseTreeKind::Glob => {
+                let path = P(self.lower_path(
+                    id,
+                    &Path {
+                        segments,
+                        span: path.span,
+                    },
+                    ParamMode::Explicit,
+                ));
+                hir::ItemKind::Use(path, hir::UseKind::Glob)
+            }
+            UseTreeKind::Nested(ref trees) => {
+                // Nested imports are desugared into simple imports.
+                // So, if we start with
+                //
+                // ```
+                // pub(x) use foo::{a, b};
+                // ```
+                //
+                // we will create three items:
+                //
+                // ```
+                // pub(x) use foo::a;
+                // pub(x) use foo::b;
+                // pub(x) use foo::{}; // <-- this is called the `ListStem`
+                // ```
+                //
+                // The first two are produced by recursively invoking
+                // `lower_use_tree` (and indeed there may be things
+                // like `use foo::{a::{b, c}}` and so forth).  They
+                // wind up being directly added to
+                // `self.items`. However, the structure of this
+                // function also requires us to return one item, and
+                // for that we return the `{}` import (called the
+                // `ListStem`).
+
+                let prefix = Path {
+                    segments,
+                    span: prefix.span.to(path.span),
+                };
+
+                // Add all the nested `PathListItem`s to the HIR.
+                for &(ref use_tree, id) in trees {
+                    let new_hir_id = self.lower_node_id(id);
+
+                    let mut prefix = prefix.clone();
+
+                    // Give the segments new node-ids since they are being cloned.
+                    for seg in &mut prefix.segments {
+                        seg.id = self.sess.next_node_id();
+                    }
+
+                    // Each `use` import is an item and thus are owners of the
+                    // names in the path. Up to this point the nested import is
+                    // the current owner, since we want each desugared import to
+                    // own its own names, we have to adjust the owner before
+                    // lowering the rest of the import.
+                    self.with_hir_id_owner(id, |this| {
+                        let mut vis = this.rebuild_vis(&vis);
+                        let mut ident = *ident;
+
+                        let item = this.lower_use_tree(use_tree,
+                                                       &prefix,
+                                                       id,
+                                                       &mut vis,
+                                                       &mut ident,
+                                                       attrs);
+
+                        this.insert_item(
+                            hir::Item {
+                                hir_id: new_hir_id,
+                                ident,
+                                attrs: attrs.into_iter().cloned().collect(),
+                                node: item,
+                                vis,
+                                span: use_tree.span,
+                            },
+                        );
+                    });
+                }
+
+                // Subtle and a bit hacky: we lower the privacy level
+                // of the list stem to "private" most of the time, but
+                // not for "restricted" paths. The key thing is that
+                // we don't want it to stay as `pub` (with no caveats)
+                // because that affects rustdoc and also the lints
+                // about `pub` items. But we can't *always* make it
+                // private -- particularly not for restricted paths --
+                // because it contains node-ids that would then be
+                // unused, failing the check that HirIds are "densely
+                // assigned".
+                match vis.node {
+                    hir::VisibilityKind::Public |
+                    hir::VisibilityKind::Crate(_) |
+                    hir::VisibilityKind::Inherited => {
+                        *vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited);
+                    }
+                    hir::VisibilityKind::Restricted { .. } => {
+                        // Do nothing here, as described in the comment on the match.
+                    }
+                }
+
+                let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err);
+                let res = self.lower_res(res);
+                let path = P(self.lower_path_extra(res, &prefix, ParamMode::Explicit, None));
+                hir::ItemKind::Use(path, hir::UseKind::ListStem)
+            }
+        }
+    }
+
+    /// Paths like the visibility path in `pub(super) use foo::{bar, baz}` are repeated
+    /// many times in the HIR tree; for each occurrence, we need to assign distinct
+    /// `NodeId`s. (See, e.g., #56128.)
+    fn rebuild_use_path(&mut self, path: &hir::Path) -> hir::Path {
+        debug!("rebuild_use_path(path = {:?})", path);
+        let segments = path.segments.iter().map(|seg| hir::PathSegment {
+            ident: seg.ident,
+            hir_id: seg.hir_id.map(|_| self.next_id()),
+            res: seg.res,
+            args: None,
+            infer_args: seg.infer_args,
+        }).collect();
+        hir::Path {
+            span: path.span,
+            res: path.res,
+            segments,
+        }
+    }
+
+    fn rebuild_vis(&mut self, vis: &hir::Visibility) -> hir::Visibility {
+        let vis_kind = match vis.node {
+            hir::VisibilityKind::Public => hir::VisibilityKind::Public,
+            hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
+            hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
+            hir::VisibilityKind::Restricted { ref path, hir_id: _ } => {
+                hir::VisibilityKind::Restricted {
+                    path: P(self.rebuild_use_path(path)),
+                    hir_id: self.next_id(),
+                }
+            }
+        };
+        respan(vis.span, vis_kind)
+    }
+
+    fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
+        let def_id = self.resolver.definitions().local_def_id(i.id);
+        hir::ForeignItem {
+            hir_id: self.lower_node_id(i.id),
+            ident: i.ident,
+            attrs: self.lower_attrs(&i.attrs),
+            node: match i.node {
+                ForeignItemKind::Fn(ref fdec, ref generics) => {
+                    let (generics, (fn_dec, fn_args)) = self.add_in_band_defs(
+                        generics,
+                        def_id,
+                        AnonymousLifetimeMode::PassThrough,
+                        |this, _| {
+                            (
+                                // Disallow impl Trait in foreign items
+                                this.lower_fn_decl(fdec, None, false, None),
+                                this.lower_fn_args_to_names(fdec),
+                            )
+                        },
+                    );
+
+                    hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
+                }
+                ForeignItemKind::Static(ref t, m) => {
+                    hir::ForeignItemKind::Static(
+                        self.lower_ty(t, ImplTraitContext::disallowed()), self.lower_mutability(m))
+                }
+                ForeignItemKind::Ty => hir::ForeignItemKind::Type,
+                ForeignItemKind::Macro(_) => panic!("shouldn't exist here"),
+            },
+            vis: self.lower_visibility(&i.vis, None),
+            span: i.span,
+        }
+    }
+
+    fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
+        hir::ForeignMod {
+            abi: fm.abi,
+            items: fm.items
+                .iter()
+                .map(|x| self.lower_foreign_item(x))
+                .collect(),
+        }
+    }
+
+    fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> {
+        P(hir::GlobalAsm {
+            asm: ga.asm,
+            ctxt: ga.ctxt,
+        })
+    }
+
+    fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
+        Spanned {
+            node: hir::VariantKind {
+                ident: v.node.ident,
+                id: self.lower_node_id(v.node.id),
+                attrs: self.lower_attrs(&v.node.attrs),
+                data: self.lower_variant_data(&v.node.data),
+                disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
+            },
+            span: v.span,
+        }
+    }
+
+    fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
+        match *vdata {
+            VariantData::Struct(ref fields, recovered) => hir::VariantData::Struct(
+                fields.iter().enumerate().map(|f| self.lower_struct_field(f)).collect(),
+                recovered,
+            ),
+            VariantData::Tuple(ref fields, id) => {
+                hir::VariantData::Tuple(
+                    fields
+                        .iter()
+                        .enumerate()
+                        .map(|f| self.lower_struct_field(f))
+                        .collect(),
+                    self.lower_node_id(id),
+                )
+            },
+            VariantData::Unit(id) => {
+                hir::VariantData::Unit(self.lower_node_id(id))
+            },
+        }
+    }
+
+    fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField {
+        let ty = if let TyKind::Path(ref qself, ref path) = f.ty.node {
+            let t = self.lower_path_ty(
+                &f.ty,
+                qself,
+                path,
+                ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124)
+                ImplTraitContext::disallowed()
+            );
+            P(t)
+        } else {
+            self.lower_ty(&f.ty, ImplTraitContext::disallowed())
+        };
+        hir::StructField {
+            span: f.span,
+            hir_id: self.lower_node_id(f.id),
+            ident: match f.ident {
+                Some(ident) => ident,
+                // FIXME(jseyfried): positional field hygiene.
+                None => Ident::new(sym::integer(index), f.span),
+            },
+            vis: self.lower_visibility(&f.vis, None),
+            ty,
+            attrs: self.lower_attrs(&f.attrs),
+        }
+    }
+
+    fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
+        let trait_item_def_id = self.resolver.definitions().local_def_id(i.id);
+
+        let (generics, node) = match i.node {
+            TraitItemKind::Const(ref ty, ref default) => (
+                self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
+                hir::TraitItemKind::Const(
+                    self.lower_ty(ty, ImplTraitContext::disallowed()),
+                    default
+                        .as_ref()
+                        .map(|x| self.lower_const_body(x)),
+                ),
+            ),
+            TraitItemKind::Method(ref sig, None) => {
+                let names = self.lower_fn_args_to_names(&sig.decl);
+                let (generics, sig) = self.lower_method_sig(
+                    &i.generics,
+                    sig,
+                    trait_item_def_id,
+                    false,
+                    None,
+                );
+                (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names)))
+            }
+            TraitItemKind::Method(ref sig, Some(ref body)) => {
+                let body_id = self.lower_fn_body_block(&sig.decl, body);
+                let (generics, sig) = self.lower_method_sig(
+                    &i.generics,
+                    sig,
+                    trait_item_def_id,
+                    false,
+                    None,
+                );
+                (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id)))
+            }
+            TraitItemKind::Type(ref bounds, ref default) => {
+                let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed());
+                let node = hir::TraitItemKind::Type(
+                    self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
+                    default
+                        .as_ref()
+                        .map(|x| self.lower_ty(x, ImplTraitContext::disallowed())),
+                );
+
+                (generics, node)
+            },
+            TraitItemKind::Macro(..) => bug!("macro item shouldn't exist at this point"),
+        };
+
+        hir::TraitItem {
+            hir_id: self.lower_node_id(i.id),
+            ident: i.ident,
+            attrs: self.lower_attrs(&i.attrs),
+            generics,
+            node,
+            span: i.span,
+        }
+    }
+
+    fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef {
+        let (kind, has_default) = match i.node {
+            TraitItemKind::Const(_, ref default) => {
+                (hir::AssocItemKind::Const, default.is_some())
+            }
+            TraitItemKind::Type(_, ref default) => {
+                (hir::AssocItemKind::Type, default.is_some())
+            }
+            TraitItemKind::Method(ref sig, ref default) => (
+                hir::AssocItemKind::Method {
+                    has_self: sig.decl.has_self(),
+                },
+                default.is_some(),
+            ),
+            TraitItemKind::Macro(..) => unimplemented!(),
+        };
+        hir::TraitItemRef {
+            id: hir::TraitItemId { hir_id: self.lower_node_id(i.id) },
+            ident: i.ident,
+            span: i.span,
+            defaultness: self.lower_defaultness(Defaultness::Default, has_default),
+            kind,
+        }
+    }
+
+    fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
+        let impl_item_def_id = self.resolver.definitions().local_def_id(i.id);
+
+        let (generics, node) = match i.node {
+            ImplItemKind::Const(ref ty, ref expr) => (
+                self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
+                hir::ImplItemKind::Const(
+                    self.lower_ty(ty, ImplTraitContext::disallowed()),
+                    self.lower_const_body(expr),
+                ),
+            ),
+            ImplItemKind::Method(ref sig, ref body) => {
+                self.current_item = Some(i.span);
+                let body_id = self.lower_maybe_async_body(
+                    &sig.decl, sig.header.asyncness.node, body
+                );
+                let impl_trait_return_allow = !self.is_in_trait_impl;
+                let (generics, sig) = self.lower_method_sig(
+                    &i.generics,
+                    sig,
+                    impl_item_def_id,
+                    impl_trait_return_allow,
+                    sig.header.asyncness.node.opt_return_id(),
+                );
+
+                (generics, hir::ImplItemKind::Method(sig, body_id))
+            }
+            ImplItemKind::TyAlias(ref ty) => (
+                self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
+                hir::ImplItemKind::TyAlias(self.lower_ty(ty, ImplTraitContext::disallowed())),
+            ),
+            ImplItemKind::OpaqueTy(ref bounds) => (
+                self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
+                hir::ImplItemKind::OpaqueTy(
+                    self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
+                ),
+            ),
+            ImplItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"),
+        };
+
+        hir::ImplItem {
+            hir_id: self.lower_node_id(i.id),
+            ident: i.ident,
+            attrs: self.lower_attrs(&i.attrs),
+            generics,
+            vis: self.lower_visibility(&i.vis, None),
+            defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
+            node,
+            span: i.span,
+        }
+
+        // [1] since `default impl` is not yet implemented, this is always true in impls
+    }
+
+    fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
+        hir::ImplItemRef {
+            id: hir::ImplItemId { hir_id: self.lower_node_id(i.id) },
+            ident: i.ident,
+            span: i.span,
+            vis: self.lower_visibility(&i.vis, Some(i.id)),
+            defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
+            kind: match i.node {
+                ImplItemKind::Const(..) => hir::AssocItemKind::Const,
+                ImplItemKind::TyAlias(..) => hir::AssocItemKind::Type,
+                ImplItemKind::OpaqueTy(..) => hir::AssocItemKind::OpaqueTy,
+                ImplItemKind::Method(ref sig, _) => hir::AssocItemKind::Method {
+                    has_self: sig.decl.has_self(),
+                },
+                ImplItemKind::Macro(..) => unimplemented!(),
+            },
+        }
+
+        // [1] since `default impl` is not yet implemented, this is always true in impls
+    }
+
+    /// If an `explicit_owner` is given, this method allocates the `HirId` in
+    /// the address space of that item instead of the item currently being
+    /// lowered. This can happen during `lower_impl_item_ref()` where we need to
+    /// lower a `Visibility` value although we haven't lowered the owning
+    /// `ImplItem` in question yet.
+    fn lower_visibility(
+        &mut self,
+        v: &Visibility,
+        explicit_owner: Option<NodeId>,
+    ) -> hir::Visibility {
+        let node = match v.node {
+            VisibilityKind::Public => hir::VisibilityKind::Public,
+            VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
+            VisibilityKind::Restricted { ref path, id } => {
+                debug!("lower_visibility: restricted path id = {:?}", id);
+                let lowered_id = if let Some(owner) = explicit_owner {
+                    self.lower_node_id_with_owner(id, owner)
+                } else {
+                    self.lower_node_id(id)
+                };
+                let res = self.expect_full_res(id);
+                let res = self.lower_res(res);
+                hir::VisibilityKind::Restricted {
+                    path: P(self.lower_path_extra(
+                        res,
+                        path,
+                        ParamMode::Explicit,
+                        explicit_owner,
+                    )),
+                    hir_id: lowered_id,
+                }
+            },
+            VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
+        };
+        respan(v.span, node)
+    }
+
+    fn lower_defaultness(&self, d: Defaultness, has_value: bool) -> hir::Defaultness {
+        match d {
+            Defaultness::Default => hir::Defaultness::Default {
+                has_value: has_value,
+            },
+            Defaultness::Final => {
+                assert!(has_value);
+                hir::Defaultness::Final
+            }
+        }
+    }
+
+    fn lower_impl_polarity(&mut self, i: ImplPolarity) -> hir::ImplPolarity {
+        match i {
+            ImplPolarity::Positive => hir::ImplPolarity::Positive,
+            ImplPolarity::Negative => hir::ImplPolarity::Negative,
+        }
+    }
+
+    fn record_body(&mut self, arguments: HirVec<hir::Arg>, value: hir::Expr) -> hir::BodyId {
+        let body = hir::Body {
+            generator_kind: self.generator_kind,
+            arguments,
+            value,
+        };
+        let id = body.id();
+        self.bodies.insert(id, body);
+        id
+    }
+
+    fn lower_body(
+        &mut self,
+        f: impl FnOnce(&mut LoweringContext<'_>) -> (HirVec<hir::Arg>, hir::Expr),
+    ) -> hir::BodyId {
+        let prev_gen_kind = self.generator_kind.take();
+        let (arguments, result) = f(self);
+        let body_id = self.record_body(arguments, result);
+        self.generator_kind = prev_gen_kind;
+        body_id
+    }
+
+    pub(super) fn lower_fn_body(
+        &mut self,
+        decl: &FnDecl,
+        body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
+    ) -> hir::BodyId {
+        self.lower_body(|this| (
+            decl.inputs.iter().map(|x| this.lower_arg(x)).collect(),
+            body(this),
+        ))
+    }
+
+    fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
+        self.lower_fn_body(decl, |this| {
+            let body = this.lower_block(body, false);
+            this.expr_block(body, ThinVec::new())
+        })
+    }
+
+    pub(super) fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId {
+        self.lower_body(|this| (hir_vec![], this.lower_expr(expr)))
+    }
+
+    fn lower_maybe_async_body(
+        &mut self,
+        decl: &FnDecl,
+        asyncness: IsAsync,
+        body: &Block,
+    ) -> hir::BodyId {
+        let closure_id = match asyncness {
+            IsAsync::Async { closure_id, .. } => closure_id,
+            IsAsync::NotAsync => return self.lower_fn_body_block(decl, body),
+        };
+
+        self.lower_body(|this| {
+            let mut arguments: Vec<hir::Arg> = Vec::new();
+            let mut statements: Vec<hir::Stmt> = Vec::new();
+
+            // Async function arguments are lowered into the closure body so that they are
+            // captured and so that the drop order matches the equivalent non-async functions.
+            //
+            // from:
+            //
+            //     async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
+            //       async move {
+            //       }
+            //     }
+            //
+            // into:
+            //
+            //     fn foo(__arg0: <ty>, __arg1: <ty>, __arg2: <ty>) {
+            //       async move {
+            //         let __arg2 = __arg2;
+            //         let <pattern> = __arg2;
+            //         let __arg1 = __arg1;
+            //         let <pattern> = __arg1;
+            //         let __arg0 = __arg0;
+            //         let <pattern> = __arg0;
+            //       }
+            //     }
+            //
+            // If `<pattern>` is a simple ident, then it is lowered to a single
+            // `let <pattern> = <pattern>;` statement as an optimization.
+            for (index, argument) in decl.inputs.iter().enumerate() {
+                let argument = this.lower_arg(argument);
+                let span = argument.pat.span;
+
+                // Check if this is a binding pattern, if so, we can optimize and avoid adding a
+                // `let <pat> = __argN;` statement. In this case, we do not rename the argument.
+                let (ident, is_simple_argument) = match argument.pat.node {
+                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _) =>
+                        (ident, true),
+                    _ => {
+                        // Replace the ident for bindings that aren't simple.
+                        let name = format!("__arg{}", index);
+                        let ident = Ident::from_str(&name);
+
+                        (ident, false)
+                    },
+                };
+
+                let desugared_span =
+                    this.mark_span_with_reason(DesugaringKind::Async, span, None);
+
+                // Construct an argument representing `__argN: <ty>` to replace the argument of the
+                // async function.
+                //
+                // If this is the simple case, this argument will end up being the same as the
+                // original argument, but with a different pattern id.
+                let mut stmt_attrs = ThinVec::new();
+                stmt_attrs.extend(argument.attrs.iter().cloned());
+                let (new_argument_pat, new_argument_id) = this.pat_ident(desugared_span, ident);
+                let new_argument = hir::Arg {
+                    attrs: argument.attrs,
+                    hir_id: argument.hir_id,
+                    pat: new_argument_pat,
+                    span: argument.span,
+                };
+
+
+                if is_simple_argument {
+                    // If this is the simple case, then we only insert one statement that is
+                    // `let <pat> = <pat>;`. We re-use the original argument's pattern so that
+                    // `HirId`s are densely assigned.
+                    let expr = this.expr_ident(desugared_span, ident, new_argument_id);
+                    let stmt = this.stmt_let_pat(
+                        stmt_attrs,
+                        desugared_span,
+                        Some(P(expr)),
+                        argument.pat,
+                        hir::LocalSource::AsyncFn
+                    );
+                    statements.push(stmt);
+                } else {
+                    // If this is not the simple case, then we construct two statements:
+                    //
+                    // ```
+                    // let __argN = __argN;
+                    // let <pat> = __argN;
+                    // ```
+                    //
+                    // The first statement moves the argument into the closure and thus ensures
+                    // that the drop order is correct.
+                    //
+                    // The second statement creates the bindings that the user wrote.
+
+                    // Construct the `let mut __argN = __argN;` statement. It must be a mut binding
+                    // because the user may have specified a `ref mut` binding in the next
+                    // statement.
+                    let (move_pat, move_id) = this.pat_ident_binding_mode(
+                        desugared_span, ident, hir::BindingAnnotation::Mutable);
+                    let move_expr = this.expr_ident(desugared_span, ident, new_argument_id);
+                    let move_stmt = this.stmt_let_pat(
+                        ThinVec::new(),
+                        desugared_span,
+                        Some(P(move_expr)),
+                        move_pat,
+                        hir::LocalSource::AsyncFn
+                    );
+
+                    // Construct the `let <pat> = __argN;` statement. We re-use the original
+                    // argument's pattern so that `HirId`s are densely assigned.
+                    let pattern_expr = this.expr_ident(desugared_span, ident, move_id);
+                    let pattern_stmt = this.stmt_let_pat(
+                        stmt_attrs,
+                        desugared_span,
+                        Some(P(pattern_expr)),
+                        argument.pat,
+                        hir::LocalSource::AsyncFn
+                    );
+
+                    statements.push(move_stmt);
+                    statements.push(pattern_stmt);
+                };
+
+                arguments.push(new_argument);
+            }
+
+            let async_expr = this.make_async_expr(
+                CaptureBy::Value, closure_id, None, body.span,
+                |this| {
+                    let body = this.lower_block_with_stmts(body, false, statements);
+                    this.expr_block(body, ThinVec::new())
+                });
+            (HirVec::from(arguments), this.expr(body.span, async_expr, ThinVec::new()))
+        })
+    }
+
+    fn lower_method_sig(
+        &mut self,
+        generics: &Generics,
+        sig: &MethodSig,
+        fn_def_id: DefId,
+        impl_trait_return_allow: bool,
+        is_async: Option<NodeId>,
+    ) -> (hir::Generics, hir::MethodSig) {
+        let header = self.lower_fn_header(sig.header);
+        let (generics, decl) = self.add_in_band_defs(
+            generics,
+            fn_def_id,
+            AnonymousLifetimeMode::PassThrough,
+            |this, idty| this.lower_fn_decl(
+                &sig.decl,
+                Some((fn_def_id, idty)),
+                impl_trait_return_allow,
+                is_async,
+            ),
+        );
+        (generics, hir::MethodSig { header, decl })
+    }
+
+    fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto {
+        match a {
+            IsAuto::Yes => hir::IsAuto::Yes,
+            IsAuto::No => hir::IsAuto::No,
+        }
+    }
+
+    fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
+        hir::FnHeader {
+            unsafety: self.lower_unsafety(h.unsafety),
+            asyncness: self.lower_asyncness(h.asyncness.node),
+            constness: self.lower_constness(h.constness),
+            abi: h.abi,
+        }
+    }
+
+    pub(super) fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
+        match u {
+            Unsafety::Unsafe => hir::Unsafety::Unsafe,
+            Unsafety::Normal => hir::Unsafety::Normal,
+        }
+    }
+
+    fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
+        match c.node {
+            Constness::Const => hir::Constness::Const,
+            Constness::NotConst => hir::Constness::NotConst,
+        }
+    }
+
+    fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {
+        match a {
+            IsAsync::Async { .. } => hir::IsAsync::Async,
+            IsAsync::NotAsync => hir::IsAsync::NotAsync,
+        }
+    }
+
+    pub(super) fn lower_generics(
+        &mut self,
+        generics: &Generics,
+        itctx: ImplTraitContext<'_>)
+        -> hir::Generics
+    {
+        // Collect `?Trait` bounds in where clause and move them to parameter definitions.
+        // FIXME: this could probably be done with less rightward drift. It also looks like two
+        // control paths where `report_error` is called are the only paths that advance to after the
+        // match statement, so the error reporting could probably just be moved there.
+        let mut add_bounds: NodeMap<Vec<_>> = Default::default();
+        for pred in &generics.where_clause.predicates {
+            if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
+                'next_bound: for bound in &bound_pred.bounds {
+                    if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound {
+                        let report_error = |this: &mut Self| {
+                            this.diagnostic().span_err(
+                                bound_pred.bounded_ty.span,
+                                "`?Trait` bounds are only permitted at the \
+                                 point where a type parameter is declared",
+                            );
+                        };
+                        // Check if the where clause type is a plain type parameter.
+                        match bound_pred.bounded_ty.node {
+                            TyKind::Path(None, ref path)
+                                if path.segments.len() == 1
+                                    && bound_pred.bound_generic_params.is_empty() =>
+                            {
+                                if let Some(Res::Def(DefKind::TyParam, def_id)) = self.resolver
+                                    .get_partial_res(bound_pred.bounded_ty.id)
+                                    .map(|d| d.base_res())
+                                {
+                                    if let Some(node_id) =
+                                        self.resolver.definitions().as_local_node_id(def_id)
+                                    {
+                                        for param in &generics.params {
+                                            match param.kind {
+                                                GenericParamKind::Type { .. } => {
+                                                    if node_id == param.id {
+                                                        add_bounds.entry(param.id)
+                                                            .or_default()
+                                                            .push(bound.clone());
+                                                        continue 'next_bound;
+                                                    }
+                                                }
+                                                _ => {}
+                                            }
+                                        }
+                                    }
+                                }
+                                report_error(self)
+                            }
+                            _ => report_error(self),
+                        }
+                    }
+                }
+            }
+        }
+
+        hir::Generics {
+            params: self.lower_generic_params(&generics.params, &add_bounds, itctx),
+            where_clause: self.lower_where_clause(&generics.where_clause),
+            span: generics.span,
+        }
+    }
+
+    fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause {
+        self.with_anonymous_lifetime_mode(
+            AnonymousLifetimeMode::ReportError,
+            |this| {
+                hir::WhereClause {
+                    predicates: wc.predicates
+                        .iter()
+                        .map(|predicate| this.lower_where_predicate(predicate))
+                        .collect(),
+                    span: wc.span,
+                }
+            },
+        )
+    }
+
+    fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate {
+        match *pred {
+            WherePredicate::BoundPredicate(WhereBoundPredicate {
+                ref bound_generic_params,
+                ref bounded_ty,
+                ref bounds,
+                span,
+            }) => {
+                self.with_in_scope_lifetime_defs(
+                    &bound_generic_params,
+                    |this| {
+                        hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+                            bound_generic_params: this.lower_generic_params(
+                                bound_generic_params,
+                                &NodeMap::default(),
+                                ImplTraitContext::disallowed(),
+                            ),
+                            bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
+                            bounds: bounds
+                                .iter()
+                                .filter_map(|bound| match *bound {
+                                    // Ignore `?Trait` bounds.
+                                    // They were copied into type parameters already.
+                                    GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
+                                    _ => Some(this.lower_param_bound(
+                                        bound,
+                                        ImplTraitContext::disallowed(),
+                                    )),
+                                })
+                                .collect(),
+                            span,
+                        })
+                    },
+                )
+            }
+            WherePredicate::RegionPredicate(WhereRegionPredicate {
+                ref lifetime,
+                ref bounds,
+                span,
+            }) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
+                span,
+                lifetime: self.lower_lifetime(lifetime),
+                bounds: self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
+            }),
+            WherePredicate::EqPredicate(WhereEqPredicate {
+                id,
+                ref lhs_ty,
+                ref rhs_ty,
+                span,
+            }) => {
+                hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
+                    hir_id: self.lower_node_id(id),
+                    lhs_ty: self.lower_ty(lhs_ty, ImplTraitContext::disallowed()),
+                    rhs_ty: self.lower_ty(rhs_ty, ImplTraitContext::disallowed()),
+                    span,
+                })
+            },
+        }
+    }
+}