Use CreateParameter mode for closures too.
This commit is contained in:
parent
32af719b07
commit
7437136f0e
6 changed files with 83 additions and 65 deletions
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue