]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/hir/lowering.rs
Fix typo in multiple lifetimes error
[rust.git] / src / librustc / hir / lowering.rs
index ec162adf52bf97ce19a8df02317321dd485a4495..2deb0b53e6bb5d37f58afb35b6719b40e3084896 100644 (file)
@@ -41,7 +41,7 @@
 //! in the HIR, especially for multiple identifiers.
 
 use dep_graph::DepGraph;
-use hir;
+use hir::{self, ParamName};
 use hir::HirVec;
 use hir::map::{DefKey, DefPathData, Definitions};
 use hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX};
@@ -125,7 +125,7 @@ pub struct LoweringContext<'a> {
     // (i.e. it doesn't appear in the in_scope_lifetimes list), it is added
     // to this list. The results of this list are then added to the list of
     // lifetime definitions in the corresponding impl or function generics.
-    lifetimes_to_define: Vec<(Span, hir::LifetimeName)>,
+    lifetimes_to_define: Vec<(Span, ParamName)>,
 
     // Whether or not in-band lifetimes are being collected. This is used to
     // indicate whether or not we're in a place where new lifetimes will result
@@ -379,7 +379,7 @@ fn visit_item(&mut self, item: &'lcx Item) {
                 });
 
                 if item_lowered {
-                    let item_lifetimes = match self.lctx.items.get(&item.id).unwrap().node {
+                    let item_generics = match self.lctx.items.get(&item.id).unwrap().node {
                         hir::Item_::ItemImpl(_, _, _, ref generics, ..)
                         | hir::Item_::ItemTrait(_, _, ref generics, ..) => {
                             generics.params.clone()
@@ -387,7 +387,7 @@ fn visit_item(&mut self, item: &'lcx Item) {
                         _ => HirVec::new(),
                     };
 
-                    self.lctx.with_parent_impl_lifetime_defs(&item_lifetimes, |this| {
+                    self.lctx.with_parent_impl_lifetime_defs(&item_generics, |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| {
@@ -449,7 +449,7 @@ fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
         }
     }
 
-    fn allocate_hir_id_counter<T: Debug>(&mut self, owner: NodeId, debug: &T) {
+    fn allocate_hir_id_counter<T: Debug>(&mut self, owner: NodeId, debug: &T) -> LoweredNodeId {
         if self.item_local_id_counters.insert(owner, 0).is_some() {
             bug!(
                 "Tried to allocate item_local_id_counter for {:?} twice",
@@ -457,7 +457,7 @@ fn allocate_hir_id_counter<T: Debug>(&mut self, owner: NodeId, debug: &T) {
             );
         }
         // Always allocate the first HirId for the owner itself
-        self.lower_node_id_with_owner(owner, owner);
+        self.lower_node_id_with_owner(owner, owner)
     }
 
     fn lower_node_id_generic<F>(&mut self, ast_node_id: NodeId, alloc_hir_id: F) -> LoweredNodeId
@@ -501,7 +501,7 @@ fn with_hir_id_owner<F, T>(&mut self, owner: NodeId, f: F) -> T
     {
         let counter = self.item_local_id_counters
             .insert(owner, HIR_ID_COUNTER_LOCKED)
-            .unwrap();
+            .unwrap_or_else(|| panic!("No item_local_id_counters entry for {:?}", owner));
         let def_index = self.resolver.definitions().opt_def_index(owner).unwrap();
         self.current_hir_id_owner.push((def_index, counter));
         let ret = f(self);
@@ -678,13 +678,8 @@ fn collect_in_band_defs<T, F>(
                 // that collisions are ok here and this shouldn't
                 // really show up for end-user.
                 let str_name = match hir_name {
-                    hir::LifetimeName::Name(n) => n.as_str(),
-                    hir::LifetimeName::Fresh(_) => keywords::UnderscoreLifetime.name().as_str(),
-                    hir::LifetimeName::Implicit
-                    | hir::LifetimeName::Underscore
-                    | hir::LifetimeName::Static => {
-                        span_bug!(span, "unexpected in-band lifetime name: {:?}", hir_name)
-                    }
+                    ParamName::Plain(name) => name.as_str(),
+                    ParamName::Fresh(_) => keywords::UnderscoreLifetime.name().as_str(),
                 };
 
                 // Add a definition for the in-band lifetime def
@@ -699,15 +694,13 @@ fn collect_in_band_defs<T, F>(
 
                 hir::GenericParam {
                     id: def_node_id,
-                    name: hir_name.name(),
+                    name: hir_name,
+                    attrs: hir_vec![],
+                    bounds: hir_vec![],
                     span,
                     pure_wrt_drop: false,
-                    bounds: vec![].into(),
-                    kind: hir::GenericParamKind::Lifetime {
-                        lt_name: hir_name,
-                        in_band: true,
-                        }
-                    }
+                    kind: hir::GenericParamKind::Lifetime { in_band: true }
+                }
             })
             .chain(in_band_ty_params.into_iter())
             .collect();
@@ -728,7 +721,7 @@ fn maybe_collect_in_band_lifetime(&mut self, span: Span, name: Name) {
             return;
         }
 
-        let hir_name = hir::LifetimeName::Name(name);
+        let hir_name = ParamName::Plain(name);
 
         if self.lifetimes_to_define.iter().any(|(_, lt_name)| *lt_name == hir_name) {
             return;
@@ -739,10 +732,10 @@ fn maybe_collect_in_band_lifetime(&mut self, span: Span, name: Name) {
 
     /// When we have either an elided or `'_` lifetime in an impl
     /// header, we convert it to
-    fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> hir::LifetimeName {
+    fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName {
         assert!(self.is_collecting_in_band_lifetimes);
         let index = self.lifetimes_to_define.len();
-        let hir_name = hir::LifetimeName::Fresh(index);
+        let hir_name = ParamName::Fresh(index);
         self.lifetimes_to_define.push((span, hir_name));
         hir_name
     }
@@ -781,7 +774,7 @@ fn with_parent_impl_lifetime_defs<T, F>(&mut self,
     {
         let old_len = self.in_scope_lifetimes.len();
         let lt_def_names = params.iter().filter_map(|param| match param.kind {
-            hir::GenericParamKind::Lifetime { .. } => Some(param.name),
+            hir::GenericParamKind::Lifetime { .. } => Some(param.name.name()),
             _ => None,
         });
         self.in_scope_lifetimes.extend(lt_def_names);
@@ -847,6 +840,46 @@ fn with_catch_scope<T, F>(&mut self, catch_id: NodeId, f: F) -> T
         result
     }
 
+    fn make_async_expr(
+        &mut self,
+        capture_clause: CaptureBy,
+        closure_node_id: NodeId,
+        ret_ty: Option<&Ty>,
+        body: impl FnOnce(&mut LoweringContext) -> hir::Expr,
+    ) -> hir::Expr_ {
+        let prev_is_generator = mem::replace(&mut self.is_generator, true);
+        let body_expr = body(self);
+        let span = body_expr.span;
+        let output = match ret_ty {
+            Some(ty) => FunctionRetTy::Ty(P(ty.clone())),
+            None => FunctionRetTy::Default(span),
+        };
+        let decl = FnDecl {
+            inputs: vec![],
+            output,
+            variadic: false
+        };
+        let body_id = self.record_body(body_expr, Some(&decl));
+        self.is_generator = prev_is_generator;
+
+        let capture_clause = self.lower_capture_clause(capture_clause);
+        let closure_hir_id = self.lower_node_id(closure_node_id).hir_id;
+        let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, false);
+        let generator = hir::Expr {
+            id: closure_node_id,
+            hir_id: closure_hir_id,
+            node: hir::ExprClosure(capture_clause, decl, body_id, span,
+                Some(hir::GeneratorMovability::Static)),
+            span,
+            attrs: ThinVec::new(),
+        };
+
+        let unstable_span = self.allow_internal_unstable(CompilerDesugaringKind::Async, span);
+        let gen_future = self.expr_std_path(
+            unstable_span, &["raw", "future_from_generator"], ThinVec::new());
+        hir::ExprCall(P(gen_future), hir_vec![generator])
+    }
+
     fn lower_body<F>(&mut self, decl: Option<&FnDecl>, f: F) -> hir::BodyId
     where
         F: FnOnce(&mut LoweringContext) -> hir::Expr,
@@ -1074,7 +1107,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
                                 ),
                                 unsafety: this.lower_unsafety(f.unsafety),
                                 abi: f.abi,
-                                decl: this.lower_fn_decl(&f.decl, None, false),
+                                decl: this.lower_fn_decl(&f.decl, None, false, false),
                                 arg_names: this.lower_fn_args_to_names(&f.decl),
                             }))
                         },
@@ -1116,11 +1149,11 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
                 let bounds = bounds
                     .iter()
                     .filter_map(|bound| match *bound {
-                        TraitTyParamBound(ref ty, TraitBoundModifier::None) => {
+                        GenericBound::Trait(ref ty, TraitBoundModifier::None) => {
                             Some(self.lower_poly_trait_ref(ty, itctx))
                         }
-                        TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
-                        Outlives(ref lifetime) => {
+                        GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
+                        GenericBound::Outlives(ref lifetime) => {
                             if lifetime_bound.is_none() {
                                 lifetime_bound = Some(self.lower_lifetime(lifetime));
                             }
@@ -1139,92 +1172,10 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
                 let span = t.span;
                 match itctx {
                     ImplTraitContext::Existential(fn_def_id) => {
-
-                        // We need to manually repeat the code of `next_id` because the lowering
-                        // needs to happen while the owner_id is pointing to the item itself,
-                        // because items are their own owners
-                        let exist_ty_node_id = self.sess.next_node_id();
-
-                        // Make sure we know that some funky desugaring has been going on here.
-                        // This is a first: there is code in other places like for loop
-                        // desugaring that explicitly states that we don't want to track that.
-                        // Not tracking it makes lints in rustc and clippy very fragile as
-                        // frequently opened issues show.
-                        let exist_ty_span = self.allow_internal_unstable(
-                            CompilerDesugaringKind::ExistentialReturnType,
-                            t.span,
-                        );
-
-                        // Pull a new definition from the ether
-                        let exist_ty_def_index = self
-                            .resolver
-                            .definitions()
-                            .create_def_with_parent(
-                            fn_def_id.index,
-                            exist_ty_node_id,
-                            DefPathData::ExistentialImplTrait,
-                            DefIndexAddressSpace::High,
-                            Mark::root(),
-                            exist_ty_span,
-                        );
-
-                        // the `t` is just for printing debug messages
-                        self.allocate_hir_id_counter(exist_ty_node_id, t);
-
-                        let hir_bounds = self.with_hir_id_owner(exist_ty_node_id, |lctx| {
-                            lctx.lower_bounds(bounds, itctx)
-                        });
-
-                        let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
-                            exist_ty_node_id,
-                            exist_ty_def_index,
-                            &hir_bounds,
-                        );
-
-                        self.with_hir_id_owner(exist_ty_node_id, |lctx| {
-                            let exist_ty_item_kind = hir::ItemExistential(hir::ExistTy {
-                                generics: hir::Generics {
-                                    params: lifetime_defs,
-                                    where_clause: hir::WhereClause {
-                                        id: lctx.next_id().node_id,
-                                        predicates: Vec::new().into(),
-                                    },
-                                    span,
-                                },
-                                bounds: hir_bounds,
-                                impl_trait_fn: Some(fn_def_id),
-                            });
-                            let exist_ty_id = lctx.lower_node_id(exist_ty_node_id);
-                            // Generate an `existential type Foo: Trait;` declaration
-                            trace!("creating existential type with id {:#?}", exist_ty_id);
-                            // Set the name to `impl Bound1 + Bound2`
-                            let exist_ty_name = Symbol::intern(&pprust::ty_to_string(t));
-
-                            trace!("exist ty def index: {:#?}", exist_ty_def_index);
-                            let exist_ty_item = hir::Item {
-                                id: exist_ty_id.node_id,
-                                hir_id: exist_ty_id.hir_id,
-                                name: exist_ty_name,
-                                attrs: Default::default(),
-                                node: exist_ty_item_kind,
-                                vis: hir::Visibility::Inherited,
-                                span: exist_ty_span,
-                            };
-
-                            // Insert the item into the global list. This usually happens
-                            // automatically for all AST items. But this existential type item
-                            // does not actually exist in the AST.
-                            lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
-
-                            // `impl Trait` now just becomes `Foo<'a, 'b, ..>`
-                            hir::TyImplTraitExistential(
-                                hir::ItemId {
-                                    id: exist_ty_id.node_id
-                                },
-                                DefId::local(exist_ty_def_index),
-                                lifetimes,
-                            )
-                        })
+                        // Set the name to `impl Bound1 + Bound2`
+                        let exist_ty_name = Symbol::intern(&pprust::ty_to_string(t));
+                        self.lower_existential_impl_trait(
+                            span, fn_def_id, exist_ty_name, |this| this.lower_bounds(bounds, itctx))
                     }
                     ImplTraitContext::Universal(def_id) => {
                         let def_node_id = self.next_id().node_id;
@@ -1244,14 +1195,14 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
                         let name = Symbol::intern(&pprust::ty_to_string(t));
                         self.in_band_ty_params.push(hir::GenericParam {
                             id: def_node_id,
-                            name,
+                            name: ParamName::Plain(name),
                             span,
                             pure_wrt_drop: false,
+                            attrs: hir_vec![],
                             bounds: hir_bounds,
                             kind: hir::GenericParamKind::Type {
                                 default: None,
                                 synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
-                                attrs: P::new(),
                             }
                         });
 
@@ -1288,11 +1239,100 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
         })
     }
 
+    fn lower_existential_impl_trait(
+        &mut self,
+        span: Span,
+        fn_def_id: DefId,
+        exist_ty_name: Name,
+        lower_bounds: impl FnOnce(&mut LoweringContext) -> hir::TyParamBounds,
+    ) -> hir::Ty_ {
+        // We need to manually repeat the code of `next_id` because the lowering
+        // needs to happen while the owner_id is pointing to the item itself,
+        // because items are their own owners
+        let exist_ty_node_id = self.sess.next_node_id();
+
+        // Make sure we know that some funky desugaring has been going on here.
+        // This is a first: there is code in other places like for loop
+        // desugaring that explicitly states that we don't want to track that.
+        // Not tracking it makes lints in rustc and clippy very fragile as
+        // frequently opened issues show.
+        let exist_ty_span = self.allow_internal_unstable(
+            CompilerDesugaringKind::ExistentialReturnType,
+            span,
+        );
+
+        // Pull a new definition from the ether
+        let exist_ty_def_index = self
+            .resolver
+            .definitions()
+            .create_def_with_parent(
+            fn_def_id.index,
+            exist_ty_node_id,
+            DefPathData::ExistentialImplTrait,
+            DefIndexAddressSpace::High,
+            Mark::root(),
+            exist_ty_span,
+        );
+
+        self.allocate_hir_id_counter(exist_ty_node_id, &"existential impl trait");
+
+        let hir_bounds = self.with_hir_id_owner(exist_ty_node_id, lower_bounds);
+
+        let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
+            exist_ty_node_id,
+            exist_ty_def_index,
+            &hir_bounds,
+        );
+
+        self.with_hir_id_owner(exist_ty_node_id, |lctx| {
+            let exist_ty_item_kind = hir::ItemExistential(hir::ExistTy {
+                generics: hir::Generics {
+                    params: lifetime_defs,
+                    where_clause: hir::WhereClause {
+                        id: lctx.next_id().node_id,
+                        predicates: Vec::new().into(),
+                    },
+                    span,
+                },
+                bounds: hir_bounds,
+                impl_trait_fn: Some(fn_def_id),
+            });
+            let exist_ty_id = lctx.lower_node_id(exist_ty_node_id);
+            // Generate an `existential type Foo: Trait;` declaration
+            trace!("creating existential type with id {:#?}", exist_ty_id);
+
+            trace!("exist ty def index: {:#?}", exist_ty_def_index);
+            let exist_ty_item = hir::Item {
+                id: exist_ty_id.node_id,
+                hir_id: exist_ty_id.hir_id,
+                name: exist_ty_name,
+                attrs: Default::default(),
+                node: exist_ty_item_kind,
+                vis: hir::Visibility::Inherited,
+                span: exist_ty_span,
+            };
+
+            // Insert the item into the global list. This usually happens
+            // automatically for all AST items. But this existential type item
+            // does not actually exist in the AST.
+            lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
+
+            // `impl Trait` now just becomes `Foo<'a, 'b, ..>`
+            hir::TyImplTraitExistential(
+                hir::ItemId {
+                    id: exist_ty_id.node_id
+                },
+                DefId::local(exist_ty_def_index),
+                lifetimes,
+            )
+        })
+    }
+
     fn lifetimes_from_impl_trait_bounds(
         &mut self,
         exist_ty_id: NodeId,
         parent_index: DefIndex,
-        bounds: &hir::ParamBounds,
+        bounds: &hir::GenericBounds,
     ) -> (HirVec<hir::Lifetime>, HirVec<hir::GenericParam>) {
         // This visitor walks over impl trait bounds and creates defs for all lifetimes which
         // appear in the bounds, excluding lifetimes that are created within the bounds.
@@ -1359,9 +1399,10 @@ fn visit_poly_trait_ref(
 
             fn visit_generic_param(&mut self, param: &'v hir::GenericParam) {
                 // Record the introduction of 'a in `for<'a> ...`
-                if let hir::GenericParamKind::Lifetime { lt_name, .. } = param.kind {
+                if let hir::GenericParamKind::Lifetime { .. } = param.kind {
                     // Introduce lifetimes one at a time so that we can handle
                     // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`
+                    let lt_name = hir::LifetimeName::Param(param.name);
                     self.currently_bound_lifetimes.push(lt_name);
                 }
 
@@ -1379,14 +1420,12 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
                             return;
                         }
                     }
-                    name @ hir::LifetimeName::Fresh(_) => name,
-                    name @ hir::LifetimeName::Name(_) => name,
+                    hir::LifetimeName::Param(_) => lifetime.name,
                     hir::LifetimeName::Static => return,
                 };
 
                 if !self.currently_bound_lifetimes.contains(&name)
-                    && !self.already_defined_lifetimes.contains(&name)
-                {
+                    && !self.already_defined_lifetimes.contains(&name) {
                     self.already_defined_lifetimes.insert(name);
 
                     self.output_lifetimes.push(hir::Lifetime {
@@ -1409,16 +1448,24 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
                         lifetime.span,
                     );
 
+                    let name = match name {
+                        hir::LifetimeName::Underscore => {
+                            hir::ParamName::Plain(keywords::UnderscoreLifetime.name())
+                        }
+                        hir::LifetimeName::Param(param_name) => param_name,
+                        _ => bug!("expected LifetimeName::Param or ParamName::Plain"),
+                    };
+
                     self.output_lifetime_params.push(hir::GenericParam {
                         id: def_node_id,
-                        name: name.name(),
+                        name,
                         span: lifetime.span,
                         pure_wrt_drop: false,
-                        bounds: vec![].into(),
+                        attrs: hir_vec![],
+                        bounds: hir_vec![],
                         kind: hir::GenericParamKind::Lifetime {
-                            lt_name: name,
                             in_band: false,
-                            }
+                        }
                     });
                 }
             }
@@ -1747,8 +1794,8 @@ fn lower_angle_bracketed_parameter_data(
 
     fn lower_parenthesized_parameter_data(
         &mut self,
-        data: &ParenthesizedParameterData,
-    ) -> (hir::PathParameters, bool) {
+        data: &ParenthesisedArgs,
+    ) -> (hir::GenericArgs, bool) {
         // Switch to `PassThrough` mode for anonymous lifetimes: this
         // means that we permit things like `&Ref<T>`, where `Ref` has
         // a hidden lifetime parameter. This is needed for backwards
@@ -1758,7 +1805,7 @@ fn lower_parenthesized_parameter_data(
             AnonymousLifetimeMode::PassThrough,
             |this| {
                 const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed;
-                let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
+                let &ParenthesisedArgs { ref inputs, ref output, span } = data;
                 let inputs = inputs.iter().map(|ty| this.lower_ty(ty, DISALLOWED)).collect();
                 let mk_tup = |this: &mut Self, tys, span| {
                     let LoweredNodeId { node_id, hir_id } = this.next_id();
@@ -1767,7 +1814,7 @@ fn lower_parenthesized_parameter_data(
 
                 (
                     hir::GenericArgs {
-                        parameters: hir_vec![GenericArg::Type(mk_tup(this, inputs, span))],
+                        args: hir_vec![GenericArg::Type(mk_tup(this, inputs, span))],
                         bindings: hir_vec![
                             hir::TypeBinding {
                                 id: this.next_id().node_id,
@@ -1829,31 +1876,40 @@ fn lower_fn_args_to_names(&mut self, decl: &FnDecl) -> hir::HirVec<Spanned<Name>
             .collect()
     }
 
+    // Lowers a function declaration.
+    //
+    // decl: the unlowered (ast) function declaration.
+    // fn_def_id: if `Some`, impl Trait arguments are lowered into generic parameters on the
+    //      given DefId, otherwise impl Trait is disallowed. Must be `Some` if
+    //      make_ret_async is true.
+    // impl_trait_return_allow: determines whether impl Trait can be used in return position.
+    //      This guards against trait declarations and implementations where impl Trait is
+    //      disallowed.
+    // make_ret_async: if enabled, converts `-> T` into `-> impl Future<Output = T>` in the
+    //      return type. This is used for `async fn` declarations.
     fn lower_fn_decl(
         &mut self,
         decl: &FnDecl,
         fn_def_id: Option<DefId>,
         impl_trait_return_allow: bool,
+        make_ret_async: bool,
     ) -> P<hir::FnDecl> {
-        // NOTE: The two last parameters here have to do with impl Trait. If fn_def_id is Some,
-        //       then impl Trait arguments are lowered into generic parameters on the given
-        //       fn_def_id, otherwise impl Trait is disallowed. (for now)
-        //
-        //       Furthermore, if impl_trait_return_allow is true, then impl Trait may be used in
-        //       return positions as well. This guards against trait declarations and their impls
-        //       where impl Trait is disallowed. (again for now)
-        P(hir::FnDecl {
-            inputs: decl.inputs
-                .iter()
-                .map(|arg| {
-                    if let Some(def_id) = fn_def_id {
-                        self.lower_ty(&arg.ty, ImplTraitContext::Universal(def_id))
-                    } else {
-                        self.lower_ty(&arg.ty, ImplTraitContext::Disallowed)
-                    }
-                })
-                .collect(),
-            output: match decl.output {
+        let inputs = decl.inputs
+            .iter()
+            .map(|arg| {
+                if let Some(def_id) = fn_def_id {
+                    self.lower_ty(&arg.ty, ImplTraitContext::Universal(def_id))
+                } else {
+                    self.lower_ty(&arg.ty, ImplTraitContext::Disallowed)
+                }
+            })
+            .collect::<HirVec<_>>();
+
+        let output = if make_ret_async {
+            self.lower_async_fn_ret_ty(
+                &inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id"))
+        } else {
+            match decl.output {
                 FunctionRetTy::Ty(ref ty) => match fn_def_id {
                     Some(def_id) if impl_trait_return_allow => {
                         hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(def_id)))
@@ -1861,7 +1917,12 @@ fn lower_fn_decl(
                     _ => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)),
                 },
                 FunctionRetTy::Default(span) => hir::DefaultReturn(span),
-            },
+            }
+        };
+
+        P(hir::FnDecl {
+            inputs,
+            output,
             variadic: decl.variadic,
             has_implicit_self: decl.inputs.get(0).map_or(false, |arg| match arg.ty.node {
                 TyKind::ImplicitSelf => true,
@@ -1871,18 +1932,255 @@ fn lower_fn_decl(
         })
     }
 
+    // Transform `-> T` into `-> impl Future<Output = T>` for `async fn`
+    //
+    // fn_span: the span of the async function declaration. Used for error reporting.
+    // inputs: lowered types of arguments to the function. Used to collect lifetimes.
+    // output: unlowered output type (`T` in `-> T`)
+    // fn_def_id: DefId of the parent function. Used to create child impl trait definition.
+    fn lower_async_fn_ret_ty(
+        &mut self,
+        inputs: &[P<hir::Ty>],
+        output: &FunctionRetTy,
+        fn_def_id: DefId,
+    ) -> hir::FunctionRetTy {
+        // Get lifetimes used in the input arguments to the function. Our output type must also
+        // have the same lifetime. FIXME(cramertj) multiple different lifetimes are not allowed
+        // because `impl Trait + 'a + 'b` doesn't allow for capture `'a` and `'b` where neither
+        // is a subset of the other. We really want some new lifetime that is a subset of all input
+        // lifetimes, but that doesn't exist at the moment.
+
+        struct AsyncFnLifetimeCollector<'r, 'a: 'r> {
+            context: &'r mut LoweringContext<'a>,
+            // Lifetimes bound by HRTB
+            currently_bound_lifetimes: Vec<hir::LifetimeName>,
+            // Whether to count elided lifetimes.
+            // Disabled inside of `Fn` or `fn` syntax.
+            collect_elided_lifetimes: bool,
+            // The lifetime found.
+            // Multiple different or elided lifetimes cannot appear in async fn for now.
+            output_lifetime: Option<(hir::LifetimeName, Span)>,
+        }
+
+        impl<'r, 'a: 'r, 'v> hir::intravisit::Visitor<'v> for AsyncFnLifetimeCollector<'r, 'a> {
+            fn nested_visit_map<'this>(
+                &'this mut self,
+            ) -> hir::intravisit::NestedVisitorMap<'this, 'v> {
+                hir::intravisit::NestedVisitorMap::None
+            }
+
+            fn visit_path_parameters(&mut self, span: Span, parameters: &'v hir::PathParameters) {
+                // Don't collect elided lifetimes used inside of `Fn()` syntax.
+                if parameters.parenthesized {
+                    let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
+                    self.collect_elided_lifetimes = false;
+                    hir::intravisit::walk_path_parameters(self, span, parameters);
+                    self.collect_elided_lifetimes = old_collect_elided_lifetimes;
+                } else {
+                    hir::intravisit::walk_path_parameters(self, span, parameters);
+                }
+            }
+
+            fn visit_ty(&mut self, t: &'v hir::Ty) {
+                // Don't collect elided lifetimes used inside of `fn()` syntax
+                if let &hir::Ty_::TyBareFn(_) = &t.node {
+                    let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
+                    self.collect_elided_lifetimes = false;
+
+                    // Record the "stack height" of `for<'a>` lifetime bindings
+                    // to be able to later fully undo their introduction.
+                    let old_len = self.currently_bound_lifetimes.len();
+                    hir::intravisit::walk_ty(self, t);
+                    self.currently_bound_lifetimes.truncate(old_len);
+
+                    self.collect_elided_lifetimes = old_collect_elided_lifetimes;
+                } else {
+                    hir::intravisit::walk_ty(self, t);
+                }
+            }
+
+            fn visit_poly_trait_ref(
+                &mut self,
+                trait_ref: &'v hir::PolyTraitRef,
+                modifier: hir::TraitBoundModifier,
+            ) {
+                // Record the "stack height" of `for<'a>` lifetime bindings
+                // to be able to later fully undo their introduction.
+                let old_len = self.currently_bound_lifetimes.len();
+                hir::intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
+                self.currently_bound_lifetimes.truncate(old_len);
+            }
+
+            fn visit_generic_param(&mut self, param: &'v hir::GenericParam) {
+                // Record the introduction of 'a in `for<'a> ...`
+                if let hir::GenericParam::Lifetime(ref lt_def) = *param {
+                    // Introduce lifetimes one at a time so that we can handle
+                    // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`
+                    self.currently_bound_lifetimes.push(lt_def.lifetime.name);
+                }
+
+                hir::intravisit::walk_generic_param(self, param);
+            }
+
+            fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
+                let name = match lifetime.name {
+                    hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
+                        if self.collect_elided_lifetimes {
+                            // Use `'_` for both implicit and underscore lifetimes in
+                            // `abstract type Foo<'_>: SomeTrait<'_>;`
+                            hir::LifetimeName::Underscore
+                        } else {
+                            return;
+                        }
+                    }
+                    name @ hir::LifetimeName::Fresh(_) => name,
+                    name @ hir::LifetimeName::Name(_) => name,
+                    hir::LifetimeName::Static => return,
+                };
+
+                if !self.currently_bound_lifetimes.contains(&name) {
+                    if let Some((current_lt_name, current_lt_span)) = self.output_lifetime {
+                        // We don't currently have a reliable way to desugar `async fn` with
+                        // multiple potentially unrelated input lifetimes into
+                        // `-> impl Trait + 'lt`, so we report an error in this case.
+                        if current_lt_name != name {
+                            struct_span_err!(
+                                self.context.sess,
+                                current_lt_span.between(lifetime.span),
+                                E0703,
+                                "multiple different lifetimes used in arguments of `async fn`",
+                            )
+                                .span_label(current_lt_span, "first lifetime here")
+                                .span_label(lifetime.span, "different lifetime here")
+                                .help("`async fn` can only accept borrowed values \
+                                      with identical lifetimes")
+                                .emit()
+                        } else if current_lt_name.is_elided() && name.is_elided() {
+                            struct_span_err!(
+                                self.context.sess,
+                                current_lt_span.between(lifetime.span),
+                                E0704,
+                                "multiple elided lifetimes used in arguments of `async fn`",
+                            )
+                                .span_label(current_lt_span, "first lifetime here")
+                                .span_label(lifetime.span, "different lifetime here")
+                                .help("consider giving these arguments named lifetimes")
+                                .emit()
+                        }
+                    } else {
+                        self.output_lifetime = Some((name, lifetime.span));
+                    }
+                }
+            }
+        }
+
+        let bound_lifetime = {
+            let mut lifetime_collector = AsyncFnLifetimeCollector {
+                context: self,
+                currently_bound_lifetimes: Vec::new(),
+                collect_elided_lifetimes: true,
+                output_lifetime: None,
+            };
+
+            for arg in inputs {
+                hir::intravisit::walk_ty(&mut lifetime_collector, arg);
+            }
+            lifetime_collector.output_lifetime
+        };
+
+        let output_ty_name_owned;
+        let (output_ty_name, span) = match output {
+            FunctionRetTy::Ty(ty) => {
+                output_ty_name_owned = pprust::ty_to_string(ty);
+                (&*output_ty_name_owned, ty.span)
+            },
+            FunctionRetTy::Default(span) => ("()", *span),
+        };
+
+        // FIXME(cramertj) add lifetimes (see FIXME below) to the name
+        let exist_ty_name = Symbol::intern(&format!("impl Future<Output = {}>", output_ty_name));
+        let impl_trait_ty = self.lower_existential_impl_trait(
+            span, fn_def_id, exist_ty_name, |this| {
+            let output_ty = match output {
+                FunctionRetTy::Ty(ty) =>
+                    this.lower_ty(ty, ImplTraitContext::Existential(fn_def_id)),
+                FunctionRetTy::Default(span) => {
+                    let LoweredNodeId { node_id, hir_id } = this.next_id();
+                    P(hir::Ty {
+                        id: node_id,
+                        hir_id: hir_id,
+                        node: hir::TyTup(hir_vec![]),
+                        span: *span,
+                    })
+                }
+            };
+
+            let hir::Path { def, segments, .. } = this.std_path(span, &["future", "Future"], false);
+            let future_path = hir::Path {
+                segments: segments.map_slice(|mut v| {
+                    v.last_mut().unwrap().parameters = Some(P(hir::PathParameters {
+                        lifetimes: hir_vec![],
+                        types: hir_vec![],
+                        bindings: hir_vec![hir::TypeBinding {
+                            name: Symbol::intern(FN_OUTPUT_NAME),
+                            ty: output_ty,
+                            id: this.next_id().node_id,
+                            span,
+                        }],
+                        parenthesized: false,
+                    }));
+                    v
+                }),
+                def, span
+            };
+
+            // FIXME(cramertj) collect input lifetimes to function and add them to
+            // the output `impl Trait` type here.
+            let mut bounds = vec![
+                hir::TyParamBound::TraitTyParamBound(
+                    hir::PolyTraitRef {
+                        trait_ref: hir::TraitRef {
+                            path: future_path,
+                            ref_id: this.next_id().node_id,
+                        },
+                        bound_generic_params: hir_vec![],
+                        span,
+                    },
+                    hir::TraitBoundModifier::None
+                ),
+            ];
+
+            if let Some((name, span)) = bound_lifetime {
+                bounds.push(hir::RegionTyParamBound(
+                    hir::Lifetime { id: this.next_id().node_id, name, span }));
+            }
+
+            hir::HirVec::from(bounds)
+        });
+
+        let LoweredNodeId { node_id, hir_id } = self.next_id();
+        let impl_trait_ty = P(hir::Ty {
+            id: node_id,
+            node: impl_trait_ty,
+            span,
+            hir_id,
+        });
+
+        hir::FunctionRetTy::Return(impl_trait_ty)
+    }
+
     fn lower_param_bound(
         &mut self,
-        tpb: &ParamBound,
+        tpb: &GenericBound,
         itctx: ImplTraitContext,
-    ) -> hir::ParamBound {
+    ) -> hir::GenericBound {
         match *tpb {
-            TraitTyParamBound(ref ty, modifier) => hir::TraitTyParamBound(
+            GenericBound::Trait(ref ty, modifier) => hir::GenericBound::Trait(
                 self.lower_poly_trait_ref(ty, itctx),
                 self.lower_trait_bound_modifier(modifier),
             ),
-            Outlives(ref lifetime) => {
-                hir::Outlives(self.lower_lifetime(lifetime))
+            GenericBound::Outlives(ref lifetime) => {
+                hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
             }
         }
     }
@@ -1894,7 +2192,7 @@ fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
             x if x == "'_" => match self.anonymous_lifetime_mode {
                 AnonymousLifetimeMode::CreateParameter => {
                     let fresh_name = self.collect_fresh_in_band_lifetime(span);
-                    self.new_named_lifetime(l.id, span, fresh_name)
+                    self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(fresh_name))
                 }
 
                 AnonymousLifetimeMode::PassThrough => {
@@ -1903,7 +2201,8 @@ fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
             },
             name => {
                 self.maybe_collect_in_band_lifetime(span, name);
-                self.new_named_lifetime(l.id, span, hir::LifetimeName::Name(name))
+                let param_name = ParamName::Plain(name);
+                self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(param_name))
             }
         }
     }
@@ -1924,7 +2223,7 @@ fn new_named_lifetime(
     fn lower_generic_params(
         &mut self,
         params: &Vec<GenericParam>,
-        add_bounds: &NodeMap<Vec<ParamBound>>,
+        add_bounds: &NodeMap<Vec<GenericBound>>,
         itctx: ImplTraitContext,
     ) -> hir::HirVec<hir::GenericParam> {
         params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect()
@@ -1932,7 +2231,7 @@ fn lower_generic_params(
 
     fn lower_generic_param(&mut self,
                            param: &GenericParam,
-                           add_bounds: &NodeMap<Vec<ParamBound>>,
+                           add_bounds: &NodeMap<Vec<GenericBound>>,
                            itctx: ImplTraitContext)
                            -> hir::GenericParam {
         let mut bounds = self.lower_param_bounds(&param.bounds, itctx);
@@ -1942,16 +2241,18 @@ fn lower_generic_param(&mut self,
                 self.is_collecting_in_band_lifetimes = false;
 
                 let lt = self.lower_lifetime(&Lifetime { id: param.id, ident: param.ident });
+                let param_name = match lt.name {
+                    hir::LifetimeName::Param(param_name) => param_name,
+                    _ => hir::ParamName::Plain(lt.name.name()),
+                };
                 let param = hir::GenericParam {
                     id: lt.id,
-                    name: lt.name.name(),
+                    name: param_name,
                     span: lt.span,
                     pure_wrt_drop: attr::contains_name(&param.attrs, "may_dangle"),
+                    attrs: self.lower_attrs(&param.attrs),
                     bounds,
-                    kind: hir::GenericParamKind::Lifetime {
-                        lt_name: lt.name,
-                        in_band: false,
-                    }
+                    kind: hir::GenericParamKind::Lifetime { in_band: false }
                 };
 
                 self.is_collecting_in_band_lifetimes = was_collecting_in_band;
@@ -1977,9 +2278,10 @@ fn lower_generic_param(&mut self,
 
                 hir::GenericParam {
                     id: self.lower_node_id(param.id).node_id,
-                    name,
+                    name: hir::ParamName::Plain(name),
                     span: param.ident.span,
                     pure_wrt_drop: attr::contains_name(&param.attrs, "may_dangle"),
+                    attrs: self.lower_attrs(&param.attrs),
                     bounds,
                     kind: hir::GenericParamKind::Type {
                         default: default.as_ref().map(|x| {
@@ -1989,7 +2291,6 @@ fn lower_generic_param(&mut self,
                                               .filter(|attr| attr.check_name("rustc_synthetic"))
                                               .map(|_| hir::SyntheticTyParamKind::ImplTrait)
                                               .next(),
-                        attrs: self.lower_attrs(&param.attrs),
                     }
                 }
             }
@@ -2010,7 +2311,7 @@ fn lower_generics(
         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 TraitTyParamBound(_, TraitBoundModifier::Maybe) = *bound {
+                    if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound {
                         let report_error = |this: &mut Self| {
                             this.diagnostic().span_err(
                                 bound_pred.bounded_ty.span,
@@ -2095,7 +2396,7 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
                                 .filter_map(|bound| match *bound {
                                     // Ignore `?Trait` bounds.
                                     // Tthey were copied into type parameters already.
-                                    TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
+                                    GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
                                     _ => Some(this.lower_param_bound(
                                         bound,
                                         ImplTraitContext::Disallowed,
@@ -2214,8 +2515,8 @@ fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy {
         }
     }
 
-    fn lower_param_bounds(&mut self, bounds: &[ParamBound], itctx: ImplTraitContext)
-        -> hir::ParamBounds {
+    fn lower_param_bounds(&mut self, bounds: &[GenericBound], itctx: ImplTraitContext)
+        -> hir::GenericBounds {
         bounds.iter().map(|bound| self.lower_param_bound(bound, itctx)).collect()
     }
 
@@ -2281,25 +2582,39 @@ fn lower_item_kind(
                 let value = self.lower_body(None, |this| this.lower_expr(e));
                 hir::ItemConst(self.lower_ty(t, ImplTraitContext::Disallowed), value)
             }
-            ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
+            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| {
+                    // Note: we can use non-async decl here because lower_body
+                    // only cares about the input argument patterns,
+                    // not the return types.
                     let body_id = this.lower_body(Some(decl), |this| {
-                        let body = this.lower_block(body, false);
-                        this.expr_block(body, ThinVec::new())
+                        if let IsAsync::Async(async_node_id) = header.asyncness {
+                            let async_expr = this.make_async_expr(
+                                CaptureBy::Value, async_node_id, None,
+                                |this| {
+                                    let body = this.lower_block(body, false);
+                                    this.expr_block(body, ThinVec::new())
+                                });
+                            this.expr(body.span, async_expr, ThinVec::new())
+                        } else {
+                            let body = this.lower_block(body, false);
+                            this.expr_block(body, ThinVec::new())
+                        }
                     });
+
                     let (generics, fn_decl) = this.add_in_band_defs(
                         generics,
                         fn_def_id,
                         AnonymousLifetimeMode::PassThrough,
-                        |this| this.lower_fn_decl(decl, Some(fn_def_id), true),
+                        |this| this.lower_fn_decl(
+                            decl, Some(fn_def_id), true, header.asyncness.is_async())
                     );
 
                     hir::ItemFn(
                         fn_decl,
-                        this.lower_unsafety(unsafety),
-                        this.lower_constness(constness),
-                        abi,
+                        this.lower_fn_header(header),
                         generics,
                         body_id,
                     )
@@ -2862,7 +3177,7 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
                         |this| {
                             (
                                 // Disallow impl Trait in foreign items
-                                this.lower_fn_decl(fdec, None, false),
+                                this.lower_fn_decl(fdec, None, false, false),
                                 this.lower_fn_args_to_names(fdec),
                             )
                         },
@@ -2888,10 +3203,8 @@ fn lower_method_sig(
         impl_trait_return_allow: bool,
     ) -> hir::MethodSig {
         hir::MethodSig {
-            abi: sig.abi,
-            unsafety: self.lower_unsafety(sig.unsafety),
-            constness: self.lower_constness(sig.constness),
-            decl: self.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow),
+            header: self.lower_fn_header(sig.header),
+            decl: self.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow, false),
         }
     }
 
@@ -2902,6 +3215,15 @@ fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto {
         }
     }
 
+    fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
+        hir::FnHeader {
+            unsafety: self.lower_unsafety(h.unsafety),
+            asyncness: self.lower_asyncness(h.asyncness),
+            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,
@@ -2916,6 +3238,13 @@ fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
         }
     }
 
+    fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {
+        match a {
+            IsAsync::Async(_) => hir::IsAsync::Async,
+            IsAsync::NotAsync => hir::IsAsync::NotAsync,
+        }
+    }
+
     fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
         match u {
             UnOp::Deref => hir::UnDeref,
@@ -3203,46 +3532,101 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 arms.iter().map(|x| self.lower_arm(x)).collect(),
                 hir::MatchSource::Normal,
             ),
-            ExprKind::Closure(capture_clause, movability, ref decl, ref body, fn_decl_span) => {
+            ExprKind::Async(capture_clause, closure_node_id, ref block) => {
+                self.make_async_expr(capture_clause, closure_node_id, None, |this| {
+                    this.with_new_scopes(|this| {
+                        let block = this.lower_block(block, false);
+                        this.expr_block(block, ThinVec::new())
+                    })
+                })
+            },
+            ExprKind::Closure(
+                capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span) =>
+            {
                 self.with_new_scopes(|this| {
-                    let mut is_generator = false;
-                    let body_id = this.lower_body(Some(decl), |this| {
-                        let e = this.lower_expr(body);
-                        is_generator = this.is_generator;
-                        e
-                    });
-                    let generator_option = if is_generator {
-                        if !decl.inputs.is_empty() {
-                            span_err!(
+                    if let IsAsync::Async(async_closure_node_id) = asyncness {
+                        // FIXME(cramertj) allow `async` non-`move` closures with
+                        if capture_clause == CaptureBy::Ref &&
+                            !decl.inputs.is_empty()
+                        {
+                            struct_span_err!(
                                 this.sess,
                                 fn_decl_span,
-                                E0628,
-                                "generators cannot have explicit arguments"
-                            );
-                            this.sess.abort_if_errors();
+                                E0705,
+                                "`async` non-`move` closures with arguments \
+                                are not currently supported",
+                            )
+                                .help("consider using `let` statements to manually capture \
+                                        variables by reference before entering an \
+                                        `async move` closure")
+                                .emit();
                         }
-                        Some(match movability {
-                            Movability::Movable => hir::GeneratorMovability::Movable,
-                            Movability::Static => hir::GeneratorMovability::Static,
-                        })
+
+                        // Transform `async |x: u8| -> X { ... }` into
+                        // `|x: u8| future_from_generator(|| -> X { ... })`
+                        let outer_decl = FnDecl {
+                            inputs: decl.inputs.clone(),
+                            output: FunctionRetTy::Default(fn_decl_span),
+                            variadic: false,
+                        };
+                        let body_id = this.lower_body(Some(&outer_decl), |this| {
+                            let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
+                                Some(&**ty)
+                            } else { None };
+                            let async_body = this.make_async_expr(
+                                capture_clause, async_closure_node_id, async_ret_ty,
+                                |this| {
+                                    this.with_new_scopes(|this| this.lower_expr(body))
+                                });
+                            this.expr(fn_decl_span, async_body, ThinVec::new())
+                        });
+                        hir::ExprClosure(
+                            this.lower_capture_clause(capture_clause),
+                            this.lower_fn_decl(&outer_decl, None, false, false),
+                            body_id,
+                            fn_decl_span,
+                            None,
+                        )
                     } else {
-                        if movability == Movability::Static {
-                            span_err!(
-                                this.sess,
-                                fn_decl_span,
-                                E0697,
-                                "closures cannot be static"
-                            );
-                        }
-                        None
-                    };
-                    hir::ExprClosure(
-                        this.lower_capture_clause(capture_clause),
-                        this.lower_fn_decl(decl, None, false),
-                        body_id,
-                        fn_decl_span,
-                        generator_option,
-                    )
+                        let mut is_generator = false;
+                        let body_id = this.lower_body(Some(decl), |this| {
+                            let e = this.lower_expr(body);
+                            is_generator = this.is_generator;
+                            e
+                        });
+                        let generator_option = if is_generator {
+                            if !decl.inputs.is_empty() {
+                                span_err!(
+                                    this.sess,
+                                    fn_decl_span,
+                                    E0628,
+                                    "generators cannot have explicit arguments"
+                                );
+                                this.sess.abort_if_errors();
+                            }
+                            Some(match movability {
+                                Movability::Movable => hir::GeneratorMovability::Movable,
+                                Movability::Static => hir::GeneratorMovability::Static,
+                            })
+                        } else {
+                            if movability == Movability::Static {
+                                span_err!(
+                                    this.sess,
+                                    fn_decl_span,
+                                    E0906,
+                                    "closures cannot be static"
+                                );
+                            }
+                            None
+                        };
+                        hir::ExprClosure(
+                            this.lower_capture_clause(capture_clause),
+                            this.lower_fn_decl(decl, None, false, false),
+                            body_id,
+                            fn_decl_span,
+                            generator_option,
+                        )
+                    }
                 })
             }
             ExprKind::Block(ref blk, opt_label) => {
@@ -4193,7 +4577,7 @@ fn elided_ref_lifetime(&mut self, span: Span) -> hir::Lifetime {
                 hir::Lifetime {
                     id: self.next_id().node_id,
                     span,
-                    name: fresh_name,
+                    name: hir::LifetimeName::Param(fresh_name),
                 }
             }