]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_ast_lowering/src/lib.rs
Completely remove captures flag
[rust.git] / compiler / rustc_ast_lowering / src / lib.rs
index a1bf0f94964bb70e8d342dd18b868482cb0bbb89..4ca771bf4738ce3de77978648716d7e6066b4112 100644 (file)
@@ -751,31 +751,6 @@ fn lifetime_res_to_generic_param(
         })
     }
 
-    /// Setup lifetime capture for and impl-trait.
-    /// The captures will be added to `captures`.
-    fn while_capturing_lifetimes<T>(
-        &mut self,
-        parent_def_id: LocalDefId,
-        captures: &mut FxHashMap<LocalDefId, (Span, NodeId, ParamName, LifetimeRes)>,
-        f: impl FnOnce(&mut Self) -> T,
-    ) -> T {
-        let lifetime_stash = std::mem::replace(
-            &mut self.captured_lifetimes,
-            Some(LifetimeCaptureContext {
-                parent_def_id,
-                captures: std::mem::take(captures),
-                binders_to_ignore: Default::default(),
-            }),
-        );
-
-        let ret = f(self);
-
-        let ctxt = std::mem::replace(&mut self.captured_lifetimes, lifetime_stash).unwrap();
-        *captures = ctxt.captures;
-
-        ret
-    }
-
     /// Register a binder to be ignored for lifetime capture.
     #[tracing::instrument(level = "debug", skip(self, f))]
     #[inline]
@@ -1293,17 +1268,17 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
             TyKind::ImplTrait(def_node_id, ref bounds) => {
                 let span = t.span;
                 match itctx {
-                    ImplTraitContext::ReturnPositionOpaqueTy { origin } => self
-                        .lower_opaque_impl_trait(span, origin, def_node_id, |this| {
-                            this.lower_param_bounds(bounds, itctx)
-                        }),
+                    ImplTraitContext::ReturnPositionOpaqueTy { origin } => {
+                        self.lower_opaque_impl_trait(span, origin, def_node_id, bounds, itctx)
+                    }
                     ImplTraitContext::TypeAliasesOpaqueTy => {
                         let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy;
                         self.lower_opaque_impl_trait(
                             span,
                             hir::OpaqueTyOrigin::TyAlias,
                             def_node_id,
-                            |this| this.lower_param_bounds(bounds, nested_itctx),
+                            bounds,
+                            nested_itctx,
                         )
                     }
                     ImplTraitContext::Universal => {
@@ -1343,13 +1318,14 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
         hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) }
     }
 
-    #[tracing::instrument(level = "debug", skip(self, lower_bounds))]
+    #[tracing::instrument(level = "debug", skip(self))]
     fn lower_opaque_impl_trait(
         &mut self,
         span: Span,
         origin: hir::OpaqueTyOrigin,
         opaque_ty_node_id: NodeId,
-        lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>,
+        bounds: &GenericBounds,
+        itctx: ImplTraitContext,
     ) -> hir::TyKind<'hir> {
         // 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
@@ -1363,13 +1339,32 @@ fn lower_opaque_impl_trait(
         let mut collected_lifetimes = FxHashMap::default();
         self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
             let hir_bounds = if origin == hir::OpaqueTyOrigin::TyAlias {
-                lower_bounds(lctx)
+                lctx.lower_param_bounds(bounds, itctx)
             } else {
-                lctx.while_capturing_lifetimes(
-                    opaque_ty_def_id,
-                    &mut collected_lifetimes,
-                    lower_bounds,
-                )
+                debug!(?lctx.captured_lifetimes);
+
+                let lifetime_stash = std::mem::replace(
+                    &mut lctx.captured_lifetimes,
+                    Some(LifetimeCaptureContext {
+                        parent_def_id: opaque_ty_def_id,
+                        captures: std::mem::take(&mut collected_lifetimes),
+                        binders_to_ignore: Default::default(),
+                    }),
+                );
+
+                let (lifetimes_in_bounds, binders_to_ignore) = ast::lifetimes_in_bounds(bounds);
+                debug!(?lifetimes_in_bounds);
+                debug!(?binders_to_ignore);
+
+                lctx.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore);
+
+                let ret = lctx.lower_param_bounds(bounds, itctx);
+
+                let ctxt = std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash).unwrap();
+
+                collected_lifetimes = ctxt.captures;
+
+                ret
             };
             debug!(?collected_lifetimes);
 
@@ -1450,6 +1445,84 @@ fn generate_opaque_type(
         hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
     }
 
+    fn create_and_capture_lifetime_defs(
+        &mut self,
+        lifetimes_in_bounds: &[&Lifetime],
+        binders_to_ignore: &FxHashMap<NodeId, Vec<NodeId>>,
+    ) {
+        for lifetime in lifetimes_in_bounds {
+            let ident = lifetime.ident;
+            let span = ident.span;
+
+            let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error);
+            debug!(?res);
+
+            if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() {
+                match res {
+                    LifetimeRes::Param { param, binder } => {
+                        if !binders_to_ignore
+                            .get(&lifetime.id)
+                            .unwrap_or(&Vec::new())
+                            .contains(&binder)
+                        {
+                            match captured_lifetimes.captures.entry(param) {
+                                Entry::Occupied(_) => {}
+                                Entry::Vacant(v) => {
+                                    let node_id = self.next_node_id();
+                                    let name = ParamName::Plain(ident);
+
+                                    self.create_def(
+                                        captured_lifetimes.parent_def_id,
+                                        node_id,
+                                        DefPathData::LifetimeNs(name.ident().name),
+                                    );
+
+                                    v.insert((span, node_id, name, res));
+                                }
+                            }
+                        }
+                    }
+
+                    LifetimeRes::Fresh { param, binder } => {
+                        debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
+                        if !binders_to_ignore
+                            .get(&lifetime.id)
+                            .unwrap_or(&Vec::new())
+                            .contains(&binder)
+                        {
+                            let param = self.local_def_id(param);
+                            match captured_lifetimes.captures.entry(param) {
+                                Entry::Occupied(_) => {}
+                                Entry::Vacant(v) => {
+                                    let node_id = self.next_node_id();
+
+                                    let name = ParamName::Fresh;
+
+                                    self.create_def(
+                                        captured_lifetimes.parent_def_id,
+                                        node_id,
+                                        DefPathData::LifetimeNs(kw::UnderscoreLifetime),
+                                    );
+
+                                    v.insert((span, node_id, name, res));
+                                }
+                            }
+                        }
+                    }
+
+                    LifetimeRes::Infer | LifetimeRes::Static | LifetimeRes::Error => {}
+
+                    res => panic!(
+                        "Unexpected lifetime resolution {:?} for {:?} at {:?}",
+                        res, lifetime.ident, lifetime.ident.span
+                    ),
+                }
+
+                self.captured_lifetimes = Some(captured_lifetimes);
+            }
+        }
+    }
+
     fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
         // Skip the `...` (`CVarArgs`) trailing arguments from the AST,
         // as they are not explicit in HIR/Ty function signatures.
@@ -1582,11 +1655,9 @@ fn lower_fn_decl(
     //
     //     type OpaqueTy<generics_from_parent_fn> = impl Future<Output = T>;
     //
-    // `inputs`: lowered types of parameters 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)
     // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created
-    // `elided_lt_replacement`: replacement for elided lifetimes in the return type
     #[tracing::instrument(level = "debug", skip(self))]
     fn lower_async_fn_ret_ty(
         &mut self,
@@ -1676,20 +1747,36 @@ fn lower_async_fn_ret_ty(
         debug!(?captures);
 
         self.with_hir_id_owner(opaque_ty_node_id, |this| {
-            let future_bound =
-                this.while_capturing_lifetimes(opaque_ty_def_id, &mut captures, |this| {
-                    // We have to be careful to get elision right here. The
-                    // idea is that we create a lifetime parameter for each
-                    // lifetime in the return type.  So, given a return type
-                    // like `async fn foo(..) -> &[&u32]`, we lower to `impl
-                    // Future<Output = &'1 [ &'2 u32 ]>`.
-                    //
-                    // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
-                    // hence the elision takes place at the fn site.
-                    this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span)
-                });
-            debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound);
-            debug!("lower_async_fn_ret_ty: captures={:#?}", captures);
+            let lifetime_stash = std::mem::replace(
+                &mut this.captured_lifetimes,
+                Some(LifetimeCaptureContext {
+                    parent_def_id: opaque_ty_def_id,
+                    captures: std::mem::take(&mut captures),
+                    binders_to_ignore: Default::default(),
+                }),
+            );
+
+            let (lifetimes_in_bounds, binders_to_ignore) = ast::lifetimes_in_ret_ty(output);
+            debug!(?lifetimes_in_bounds);
+            debug!(?binders_to_ignore);
+
+            this.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore);
+
+            // We have to be careful to get elision right here. The
+            // idea is that we create a lifetime parameter for each
+            // lifetime in the return type.  So, given a return type
+            // like `async fn foo(..) -> &[&u32]`, we lower to `impl
+            // Future<Output = &'1 [ &'2 u32 ]>`.
+            //
+            // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
+            // hence the elision takes place at the fn site.
+            let ret = this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span);
+
+            let ctxt = std::mem::replace(&mut this.captured_lifetimes, lifetime_stash).unwrap();
+
+            captures = ctxt.captures;
+
+            let future_bound = ret;
 
             let generic_params =
                 this.arena.alloc_from_iter(captures.iter().map(|(_, &(span, p_id, p_name, _))| {
@@ -1833,6 +1920,7 @@ fn new_named_lifetime_with_res(
         res: LifetimeRes,
     ) -> hir::Lifetime {
         debug!(?self.captured_lifetimes);
+
         let name = match res {
             LifetimeRes::Param { mut param, binder } => {
                 let p_name = ParamName::Plain(ident);
@@ -1842,6 +1930,7 @@ fn new_named_lifetime_with_res(
                             Entry::Occupied(o) => param = self.local_def_id(o.get().1),
                             Entry::Vacant(v) => {
                                 let p_id = self.next_node_id();
+
                                 let p_def_id = self.create_def(
                                     captured_lifetimes.parent_def_id,
                                     p_id,
@@ -1856,10 +1945,12 @@ fn new_named_lifetime_with_res(
 
                     self.captured_lifetimes = Some(captured_lifetimes);
                 }
+
                 hir::LifetimeName::Param(param, p_name)
             }
             LifetimeRes::Fresh { param, binder } => {
                 debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
+
                 let mut param = self.local_def_id(param);
                 if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() {
                     if !captured_lifetimes.binders_to_ignore.contains(&binder) {
@@ -1867,6 +1958,7 @@ fn new_named_lifetime_with_res(
                             Entry::Occupied(o) => param = self.local_def_id(o.get().1),
                             Entry::Vacant(v) => {
                                 let p_id = self.next_node_id();
+
                                 let p_def_id = self.create_def(
                                     captured_lifetimes.parent_def_id,
                                     p_id,
@@ -2015,7 +2107,6 @@ fn lower_generic_and_bounds(
         // Add a definition for the in-band `Param`.
         let def_id = self.local_def_id(node_id);
 
-        let hir_bounds = self.lower_param_bounds(bounds, ImplTraitContext::Universal);
         // Set the name to `impl Bound1 + Bound2`.
         let param = hir::GenericParam {
             hir_id: self.lower_node_id(node_id),
@@ -2030,7 +2121,8 @@ fn lower_generic_and_bounds(
             ident,
             node_id,
             &GenericParamKind::Type { default: None },
-            hir_bounds,
+            bounds,
+            ImplTraitContext::Universal,
             hir::PredicateOrigin::ImplTrait,
         );