introduce closure_env_ty helper to compute ty of closure env arg

Previously the code was somewhat duplicated.
This commit is contained in:
Niko Matsakis 2017-11-21 11:18:40 -05:00
parent 7f247add41
commit fa813f74a2
4 changed files with 42 additions and 31 deletions

View file

@ -1921,6 +1921,12 @@ impl<'a, 'gcx, 'tcx> FieldDef {
}
}
/// Represents the various closure traits in the Rust language. This
/// will determine the type of the environment (`self`, in the
/// desuaring) argument that the closure expects.
///
/// You can get the environment type of a closure using
/// `tcx.closure_env_ty()`.
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub enum ClosureKind {
// Warning: Ordering is significant here! The ordering is chosen

View file

@ -634,6 +634,33 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
def_id
}
/// Given the def-id and substs a closure, creates the type of
/// `self` argument that the closure expects. For example, for a
/// `Fn` closure, this would return a reference type `&T` where
/// `T=closure_ty`.
///
/// Returns `None` if this closure's kind has not yet been inferred.
/// This should only be possible during type checking.
///
/// Note that the return value is a late-bound region and hence
/// wrapped in a binder.
pub fn closure_env_ty(self,
closure_def_id: DefId,
closure_substs: ty::ClosureSubsts<'tcx>)
-> Option<ty::Binder<Ty<'tcx>>>
{
let closure_ty = self.mk_closure(closure_def_id, closure_substs);
let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self);
let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
let env_ty = match closure_kind {
ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),
ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
ty::ClosureKind::FnOnce => closure_ty,
};
Some(ty::Binder(env_ty))
}
/// Given the def-id of some item that has no type parameters, make
/// a suitable "empty substs" for it.
pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx ty::Substs<'tcx> {

View file

@ -100,7 +100,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
// HACK(eddyb) Avoid having RustCall on closures,
// as it adds unnecessary (and wrong) auto-tupling.
abi = Abi::Rust;
Some((closure_self_ty(tcx, id, body_id), None))
Some((liberated_closure_env_ty(tcx, id, body_id), None))
}
ty::TyGenerator(..) => {
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>,
///////////////////////////////////////////////////////////////////////////
// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
pub fn closure_self_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
closure_expr_id: ast::NodeId,
body_id: hir::BodyId)
-> Ty<'tcx> {
fn liberated_closure_env_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
closure_expr_id: ast::NodeId,
body_id: hir::BodyId)
-> Ty<'tcx> {
let closure_expr_hir_id = tcx.hir.node_to_hir_id(closure_expr_id);
let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_hir_id);
@ -258,24 +258,8 @@ pub fn closure_self_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
_ => bug!("closure expr does not have closure type: {:?}", closure_ty)
};
let region = ty::ReFree(ty::FreeRegion {
scope: closure_def_id,
bound_region: ty::BoundRegion::BrEnv,
});
let region = tcx.mk_region(region);
match closure_substs.closure_kind_ty(closure_def_id, tcx).to_opt_closure_kind().unwrap() {
ty::ClosureKind::Fn =>
tcx.mk_ref(region,
ty::TypeAndMut { ty: closure_ty,
mutbl: hir::MutImmutable }),
ty::ClosureKind::FnMut =>
tcx.mk_ref(region,
ty::TypeAndMut { ty: closure_ty,
mutbl: hir::MutMutable }),
ty::ClosureKind::FnOnce =>
closure_ty
}
let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap();
tcx.liberate_late_bound_regions(closure_def_id, &closure_env_ty)
}
struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {

View file

@ -395,15 +395,9 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let tcx = ccx.tcx();
let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs);
let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
let env_ty = match substs.closure_kind(def_id, tcx) {
ty::ClosureKind::Fn => tcx.mk_imm_ref(tcx.mk_region(env_region), ty),
ty::ClosureKind::FnMut => tcx.mk_mut_ref(tcx.mk_region(env_region), ty),
ty::ClosureKind::FnOnce => ty,
};
let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
sig.map_bound(|sig| tcx.mk_fn_sig(
iter::once(env_ty).chain(sig.inputs().iter().cloned()),
iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()),
sig.output(),
sig.variadic,
sig.unsafety,