]> git.lizzy.rs Git - rust.git/commitdiff
Remove some global state from the lowering pass
authorOliver Schneider <github35764891676564198441@oli-obk.de>
Tue, 19 Jun 2018 11:47:53 +0000 (13:47 +0200)
committerOliver Schneider <github35764891676564198441@oli-obk.de>
Sat, 30 Jun 2018 09:45:11 +0000 (11:45 +0200)
src/librustc/hir/lowering.rs

index 530733d5f837ecf2a774b3890eec2fb4098815ad..8f2ce9a18eef45d81e2f7618717fbc32b717df8c 100644 (file)
@@ -110,13 +110,6 @@ pub struct LoweringContext<'a> {
     /// written at all (e.g., `&T` or `std::cell::Ref<T>`).
     anonymous_lifetime_mode: AnonymousLifetimeMode,
 
-    // This is a list of in-band type definitions being generated by
-    // Argument-position `impl Trait`.
-    // When traversing a signature such as `fn foo(x: impl Trait)`,
-    // we record `impl Trait` as a new type parameter, then later
-    // add it on to `foo`s generics.
-    in_band_ty_params: Vec<hir::GenericParam>,
-
     // Used to create lifetime definitions from in-band lifetime usages.
     // e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8`
     // When a named lifetime is encountered in a function or impl header and
@@ -172,12 +165,14 @@ fn resolve_str_path(
     ) -> hir::Path;
 }
 
-#[derive(Clone, Copy, Debug)]
-enum ImplTraitContext {
+#[derive(Debug)]
+enum ImplTraitContext<'a> {
     /// Treat `impl Trait` as shorthand for a new universal generic parameter.
     /// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually
     /// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.
-    Universal,
+    ///
+    /// 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.
     /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
@@ -190,6 +185,17 @@ enum ImplTraitContext {
     Disallowed,
 }
 
+impl<'a> ImplTraitContext<'a> {
+    fn reborrow(&'b mut self) -> ImplTraitContext<'b> {
+        use self::ImplTraitContext::*;
+        match self {
+            Universal(params) => Universal(params),
+            Existential(did) => Existential(*did),
+            Disallowed => Disallowed,
+        }
+    }
+}
+
 pub fn lower_crate(
     sess: &Session,
     cstore: &CrateStore,
@@ -224,7 +230,6 @@ pub fn lower_crate(
         node_id_to_hir_id: IndexVec::new(),
         is_generator: false,
         is_in_trait_impl: false,
-        in_band_ty_params: Vec::new(),
         lifetimes_to_define: Vec::new(),
         is_collecting_in_band_lifetimes: false,
         in_scope_lifetimes: Vec::new(),
@@ -645,7 +650,7 @@ fn collect_in_band_defs<T, F>(
         f: F,
     ) -> (Vec<hir::GenericParam>, T)
     where
-        F: FnOnce(&mut LoweringContext) -> T,
+        F: FnOnce(&mut LoweringContext) -> (Vec<hir::GenericParam>, T),
     {
         assert!(!self.is_collecting_in_band_lifetimes);
         assert!(self.lifetimes_to_define.is_empty());
@@ -656,13 +661,11 @@ fn collect_in_band_defs<T, F>(
             self.anonymous_lifetime_mode = anonymous_lifetime_mode;
         }
 
-        assert!(self.in_band_ty_params.is_empty());
-        let res = f(self);
+        let (in_band_ty_params, res) = f(self);
 
         self.is_collecting_in_band_lifetimes = false;
         self.anonymous_lifetime_mode = old_anonymous_lifetime_mode;
 
-        let in_band_ty_params = self.in_band_ty_params.split_off(0);
         let lifetimes_to_define = self.lifetimes_to_define.split_off(0);
 
         let params = lifetimes_to_define
@@ -796,14 +799,19 @@ fn add_in_band_defs<F, T>(
         f: F,
     ) -> (hir::Generics, T)
     where
-        F: FnOnce(&mut LoweringContext) -> 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,
             |this| {
-                let itctx = ImplTraitContext::Universal;
                 this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| {
-                    (this.lower_generics(generics, itctx), f(this))
+                    let mut params = Vec::new();
+                    let generics = this.lower_generics(
+                        generics,
+                        ImplTraitContext::Universal(&mut params),
+                    );
+                    let res = f(this, &mut params);
+                    (params, (generics, res))
                 })
             },
         );
@@ -1069,7 +1077,7 @@ 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, 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::TyInfer,
             TyKind::Err => hir::TyErr,
@@ -1106,7 +1114,9 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty {
             ),
             TyKind::Never => hir::TyNever,
             TyKind::Tup(ref tys) => {
-                hir::TyTup(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx)).collect())
+                hir::TyTup(tys.iter().map(|ty| {
+                    self.lower_ty_direct(ty, itctx.reborrow())
+                }).collect())
             }
             TyKind::Paren(ref ty) => {
                 return self.lower_ty_direct(ty, itctx);
@@ -1140,7 +1150,7 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty {
                     .iter()
                     .filter_map(|bound| match *bound {
                         GenericBound::Trait(ref ty, TraitBoundModifier::None) => {
-                            Some(self.lower_poly_trait_ref(ty, itctx))
+                            Some(self.lower_poly_trait_ref(ty, itctx.reborrow()))
                         }
                         GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
                         GenericBound::Outlives(ref lifetime) => {
@@ -1167,7 +1177,7 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty {
                             |this| this.lower_param_bounds(bounds, itctx),
                         )
                     }
-                    ImplTraitContext::Universal => {
+                    ImplTraitContext::Universal(in_band_ty_params) => {
                         self.lower_node_id(def_node_id);
                         // Add a definition for the in-band TyParam
                         let def_index = self
@@ -1176,10 +1186,13 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty {
                             .opt_def_index(def_node_id)
                             .unwrap();
 
-                        let hir_bounds = self.lower_param_bounds(bounds, itctx);
+                        let hir_bounds = self.lower_param_bounds(
+                            bounds,
+                            ImplTraitContext::Universal(in_band_ty_params),
+                        );
                         // Set the name to `impl Bound1 + Bound2`
                         let ident = Ident::from_str(&pprust::ty_to_string(t)).with_span_pos(span);
-                        self.in_band_ty_params.push(hir::GenericParam {
+                        in_band_ty_params.push(hir::GenericParam {
                             id: def_node_id,
                             name: ParamName::Plain(ident),
                             pure_wrt_drop: false,
@@ -1502,10 +1515,10 @@ fn lower_qpath(
         qself: &Option<QSelf>,
         p: &Path,
         param_mode: ParamMode,
-        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));
+        let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow()));
 
         let resolution = self.resolver
             .get_resolution(id)
@@ -1592,7 +1605,7 @@ fn lower_qpath(
                         param_mode,
                         num_lifetimes,
                         parenthesized_generic_args,
-                        itctx,
+                        itctx.reborrow(),
                     )
                 })
                 .collect(),
@@ -1635,7 +1648,7 @@ fn lower_qpath(
                 param_mode,
                 0,
                 ParenthesizedGenericArgs::Warn,
-                itctx,
+                itctx.reborrow(),
             ));
             let qpath = hir::QPath::TypeRelative(ty, segment);
 
@@ -1752,7 +1765,7 @@ fn lower_angle_bracketed_parameter_data(
         &mut self,
         data: &AngleBracketedArgs,
         param_mode: ParamMode,
-        itctx: ImplTraitContext,
+        mut itctx: ImplTraitContext,
     ) -> (hir::GenericArgs, bool) {
         let &AngleBracketedArgs { ref args, ref bindings, .. } = data;
         let has_types = args.iter().any(|arg| match arg {
@@ -1760,8 +1773,8 @@ fn lower_angle_bracketed_parameter_data(
             _ => false,
         });
         (hir::GenericArgs {
-            args: args.iter().map(|a| self.lower_generic_arg(a, itctx)).collect(),
-            bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx)).collect(),
+            args: args.iter().map(|a| self.lower_generic_arg(a, itctx.reborrow())).collect(),
+            bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx.reborrow())).collect(),
             parenthesized: false,
         },
         !has_types && param_mode == ParamMode::Optional)
@@ -1866,15 +1879,15 @@ fn lower_fn_args_to_names(&mut self, decl: &FnDecl) -> hir::HirVec<Ident> {
     fn lower_fn_decl(
         &mut self,
         decl: &FnDecl,
-        fn_def_id: Option<DefId>,
+        mut in_band_ty_params: Option<(DefId, &mut Vec<hir::GenericParam>)>,
         impl_trait_return_allow: bool,
         make_ret_async: Option<NodeId>,
     ) -> P<hir::FnDecl> {
         let inputs = decl.inputs
             .iter()
             .map(|arg| {
-                if fn_def_id.is_some() {
-                    self.lower_ty_direct(&arg.ty, ImplTraitContext::Universal)
+                if let Some((_, ref mut ibty)) = in_band_ty_params {
+                    self.lower_ty_direct(&arg.ty, ImplTraitContext::Universal(ibty))
                 } else {
                     self.lower_ty_direct(&arg.ty, ImplTraitContext::Disallowed)
                 }
@@ -1883,11 +1896,15 @@ fn lower_fn_decl(
 
         let output = if let Some(ret_id) = make_ret_async {
             self.lower_async_fn_ret_ty(
-                &inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id"), ret_id)
+                &inputs,
+                &decl.output,
+                in_band_ty_params.expect("make_ret_async but no fn_def_id").0,
+                ret_id,
+            )
         } else {
             match decl.output {
-                FunctionRetTy::Ty(ref ty) => match fn_def_id {
-                    Some(def_id) if impl_trait_return_allow => {
+                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::Disallowed)),
@@ -2191,17 +2208,19 @@ fn lower_generic_params(
         &mut self,
         params: &Vec<GenericParam>,
         add_bounds: &NodeMap<Vec<GenericBound>>,
-        itctx: ImplTraitContext,
+        mut itctx: ImplTraitContext,
     ) -> hir::HirVec<hir::GenericParam> {
-        params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect()
+        params.iter().map(|param| {
+            self.lower_generic_param(param, add_bounds, itctx.reborrow())
+        }).collect()
     }
 
     fn lower_generic_param(&mut self,
                            param: &GenericParam,
                            add_bounds: &NodeMap<Vec<GenericBound>>,
-                           itctx: ImplTraitContext)
+                           mut itctx: ImplTraitContext)
                            -> hir::GenericParam {
-        let mut bounds = self.lower_param_bounds(&param.bounds, itctx);
+        let mut bounds = self.lower_param_bounds(&param.bounds, itctx.reborrow());
         match param.kind {
             GenericParamKind::Lifetime => {
                 let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
@@ -2238,8 +2257,9 @@ fn lower_generic_param(&mut self,
 
                 let add_bounds = add_bounds.get(&param.id).map_or(&[][..], |x| &x);
                 if !add_bounds.is_empty() {
+                    let params = self.lower_param_bounds(add_bounds, itctx.reborrow()).into_iter();
                     bounds = bounds.into_iter()
-                                   .chain(self.lower_param_bounds(add_bounds, itctx).into_iter())
+                                   .chain(params)
                                    .collect();
                 }
 
@@ -2434,10 +2454,10 @@ fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::Tra
     fn lower_poly_trait_ref(
         &mut self,
         p: &PolyTraitRef,
-        itctx: ImplTraitContext,
+        mut itctx: ImplTraitContext,
     ) -> hir::PolyTraitRef {
         let bound_generic_params =
-            self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx);
+            self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx.reborrow());
         let trait_ref = self.with_parent_impl_lifetime_defs(
             &bound_generic_params,
             |this| this.lower_trait_ref(&p.trait_ref, itctx),
@@ -2482,9 +2502,9 @@ fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy {
         }
     }
 
-    fn lower_param_bounds(&mut self, bounds: &[GenericBound], 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)).collect()
+        bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
     }
 
     fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
@@ -2585,8 +2605,8 @@ fn lower_item_kind(
                         generics,
                         fn_def_id,
                         AnonymousLifetimeMode::PassThrough,
-                        |this| this.lower_fn_decl(
-                            decl, Some(fn_def_id), true, header.asyncness.opt_return_id())
+                        |this, idty| this.lower_fn_decl(
+                            decl, Some((fn_def_id, idty)), true, header.asyncness.opt_return_id()),
                     );
 
                     hir::ItemFn(
@@ -2656,7 +2676,7 @@ fn lower_item_kind(
                     ast_generics,
                     def_id,
                     AnonymousLifetimeMode::CreateParameter,
-                    |this| {
+                    |this, _| {
                         let trait_ref = trait_ref.as_ref().map(|trait_ref| {
                             this.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed)
                         });
@@ -3191,7 +3211,7 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
                         generics,
                         def_id,
                         AnonymousLifetimeMode::PassThrough,
-                        |this| {
+                        |this, _| {
                             (
                                 // Disallow impl Trait in foreign items
                                 this.lower_fn_decl(fdec, None, false, None),
@@ -3226,7 +3246,12 @@ fn lower_method_sig(
             generics,
             fn_def_id,
             AnonymousLifetimeMode::PassThrough,
-            |cx| cx.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow, is_async),
+            |this, idty| this.lower_fn_decl(
+                &sig.decl,
+                Some((fn_def_id, idty)),
+                impl_trait_return_allow,
+                is_async,
+            ),
         );
         (generics, hir::MethodSig { header, decl })
     }