]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/hir/lowering.rs
Nest the `impl Trait` existential item inside the return type
[rust.git] / src / librustc / hir / lowering.rs
index bd8770abb135c55b0f77cc6ff0d21869a4e26af9..40990917959f9736f68796fbedced6522a814bfe 100644 (file)
@@ -52,7 +52,6 @@
 use middle::cstore::CrateStore;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::small_vec::OneVector;
 use rustc_data_structures::thin_vec::ThinVec;
 use session::Session;
 use util::common::FN_OUTPUT_NAME;
@@ -62,6 +61,7 @@
 use std::fmt::Debug;
 use std::iter;
 use std::mem;
+use smallvec::SmallVec;
 use syntax::attr;
 use syntax::ast;
 use syntax::ast::*;
@@ -175,15 +175,17 @@ enum ImplTraitContext<'a> {
     /// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually
     /// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.
     ///
-    /// Newly generated parameters should be inserted into the given `Vec`
+    /// Newly generated parameters should be inserted into the given `Vec`.
     Universal(&'a mut Vec<hir::GenericParam>),
 
-    /// Treat `impl Trait` as shorthand for a new universal existential parameter.
+    /// Treat `impl Trait` as shorthand for a new existential parameter.
     /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
-    /// equivalent to a fresh existential parameter like `abstract type T; fn foo() -> T`.
+    /// equivalent to a fresh existential parameter like `existential type T; fn foo() -> T`.
     ///
-    /// We store a DefId here so we can look up necessary information later
-    Existential(DefId),
+    /// We optionally store a `DefId` for the parent item here so we can look up necessary
+    /// information later. It is `None` when no information about the context should be stored,
+    /// e.g. for consts and statics.
+    Existential(Option<DefId>),
 
     /// `impl Trait` is not accepted in this position.
     Disallowed,
@@ -305,6 +307,35 @@ enum AnonymousLifetimeMode {
     PassThrough,
 }
 
+struct ImplTraitTypeIdVisitor<'a> { ids: &'a mut SmallVec<[hir::ItemId; 1]> }
+
+impl<'a, 'b> Visitor<'a> for ImplTraitTypeIdVisitor<'b> {
+    fn visit_ty(&mut self, ty: &'a Ty) {
+        match ty.node {
+            | TyKind::Typeof(_)
+            | TyKind::BareFn(_)
+            => return,
+
+            TyKind::ImplTrait(id, _) => self.ids.push(hir::ItemId { id }),
+            _ => {},
+        }
+        visit::walk_ty(self, ty);
+    }
+
+    fn visit_path_segment(
+        &mut self,
+        path_span: Span,
+        path_segment: &'v PathSegment,
+    ) {
+        if let Some(ref p) = path_segment.args {
+            if let GenericArgs::Parenthesized(_) = **p {
+                return;
+            }
+        }
+        visit::walk_path_segment(self, path_span, path_segment)
+    }
+}
+
 impl<'a> LoweringContext<'a> {
     fn lower_crate(mut self, c: &Crate) -> hir::Crate {
         /// Full-crate AST visitor that inserts into a fresh
@@ -396,7 +427,7 @@ fn visit_item(&mut self, item: &'lcx Item) {
 
                     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 {
+                        if let ItemKind::Impl(.., ref opt_trait_ref, _, _) = item.node {
                             this.with_trait_impl_ref(opt_trait_ref, |this| {
                                 visit::walk_item(this, item)
                             });
@@ -655,7 +686,7 @@ fn collect_in_band_defs<T, F>(
         f: F,
     ) -> (Vec<hir::GenericParam>, T)
     where
-        F: FnOnce(&mut LoweringContext) -> (Vec<hir::GenericParam>, T),
+        F: FnOnce(&mut LoweringContext<'_>) -> (Vec<hir::GenericParam>, T),
     {
         assert!(!self.is_collecting_in_band_lifetimes);
         assert!(self.lifetimes_to_define.is_empty());
@@ -757,7 +788,7 @@ fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName {
     // for them.
     fn with_in_scope_lifetime_defs<T, F>(&mut self, params: &[GenericParam], f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext) -> T,
+        F: FnOnce(&mut LoweringContext<'_>) -> T,
     {
         let old_len = self.in_scope_lifetimes.len();
         let lt_def_names = params.iter().filter_map(|param| match param.kind {
@@ -781,7 +812,7 @@ fn with_parent_impl_lifetime_defs<T, F>(&mut self,
         params: &HirVec<hir::GenericParam>,
         f: F
     ) -> T where
-        F: FnOnce(&mut LoweringContext) -> T,
+        F: FnOnce(&mut LoweringContext<'_>) -> T,
     {
         let old_len = self.in_scope_lifetimes.len();
         let lt_def_names = params.iter().filter_map(|param| match param.kind {
@@ -810,7 +841,7 @@ fn add_in_band_defs<F, T>(
         f: F,
     ) -> (hir::Generics, T)
     where
-        F: FnOnce(&mut LoweringContext, &mut Vec<hir::GenericParam>) -> T,
+        F: FnOnce(&mut LoweringContext<'_>, &mut Vec<hir::GenericParam>) -> T,
     {
         let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs(
             &generics.params,
@@ -839,7 +870,7 @@ fn add_in_band_defs<F, T>(
 
     fn with_catch_scope<T, F>(&mut self, catch_id: NodeId, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext) -> T,
+        F: FnOnce(&mut LoweringContext<'_>) -> T,
     {
         let len = self.catch_scopes.len();
         self.catch_scopes.push(catch_id);
@@ -861,7 +892,7 @@ fn make_async_expr(
         capture_clause: CaptureBy,
         closure_node_id: NodeId,
         ret_ty: Option<&Ty>,
-        body: impl FnOnce(&mut LoweringContext) -> hir::Expr,
+        body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
     ) -> hir::ExprKind {
         let prev_is_generator = mem::replace(&mut self.is_generator, true);
         let body_expr = body(self);
@@ -898,7 +929,7 @@ fn make_async_expr(
 
     fn lower_body<F>(&mut self, decl: Option<&FnDecl>, f: F) -> hir::BodyId
     where
-        F: FnOnce(&mut LoweringContext) -> hir::Expr,
+        F: FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
     {
         let prev = mem::replace(&mut self.is_generator, false);
         let result = f(self);
@@ -909,7 +940,7 @@ fn lower_body<F>(&mut self, decl: Option<&FnDecl>, f: F) -> hir::BodyId
 
     fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext) -> T,
+        F: FnOnce(&mut LoweringContext<'_>) -> T,
     {
         // We're no longer in the base loop's condition; we're in another loop.
         let was_in_loop_condition = self.is_in_loop_condition;
@@ -934,7 +965,7 @@ fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
 
     fn with_loop_condition_scope<T, F>(&mut self, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext) -> T,
+        F: FnOnce(&mut LoweringContext<'_>) -> T,
     {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = true;
@@ -948,20 +979,20 @@ fn with_loop_condition_scope<T, F>(&mut self, f: F) -> T
 
     fn with_new_scopes<T, F>(&mut self, f: F) -> T
     where
-        F: FnOnce(&mut LoweringContext) -> T,
+        F: FnOnce(&mut LoweringContext<'_>) -> T,
     {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
 
         let catch_scopes = mem::replace(&mut self.catch_scopes, Vec::new());
         let loop_scopes = mem::replace(&mut self.loop_scopes, Vec::new());
-        let result = f(self);
+        let ret = f(self);
         self.catch_scopes = catch_scopes;
         self.loop_scopes = loop_scopes;
 
         self.is_in_loop_condition = was_in_loop_condition;
 
-        result
+        ret
     }
 
     fn def_key(&mut self, id: DefId) -> DefKey {
@@ -1063,7 +1094,8 @@ fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
         }
     }
 
-    fn lower_ty_binding(&mut self, b: &TypeBinding, itctx: ImplTraitContext) -> hir::TypeBinding {
+    fn lower_ty_binding(&mut self, b: &TypeBinding,
+                        itctx: ImplTraitContext<'_>) -> hir::TypeBinding {
         hir::TypeBinding {
             id: self.lower_node_id(b.id).node_id,
             ident: b.ident,
@@ -1074,7 +1106,7 @@ fn lower_ty_binding(&mut self, b: &TypeBinding, itctx: ImplTraitContext) -> hir:
 
     fn lower_generic_arg(&mut self,
                         arg: &ast::GenericArg,
-                        itctx: ImplTraitContext)
+                        itctx: ImplTraitContext<'_>)
                         -> hir::GenericArg {
         match arg {
             ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
@@ -1082,11 +1114,11 @@ fn lower_generic_arg(&mut self,
         }
     }
 
-    fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
+    fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext<'_>) -> P<hir::Ty> {
         P(self.lower_ty_direct(t, itctx))
     }
 
-    fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext) -> hir::Ty {
+    fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::Ty {
         let kind = match t.node {
             TyKind::Infer => hir::TyKind::Infer,
             TyKind::Err => hir::TyKind::Err,
@@ -1224,12 +1256,18 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext) -> hir::Ty {
                         ))
                     }
                     ImplTraitContext::Disallowed => {
+                        let allowed_in = if self.sess.features_untracked()
+                                                .impl_trait_in_bindings {
+                            "bindings or function and inherent method return types"
+                        } else {
+                            "function and inherent method return types"
+                        };
                         span_err!(
                             self.sess,
                             t.span,
                             E0562,
-                            "`impl Trait` not allowed outside of function \
-                             and inherent method return types"
+                            "`impl Trait` not allowed outside of {}",
+                            allowed_in,
                         );
                         hir::TyKind::Err
                     }
@@ -1250,9 +1288,9 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext) -> hir::Ty {
     fn lower_existential_impl_trait(
         &mut self,
         span: Span,
-        fn_def_id: DefId,
+        fn_def_id: Option<DefId>,
         exist_ty_node_id: NodeId,
-        lower_bounds: impl FnOnce(&mut LoweringContext) -> hir::GenericBounds,
+        lower_bounds: impl FnOnce(&mut LoweringContext<'_>) -> hir::GenericBounds,
     ) -> hir::TyKind {
         // 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
@@ -1270,7 +1308,6 @@ fn lower_existential_impl_trait(
             .opt_def_index(exist_ty_node_id)
             .unwrap();
 
-
         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);
@@ -1292,7 +1329,7 @@ fn lower_existential_impl_trait(
                     span,
                 },
                 bounds: hir_bounds,
-                impl_trait_fn: Some(fn_def_id),
+                impl_trait_fn: fn_def_id,
             });
             let exist_ty_id = lctx.lower_node_id(exist_ty_node_id);
             // Generate an `existential type Foo: Trait;` declaration
@@ -1315,20 +1352,7 @@ fn lower_existential_impl_trait(
             lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
 
             // `impl Trait` now just becomes `Foo<'a, 'b, ..>`
-            let path = P(hir::Path {
-                span: exist_ty_span,
-                def: Def::Existential(DefId::local(exist_ty_def_index)),
-                segments: hir_vec![hir::PathSegment {
-                    infer_types: false,
-                    ident: Ident::new(keywords::Invalid.name(), exist_ty_span),
-                    args: Some(P(hir::GenericArgs {
-                        parenthesized: false,
-                        bindings: HirVec::new(),
-                        args: lifetimes,
-                    }))
-                }],
-            });
-            hir::TyKind::Path(hir::QPath::Resolved(None, path))
+            hir::TyKind::Def(hir::ItemId { id: exist_ty_id.node_id }, lifetimes)
         })
     }
 
@@ -1531,7 +1555,7 @@ fn lower_qpath(
         qself: &Option<QSelf>,
         p: &Path,
         param_mode: ParamMode,
-        mut itctx: ImplTraitContext,
+        mut itctx: ImplTraitContext<'_>,
     ) -> hir::QPath {
         let qself_position = qself.as_ref().map(|q| q.position);
         let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow()));
@@ -1726,7 +1750,7 @@ fn lower_path_segment(
         param_mode: ParamMode,
         expected_lifetimes: usize,
         parenthesized_generic_args: ParenthesizedGenericArgs,
-        itctx: ImplTraitContext,
+        itctx: ImplTraitContext<'_>,
     ) -> hir::PathSegment {
         let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args {
             let msg = "parenthesized parameters may only be used with a trait";
@@ -1808,7 +1832,7 @@ fn lower_angle_bracketed_parameter_data(
         &mut self,
         data: &AngleBracketedArgs,
         param_mode: ParamMode,
-        mut itctx: ImplTraitContext,
+        mut itctx: ImplTraitContext<'_>,
     ) -> (hir::GenericArgs, bool) {
         let &AngleBracketedArgs { ref args, ref bindings, .. } = data;
         let has_types = args.iter().any(|arg| match arg {
@@ -1835,7 +1859,7 @@ fn lower_parenthesized_parameter_data(
         self.with_anonymous_lifetime_mode(
             AnonymousLifetimeMode::PassThrough,
             |this| {
-                const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed;
+                const DISALLOWED: ImplTraitContext<'_> = ImplTraitContext::Disallowed;
                 let &ParenthesisedArgs { ref inputs, ref output, span } = data;
                 let inputs = inputs.iter().map(|ty| this.lower_ty_direct(ty, DISALLOWED)).collect();
                 let mk_tup = |this: &mut Self, tys, span| {
@@ -1865,20 +1889,34 @@ fn lower_parenthesized_parameter_data(
         )
     }
 
-    fn lower_local(&mut self, l: &Local) -> P<hir::Local> {
+    fn lower_local(&mut self, l: &Local) -> (P<hir::Local>, SmallVec<[hir::ItemId; 1]>) {
         let LoweredNodeId { node_id, hir_id } = self.lower_node_id(l.id);
-        P(hir::Local {
+        let mut ids = SmallVec::<[hir::ItemId; 1]>::new();
+        if self.sess.features_untracked().impl_trait_in_bindings {
+            if let Some(ref ty) = l.ty {
+                let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
+                visitor.visit_ty(ty);
+            }
+        }
+        let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
+        (P(hir::Local {
             id: node_id,
             hir_id,
             ty: l.ty
                 .as_ref()
-                .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed)),
+                .map(|t| self.lower_ty(t,
+                    if self.sess.features_untracked().impl_trait_in_bindings {
+                        ImplTraitContext::Existential(Some(parent_def_id))
+                    } else {
+                        ImplTraitContext::Disallowed
+                    }
+                )),
             pat: self.lower_pat(&l.pat),
             init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
             span: l.span,
             attrs: l.attrs.clone(),
             source: hir::LocalSource::Normal,
-        })
+        }), ids)
     }
 
     fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
@@ -1948,7 +1986,7 @@ fn lower_fn_decl(
             match decl.output {
                 FunctionRetTy::Ty(ref ty) => match in_band_ty_params {
                     Some((def_id, _)) if impl_trait_return_allow => {
-                        hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(def_id)))
+                        hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(Some(def_id))))
                     }
                     _ => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)),
                 },
@@ -2131,10 +2169,11 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
         };
 
         let impl_trait_ty = self.lower_existential_impl_trait(
-            span, fn_def_id, return_impl_trait_id, |this| {
+            span, Some(fn_def_id), return_impl_trait_id, |this| {
             let output_ty = match output {
-                FunctionRetTy::Ty(ty) =>
-                    this.lower_ty(ty, ImplTraitContext::Existential(fn_def_id)),
+                FunctionRetTy::Ty(ty) => {
+                    this.lower_ty(ty, ImplTraitContext::Existential(Some(fn_def_id)))
+                }
                 FunctionRetTy::Default(span) => {
                     let LoweredNodeId { node_id, hir_id } = this.next_id();
                     P(hir::Ty {
@@ -2199,7 +2238,7 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
     fn lower_param_bound(
         &mut self,
         tpb: &GenericBound,
-        itctx: ImplTraitContext,
+        itctx: ImplTraitContext<'_>,
     ) -> hir::GenericBound {
         match *tpb {
             GenericBound::Trait(ref ty, modifier) => hir::GenericBound::Trait(
@@ -2253,7 +2292,7 @@ fn lower_generic_params(
         &mut self,
         params: &[GenericParam],
         add_bounds: &NodeMap<Vec<GenericBound>>,
-        mut itctx: ImplTraitContext,
+        mut itctx: ImplTraitContext<'_>,
     ) -> hir::HirVec<hir::GenericParam> {
         params.iter().map(|param| {
             self.lower_generic_param(param, add_bounds, itctx.reborrow())
@@ -2263,7 +2302,7 @@ fn lower_generic_params(
     fn lower_generic_param(&mut self,
                            param: &GenericParam,
                            add_bounds: &NodeMap<Vec<GenericBound>>,
-                           mut itctx: ImplTraitContext)
+                           mut itctx: ImplTraitContext<'_>)
                            -> hir::GenericParam {
         let mut bounds = self.lower_param_bounds(&param.bounds, itctx.reborrow());
         match param.kind {
@@ -2332,7 +2371,7 @@ fn lower_generic_param(&mut self,
     fn lower_generics(
         &mut self,
         generics: &Generics,
-        itctx: ImplTraitContext)
+        itctx: ImplTraitContext<'_>)
         -> hir::Generics
     {
         // Collect `?Trait` bounds in where clause and move them to parameter definitions.
@@ -2485,7 +2524,7 @@ fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
         }
     }
 
-    fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::TraitRef {
+    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.and_then(|path| path),
             qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
@@ -2501,7 +2540,7 @@ fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::Tra
     fn lower_poly_trait_ref(
         &mut self,
         p: &PolyTraitRef,
-        mut itctx: ImplTraitContext,
+        mut itctx: ImplTraitContext<'_>,
     ) -> hir::PolyTraitRef {
         let bound_generic_params =
             self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx.reborrow());
@@ -2542,14 +2581,14 @@ fn lower_field(&mut self, f: &Field) -> hir::Field {
         }
     }
 
-    fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy {
+    fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_>) -> hir::MutTy {
         hir::MutTy {
             ty: self.lower_ty(&mt.ty, itctx),
             mutbl: self.lower_mutability(mt.mutbl),
         }
     }
 
-    fn lower_param_bounds(&mut self, bounds: &[GenericBound], mut itctx: ImplTraitContext)
+    fn lower_param_bounds(&mut self, bounds: &[GenericBound], mut itctx: ImplTraitContext<'_>)
         -> hir::GenericBounds {
         bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
     }
@@ -2629,18 +2668,34 @@ fn lower_item_kind(
             ItemKind::Static(ref t, m, ref e) => {
                 let value = self.lower_body(None, |this| this.lower_expr(e));
                 hir::ItemKind::Static(
-                    self.lower_ty(t, ImplTraitContext::Disallowed),
+                    self.lower_ty(
+                        t,
+                        if self.sess.features_untracked().impl_trait_in_bindings {
+                            ImplTraitContext::Existential(None)
+                        } else {
+                            ImplTraitContext::Disallowed
+                        }
+                    ),
                     self.lower_mutability(m),
                     value,
                 )
             }
             ItemKind::Const(ref t, ref e) => {
                 let value = self.lower_body(None, |this| this.lower_expr(e));
-                hir::ItemKind::Const(self.lower_ty(t, ImplTraitContext::Disallowed), value)
+                hir::ItemKind::Const(
+                    self.lower_ty(
+                        t,
+                        if self.sess.features_untracked().impl_trait_in_bindings {
+                            ImplTraitContext::Existential(None)
+                        } else {
+                            ImplTraitContext::Disallowed
+                        }
+                    ),
+                    value
+                )
             }
             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 don't need to change the return type from `T` to
                     // `impl Future<Output = T>` here because lower_body
@@ -2653,7 +2708,11 @@ fn lower_item_kind(
                         fn_def_id,
                         AnonymousLifetimeMode::PassThrough,
                         |this, idty| this.lower_fn_decl(
-                            decl, Some((fn_def_id, idty)), true, header.asyncness.opt_return_id()),
+                            decl,
+                            Some((fn_def_id, idty)),
+                            true,
+                            header.asyncness.opt_return_id()
+                        ),
                     );
 
                     hir::ItemKind::Fn(
@@ -2995,7 +3054,6 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
                     let body = this.lower_block(body, false);
                     this.expr_block(body, ThinVec::new())
                 });
-
                 let (generics, sig) = self.lower_method_sig(
                     &i.generics,
                     sig,
@@ -3003,7 +3061,6 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
                     false,
                     None,
                 );
-
                 (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id)))
             }
             TraitItemKind::Type(ref bounds, ref default) => (
@@ -3137,68 +3194,29 @@ fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
         }
     }
 
-    /// Lowers `impl Trait` items and appends them to the list
-    fn lower_impl_trait_ids(
-        &mut self,
-        decl: &FnDecl,
-        header: &FnHeader,
-        ids: &mut OneVector<hir::ItemId>,
-    ) {
-        if let Some(id) = header.asyncness.opt_return_id() {
-            ids.push(hir::ItemId { id });
-        }
-        struct IdVisitor<'a> { ids: &'a mut OneVector<hir::ItemId> }
-        impl<'a, 'b> Visitor<'a> for IdVisitor<'b> {
-            fn visit_ty(&mut self, ty: &'a Ty) {
-                match ty.node {
-                    | TyKind::Typeof(_)
-                    | TyKind::BareFn(_)
-                    => return,
-
-                    TyKind::ImplTrait(id, _) => self.ids.push(hir::ItemId { id }),
-                    _ => {},
-                }
-                visit::walk_ty(self, ty);
-            }
-            fn visit_path_segment(
-                &mut self,
-                path_span: Span,
-                path_segment: &'v PathSegment,
-            ) {
-                if let Some(ref p) = path_segment.args {
-                    if let GenericArgs::Parenthesized(_) = **p {
-                        return;
-                    }
-                }
-                visit::walk_path_segment(self, path_span, path_segment)
-            }
-        }
-        let mut visitor = IdVisitor { ids };
-        match decl.output {
-            FunctionRetTy::Default(_) => {},
-            FunctionRetTy::Ty(ref ty) => visitor.visit_ty(ty),
-        }
-    }
-
-    fn lower_item_id(&mut self, i: &Item) -> OneVector<hir::ItemId> {
+    fn lower_item_id(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
         match i.node {
             ItemKind::Use(ref use_tree) => {
                 let mut vec = smallvec![hir::ItemId { id: i.id }];
                 self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
                 vec
             }
-            ItemKind::MacroDef(..) => OneVector::new(),
-            ItemKind::Fn(ref decl, ref header, ..) => {
+            ItemKind::MacroDef(..) => SmallVec::new(),
+            ItemKind::Fn(..) |
+            ItemKind::Impl(.., None, _, _) => smallvec![hir::ItemId { id: i.id }],
+            ItemKind::Static(ref ty, ..) => {
                 let mut ids = smallvec![hir::ItemId { id: i.id }];
-                self.lower_impl_trait_ids(decl, header, &mut ids);
+                if self.sess.features_untracked().impl_trait_in_bindings {
+                    let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
+                    visitor.visit_ty(ty);
+                }
                 ids
             },
-            ItemKind::Impl(.., None, _, ref items) => {
+            ItemKind::Const(ref ty, ..) => {
                 let mut ids = smallvec![hir::ItemId { id: i.id }];
-                for item in items {
-                    if let ImplItemKind::Method(ref sig, _) = item.node {
-                        self.lower_impl_trait_ids(&sig.decl, &sig.header, &mut ids);
-                    }
+                if self.sess.features_untracked().impl_trait_in_bindings {
+                    let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
+                    visitor.visit_ty(ty);
                 }
                 ids
             },
@@ -3209,7 +3227,7 @@ fn lower_item_id(&mut self, i: &Item) -> OneVector<hir::ItemId> {
     fn lower_item_id_use_tree(&mut self,
                               tree: &UseTree,
                               base_id: NodeId,
-                              vec: &mut OneVector<hir::ItemId>)
+                              vec: &mut SmallVec<[hir::ItemId; 1]>)
     {
         match tree.kind {
             UseTreeKind::Nested(ref nested_vec) => for &(ref nested, id) in nested_vec {
@@ -3761,8 +3779,8 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
             }
             ExprKind::Block(ref blk, opt_label) => {
                 hir::ExprKind::Block(self.lower_block(blk,
-                                                opt_label.is_some()),
-                                                self.lower_label(opt_label))
+                                                      opt_label.is_some()),
+                                                      self.lower_label(opt_label))
             }
             ExprKind::Assign(ref el, ref er) => {
                 hir::ExprKind::Assign(P(self.lower_expr(el)), P(self.lower_expr(er)))
@@ -4310,17 +4328,34 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
         }
     }
 
-    fn lower_stmt(&mut self, s: &Stmt) -> OneVector<hir::Stmt> {
+    fn lower_stmt(&mut self, s: &Stmt) -> SmallVec<[hir::Stmt; 1]> {
         smallvec![match s.node {
-            StmtKind::Local(ref l) => Spanned {
-                node: hir::StmtKind::Decl(
-                    P(Spanned {
-                        node: hir::DeclKind::Local(self.lower_local(l)),
+            StmtKind::Local(ref l) => {
+                let (l, item_ids) = self.lower_local(l);
+                let mut ids: SmallVec<[hir::Stmt; 1]> = item_ids
+                    .into_iter()
+                    .map(|item_id| Spanned {
+                        node: hir::StmtKind::Decl(
+                            P(Spanned {
+                                node: hir::DeclKind::Item(item_id),
+                                span: s.span,
+                            }),
+                            self.next_id().node_id,
+                        ),
                         span: s.span,
-                    }),
-                    self.lower_node_id(s.id).node_id,
-                ),
-                span: s.span,
+                    })
+                    .collect();
+                ids.push(Spanned {
+                    node: hir::StmtKind::Decl(
+                        P(Spanned {
+                            node: hir::DeclKind::Local(l),
+                            span: s.span,
+                        }),
+                        self.lower_node_id(s.id).node_id,
+                    ),
+                    span: s.span,
+                });
+                return ids;
             },
             StmtKind::Item(ref it) => {
                 // Can only use the ID once.
@@ -4334,8 +4369,8 @@ fn lower_stmt(&mut self, s: &Stmt) -> OneVector<hir::Stmt> {
                                 span: s.span,
                             }),
                             id.take()
-                                .map(|id| self.lower_node_id(id).node_id)
-                                .unwrap_or_else(|| self.next_id().node_id),
+                              .map(|id| self.lower_node_id(id).node_id)
+                              .unwrap_or_else(|| self.next_id().node_id),
                         ),
                         span: s.span,
                     })