提交 e0eb3ccb 编写于 作者: A Ariel Ben-Yehuda 提交者: Ariel Ben-Yehuda

Kill TraitStore

上级 4032b85a
......@@ -243,19 +243,6 @@ fn parse_size(st: &mut PState) -> Option<uint> {
}
}
fn parse_trait_store_<F>(st: &mut PState, conv: &mut F) -> ty::TraitStore where
F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
{
match next(st) {
'~' => ty::UniqTraitStore,
'&' => ty::RegionTraitStore(parse_region_(st, conv), parse_mutability(st)),
c => {
st.tcx.sess.bug(&format!("parse_trait_store(): bad input '{}'",
c)[])
}
}
}
fn parse_vec_per_param_space<'a, 'tcx, T, F>(st: &mut PState<'a, 'tcx>,
mut f: F)
-> VecPerParamSpace<T> where
......@@ -662,14 +649,12 @@ fn parse_closure_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
{
let unsafety = parse_unsafety(next(st));
let onceness = parse_onceness(next(st));
let store = parse_trait_store_(st, conv);
let bounds = parse_existential_bounds_(st, conv);
let sig = parse_sig_(st, conv);
let abi = parse_abi_set(st);
ty::ClosureTy {
unsafety: unsafety,
onceness: onceness,
store: store,
bounds: bounds,
sig: sig,
abi: abi,
......
......@@ -305,17 +305,6 @@ pub fn enc_trait_ref<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
enc_substs(w, cx, s.substs);
}
pub fn enc_trait_store(w: &mut SeekableMemWriter, cx: &ctxt, s: ty::TraitStore) {
match s {
ty::UniqTraitStore => mywrite!(w, "~"),
ty::RegionTraitStore(re, m) => {
mywrite!(w, "&");
enc_region(w, cx, re);
enc_mutability(w, m);
}
}
}
fn enc_unsafety(w: &mut SeekableMemWriter, p: ast::Unsafety) {
match p {
ast::Unsafety::Normal => mywrite!(w, "n"),
......@@ -347,7 +336,6 @@ pub fn enc_closure_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
ft: &ty::ClosureTy<'tcx>) {
enc_unsafety(w, ft.unsafety);
enc_onceness(w, ft.onceness);
enc_trait_store(w, cx, ft.store);
enc_existential_bounds(w, cx, &ft.bounds);
enc_fn_sig(w, cx, &ft.sig);
enc_abi(w, ft.abi);
......
......@@ -515,17 +515,6 @@ fn tr(&self, dcx: &DecodeContext) -> ty::BoundRegion {
}
}
impl tr for ty::TraitStore {
fn tr(&self, dcx: &DecodeContext) -> ty::TraitStore {
match *self {
ty::RegionTraitStore(r, m) => {
ty::RegionTraitStore(r.tr(dcx), m)
}
ty::UniqTraitStore => ty::UniqTraitStore
}
}
}
// ______________________________________________________________________
// Encoding and decoding of freevar information
......
......@@ -202,39 +202,6 @@ fn bare_fn_tys(&self, a: &ty::BareFnTy<'tcx>,
sig: sig})
}
fn closure_tys(&self, a: &ty::ClosureTy<'tcx>,
b: &ty::ClosureTy<'tcx>) -> cres<'tcx, ty::ClosureTy<'tcx>> {
let store = match (a.store, b.store) {
(ty::RegionTraitStore(a_r, a_m),
ty::RegionTraitStore(b_r, b_m)) if a_m == b_m => {
let r = try!(self.contraregions(a_r, b_r));
ty::RegionTraitStore(r, a_m)
}
_ if a.store == b.store => {
a.store
}
_ => {
return Err(ty::terr_sigil_mismatch(expected_found(self, a.store, b.store)))
}
};
let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety));
let onceness = try!(self.oncenesses(a.onceness, b.onceness));
let bounds = try!(self.existential_bounds(&a.bounds, &b.bounds));
let sig = try!(self.binders(&a.sig, &b.sig));
let abi = try!(self.abi(a.abi, b.abi));
Ok(ty::ClosureTy {
unsafety: unsafety,
onceness: onceness,
store: store,
bounds: bounds,
sig: sig,
abi: abi,
})
}
fn fn_sigs(&self, a: &ty::FnSig<'tcx>, b: &ty::FnSig<'tcx>) -> cres<'tcx, ty::FnSig<'tcx>> {
if a.variadic != b.variadic {
return Err(ty::terr_variadic_mismatch(expected_found(self, a.variadic, b.variadic)));
......@@ -356,31 +323,6 @@ fn contraregions(&self, a: ty::Region, b: ty::Region)
fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region>;
fn trait_stores(&self,
vk: ty::terr_vstore_kind,
a: ty::TraitStore,
b: ty::TraitStore)
-> cres<'tcx, ty::TraitStore> {
debug!("{}.trait_stores(a={:?}, b={:?})", self.tag(), a, b);
match (a, b) {
(ty::RegionTraitStore(a_r, a_m),
ty::RegionTraitStore(b_r, b_m)) if a_m == b_m => {
self.contraregions(a_r, b_r).and_then(|r| {
Ok(ty::RegionTraitStore(r, a_m))
})
}
_ if a == b => {
Ok(a)
}
_ => {
Err(ty::terr_trait_stores_differ(vk, expected_found(self, a, b)))
}
}
}
fn trait_refs(&self,
a: &ty::TraitRef<'tcx>,
b: &ty::TraitRef<'tcx>)
......
......@@ -17,7 +17,6 @@
pub use self::InferRegion::*;
pub use self::ImplOrTraitItemId::*;
pub use self::UnboxedClosureKind::*;
pub use self::TraitStore::*;
pub use self::ast_ty_to_ty_cache_entry::*;
pub use self::Variance::*;
pub use self::AutoAdjustment::*;
......@@ -61,7 +60,7 @@
use middle::ty_fold::{self, TypeFoldable, TypeFolder};
use middle::ty_walk::TypeWalker;
use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string};
use util::ppaux::{trait_store_to_string, ty_to_string};
use util::ppaux::ty_to_string;
use util::ppaux::{Repr, UserString};
use util::common::{memoized, ErrorReported};
use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
......@@ -247,14 +246,6 @@ pub struct mt<'tcx> {
pub mutbl: ast::Mutability,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Show)]
pub enum TraitStore {
/// Box<Trait>
UniqTraitStore,
/// &Trait and &mut Trait
RegionTraitStore(Region, ast::Mutability),
}
#[derive(Clone, Copy, Show)]
pub struct field_ty {
pub name: Name,
......@@ -1042,7 +1033,6 @@ pub struct BareFnTy<'tcx> {
pub struct ClosureTy<'tcx> {
pub unsafety: ast::Unsafety,
pub onceness: ast::Onceness,
pub store: TraitStore,
pub bounds: ExistentialBounds<'tcx>,
pub sig: PolyFnSig<'tcx>,
pub abi: abi::Abi,
......@@ -1545,7 +1535,6 @@ pub enum type_err<'tcx> {
terr_onceness_mismatch(expected_found<Onceness>),
terr_abi_mismatch(expected_found<abi::Abi>),
terr_mutability,
terr_sigil_mismatch(expected_found<TraitStore>),
terr_box_mutability,
terr_ptr_mutability,
terr_ref_mutability,
......@@ -1559,7 +1548,6 @@ pub enum type_err<'tcx> {
terr_regions_no_overlap(Region, Region),
terr_regions_insufficiently_polymorphic(BoundRegion, Region),
terr_regions_overly_polymorphic(BoundRegion, Region),
terr_trait_stores_differ(terr_vstore_kind, expected_found<TraitStore>),
terr_sorts(expected_found<Ty<'tcx>>),
terr_integer_as_char,
terr_int_mismatch(expected_found<IntVarValue>),
......@@ -4194,19 +4182,6 @@ pub fn ty_fn_args<'tcx>(fty: Ty<'tcx>) -> ty::Binder<Vec<Ty<'tcx>>> {
ty_fn_sig(fty).inputs()
}
pub fn ty_closure_store(fty: Ty) -> TraitStore {
match fty.sty {
ty_unboxed_closure(..) => {
// Close enough for the purposes of all the callers of this
// function (which is soon to be deprecated anyhow).
UniqTraitStore
}
ref s => {
panic!("ty_closure_store() called on non-closure type: {:?}", s)
}
}
}
pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> Binder<FnOutput<'tcx>> {
match fty.sty {
ty_bare_fn(_, ref f) => f.sig.output(),
......@@ -4751,13 +4726,6 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
/// afterwards to present additional details, particularly when it comes to lifetime-related
/// errors.
pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String {
fn tstore_to_closure(s: &TraitStore) -> String {
match s {
&UniqTraitStore => "proc".to_string(),
&RegionTraitStore(..) => "closure".to_string()
}
}
match *err {
terr_cyclic_ty => "cyclic type of infinite size".to_string(),
terr_mismatch => "types differ".to_string(),
......@@ -4776,11 +4744,6 @@ fn tstore_to_closure(s: &TraitStore) -> String {
values.expected,
values.found)
}
terr_sigil_mismatch(values) => {
format!("expected {}, found {}",
tstore_to_closure(&values.expected),
tstore_to_closure(&values.found))
}
terr_mutability => "values differ in mutability".to_string(),
terr_box_mutability => {
"boxed values differ in mutability".to_string()
......@@ -4828,11 +4791,6 @@ fn tstore_to_closure(s: &TraitStore) -> String {
found bound lifetime parameter {}",
bound_region_ptr_to_string(cx, br))
}
terr_trait_stores_differ(_, ref values) => {
format!("trait storage differs: expected `{}`, found `{}`",
trait_store_to_string(cx, (*values).expected),
trait_store_to_string(cx, (*values).found))
}
terr_sorts(values) => {
// A naive approach to making sure that we're not reporting silly errors such as:
// (expected closure, found closure).
......@@ -7338,10 +7296,9 @@ fn references_error(&self) -> bool {
impl<'tcx> Repr<'tcx> for ClosureTy<'tcx> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
format!("ClosureTy({},{},{:?},{},{},{})",
format!("ClosureTy({},{},{},{},{})",
self.unsafety,
self.onceness,
self.store,
self.bounds.repr(tcx),
self.sig.repr(tcx),
self.abi)
......
......@@ -124,10 +124,6 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
r
}
fn fold_trait_store(&mut self, s: ty::TraitStore) -> ty::TraitStore {
super_fold_trait_store(self, s)
}
fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
-> ty::ExistentialBounds<'tcx> {
super_fold_existential_bounds(self, s)
......@@ -225,12 +221,6 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> VecPerParamSpace<T>
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::TraitStore {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitStore {
folder.fold_trait_store(*self)
}
}
impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Ty<'tcx> {
folder.fold_ty(*self)
......@@ -699,7 +689,6 @@ pub fn super_fold_closure_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
-> ty::ClosureTy<'tcx>
{
ty::ClosureTy {
store: fty.store.fold_with(this),
sig: fty.sig.fold_with(this),
unsafety: fty.unsafety,
onceness: fty.onceness,
......@@ -726,17 +715,6 @@ pub fn super_fold_mt<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
mutbl: mt.mutbl}
}
pub fn super_fold_trait_store<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
trait_store: ty::TraitStore)
-> ty::TraitStore {
match trait_store {
ty::UniqTraitStore => ty::UniqTraitStore,
ty::RegionTraitStore(r, m) => {
ty::RegionTraitStore(r.fold_with(this), m)
}
}
}
pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(
this: &mut T,
bounds: &ty::ExistentialBounds<'tcx>)
......
......@@ -237,15 +237,6 @@ pub fn mt_to_string<'tcx>(cx: &ctxt<'tcx>, m: &mt<'tcx>) -> String {
ty_to_string(cx, m.ty))
}
pub fn trait_store_to_string(cx: &ctxt, s: ty::TraitStore) -> String {
match s {
ty::UniqTraitStore => "Box ".to_string(),
ty::RegionTraitStore(r, m) => {
format!("{}{}", region_ptr_to_string(cx, r), mutability_to_string(m))
}
}
}
pub fn vec_map_to_string<T, F>(ts: &[T], f: F) -> String where
F: FnMut(&T) -> String,
{
......@@ -303,13 +294,6 @@ fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>,
fn closure_to_string<'tcx>(cx: &ctxt<'tcx>, cty: &ty::ClosureTy<'tcx>) -> String {
let mut s = String::new();
match cty.store {
ty::UniqTraitStore => {}
ty::RegionTraitStore(region, _) => {
s.push_str(&region_to_string(cx, "", true, region)[]);
}
}
match cty.unsafety {
ast::Unsafety::Normal => {}
ast::Unsafety::Unsafe => {
......@@ -320,22 +304,12 @@ fn closure_to_string<'tcx>(cx: &ctxt<'tcx>, cty: &ty::ClosureTy<'tcx>) -> String
let bounds_str = cty.bounds.user_string(cx);
match cty.store {
ty::UniqTraitStore => {
assert_eq!(cty.onceness, ast::Once);
s.push_str("proc");
push_sig_to_string(cx, &mut s, '(', ')', &cty.sig,
&bounds_str[]);
}
ty::RegionTraitStore(..) => {
match cty.onceness {
ast::Many => {}
ast::Once => s.push_str("once ")
}
push_sig_to_string(cx, &mut s, '|', '|', &cty.sig,
&bounds_str[]);
}
match cty.onceness {
ast::Many => {}
ast::Once => s.push_str("once ")
}
push_sig_to_string(cx, &mut s, '|', '|', &cty.sig,
&bounds_str[]);
s
}
......@@ -1090,12 +1064,6 @@ fn repr(&self, tcx: &ctxt<'tcx>) -> String {
}
}
impl<'tcx> Repr<'tcx> for ty::TraitStore {
fn repr(&self, tcx: &ctxt) -> String {
trait_store_to_string(tcx, *self)
}
}
impl<'tcx> Repr<'tcx> for ty::BuiltinBound {
fn repr(&self, _tcx: &ctxt) -> String {
format!("{:?}", *self)
......
......@@ -362,18 +362,6 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId,
}
}
// Returns a pointer to the body for the box. The box may be an opaque
// box. The result will be casted to the type of body_t, if it is statically
// known.
pub fn at_box_body<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
body_t: Ty<'tcx>, boxptr: ValueRef) -> ValueRef {
let _icx = push_ctxt("at_box_body");
let ccx = bcx.ccx();
let ty = Type::at_box(ccx, type_of(ccx, body_t));
let boxptr = PointerCast(bcx, boxptr, ty.ptr_to());
GEPi(bcx, boxptr, &[0u, abi::BOX_FIELD_BODY])
}
fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
info_ty: Ty<'tcx>, it: LangItem) -> ast::DefId {
match bcx.tcx().lang_items.require(it) {
......@@ -1832,7 +1820,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
.map(|arg| node_id_type(bcx, arg.id))
.collect::<Vec<_>>();
let monomorphized_arg_types = match closure_env.kind {
closure::NotClosure | closure::BoxedClosure(..) => {
closure::NotClosure => {
monomorphized_arg_types
}
......@@ -1859,7 +1847,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
};
bcx = match closure_env.kind {
closure::NotClosure | closure::BoxedClosure(..) => {
closure::NotClosure => {
copy_args_to_allocas(bcx,
arg_scope,
&decl.inputs[],
......
......@@ -10,270 +10,26 @@
pub use self::ClosureKind::*;
use back::abi;
use back::link::mangle_internal_name_by_path_and_seq;
use llvm::ValueRef;
use middle::mem_categorization::Typer;
use trans::adt;
use trans::base::*;
use trans::build::*;
use trans::cleanup::{CleanupMethods, ScopeId};
use trans::common::*;
use trans::datum::{Datum, Lvalue, rvalue_scratch_datum};
use trans::datum::{Datum, rvalue_scratch_datum};
use trans::datum::{Rvalue, ByValue};
use trans::debuginfo;
use trans::expr;
use trans::monomorphize::{self, MonoId};
use trans::type_of::*;
use trans::type_::Type;
use middle::ty::{self, Ty, UnboxedClosureTyper};
use middle::ty::{self, UnboxedClosureTyper};
use middle::subst::{Substs};
use session::config::FullDebugInfo;
use util::ppaux::ty_to_string;
use syntax::ast;
use syntax::ast_util;
// ___Good to know (tm)__________________________________________________
//
// The layout of a closure environment in memory is
// roughly as follows:
//
// struct rust_opaque_box { // see rust_internal.h
// unsigned ref_count; // obsolete (part of @T's header)
// fn(void*) *drop_glue; // destructor (for proc)
// rust_opaque_box *prev; // obsolete (part of @T's header)
// rust_opaque_box *next; // obsolete (part of @T's header)
// struct closure_data {
// upvar1_t upvar1;
// ...
// upvarN_t upvarN;
// }
// };
//
// Note that the closure is itself a rust_opaque_box. This is true
// even for ~fn and ||, because we wish to keep binary compatibility
// between all kinds of closures. The allocation strategy for this
// closure depends on the closure type. For a sendfn, the closure
// (and the referenced type descriptors) will be allocated in the
// exchange heap. For a fn, the closure is allocated in the task heap
// and is reference counted. For a block, the closure is allocated on
// the stack.
//
// ## Opaque closures and the embedded type descriptor ##
//
// One interesting part of closures is that they encapsulate the data
// that they close over. So when I have a ptr to a closure, I do not
// know how many type descriptors it contains nor what upvars are
// captured within. That means I do not know precisely how big it is
// nor where its fields are located. This is called an "opaque
// closure".
//
// Typically an opaque closure suffices because we only manipulate it
// by ptr. The routine Type::at_box().ptr_to() returns an appropriate
// type for such an opaque closure; it allows access to the box fields,
// but not the closure_data itself.
//
// But sometimes, such as when cloning or freeing a closure, we need
// to know the full information. That is where the type descriptor
// that defines the closure comes in handy. We can use its take and
// drop glue functions to allocate/free data as needed.
//
// ## Subtleties concerning alignment ##
//
// It is important that we be able to locate the closure data *without
// knowing the kind of data that is being bound*. This can be tricky
// because the alignment requirements of the bound data affects the
// alignment requires of the closure_data struct as a whole. However,
// right now this is a non-issue in any case, because the size of the
// rust_opaque_box header is always a multiple of 16-bytes, which is
// the maximum alignment requirement we ever have to worry about.
//
// The only reason alignment matters is that, in order to learn what data
// is bound, we would normally first load the type descriptors: but their
// location is ultimately depend on their content! There is, however, a
// workaround. We can load the tydesc from the rust_opaque_box, which
// describes the closure_data struct and has self-contained derived type
// descriptors, and read the alignment from there. It's just annoying to
// do. Hopefully should this ever become an issue we'll have monomorphized
// and type descriptors will all be a bad dream.
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#[derive(Copy)]
pub struct EnvValue<'tcx> {
action: ast::CaptureClause,
datum: Datum<'tcx, Lvalue>
}
impl<'tcx> EnvValue<'tcx> {
pub fn to_string<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> String {
format!("{:?}({})", self.action, self.datum.to_string(ccx))
}
}
// Given a closure ty, emits a corresponding tuple ty
pub fn mk_closure_tys<'tcx>(tcx: &ty::ctxt<'tcx>,
bound_values: &[EnvValue<'tcx>])
-> Ty<'tcx> {
// determine the types of the values in the env. Note that this
// is the actual types that will be stored in the map, not the
// logical types as the user sees them, so by-ref upvars must be
// converted to ptrs.
let bound_tys = bound_values.iter().map(|bv| {
match bv.action {
ast::CaptureByValue => bv.datum.ty,
ast::CaptureByRef => ty::mk_mut_ptr(tcx, bv.datum.ty)
}
}).collect();
let cdata_ty = ty::mk_tup(tcx, bound_tys);
debug!("cdata_ty={}", ty_to_string(tcx, cdata_ty));
return cdata_ty;
}
fn tuplify_box_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Ty<'tcx> {
let ptr = ty::mk_imm_ptr(tcx, tcx.types.i8);
ty::mk_tup(tcx, vec!(tcx.types.uint, ty::mk_nil_ptr(tcx), ptr, ptr, t))
}
pub struct ClosureResult<'blk, 'tcx: 'blk> {
llbox: ValueRef, // llvalue of ptr to closure
cdata_ty: Ty<'tcx>, // type of the closure data
bcx: Block<'blk, 'tcx> // final bcx
}
// Given a block context and a list of tydescs and values to bind
// construct a closure out of them. If copying is true, it is a
// heap allocated closure that copies the upvars into environment.
// Otherwise, it is stack allocated and copies pointers to the upvars.
pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
bound_values: Vec<EnvValue<'tcx>>)
-> ClosureResult<'blk, 'tcx> {
let _icx = push_ctxt("closure::store_environment");
let ccx = bcx.ccx();
let tcx = ccx.tcx();
// compute the type of the closure
let cdata_ty = mk_closure_tys(tcx, &bound_values[]);
// cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a
// tuple. This could be a ptr in uniq or a box or on stack,
// whatever.
let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
let cboxptr_ty = ty::mk_ptr(tcx, ty::mt {ty:cbox_ty, mutbl:ast::MutImmutable});
let llboxptr_ty = type_of(ccx, cboxptr_ty);
// If there are no bound values, no point in allocating anything.
if bound_values.is_empty() {
return ClosureResult {llbox: C_null(llboxptr_ty),
cdata_ty: cdata_ty,
bcx: bcx};
}
// allocate closure in the heap
let llbox = alloc_ty(bcx, cbox_ty, "__closure");
let llbox = PointerCast(bcx, llbox, llboxptr_ty);
debug!("tuplify_box_ty = {}", ty_to_string(tcx, cbox_ty));
// Copy expr values into boxed bindings.
let mut bcx = bcx;
for (i, bv) in bound_values.into_iter().enumerate() {
debug!("Copy {} into closure", bv.to_string(ccx));
if ccx.sess().asm_comments() {
add_comment(bcx, &format!("Copy {} into closure",
bv.to_string(ccx))[]);
}
let bound_data = GEPi(bcx, llbox, &[0u, abi::BOX_FIELD_BODY, i]);
match bv.action {
ast::CaptureByValue => {
bcx = bv.datum.store_to(bcx, bound_data);
}
ast::CaptureByRef => {
Store(bcx, bv.datum.to_llref(), bound_data);
}
}
}
ClosureResult { llbox: llbox, cdata_ty: cdata_ty, bcx: bcx }
}
// Given a context and a list of upvars, build a closure. This just
// collects the upvars and packages them up for store_environment.
fn build_closure<'blk, 'tcx>(bcx0: Block<'blk, 'tcx>,
freevar_mode: ast::CaptureClause,
freevars: &Vec<ty::Freevar>)
-> ClosureResult<'blk, 'tcx> {
let _icx = push_ctxt("closure::build_closure");
// If we need to, package up the iterator body to call
let bcx = bcx0;
// Package up the captured upvars
let mut env_vals = Vec::new();
for freevar in freevars.iter() {
let datum = expr::trans_local_var(bcx, freevar.def);
env_vals.push(EnvValue {action: freevar_mode, datum: datum});
}
store_environment(bcx, env_vals)
}
// Given an enclosing block context, a new function context, a closure type,
// and a list of upvars, generate code to load and populate the environment
// with the upvars and type descriptors.
fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
cdata_ty: Ty<'tcx>,
freevars: &[ty::Freevar],
store: ty::TraitStore)
-> Block<'blk, 'tcx> {
let _icx = push_ctxt("closure::load_environment");
// Load a pointer to the closure data, skipping over the box header:
let llcdata = at_box_body(bcx, cdata_ty, bcx.fcx.llenv.unwrap());
// Store the pointer to closure data in an alloca for debug info because that's what the
// llvm.dbg.declare intrinsic expects
let env_pointer_alloca = if bcx.sess().opts.debuginfo == FullDebugInfo {
let alloc = alloc_ty(bcx, ty::mk_mut_ptr(bcx.tcx(), cdata_ty), "__debuginfo_env_ptr");
Store(bcx, llcdata, alloc);
Some(alloc)
} else {
None
};
// Populate the upvars from the environment
let mut i = 0u;
for freevar in freevars.iter() {
let mut upvarptr = GEPi(bcx, llcdata, &[0u, i]);
let captured_by_ref = match store {
ty::RegionTraitStore(..) => {
upvarptr = Load(bcx, upvarptr);
true
}
ty::UniqTraitStore => false
};
let def_id = freevar.def.def_id();
bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvarptr);
if let Some(env_pointer_alloca) = env_pointer_alloca {
debuginfo::create_captured_var_metadata(
bcx,
def_id.node,
env_pointer_alloca,
i,
captured_by_ref,
freevar.span);
}
i += 1u;
}
bcx
}
fn load_unboxed_closure_environment<'blk, 'tcx>(
bcx: Block<'blk, 'tcx>,
......@@ -281,7 +37,7 @@ fn load_unboxed_closure_environment<'blk, 'tcx>(
freevar_mode: ast::CaptureClause,
freevars: &[ty::Freevar])
-> Block<'blk, 'tcx> {
let _icx = push_ctxt("closure::load_environment");
let _icx = push_ctxt("closure::load_unboxed_closure_environment");
// Special case for small by-value selfs.
let closure_id = ast_util::local_def(bcx.fcx.id);
......@@ -341,17 +97,9 @@ fn load_unboxed_closure_environment<'blk, 'tcx>(
bcx
}
fn fill_fn_pair(bcx: Block, pair: ValueRef, llfn: ValueRef, llenvptr: ValueRef) {
Store(bcx, llfn, GEPi(bcx, pair, &[0u, abi::FAT_PTR_ADDR]));
let llenvptr = PointerCast(bcx, llenvptr, Type::i8p(bcx.ccx()));
Store(bcx, llenvptr, GEPi(bcx, pair, &[0u, abi::FAT_PTR_EXTRA]));
}
#[derive(PartialEq)]
pub enum ClosureKind<'tcx> {
NotClosure,
// See load_environment.
BoxedClosure(Ty<'tcx>, ty::TraitStore),
// See load_unboxed_closure_environment.
UnboxedClosure(ast::CaptureClause)
}
......@@ -379,9 +127,6 @@ pub fn load<'blk>(self, bcx: Block<'blk, 'tcx>, arg_scope: ScopeId)
match self.kind {
NotClosure => bcx,
BoxedClosure(cdata_ty, store) => {
load_environment(bcx, cdata_ty, self.freevars, store)
}
UnboxedClosure(freevar_mode) => {
load_unboxed_closure_environment(bcx, arg_scope, freevar_mode, self.freevars)
}
......@@ -389,67 +134,6 @@ pub fn load<'blk>(self, bcx: Block<'blk, 'tcx>, arg_scope: ScopeId)
}
}
/// Translates the body of a closure expression.
///
/// - `store`
/// - `decl`
/// - `body`
/// - `id`: The id of the closure expression.
/// - `cap_clause`: information about captured variables, if any.
/// - `dest`: where to write the closure value, which must be a
/// (fn ptr, env) pair
pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
store: ty::TraitStore,
decl: &ast::FnDecl,
body: &ast::Block,
id: ast::NodeId,
dest: expr::Dest)
-> Block<'blk, 'tcx> {
let _icx = push_ctxt("closure::trans_expr_fn");
let dest_addr = match dest {
expr::SaveIn(p) => p,
expr::Ignore => {
return bcx; // closure construction is non-side-effecting
}
};
let ccx = bcx.ccx();
let tcx = bcx.tcx();
let fty = node_id_type(bcx, id);
let s = tcx.map.with_path(id, |path| {
mangle_internal_name_by_path_and_seq(path, "closure")
});
let llfn = decl_internal_rust_fn(ccx, fty, &s[]);
// set an inline hint for all closures
set_inline_hint(llfn);
let freevar_mode = tcx.capture_mode(id);
let freevars: Vec<ty::Freevar> =
ty::with_freevars(tcx, id, |fv| fv.iter().map(|&fv| fv).collect());
let ClosureResult {
llbox,
cdata_ty,
bcx
} = build_closure(bcx, freevar_mode, &freevars);
trans_closure(ccx,
decl,
body,
llfn,
bcx.fcx.param_substs,
id,
&[],
ty::erase_late_bound_regions(ccx.tcx(), &ty::ty_fn_ret(fty)),
ty::ty_fn_abi(fty),
ClosureEnv::new(&freevars[],
BoxedClosure(cdata_ty, store)));
fill_fn_pair(bcx, dest_addr, llfn, llbox);
bcx
}
/// Returns the LLVM function declaration for an unboxed closure, creating it
/// if necessary. If the ID does not correspond to a closure ID, returns None.
pub fn get_or_create_declaration_if_unboxed_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
......
......@@ -552,7 +552,6 @@ fn get_unique_type_id_of_closure_type<'a>(&mut self,
unique_type_id: &mut String) {
let ty::ClosureTy { unsafety,
onceness,
store,
ref bounds,
ref sig,
abi: _ } = closure_ty;
......@@ -564,15 +563,7 @@ fn get_unique_type_id_of_closure_type<'a>(&mut self,
unique_type_id.push_str("once ");
}
match store {
ty::UniqTraitStore => unique_type_id.push_str("~|"),
ty::RegionTraitStore(_, ast::MutMutable) => {
unique_type_id.push_str("&mut|")
}
ty::RegionTraitStore(_, ast::MutImmutable) => {
unique_type_id.push_str("&|")
}
};
unique_type_id.push_str("|");
let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
......
......@@ -65,7 +65,6 @@
use trans::type_::Type;
use syntax::{ast, ast_util, codemap};
use syntax::print::pprust::{expr_to_string};
use syntax::ptr::P;
use syntax::parse::token;
use std::rc::Rc;
......@@ -1102,17 +1101,7 @@ fn make_field(field_name: &str, expr: P<ast::Expr>) -> ast::Field {
// closure or an older, legacy style closure. Store this
// into a variable to ensure the the RefCell-lock is
// released before we recurse.
let is_unboxed_closure =
bcx.tcx().unboxed_closures.borrow().contains_key(&ast_util::local_def(expr.id));
if is_unboxed_closure {
closure::trans_unboxed_closure(bcx, &**decl, &**body, expr.id, dest)
} else {
let expr_ty = expr_ty(bcx, expr);
let store = ty::ty_closure_store(expr_ty);
debug!("translating block function {} with type {}",
expr_to_string(expr), expr_ty.repr(tcx));
closure::trans_expr_fn(bcx, store, &**decl, &**body, expr.id, dest)
}
closure::trans_unboxed_closure(bcx, &**decl, &**body, expr.id, dest)
}
ast::ExprCall(ref f, ref args) => {
if bcx.tcx().is_method_call(expr.id) {
......
......@@ -227,14 +227,6 @@ pub fn opaque_vec(ccx: &CrateContext) -> Type {
Type::vec(ccx, &Type::i8(ccx))
}
// The box pointed to by @T.
pub fn at_box(ccx: &CrateContext, ty: Type) -> Type {
Type::struct_(ccx, &[
ccx.int_type(), Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to(),
Type::i8p(ccx), Type::i8p(ccx), ty
], false)
}
pub fn vtable_ptr(ccx: &CrateContext) -> Type {
Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to()
}
......
......@@ -1459,7 +1459,6 @@ pub fn ty_of_closure<'tcx>(
unsafety: ast::Unsafety,
onceness: ast::Onceness,
bounds: ty::ExistentialBounds<'tcx>,
store: ty::TraitStore,
decl: &ast::FnDecl,
abi: abi::Abi,
expected_sig: Option<ty::FnSig<'tcx>>)
......@@ -1510,7 +1509,6 @@ pub fn ty_of_closure<'tcx>(
ty::ClosureTy {
unsafety: unsafety,
onceness: onceness,
store: store,
bounds: bounds,
abi: abi,
sig: ty::Binder(ty::FnSig {inputs: input_tys,
......
......@@ -96,7 +96,6 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
//
// FIXME(pcwalton): Refactor this API.
ty::region_existential_bound(ty::ReStatic),
ty::RegionTraitStore(ty::ReStatic, ast::MutImmutable),
decl,
abi::RustCall,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册