about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2022-05-23 15:50:02 +0200
committerCamille GILLOT <gillot.camille@gmail.com>2022-06-21 21:13:43 +0200
commit7437136f0eac3f2ee58de08a784b1e9eae42b619 (patch)
tree0924e2ca0dbce0946a33a5bf1cd887207eda16cc
parent32af719b07217ff89e61a2031500cee138599baa (diff)
downloadrust-7437136f0eac3f2ee58de08a784b1e9eae42b619.tar.gz
rust-7437136f0eac3f2ee58de08a784b1e9eae42b619.zip
Use CreateParameter mode for closures too.
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs57
-rw-r--r--compiler/rustc_hir/src/hir.rs3
-rw-r--r--compiler/rustc_hir/src/intravisit.rs6
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs15
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs69
6 files changed, 85 insertions, 67 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 095a4b26a86..3babe73030a 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -165,6 +165,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     if let Async::Yes { closure_id, .. } = asyncness {
                         self.lower_expr_async_closure(
                             capture_clause,
+                            e.id,
                             closure_id,
                             decl,
                             body,
@@ -173,6 +174,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     } else {
                         self.lower_expr_closure(
                             capture_clause,
+                            e.id,
                             movability,
                             decl,
                             body,
@@ -604,6 +606,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // `static |_task_context| -> <ret_ty> { body }`:
         let generator_kind = hir::ExprKind::Closure {
             capture_clause,
+            bound_generic_params: &[],
             fn_decl,
             body,
             fn_decl_span: self.lower_span(span),
@@ -828,6 +831,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_expr_closure(
         &mut self,
         capture_clause: CaptureBy,
+        closure_id: NodeId,
         movability: Movability,
         decl: &FnDecl,
         body: &Expr,
@@ -848,16 +852,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
             (body_id, generator_option)
         });
 
-        // Lower outside new scope to preserve `is_in_loop_condition`.
-        let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
-
-        hir::ExprKind::Closure {
-            capture_clause,
-            fn_decl,
-            body,
-            fn_decl_span: self.lower_span(fn_decl_span),
-            movability: generator_option,
-        }
+        self.with_lifetime_binder(closure_id, &[], |this, bound_generic_params| {
+            // Lower outside new scope to preserve `is_in_loop_condition`.
+            let fn_decl = this.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
+
+            hir::ExprKind::Closure {
+                capture_clause,
+                bound_generic_params,
+                fn_decl,
+                body,
+                fn_decl_span: this.lower_span(fn_decl_span),
+                movability: generator_option,
+            }
+        })
     }
 
     fn generator_movability_for_fn(
@@ -897,6 +904,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         &mut self,
         capture_clause: CaptureBy,
         closure_id: NodeId,
+        inner_closure_id: NodeId,
         decl: &FnDecl,
         body: &Expr,
         fn_decl_span: Span,
@@ -927,7 +935,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None };
                 let async_body = this.make_async_expr(
                     capture_clause,
-                    closure_id,
+                    inner_closure_id,
                     async_ret_ty,
                     body.span,
                     hir::AsyncGeneratorKind::Closure,
@@ -938,18 +946,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
             body_id
         });
 
-        // We need to lower the declaration outside the new scope, because we
-        // have to conserve the state of being inside a loop condition for the
-        // closure argument types.
-        let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
-
-        hir::ExprKind::Closure {
-            capture_clause,
-            fn_decl,
-            body,
-            fn_decl_span: self.lower_span(fn_decl_span),
-            movability: None,
-        }
+        self.with_lifetime_binder(closure_id, &[], |this, bound_generic_params| {
+            // We need to lower the declaration outside the new scope, because we
+            // have to conserve the state of being inside a loop condition for the
+            // closure argument types.
+            let fn_decl = this.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
+
+            hir::ExprKind::Closure {
+                capture_clause,
+                bound_generic_params,
+                fn_decl,
+                body,
+                fn_decl_span: this.lower_span(fn_decl_span),
+                movability: None,
+            }
+        })
     }
 
     /// Destructure the LHS of complex assignments.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 5a06f8eab7e..a7fc59255d7 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1932,6 +1932,7 @@ pub enum ExprKind<'hir> {
     /// `Option<Movability>`.
     Closure {
         capture_clause: CaptureBy,
+        bound_generic_params: &'hir [GenericParam<'hir>],
         fn_decl: &'hir FnDecl<'hir>,
         body: BodyId,
         fn_decl_span: Span,
@@ -3480,7 +3481,7 @@ impl<'hir> Node<'hir> {
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 mod size_asserts {
     rustc_data_structures::static_assert_size!(super::Block<'static>, 48);
-    rustc_data_structures::static_assert_size!(super::Expr<'static>, 56);
+    rustc_data_structures::static_assert_size!(super::Expr<'static>, 64);
     rustc_data_structures::static_assert_size!(super::Pat<'static>, 88);
     rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
     rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index cce5aa9f732..e68274e2ad9 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -1169,12 +1169,16 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             walk_list!(visitor, visit_arm, arms);
         }
         ExprKind::Closure {
+            bound_generic_params,
             ref fn_decl,
             body,
             capture_clause: _,
             fn_decl_span: _,
             movability: _,
-        } => visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id),
+        } => {
+            walk_list!(visitor, visit_generic_param, bound_generic_params);
+            visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id)
+        }
         ExprKind::Block(ref block, ref opt_label) => {
             walk_list!(visitor, visit_label, opt_label);
             visitor.visit_block(block);
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 7317ce7335a..7bf91df9f76 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1459,11 +1459,13 @@ impl<'a> State<'a> {
             }
             hir::ExprKind::Closure {
                 capture_clause,
+                bound_generic_params,
                 ref fn_decl,
                 body,
                 fn_decl_span: _,
                 movability: _,
             } => {
+                self.print_formal_generic_params(bound_generic_params);
                 self.print_capture_clause(capture_clause);
 
                 self.print_closure_params(&fn_decl, body);
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 08d6134237a..e36f55b2e02 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -845,11 +845,13 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                         }
                     }
                     FnKind::Closure(declaration, body) => {
-                        // Do not attempt to create generic lifetime parameters.
-                        // FIXME: Revisit this decision once `for<>` bounds on closures become a
-                        // thing.
+                        // We do not have any explicit generic lifetime parameter.
+                        // FIXME(rfc3216): Change when implementing `for<>` bounds on closures.
                         this.with_lifetime_rib(
-                            LifetimeRibKind::AnonymousPassThrough(fn_id, false),
+                            LifetimeRibKind::AnonymousCreateParameter {
+                                binder: fn_id,
+                                report_in_path: false,
+                            },
                             // Add each argument to the rib.
                             |this| this.resolve_params(&declaration.inputs),
                         );
@@ -1582,7 +1584,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                             }
                             break;
                         }
-                        _ => {}
+                        LifetimeRibKind::AnonymousCreateParameter { .. }
+                        | LifetimeRibKind::Generics { .. }
+                        | LifetimeRibKind::ConstGeneric
+                        | LifetimeRibKind::AnonConst => {}
                     }
                 }
                 continue;
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index 53f6870bdf5..172dc7ffe95 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -29,8 +29,6 @@ use std::cell::Cell;
 use std::fmt;
 use std::mem::take;
 
-use tracing::{debug, span, Level};
-
 trait RegionExt {
     fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region);
 
@@ -572,41 +570,38 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         });
     }
 
-    fn visit_fn(
-        &mut self,
-        fk: intravisit::FnKind<'tcx>,
-        fd: &'tcx hir::FnDecl<'tcx>,
-        b: hir::BodyId,
-        s: rustc_span::Span,
-        hir_id: hir::HirId,
-    ) {
-        let name = match fk {
-            intravisit::FnKind::ItemFn(id, _, _) => id.name,
-            intravisit::FnKind::Method(id, _) => id.name,
-            intravisit::FnKind::Closure => sym::closure,
-        };
-        let name = name.as_str();
-        let span = span!(Level::DEBUG, "visit_fn", name);
-        let _enter = span.enter();
-        match fk {
-            // Any `Binders` are handled elsewhere
-            intravisit::FnKind::ItemFn(..) | intravisit::FnKind::Method(..) => {
-                intravisit::walk_fn(self, fk, fd, b, s, hir_id)
-            }
-            intravisit::FnKind::Closure => {
-                self.map.late_bound_vars.insert(hir_id, vec![]);
-                let scope = Scope::Binder {
-                    hir_id,
-                    lifetimes: FxIndexMap::default(),
-                    next_early_index: self.next_early_index(),
-                    s: self.scope,
-                    opaque_type_parent: false,
-                    scope_type: BinderScopeType::Normal,
-                    allow_late_bound: true,
-                    where_bound_origin: None,
-                };
-                self.with(scope, move |this| intravisit::walk_fn(this, fk, fd, b, s, hir_id));
-            }
+    fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
+        if let hir::ExprKind::Closure { bound_generic_params, .. } = e.kind {
+            let next_early_index = self.next_early_index();
+            let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
+                bound_generic_params
+                    .iter()
+                    .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
+                    .enumerate()
+                    .map(|(late_bound_idx, param)| {
+                        let pair = Region::late(late_bound_idx as u32, self.tcx.hir(), param);
+                        let r = late_region_as_bound_region(self.tcx, &pair.1);
+                        (pair, r)
+                    })
+                    .unzip();
+            self.map.late_bound_vars.insert(e.hir_id, binders);
+            let scope = Scope::Binder {
+                hir_id: e.hir_id,
+                lifetimes,
+                s: self.scope,
+                next_early_index,
+                opaque_type_parent: false,
+                scope_type: BinderScopeType::Normal,
+                allow_late_bound: true,
+                where_bound_origin: None,
+            };
+            self.with(scope, |this| {
+                // a closure has no bounds, so everything
+                // contained within is scoped within its binder.
+                intravisit::walk_expr(this, e)
+            });
+        } else {
+            intravisit::walk_expr(self, e)
         }
     }