1
Fork 0

Use CreateParameter mode for closures too.

This commit is contained in:
Camille GILLOT 2022-05-23 15:50:02 +02:00
parent 32af719b07
commit 7437136f0e
6 changed files with 83 additions and 65 deletions

View file

@ -165,6 +165,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
if let Async::Yes { closure_id, .. } = asyncness { if let Async::Yes { closure_id, .. } = asyncness {
self.lower_expr_async_closure( self.lower_expr_async_closure(
capture_clause, capture_clause,
e.id,
closure_id, closure_id,
decl, decl,
body, body,
@ -173,6 +174,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
} else { } else {
self.lower_expr_closure( self.lower_expr_closure(
capture_clause, capture_clause,
e.id,
movability, movability,
decl, decl,
body, body,
@ -604,6 +606,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `static |_task_context| -> <ret_ty> { body }`: // `static |_task_context| -> <ret_ty> { body }`:
let generator_kind = hir::ExprKind::Closure { let generator_kind = hir::ExprKind::Closure {
capture_clause, capture_clause,
bound_generic_params: &[],
fn_decl, fn_decl,
body, body,
fn_decl_span: self.lower_span(span), fn_decl_span: self.lower_span(span),
@ -828,6 +831,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_expr_closure( fn lower_expr_closure(
&mut self, &mut self,
capture_clause: CaptureBy, capture_clause: CaptureBy,
closure_id: NodeId,
movability: Movability, movability: Movability,
decl: &FnDecl, decl: &FnDecl,
body: &Expr, body: &Expr,
@ -848,16 +852,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
(body_id, generator_option) (body_id, generator_option)
}); });
// Lower outside new scope to preserve `is_in_loop_condition`. self.with_lifetime_binder(closure_id, &[], |this, bound_generic_params| {
let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None); // 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 { hir::ExprKind::Closure {
capture_clause, capture_clause,
fn_decl, bound_generic_params,
body, fn_decl,
fn_decl_span: self.lower_span(fn_decl_span), body,
movability: generator_option, fn_decl_span: this.lower_span(fn_decl_span),
} movability: generator_option,
}
})
} }
fn generator_movability_for_fn( fn generator_movability_for_fn(
@ -897,6 +904,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&mut self, &mut self,
capture_clause: CaptureBy, capture_clause: CaptureBy,
closure_id: NodeId, closure_id: NodeId,
inner_closure_id: NodeId,
decl: &FnDecl, decl: &FnDecl,
body: &Expr, body: &Expr,
fn_decl_span: Span, fn_decl_span: Span,
@ -927,7 +935,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None }; if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None };
let async_body = this.make_async_expr( let async_body = this.make_async_expr(
capture_clause, capture_clause,
closure_id, inner_closure_id,
async_ret_ty, async_ret_ty,
body.span, body.span,
hir::AsyncGeneratorKind::Closure, hir::AsyncGeneratorKind::Closure,
@ -938,18 +946,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
body_id body_id
}); });
// We need to lower the declaration outside the new scope, because we self.with_lifetime_binder(closure_id, &[], |this, bound_generic_params| {
// have to conserve the state of being inside a loop condition for the // We need to lower the declaration outside the new scope, because we
// closure argument types. // have to conserve the state of being inside a loop condition for the
let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None); // closure argument types.
let fn_decl = this.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
hir::ExprKind::Closure { hir::ExprKind::Closure {
capture_clause, capture_clause,
fn_decl, bound_generic_params,
body, fn_decl,
fn_decl_span: self.lower_span(fn_decl_span), body,
movability: None, fn_decl_span: this.lower_span(fn_decl_span),
} movability: None,
}
})
} }
/// Destructure the LHS of complex assignments. /// Destructure the LHS of complex assignments.

View file

@ -1932,6 +1932,7 @@ pub enum ExprKind<'hir> {
/// `Option<Movability>`. /// `Option<Movability>`.
Closure { Closure {
capture_clause: CaptureBy, capture_clause: CaptureBy,
bound_generic_params: &'hir [GenericParam<'hir>],
fn_decl: &'hir FnDecl<'hir>, fn_decl: &'hir FnDecl<'hir>,
body: BodyId, body: BodyId,
fn_decl_span: Span, fn_decl_span: Span,
@ -3480,7 +3481,7 @@ impl<'hir> Node<'hir> {
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
mod size_asserts { mod size_asserts {
rustc_data_structures::static_assert_size!(super::Block<'static>, 48); 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::Pat<'static>, 88);
rustc_data_structures::static_assert_size!(super::QPath<'static>, 24); rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
rustc_data_structures::static_assert_size!(super::Ty<'static>, 72); rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);

View file

@ -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); walk_list!(visitor, visit_arm, arms);
} }
ExprKind::Closure { ExprKind::Closure {
bound_generic_params,
ref fn_decl, ref fn_decl,
body, body,
capture_clause: _, capture_clause: _,
fn_decl_span: _, fn_decl_span: _,
movability: _, 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) => { ExprKind::Block(ref block, ref opt_label) => {
walk_list!(visitor, visit_label, opt_label); walk_list!(visitor, visit_label, opt_label);
visitor.visit_block(block); visitor.visit_block(block);

View file

@ -1459,11 +1459,13 @@ impl<'a> State<'a> {
} }
hir::ExprKind::Closure { hir::ExprKind::Closure {
capture_clause, capture_clause,
bound_generic_params,
ref fn_decl, ref fn_decl,
body, body,
fn_decl_span: _, fn_decl_span: _,
movability: _, movability: _,
} => { } => {
self.print_formal_generic_params(bound_generic_params);
self.print_capture_clause(capture_clause); self.print_capture_clause(capture_clause);
self.print_closure_params(&fn_decl, body); self.print_closure_params(&fn_decl, body);

View file

@ -845,11 +845,13 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
} }
} }
FnKind::Closure(declaration, body) => { FnKind::Closure(declaration, body) => {
// Do not attempt to create generic lifetime parameters. // We do not have any explicit generic lifetime parameter.
// FIXME: Revisit this decision once `for<>` bounds on closures become a // FIXME(rfc3216): Change when implementing `for<>` bounds on closures.
// thing.
this.with_lifetime_rib( this.with_lifetime_rib(
LifetimeRibKind::AnonymousPassThrough(fn_id, false), LifetimeRibKind::AnonymousCreateParameter {
binder: fn_id,
report_in_path: false,
},
// Add each argument to the rib. // Add each argument to the rib.
|this| this.resolve_params(&declaration.inputs), |this| this.resolve_params(&declaration.inputs),
); );
@ -1582,7 +1584,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
} }
break; break;
} }
_ => {} LifetimeRibKind::AnonymousCreateParameter { .. }
| LifetimeRibKind::Generics { .. }
| LifetimeRibKind::ConstGeneric
| LifetimeRibKind::AnonConst => {}
} }
} }
continue; continue;

View file

@ -29,8 +29,6 @@ use std::cell::Cell;
use std::fmt; use std::fmt;
use std::mem::take; use std::mem::take;
use tracing::{debug, span, Level};
trait RegionExt { trait RegionExt {
fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region); 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( fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
&mut self, if let hir::ExprKind::Closure { bound_generic_params, .. } = e.kind {
fk: intravisit::FnKind<'tcx>, let next_early_index = self.next_early_index();
fd: &'tcx hir::FnDecl<'tcx>, let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
b: hir::BodyId, bound_generic_params
s: rustc_span::Span, .iter()
hir_id: hir::HirId, .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
) { .enumerate()
let name = match fk { .map(|(late_bound_idx, param)| {
intravisit::FnKind::ItemFn(id, _, _) => id.name, let pair = Region::late(late_bound_idx as u32, self.tcx.hir(), param);
intravisit::FnKind::Method(id, _) => id.name, let r = late_region_as_bound_region(self.tcx, &pair.1);
intravisit::FnKind::Closure => sym::closure, (pair, r)
}; })
let name = name.as_str(); .unzip();
let span = span!(Level::DEBUG, "visit_fn", name); self.map.late_bound_vars.insert(e.hir_id, binders);
let _enter = span.enter(); let scope = Scope::Binder {
match fk { hir_id: e.hir_id,
// Any `Binders` are handled elsewhere lifetimes,
intravisit::FnKind::ItemFn(..) | intravisit::FnKind::Method(..) => { s: self.scope,
intravisit::walk_fn(self, fk, fd, b, s, hir_id) next_early_index,
} opaque_type_parent: false,
intravisit::FnKind::Closure => { scope_type: BinderScopeType::Normal,
self.map.late_bound_vars.insert(hir_id, vec![]); allow_late_bound: true,
let scope = Scope::Binder { where_bound_origin: None,
hir_id, };
lifetimes: FxIndexMap::default(), self.with(scope, |this| {
next_early_index: self.next_early_index(), // a closure has no bounds, so everything
s: self.scope, // contained within is scoped within its binder.
opaque_type_parent: false, intravisit::walk_expr(this, e)
scope_type: BinderScopeType::Normal, });
allow_late_bound: true, } else {
where_bound_origin: None, intravisit::walk_expr(self, e)
};
self.with(scope, move |this| intravisit::walk_fn(this, fk, fd, b, s, hir_id));
}
} }
} }