assert_eq!(next(st), '[');
let did = parse_def_(st, ClosureSource, conv);
let substs = parse_substs_(st, conv);
+ let mut tys = vec![];
+ while peek(st) != '.' {
+ tys.push(parse_ty_(st, conv));
+ }
+ assert_eq!(next(st), '.');
assert_eq!(next(st), ']');
- return st.tcx.mk_closure(did, st.tcx.mk_substs(substs));
+ return st.tcx.mk_closure(did, st.tcx.mk_substs(substs), tys);
}
'P' => {
assert_eq!(next(st), '[');
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
- ty::TyClosure(def, substs) => {
+ ty::TyClosure(def, substs, ref tys) => {
mywrite!(w, "k[{}|", (cx.ds)(def));
enc_substs(w, cx, substs);
+ for ty in tys {
+ enc_ty(w, cx, ty);
+ }
+ mywrite!(w, ".");
mywrite!(w, "]");
}
ty::TyProjection(ref data) => {
Err(msg) => tcx.sess.fatal(&msg),
}
}
- ty::TyClosure(def_id, _) => {
+ ty::TyClosure(def_id, _, _) => {
Some(ClosureSimplifiedType(def_id))
}
ty::TyTuple(ref tys) => {
// No borrowed content reachable here.
}
- ty::TyClosure(def_id, substs) => {
+ ty::TyClosure(def_id, substs, _) => {
+ // TODO remove RegionSubClosure
let &(r_a, opt_ty) = self.stack.last().unwrap();
self.out.push(Implication::RegionSubClosure(opt_ty, r_a, def_id, substs));
}
fn fn_ret(&self, id: NodeId) -> ty::PolyFnOutput<'tcx> {
let fn_ty = self.ir.tcx.node_id_to_type(id);
match fn_ty.sty {
- ty::TyClosure(closure_def_id, substs) =>
+ ty::TyClosure(closure_def_id, substs, _) =>
self.ir.tcx.closure_type(closure_def_id, substs).sig.output(),
_ => fn_ty.fn_ret()
}
def::DefUpvar(var_id, fn_node_id) => {
let ty = try!(self.node_ty(fn_node_id));
match ty.sty {
- ty::TyClosure(closure_id, _) => {
+ ty::TyClosure(closure_id, _, _) => {
match self.typer.closure_kind(closure_id) {
Some(kind) => {
self.cat_upvar(id, span, var_id, fn_node_id, kind)
pub struct VtableClosureData<'tcx, N> {
pub closure_def_id: ast::DefId,
pub substs: subst::Substs<'tcx>,
+ pub upvar_tys: Vec<Ty<'tcx>>,
/// Nested obligations. This can be non-empty if the closure
/// signature contains associated types.
pub nested: Vec<N>
VtableClosure(c) => VtableClosure(VtableClosureData {
closure_def_id: c.closure_def_id,
substs: c.substs,
- nested: c.nested.into_iter().map(f).collect()
+ nested: c.nested.into_iter().map(f).collect(),
+ upvar_tys: c.upvar_tys,
})
}
}
debug!("consider_unification_despite_ambiguity: self_ty.sty={:?}",
self_ty.sty);
match self_ty.sty {
- ty::TyClosure(closure_def_id, substs) => {
+ ty::TyClosure(closure_def_id, substs, _) => {
let closure_typer = selcx.closure_typer();
let closure_type = closure_typer.closure_type(closure_def_id, substs);
let ty::Binder((_, ret_type)) =
/// Implementation of a `Fn`-family trait by one of the
/// anonymous types generated for a `||` expression.
- ClosureCandidate(/* closure */ ast::DefId, Substs<'tcx>),
+ ClosureCandidate(/* closure */ ast::DefId, &'tcx Substs<'tcx>, &'tcx Vec<Ty<'tcx>>),
/// Implementation of a `Fn`-family trait by one of the anonymous
/// types generated for a fn pointer type (e.g., `fn(int)->int`)
// lifetimes can appear inside the self-type.
let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
let (closure_def_id, substs) = match self_ty.sty {
- ty::TyClosure(id, ref substs) => (id, substs.clone()),
+ ty::TyClosure(id, ref substs, _) => (id, substs.clone()),
_ => { return; }
};
assert!(!substs.has_escaping_regions());
// touch bound regions, they just capture the in-scope
// type/region parameters
let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
- let (closure_def_id, substs) = match self_ty.sty {
- ty::TyClosure(id, substs) => (id, substs),
+ let (closure_def_id, substs, upvar_tys) = match self_ty.sty {
+ ty::TyClosure(id, substs, ref upvar_tys) => (id, substs, upvar_tys),
ty::TyInfer(ty::TyVar(_)) => {
debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
candidates.ambiguous = true;
Some(closure_kind) => {
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
if closure_kind.extends(kind) {
- candidates.vec.push(ClosureCandidate(closure_def_id,
- substs.clone()));
+ candidates.vec.push(ClosureCandidate(closure_def_id, substs, upvar_tys));
}
}
None => {
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
ty::TyTuple(ref tys) => ok_if(tys.clone()),
- ty::TyClosure(def_id, substs) => {
+ ty::TyClosure(def_id, substs, _) => {
// FIXME -- This case is tricky. In the case of by-ref
// closures particularly, we need the results of
// inference to decide how to reflect the type of each
return ok_if(Vec::new());
}
+ // TODO
match self.infcx.closure_upvars(def_id, substs) {
Some(upvars) => ok_if(upvars.iter().map(|c| c.ty).collect()),
None => {
Some(tys.clone())
}
- ty::TyClosure(def_id, substs) => {
+ ty::TyClosure(def_id, substs, _) => {
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
+ // TODO
match self.infcx.closure_upvars(def_id, substs) {
Some(upvars) => {
Some(upvars.iter().map(|c| c.ty).collect())
Ok(VtableImpl(vtable_impl))
}
- ClosureCandidate(closure_def_id, substs) => {
+ ClosureCandidate(closure_def_id, substs, upvar_tys) => {
let vtable_closure =
- try!(self.confirm_closure_candidate(obligation, closure_def_id, &substs));
+ try!(self.confirm_closure_candidate(obligation, closure_def_id,
+ &substs, upvar_tys));
Ok(VtableClosure(vtable_closure))
}
fn confirm_closure_candidate(&mut self,
obligation: &TraitObligation<'tcx>,
closure_def_id: ast::DefId,
- substs: &Substs<'tcx>)
+ substs: &Substs<'tcx>,
+ upvar_tys: &'tcx Vec<Ty<'tcx>>)
-> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>,
SelectionError<'tcx>>
{
Ok(VtableClosureData {
closure_def_id: closure_def_id,
substs: substs.clone(),
+ upvar_tys: upvar_tys.clone(),
nested: obligations
})
}
/// The anonymous type of a closure. Used to represent the type of
/// `|a| a`.
- TyClosure(DefId, &'tcx Substs<'tcx>),
+ TyClosure(DefId, &'tcx Substs<'tcx>, Vec<Ty<'tcx>>),
/// A tuple type. For example, `(i32, bool)`.
TyTuple(Vec<Ty<'tcx>>),
}
}
- &TyClosure(_, substs) => {
+ &TyClosure(_, substs, ref tys) => {
self.add_flags(TypeFlags::HAS_TY_CLOSURE);
self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
self.add_substs(substs);
+ self.add_tys(tys);
}
&TyInfer(_) => {
self.mk_ty(TyStruct(struct_id, substs))
}
- pub fn mk_closure(&self, closure_id: ast::DefId, substs: &'tcx Substs<'tcx>)
+ pub fn mk_closure(&self,
+ closure_id: ast::DefId,
+ substs: &'tcx Substs<'tcx>,
+ tys: Vec<Ty<'tcx>>)
-> Ty<'tcx> {
- self.mk_ty(TyClosure(closure_id, substs))
+ self.mk_ty(TyClosure(closure_id, substs, tys))
}
pub fn mk_var(&self, v: TyVid) -> Ty<'tcx> {
TyTrait(ref tt) => Some(tt.principal_def_id()),
TyStruct(id, _) |
TyEnum(id, _) |
- TyClosure(id, _) => Some(id),
+ TyClosure(id, _, _) => Some(id),
_ => None
}
}
apply_lang_items(cx, did, res)
}
- TyClosure(did, substs) => {
+ TyClosure(did, substs, _) => {
let param_env = cx.empty_parameter_environment();
let infcx = infer::new_infer_ctxt(cx, &cx.tables, Some(param_env), false);
let upvars = infcx.closure_upvars(did, substs).unwrap();
}
TyInfer(_) => unreachable!(),
TyError => byte!(21),
- TyClosure(d, _) => {
+ TyClosure(d, _, _) => {
byte!(22);
did(state, d);
}
closure_def_id: self.closure_def_id,
substs: self.substs.fold_with(folder),
nested: self.nested.fold_with(folder),
+ upvar_tys: self.upvar_tys.fold_with(folder),
}
}
}
let substs = substs.fold_with(this);
ty::TyStruct(did, this.tcx().mk_substs(substs))
}
- ty::TyClosure(did, ref substs) => {
+ ty::TyClosure(did, ref substs, ref tys) => {
let s = substs.fold_with(this);
- ty::TyClosure(did, this.tcx().mk_substs(s))
+ let tys = tys.fold_with(this);
+ ty::TyClosure(did, this.tcx().mk_substs(s), tys)
}
ty::TyProjection(ref data) => {
ty::TyProjection(data.fold_with(this))
Relate::relate(self, a, b)
}
+ /// Relete elements of two slices pairwise.
+ fn relate_zip<T:Relate<'a,'tcx>>(&mut self, a: &[T], b: &[T]) -> RelateResult<'tcx, Vec<T>> {
+ assert_eq!(a.len(), b.len());
+ a.iter().zip(b).map(|(a, b)| self.relate(a, b)).collect()
+ }
+
/// Switch variance for the purpose of relating `a` and `b`.
fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
variance: ty::Variance,
Ok(tcx.mk_struct(a_id, tcx.mk_substs(substs)))
}
- (&ty::TyClosure(a_id, a_substs),
- &ty::TyClosure(b_id, b_substs))
+ (&ty::TyClosure(a_id, a_substs, ref a_tys),
+ &ty::TyClosure(b_id, b_substs, ref b_tys))
if a_id == b_id =>
{
// All TyClosure types with the same id represent
// the (anonymous) type of the same closure expression. So
// all of their regions should be equated.
let substs = try!(relate_substs(relation, None, a_substs, b_substs));
- Ok(tcx.mk_closure(a_id, tcx.mk_substs(substs)))
+ let tys = try!(relation.relate_zip(a_tys, b_tys));
+ Ok(tcx.mk_closure(a_id, tcx.mk_substs(substs), tys))
}
(&ty::TyBox(a_inner), &ty::TyBox(b_inner)) =>
}).collect::<Vec<_>>());
}
ty::TyEnum(_, ref substs) |
- ty::TyStruct(_, ref substs) |
- ty::TyClosure(_, ref substs) => {
+ ty::TyStruct(_, ref substs) => {
push_reversed(stack, substs.types.as_slice());
}
+ ty::TyClosure(_, ref substs, ref tys) => {
+ push_reversed(stack, substs.types.as_slice());
+ push_reversed(stack, tys);
+ }
ty::TyTuple(ref ts) => {
push_reversed(stack, ts);
}
TyTrait(ref data) => write!(f, "{}", data),
ty::TyProjection(ref data) => write!(f, "{}", data),
TyStr => write!(f, "str"),
- TyClosure(ref did, substs) => ty::tls::with(|tcx| {
+ TyClosure(ref did, substs, _) => ty::tls::with(|tcx| {
try!(write!(f, "[closure"));
let closure_tys = &tcx.tables.borrow().closure_tys;
try!(closure_tys.get(did).map(|cty| &cty.sig).and_then(|sig| {
match dtor_self_type.sty {
ty::TyEnum(self_type_did, _) |
ty::TyStruct(self_type_did, _) |
- ty::TyClosure(self_type_did, _) => {
+ ty::TyClosure(self_type_did, _, _) => {
let hints = ctx.tcx.lookup_repr_hints(self_type_did);
if hints.iter().any(|attr| *attr == attr::ReprExtern) &&
ctx.tcx.ty_dtor(self_type_did).has_drop_flag() {
Univariant(mk_struct(cx, &ftys[..], packed, t), dtor_to_init_u8(dtor))
}
- ty::TyClosure(def_id, substs) => {
+ ty::TyClosure(def_id, substs, _) => {
let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
- let upvars = infcx.closure_upvars(def_id, substs).unwrap();
+ let upvars = infcx.closure_upvars(def_id, substs).unwrap(); // TODO
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
Univariant(mk_struct(cx, &upvar_types[..], false, t), 0)
}
// Perhaps one of the upvars of this struct is non-zero
// Let's recurse and find out!
- ty::TyClosure(def_id, substs) => {
+ ty::TyClosure(def_id, substs, _) => {
let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
- let upvars = infcx.closure_upvars(def_id, substs).unwrap();
+ let upvars = infcx.closure_upvars(def_id, substs).unwrap(); // TODO
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
for (j, &ty) in upvar_types.iter().enumerate() {
let function_type;
let (fn_sig, abi, env_ty) = match fn_type.sty {
ty::TyBareFn(_, ref f) => (&f.sig, f.abi, None),
- ty::TyClosure(closure_did, substs) => {
+ ty::TyClosure(closure_did, substs, _) => {
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
function_type = infcx.closure_type(closure_did, substs);
let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
}
})
}
- ty::TyClosure(def_id, substs) => {
+ ty::TyClosure(def_id, substs, _) => { // TODO
let repr = adt::represent_type(cx.ccx(), t);
let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
let upvars = infcx.closure_upvars(def_id, substs).unwrap();
use back::link::{self, mangle_internal_name_by_path_and_seq};
use llvm::{ValueRef, get_params};
use middle::infer;
+use middle::ty::Ty;
use trans::adt;
use trans::attributes;
use trans::base::*;
// duplicate declarations
let function_type = erase_regions(ccx.tcx(), &function_type);
let params = match function_type.sty {
- ty::TyClosure(_, substs) => &substs.types,
+ ty::TyClosure(_, substs, _) => &substs.types,
_ => unreachable!()
};
let mono_id = MonoId {
pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
closure_def_id: ast::DefId,
substs: Substs<'tcx>,
+ upvar_tys: Vec<Ty<'tcx>>,
node: ExprOrMethodCall,
param_substs: &'tcx Substs<'tcx>,
trait_closure_kind: ty::ClosureKind)
trans_closure_adapter_shim(ccx,
closure_def_id,
substs,
+ upvar_tys,
closure_kind,
trait_closure_kind,
llfn)
ccx: &'a CrateContext<'a, 'tcx>,
closure_def_id: ast::DefId,
substs: Substs<'tcx>,
+ upvar_tys: Vec<Ty<'tcx>>,
llfn_closure_kind: ty::ClosureKind,
trait_closure_kind: ty::ClosureKind,
llfn: ValueRef)
// fn call_once(mut self, ...) { call_mut(&mut self, ...) }
//
// These are both the same at trans time.
- trans_fn_once_adapter_shim(ccx, closure_def_id, substs, llfn)
+ trans_fn_once_adapter_shim(ccx, closure_def_id, substs, upvar_tys, llfn)
}
_ => {
tcx.sess.bug(&format!("trans_closure_adapter_shim: cannot convert {:?} to {:?}",
ccx: &'a CrateContext<'a, 'tcx>,
closure_def_id: ast::DefId,
substs: Substs<'tcx>,
+ upvar_tys: Vec<Ty<'tcx>>,
llreffn: ValueRef)
-> ValueRef
{
// Find a version of the closure type. Substitute static for the
// region since it doesn't really matter.
let substs = tcx.mk_substs(substs);
- let closure_ty = tcx.mk_closure(closure_def_id, substs);
+ let closure_ty = tcx.mk_closure(closure_def_id, substs, upvar_tys);
let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic), closure_ty);
// Make a version with the type of by-ref closure.
}
}
},
- ty::TyClosure(def_id, substs) => {
+ ty::TyClosure(def_id, substs, _) => {
let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
let closure_ty = infcx.closure_type(def_id, substs);
self.get_unique_type_id_of_closure_type(cx,
MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)
}
- ty::TyClosure(def_id, substs) => {
+ ty::TyClosure(def_id, substs, _) => {
let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
let upvars = infcx.closure_upvars(def_id, substs).unwrap();
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
ty::TyBareFn(_, ref f) => {
(&f.sig, f.abi, None)
}
- ty::TyClosure(closure_did, substs) => {
+ ty::TyClosure(closure_did, substs, _) => {
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
function_type = infcx.closure_type(closure_did, substs);
let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
let llfn = closure::trans_closure_method(bcx.ccx(),
vtable_closure.closure_def_id,
vtable_closure.substs,
+ vtable_closure.upvar_tys,
MethodCallKey(method_call),
bcx.fcx.param_substs,
trait_closure_kind);
traits::VtableClosureData {
closure_def_id,
substs,
+ upvar_tys,
nested: _ }) => {
let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap();
let llfn = closure::trans_closure_method(ccx,
closure_def_id,
substs,
+ upvar_tys,
ExprId(0),
param_substs,
trait_closure_kind);
return Some(CallStep::Builtin);
}
- ty::TyClosure(def_id, substs) => {
+ ty::TyClosure(def_id, substs, _) => {
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
// Check whether this is a call to a closure where we
abi::RustCall,
expected_sig);
- let closure_type = fcx.ccx.tcx.mk_closure(expr_def_id,
- fcx.ccx.tcx.mk_substs(fcx.inh.infcx.parameter_environment.free_substs.clone()));
+ let freevar_tys =
+ fcx.tcx().with_freevars(expr.id, |fv| {
+ fv.iter()
+ .map(|_| fcx.tcx().types.bool) // TODO
+ .collect()
+ });
+
+ let closure_type =
+ fcx.ccx.tcx.mk_closure(
+ expr_def_id,
+ fcx.ccx.tcx.mk_substs(fcx.inh.infcx.parameter_environment.free_substs.clone()),
+ freevar_tys);
fcx.write_ty(expr.id, closure_type);
match dtor_self_type.sty {
ty::TyEnum(self_type_did, self_to_impl_substs) |
ty::TyStruct(self_type_did, self_to_impl_substs) |
- ty::TyClosure(self_type_did, self_to_impl_substs) => {
+ ty::TyClosure(self_type_did, self_to_impl_substs, _) => {
try!(ensure_drop_params_and_item_params_correspond(tcx,
drop_impl_did,
dtor_generics,
}
ty::TyEnum(did, _) |
ty::TyStruct(did, _) |
- ty::TyClosure(did, _) => {
+ ty::TyClosure(did, _, _) => {
self.assemble_inherent_impl_candidates_for_type(did);
}
ty::TyBox(_) => {
let steps = self.steps.clone();
for step in steps.iter() {
let closure_def_id = match step.self_ty.sty {
- ty::TyClosure(a, _) => a,
+ ty::TyClosure(a, _, _) => a,
_ => continue,
};
match self_type.ty.sty {
ty::TyEnum(type_def_id, _) |
ty::TyStruct(type_def_id, _) |
- ty::TyClosure(type_def_id, _) => {
+ ty::TyClosure(type_def_id, _, _) => {
tcx.destructor_for_type
.borrow_mut()
.insert(type_def_id, method_def_id.def_id());