Skip to content

Commit fa813f7

Browse files
committed
introduce closure_env_ty helper to compute ty of closure env arg
Previously the code was somewhat duplicated.
1 parent 7f247ad commit fa813f7

File tree

4 files changed

+42
-31
lines changed

4 files changed

+42
-31
lines changed

src/librustc/ty/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,6 +1921,12 @@ impl<'a, 'gcx, 'tcx> FieldDef {
19211921
}
19221922
}
19231923

1924+
/// Represents the various closure traits in the Rust language. This
1925+
/// will determine the type of the environment (`self`, in the
1926+
/// desuaring) argument that the closure expects.
1927+
///
1928+
/// You can get the environment type of a closure using
1929+
/// `tcx.closure_env_ty()`.
19241930
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
19251931
pub enum ClosureKind {
19261932
// Warning: Ordering is significant here! The ordering is chosen

src/librustc/ty/util.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,33 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
634634
def_id
635635
}
636636

637+
/// Given the def-id and substs a closure, creates the type of
638+
/// `self` argument that the closure expects. For example, for a
639+
/// `Fn` closure, this would return a reference type `&T` where
640+
/// `T=closure_ty`.
641+
///
642+
/// Returns `None` if this closure's kind has not yet been inferred.
643+
/// This should only be possible during type checking.
644+
///
645+
/// Note that the return value is a late-bound region and hence
646+
/// wrapped in a binder.
647+
pub fn closure_env_ty(self,
648+
closure_def_id: DefId,
649+
closure_substs: ty::ClosureSubsts<'tcx>)
650+
-> Option<ty::Binder<Ty<'tcx>>>
651+
{
652+
let closure_ty = self.mk_closure(closure_def_id, closure_substs);
653+
let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
654+
let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self);
655+
let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
656+
let env_ty = match closure_kind {
657+
ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),
658+
ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
659+
ty::ClosureKind::FnOnce => closure_ty,
660+
};
661+
Some(ty::Binder(env_ty))
662+
}
663+
637664
/// Given the def-id of some item that has no type parameters, make
638665
/// a suitable "empty substs" for it.
639666
pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx ty::Substs<'tcx> {

src/librustc_mir/build/mod.rs

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
100100
// HACK(eddyb) Avoid having RustCall on closures,
101101
// as it adds unnecessary (and wrong) auto-tupling.
102102
abi = Abi::Rust;
103-
Some((closure_self_ty(tcx, id, body_id), None))
103+
Some((liberated_closure_env_ty(tcx, id, body_id), None))
104104
}
105105
ty::TyGenerator(..) => {
106106
let gen_ty = tcx.body_tables(body_id).node_id_to_type(fn_hir_id);
@@ -246,10 +246,10 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
246246
///////////////////////////////////////////////////////////////////////////
247247
// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
248248

249-
pub fn closure_self_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
250-
closure_expr_id: ast::NodeId,
251-
body_id: hir::BodyId)
252-
-> Ty<'tcx> {
249+
fn liberated_closure_env_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
250+
closure_expr_id: ast::NodeId,
251+
body_id: hir::BodyId)
252+
-> Ty<'tcx> {
253253
let closure_expr_hir_id = tcx.hir.node_to_hir_id(closure_expr_id);
254254
let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_hir_id);
255255

@@ -258,24 +258,8 @@ pub fn closure_self_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
258258
_ => bug!("closure expr does not have closure type: {:?}", closure_ty)
259259
};
260260

261-
let region = ty::ReFree(ty::FreeRegion {
262-
scope: closure_def_id,
263-
bound_region: ty::BoundRegion::BrEnv,
264-
});
265-
let region = tcx.mk_region(region);
266-
267-
match closure_substs.closure_kind_ty(closure_def_id, tcx).to_opt_closure_kind().unwrap() {
268-
ty::ClosureKind::Fn =>
269-
tcx.mk_ref(region,
270-
ty::TypeAndMut { ty: closure_ty,
271-
mutbl: hir::MutImmutable }),
272-
ty::ClosureKind::FnMut =>
273-
tcx.mk_ref(region,
274-
ty::TypeAndMut { ty: closure_ty,
275-
mutbl: hir::MutMutable }),
276-
ty::ClosureKind::FnOnce =>
277-
closure_ty
278-
}
261+
let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap();
262+
tcx.liberate_late_bound_regions(closure_def_id, &closure_env_ty)
279263
}
280264

281265
struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {

src/librustc_trans/common.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -395,15 +395,9 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
395395
let tcx = ccx.tcx();
396396
let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs);
397397

398-
let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
399-
let env_ty = match substs.closure_kind(def_id, tcx) {
400-
ty::ClosureKind::Fn => tcx.mk_imm_ref(tcx.mk_region(env_region), ty),
401-
ty::ClosureKind::FnMut => tcx.mk_mut_ref(tcx.mk_region(env_region), ty),
402-
ty::ClosureKind::FnOnce => ty,
403-
};
404-
398+
let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
405399
sig.map_bound(|sig| tcx.mk_fn_sig(
406-
iter::once(env_ty).chain(sig.inputs().iter().cloned()),
400+
iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()),
407401
sig.output(),
408402
sig.variadic,
409403
sig.unsafety,

0 commit comments

Comments
 (0)