Introduce ClosureSubsts rather than just having random fields in the
TyClosure variant; thread this through wherever closure substitutions are expected, which leads to a net simplification. Simplify trans treatment of closures in particular.
This commit is contained in:
parent
69d62e04e5
commit
1e2677be72
30 changed files with 256 additions and 159 deletions
|
|
@ -143,10 +143,10 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
|
|||
enc_substs(w, cx, substs);
|
||||
mywrite!(w, "]");
|
||||
}
|
||||
ty::TyClosure(def, substs, ref tys) => {
|
||||
ty::TyClosure(def, ref substs) => {
|
||||
mywrite!(w, "k[{}|", (cx.ds)(def));
|
||||
enc_substs(w, cx, substs);
|
||||
for ty in tys {
|
||||
enc_substs(w, cx, &substs.func_substs);
|
||||
for ty in &substs.upvar_tys {
|
||||
enc_ty(w, cx, ty);
|
||||
}
|
||||
mywrite!(w, ".");
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ pub fn simplify_type(tcx: &ty::ctxt,
|
|||
Err(msg) => tcx.sess.fatal(&msg),
|
||||
}
|
||||
}
|
||||
ty::TyClosure(def_id, _, _) => {
|
||||
ty::TyClosure(def_id, _) => {
|
||||
Some(ClosureSimplifiedType(def_id))
|
||||
}
|
||||
ty::TyTuple(ref tys) => {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ use util::nodemap::FnvHashSet;
|
|||
pub enum Implication<'tcx> {
|
||||
RegionSubRegion(Option<Ty<'tcx>>, ty::Region, ty::Region),
|
||||
RegionSubGeneric(Option<Ty<'tcx>>, ty::Region, GenericKind<'tcx>),
|
||||
RegionSubClosure(Option<Ty<'tcx>>, ty::Region, ast::DefId, &'tcx Substs<'tcx>),
|
||||
RegionSubClosure(Option<Ty<'tcx>>, ty::Region, ast::DefId, &'tcx ty::ClosureSubsts<'tcx>),
|
||||
Predicate(ast::DefId, ty::Predicate<'tcx>),
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
|
|||
// No borrowed content reachable here.
|
||||
}
|
||||
|
||||
ty::TyClosure(def_id, substs, _) => {
|
||||
ty::TyClosure(def_id, ref 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));
|
||||
|
|
|
|||
|
|
@ -1374,17 +1374,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn closure_type(&self,
|
||||
def_id: ast::DefId,
|
||||
substs: &subst::Substs<'tcx>)
|
||||
-> ty::ClosureTy<'tcx>
|
||||
def_id: ast::DefId,
|
||||
substs: &ty::ClosureSubsts<'tcx>)
|
||||
-> ty::ClosureTy<'tcx>
|
||||
{
|
||||
|
||||
let closure_ty = self.tables
|
||||
.borrow()
|
||||
.closure_tys
|
||||
.get(&def_id)
|
||||
.unwrap()
|
||||
.subst(self.tcx, substs);
|
||||
.subst(self.tcx, &substs.func_substs);
|
||||
|
||||
if self.normalize {
|
||||
normalize_associated_type(&self.tcx, &closure_ty)
|
||||
|
|
@ -1395,7 +1394,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
|
||||
pub fn closure_upvars(&self,
|
||||
def_id: ast::DefId,
|
||||
substs: &Substs<'tcx>)
|
||||
substs: &ty::ClosureSubsts<'tcx>)
|
||||
-> Option<Vec<ty::ClosureUpvar<'tcx>>>
|
||||
{
|
||||
let result = ty::ctxt::closure_upvars(self, def_id, substs);
|
||||
|
|
|
|||
|
|
@ -1493,7 +1493,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
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, ref substs) =>
|
||||
self.ir.tcx.closure_type(closure_def_id, substs).sig.output(),
|
||||
_ => fn_ty.fn_ret()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -584,7 +584,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -270,8 +270,7 @@ pub struct VtableImplData<'tcx, N> {
|
|||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct VtableClosureData<'tcx, N> {
|
||||
pub closure_def_id: ast::DefId,
|
||||
pub substs: subst::Substs<'tcx>,
|
||||
pub upvar_tys: Vec<Ty<'tcx>>,
|
||||
pub substs: ty::ClosureSubsts<'tcx>,
|
||||
/// Nested obligations. This can be non-empty if the closure
|
||||
/// signature contains associated types.
|
||||
pub nested: Vec<N>
|
||||
|
|
@ -550,7 +549,6 @@ impl<'tcx, N> Vtable<'tcx, N> {
|
|||
closure_def_id: c.closure_def_id,
|
||||
substs: c.substs,
|
||||
nested: c.nested.into_iter().map(f).collect(),
|
||||
upvar_tys: c.upvar_tys,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext
|
|||
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, ref substs) => {
|
||||
let closure_typer = selcx.closure_typer();
|
||||
let closure_type = closure_typer.closure_type(closure_def_id, substs);
|
||||
let ty::Binder((_, ret_type)) =
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ enum SelectionCandidate<'tcx> {
|
|||
|
||||
/// Implementation of a `Fn`-family trait by one of the
|
||||
/// anonymous types generated for a `||` expression.
|
||||
ClosureCandidate(/* closure */ ast::DefId, &'tcx Substs<'tcx>, &'tcx Vec<Ty<'tcx>>),
|
||||
ClosureCandidate(/* closure */ ast::DefId, &'tcx ty::ClosureSubsts<'tcx>),
|
||||
|
||||
/// Implementation of a `Fn`-family trait by one of the anonymous
|
||||
/// types generated for a fn pointer type (e.g., `fn(int)->int`)
|
||||
|
|
@ -348,7 +348,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// 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),
|
||||
_ => { return; }
|
||||
};
|
||||
assert!(!substs.has_escaping_regions());
|
||||
|
|
@ -1142,8 +1142,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// 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, upvar_tys) = match self_ty.sty {
|
||||
ty::TyClosure(id, substs, ref upvar_tys) => (id, substs, upvar_tys),
|
||||
let (closure_def_id, substs) = match self_ty.sty {
|
||||
ty::TyClosure(id, ref substs) => (id, substs),
|
||||
ty::TyInfer(ty::TyVar(_)) => {
|
||||
debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
|
||||
candidates.ambiguous = true;
|
||||
|
|
@ -1161,7 +1161,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
Some(closure_kind) => {
|
||||
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
|
||||
if closure_kind.extends(kind) {
|
||||
candidates.vec.push(ClosureCandidate(closure_def_id, substs, upvar_tys));
|
||||
candidates.vec.push(ClosureCandidate(closure_def_id, substs));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
|
|
@ -1703,7 +1703,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// (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, ref 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
|
||||
|
|
@ -1865,7 +1865,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
Some(tys.clone())
|
||||
}
|
||||
|
||||
ty::TyClosure(def_id, substs, _) => {
|
||||
ty::TyClosure(def_id, ref substs) => {
|
||||
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
|
||||
|
||||
// TODO
|
||||
|
|
@ -2015,10 +2015,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
Ok(VtableImpl(vtable_impl))
|
||||
}
|
||||
|
||||
ClosureCandidate(closure_def_id, substs, upvar_tys) => {
|
||||
ClosureCandidate(closure_def_id, substs) => {
|
||||
let vtable_closure =
|
||||
try!(self.confirm_closure_candidate(obligation, closure_def_id,
|
||||
&substs, upvar_tys));
|
||||
try!(self.confirm_closure_candidate(obligation, closure_def_id, substs));
|
||||
Ok(VtableClosure(vtable_closure))
|
||||
}
|
||||
|
||||
|
|
@ -2367,8 +2366,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
fn confirm_closure_candidate(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
closure_def_id: ast::DefId,
|
||||
substs: &Substs<'tcx>,
|
||||
upvar_tys: &'tcx Vec<Ty<'tcx>>)
|
||||
substs: &ty::ClosureSubsts<'tcx>)
|
||||
-> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>,
|
||||
SelectionError<'tcx>>
|
||||
{
|
||||
|
|
@ -2394,7 +2392,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
Ok(VtableClosureData {
|
||||
closure_def_id: closure_def_id,
|
||||
substs: substs.clone(),
|
||||
upvar_tys: upvar_tys.clone(),
|
||||
nested: obligations
|
||||
})
|
||||
}
|
||||
|
|
@ -2856,7 +2853,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
fn closure_trait_ref_unnormalized(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
closure_def_id: ast::DefId,
|
||||
substs: &Substs<'tcx>)
|
||||
substs: &ty::ClosureSubsts<'tcx>)
|
||||
-> ty::PolyTraitRef<'tcx>
|
||||
{
|
||||
let closure_type = self.infcx.closure_type(closure_def_id, substs);
|
||||
|
|
@ -2878,7 +2875,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
fn closure_trait_ref(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
closure_def_id: ast::DefId,
|
||||
substs: &Substs<'tcx>)
|
||||
substs: &ty::ClosureSubsts<'tcx>)
|
||||
-> Normalized<'tcx, ty::PolyTraitRef<'tcx>>
|
||||
{
|
||||
let trait_ref = self.closure_trait_ref_unnormalized(
|
||||
|
|
|
|||
|
|
@ -1767,7 +1767,7 @@ pub enum TypeVariants<'tcx> {
|
|||
|
||||
/// The anonymous type of a closure. Used to represent the type of
|
||||
/// `|a| a`.
|
||||
TyClosure(DefId, &'tcx Substs<'tcx>, Vec<Ty<'tcx>>),
|
||||
TyClosure(DefId, Box<ClosureSubsts<'tcx>>),
|
||||
|
||||
/// A tuple type. For example, `(i32, bool)`.
|
||||
TyTuple(Vec<Ty<'tcx>>),
|
||||
|
|
@ -1787,6 +1787,93 @@ pub enum TypeVariants<'tcx> {
|
|||
TyError,
|
||||
}
|
||||
|
||||
/// A closure can be modeled as a struct that looks like:
|
||||
///
|
||||
/// struct Closure<'l0...'li, T0...Tj, U0...Uk> {
|
||||
/// upvar0: U0,
|
||||
/// ...
|
||||
/// upvark: Uk
|
||||
/// }
|
||||
///
|
||||
/// where 'l0...'li and T0...Tj are the lifetime and type parameters
|
||||
/// in scope on the function that defined the closure, and U0...Uk are
|
||||
/// type parameters representing the types of its upvars (borrowed, if
|
||||
/// appropriate).
|
||||
///
|
||||
/// So, for example, given this function:
|
||||
///
|
||||
/// fn foo<'a, T>(data: &'a mut T) {
|
||||
/// do(|| data.count += 1)
|
||||
/// }
|
||||
///
|
||||
/// the type of the closure would be something like:
|
||||
///
|
||||
/// struct Closure<'a, T, U0> {
|
||||
/// data: U0
|
||||
/// }
|
||||
///
|
||||
/// Note that the type of the upvar is not specified in the struct.
|
||||
/// You may wonder how the impl would then be able to use the upvar,
|
||||
/// if it doesn't know it's type? The answer is that the impl is
|
||||
/// (conceptually) not fully generic over Closure but rather tied to
|
||||
/// instances with the expected upvar types:
|
||||
///
|
||||
/// impl<'b, 'a, T> FnMut() for Closure<'a, T, &'b mut &'a mut T> {
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// You can see that the *impl* fully specified the type of the upvar
|
||||
/// and thus knows full well that `data` has type `&'b mut &'a mut T`.
|
||||
/// (Here, I am assuming that `data` is mut-borrowed.)
|
||||
///
|
||||
/// Now, the last question you may ask is: Why include the upvar types
|
||||
/// as extra type parameters? The reason for this design is that the
|
||||
/// upvar types can reference lifetimes that are internal to the
|
||||
/// creating function. In my example above, for example, the lifetime
|
||||
/// `'b` represents the extent of the closure itself; this is some
|
||||
/// subset of `foo`, probably just the extent of the call to the to
|
||||
/// `do()`. If we just had the lifetime/type parameters from the
|
||||
/// enclosing function, we couldn't name this lifetime `'b`. Note that
|
||||
/// there can also be lifetimes in the types of the upvars themselves,
|
||||
/// if one of them happens to be a reference to something that the
|
||||
/// creating fn owns.
|
||||
///
|
||||
/// OK, you say, so why not create a more minimal set of parameters
|
||||
/// that just includes the extra lifetime parameters? The answer is
|
||||
/// primarily that it would be hard --- we don't know at the time when
|
||||
/// we create the closure type what the full types of the upvars are,
|
||||
/// nor do we know which are borrowed and which are not. In this
|
||||
/// design, we can just supply a fresh type parameter and figure that
|
||||
/// out later.
|
||||
///
|
||||
/// All right, you say, but why include the type parameters from the
|
||||
/// original function then? The answer is that trans may need them
|
||||
/// when monomorphizing, and they may not appear in the upvars. A
|
||||
/// closure could capture no variables but still make use of some
|
||||
/// in-scope type parameter with a bound (e.g., if our example above
|
||||
/// had an extra `U: Default`, and the closure called `U::default()`).
|
||||
///
|
||||
/// There is another reason. This design (implicitly) prohibits
|
||||
/// closures from capturing themselves (except via a trait
|
||||
/// object). This simplifies closure inference considerably, since it
|
||||
/// means that when we infer the kind of a closure or its upvars, we
|
||||
/// don't have to handles cycles where the decisions we make wind up
|
||||
/// for closure C wind up influencing the decisions we ought to make
|
||||
/// for closure C (which would then require fixed point iteration to
|
||||
/// handle). Plus it fixes an ICE. :P
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct ClosureSubsts<'tcx> {
|
||||
/// Lifetime and type parameters from the enclosing function.
|
||||
/// These are separated out because trans wants to pass them around
|
||||
/// when monomorphizing.
|
||||
pub func_substs: &'tcx Substs<'tcx>,
|
||||
|
||||
/// The types of the upvars. The list parallels the freevars and
|
||||
/// `upvar_borrows` lists. These are kept distinct so that we can
|
||||
/// easily index into them.
|
||||
pub upvar_tys: Vec<Ty<'tcx>>
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct TraitTy<'tcx> {
|
||||
pub principal: ty::PolyTraitRef<'tcx>,
|
||||
|
|
@ -3214,11 +3301,11 @@ impl FlagComputation {
|
|||
}
|
||||
}
|
||||
|
||||
&TyClosure(_, substs, ref tys) => {
|
||||
&TyClosure(_, ref substs) => {
|
||||
self.add_flags(TypeFlags::HAS_TY_CLOSURE);
|
||||
self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
|
||||
self.add_substs(substs);
|
||||
self.add_tys(tys);
|
||||
self.add_substs(&substs.func_substs);
|
||||
self.add_tys(&substs.upvar_tys);
|
||||
}
|
||||
|
||||
&TyInfer(_) => {
|
||||
|
|
@ -3462,10 +3549,10 @@ impl<'tcx> ctxt<'tcx> {
|
|||
|
||||
pub fn closure_type(&self,
|
||||
def_id: ast::DefId,
|
||||
substs: &subst::Substs<'tcx>)
|
||||
substs: &ClosureSubsts<'tcx>)
|
||||
-> ty::ClosureTy<'tcx>
|
||||
{
|
||||
self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self, substs)
|
||||
self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self, &substs.func_substs)
|
||||
}
|
||||
|
||||
pub fn type_parameter_def(&self,
|
||||
|
|
@ -3665,7 +3752,17 @@ impl<'tcx> ctxt<'tcx> {
|
|||
substs: &'tcx Substs<'tcx>,
|
||||
tys: Vec<Ty<'tcx>>)
|
||||
-> Ty<'tcx> {
|
||||
self.mk_ty(TyClosure(closure_id, substs, tys))
|
||||
self.mk_closure_from_closure_substs(closure_id, Box::new(ClosureSubsts {
|
||||
func_substs: substs,
|
||||
upvar_tys: tys
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn mk_closure_from_closure_substs(&self,
|
||||
closure_id: ast::DefId,
|
||||
closure_substs: Box<ClosureSubsts<'tcx>>)
|
||||
-> Ty<'tcx> {
|
||||
self.mk_ty(TyClosure(closure_id, closure_substs))
|
||||
}
|
||||
|
||||
pub fn mk_var(&self, v: TyVid) -> Ty<'tcx> {
|
||||
|
|
@ -3932,7 +4029,7 @@ impl<'tcx> TyS<'tcx> {
|
|||
TyTrait(ref tt) => Some(tt.principal_def_id()),
|
||||
TyStruct(id, _) |
|
||||
TyEnum(id, _) |
|
||||
TyClosure(id, _, _) => Some(id),
|
||||
TyClosure(id, _) => Some(id),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
|
@ -4150,7 +4247,8 @@ impl<'tcx> TyS<'tcx> {
|
|||
apply_lang_items(cx, did, res)
|
||||
}
|
||||
|
||||
TyClosure(did, substs, _) => {
|
||||
TyClosure(did, ref substs) => {
|
||||
// TODO
|
||||
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();
|
||||
|
|
@ -5911,9 +6009,9 @@ impl<'tcx> ctxt<'tcx> {
|
|||
|
||||
// Returns a list of `ClosureUpvar`s for each upvar.
|
||||
pub fn closure_upvars<'a>(typer: &infer::InferCtxt<'a, 'tcx>,
|
||||
closure_id: ast::DefId,
|
||||
substs: &Substs<'tcx>)
|
||||
-> Option<Vec<ClosureUpvar<'tcx>>>
|
||||
closure_id: ast::DefId,
|
||||
substs: &ClosureSubsts<'tcx>)
|
||||
-> Option<Vec<ClosureUpvar<'tcx>>>
|
||||
{
|
||||
// Presently an unboxed closure type cannot "escape" out of a
|
||||
// function, so we will only encounter ones that originated in the
|
||||
|
|
@ -5932,7 +6030,7 @@ impl<'tcx> ctxt<'tcx> {
|
|||
Ok(t) => { t }
|
||||
Err(()) => { return None; }
|
||||
};
|
||||
let freevar_ty = freevar_ty.subst(tcx, substs);
|
||||
let freevar_ty = freevar_ty.subst(tcx, &substs.func_substs);
|
||||
|
||||
let upvar_id = ty::UpvarId {
|
||||
var_id: freevar_def_id.node,
|
||||
|
|
@ -6382,7 +6480,7 @@ impl<'tcx> ctxt<'tcx> {
|
|||
}
|
||||
TyInfer(_) => unreachable!(),
|
||||
TyError => byte!(21),
|
||||
TyClosure(d, _, _) => {
|
||||
TyClosure(d, _) => {
|
||||
byte!(22);
|
||||
did(state, d);
|
||||
}
|
||||
|
|
@ -6763,6 +6861,13 @@ impl<'tcx> RegionEscape for Substs<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ClosureSubsts<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.func_substs.has_regions_escaping_depth(depth) ||
|
||||
self.upvar_tys.iter().any(|t| t.has_regions_escaping_depth(depth))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T:RegionEscape> RegionEscape for Vec<T> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.iter().any(|t| t.has_regions_escaping_depth(depth))
|
||||
|
|
@ -7106,6 +7211,15 @@ impl<'tcx> HasTypeFlags for BareFnTy<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ClosureSubsts<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.func_substs.has_type_flags(flags) ||
|
||||
self.upvar_tys.iter().any(|t| t.has_type_flags(flags))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<'tcx> fmt::Debug for ClosureTy<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "ClosureTy({},{:?},{})",
|
||||
|
|
|
|||
|
|
@ -296,6 +296,16 @@ impl<'tcx> TypeFoldable<'tcx> for subst::Substs<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ClosureSubsts<'tcx> {
|
||||
let func_substs = self.func_substs.fold_with(folder);
|
||||
ty::ClosureSubsts {
|
||||
func_substs: folder.tcx().mk_substs(func_substs),
|
||||
upvar_tys: self.upvar_tys.fold_with(folder),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::ItemSubsts<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ItemSubsts<'tcx> {
|
||||
ty::ItemSubsts {
|
||||
|
|
@ -450,7 +460,6 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableClosureDa
|
|||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -603,10 +612,9 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
|||
let substs = substs.fold_with(this);
|
||||
ty::TyStruct(did, this.tcx().mk_substs(substs))
|
||||
}
|
||||
ty::TyClosure(did, ref substs, ref tys) => {
|
||||
ty::TyClosure(did, ref substs) => {
|
||||
let s = substs.fold_with(this);
|
||||
let tys = tys.fold_with(this);
|
||||
ty::TyClosure(did, this.tcx().mk_substs(s), tys)
|
||||
ty::TyClosure(did, s)
|
||||
}
|
||||
ty::TyProjection(ref data) => {
|
||||
ty::TyProjection(data.fold_with(this))
|
||||
|
|
|
|||
|
|
@ -506,16 +506,15 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
|
|||
Ok(tcx.mk_struct(a_id, tcx.mk_substs(substs)))
|
||||
}
|
||||
|
||||
(&ty::TyClosure(a_id, a_substs, ref a_tys),
|
||||
&ty::TyClosure(b_id, b_substs, ref b_tys))
|
||||
(&ty::TyClosure(a_id, ref a_substs),
|
||||
&ty::TyClosure(b_id, ref b_substs))
|
||||
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));
|
||||
let tys = try!(relation.relate_zip(a_tys, b_tys));
|
||||
Ok(tcx.mk_closure(a_id, tcx.mk_substs(substs), tys))
|
||||
let substs = try!(relation.relate(a_substs, b_substs));
|
||||
Ok(tcx.mk_closure_from_closure_substs(a_id, substs))
|
||||
}
|
||||
|
||||
(&ty::TyBox(a_inner), &ty::TyBox(b_inner)) =>
|
||||
|
|
@ -588,6 +587,20 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ClosureSubsts<'tcx> {
|
||||
fn relate<R>(relation: &mut R,
|
||||
a: &ty::ClosureSubsts<'tcx>,
|
||||
b: &ty::ClosureSubsts<'tcx>)
|
||||
-> RelateResult<'tcx, ty::ClosureSubsts<'tcx>>
|
||||
where R: TypeRelation<'a,'tcx>
|
||||
{
|
||||
let func_substs = try!(relate_substs(relation, None, a.func_substs, b.func_substs));
|
||||
let upvar_tys = try!(relation.relate_zip(&a.upvar_tys, &b.upvar_tys));
|
||||
Ok(ty::ClosureSubsts { func_substs: relation.tcx().mk_substs(func_substs),
|
||||
upvar_tys: upvar_tys })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::Region {
|
||||
fn relate<R>(relation: &mut R,
|
||||
a: &ty::Region,
|
||||
|
|
|
|||
|
|
@ -91,9 +91,9 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
|
|||
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::TyClosure(_, ref substs) => {
|
||||
push_reversed(stack, substs.func_substs.types.as_slice());
|
||||
push_reversed(stack, &substs.upvar_tys);
|
||||
}
|
||||
ty::TyTuple(ref ts) => {
|
||||
push_reversed(stack, ts);
|
||||
|
|
|
|||
|
|
@ -662,11 +662,14 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
|
|||
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, ref substs) => ty::tls::with(|tcx| {
|
||||
try!(write!(f, "[closure"));
|
||||
|
||||
// TODO consider changing this to print out the upvar types instead
|
||||
|
||||
let closure_tys = &tcx.tables.borrow().closure_tys;
|
||||
try!(closure_tys.get(did).map(|cty| &cty.sig).and_then(|sig| {
|
||||
tcx.lift(&substs).map(|substs| sig.subst(tcx, substs))
|
||||
tcx.lift(&substs.func_substs).map(|substs| sig.subst(tcx, substs))
|
||||
}).map(|sig| {
|
||||
fn_sig(f, &sig.0.inputs, false, sig.0.output)
|
||||
}).unwrap_or_else(|| {
|
||||
|
|
|
|||
|
|
@ -2529,7 +2529,7 @@ impl LintPass for DropWithReprExtern {
|
|||
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() {
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
|
||||
Univariant(mk_struct(cx, &ftys[..], packed, t), dtor_to_init_u8(dtor))
|
||||
}
|
||||
ty::TyClosure(def_id, substs, _) => {
|
||||
ty::TyClosure(def_id, ref substs) => {
|
||||
let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
|
||||
let upvars = infcx.closure_upvars(def_id, substs).unwrap(); // TODO
|
||||
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
|
||||
|
|
@ -441,7 +441,7 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||
|
||||
// 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, ref substs) => {
|
||||
let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
|
||||
let upvars = infcx.closure_upvars(def_id, substs).unwrap(); // TODO
|
||||
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
|
|||
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, ref 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);
|
||||
|
|
|
|||
|
|
@ -470,7 +470,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
|
|||
}
|
||||
})
|
||||
}
|
||||
ty::TyClosure(def_id, substs, _) => { // TODO
|
||||
ty::TyClosure(def_id, ref 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();
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ use trans::build::*;
|
|||
use trans::callee;
|
||||
use trans::cleanup;
|
||||
use trans::cleanup::CleanupMethods;
|
||||
use trans::closure;
|
||||
use trans::common::{self, Block, Result, NodeIdAndSpan, ExprId, CrateContext,
|
||||
ExprOrMethodCall, FunctionContext, MethodCallKey};
|
||||
use trans::consts;
|
||||
|
|
@ -446,12 +445,6 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
|
|||
}
|
||||
};
|
||||
|
||||
// If this is a closure, redirect to it.
|
||||
match closure::get_or_create_declaration_if_closure(ccx, def_id, substs) {
|
||||
None => {}
|
||||
Some(llfn) => return llfn,
|
||||
}
|
||||
|
||||
// Check whether this fn has an inlined copy and, if so, redirect
|
||||
// def_id to the local id of the inlined copy.
|
||||
let def_id = inline::maybe_instantiate_inline(ccx, def_id);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ use arena::TypedArena;
|
|||
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::*;
|
||||
|
|
@ -24,10 +23,9 @@ use trans::datum::{self, Datum, rvalue_scratch_datum, Rvalue, ByValue};
|
|||
use trans::debuginfo::{self, DebugLoc};
|
||||
use trans::declare;
|
||||
use trans::expr;
|
||||
use trans::monomorphize::{self, MonoId};
|
||||
use trans::monomorphize::{MonoId};
|
||||
use trans::type_of::*;
|
||||
use middle::ty;
|
||||
use middle::subst::Substs;
|
||||
use session::config::FullDebugInfo;
|
||||
|
||||
use syntax::abi::RustCall;
|
||||
|
|
@ -127,47 +125,32 @@ impl<'a> ClosureEnv<'a> {
|
|||
|
||||
/// Returns the LLVM function declaration for a closure, creating it if
|
||||
/// necessary. If the ID does not correspond to a closure ID, returns None.
|
||||
pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
closure_id: ast::DefId,
|
||||
substs: &Substs<'tcx>)
|
||||
-> Option<Datum<'tcx, Rvalue>> {
|
||||
if !ccx.tcx().tables.borrow().closure_kinds.contains_key(&closure_id) {
|
||||
// Not a closure.
|
||||
return None
|
||||
}
|
||||
|
||||
let function_type = ccx.tcx().node_id_to_type(closure_id.node);
|
||||
let function_type = monomorphize::apply_param_substs(ccx.tcx(), substs, &function_type);
|
||||
|
||||
pub fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
closure_id: ast::DefId,
|
||||
substs: &ty::ClosureSubsts<'tcx>)
|
||||
-> ValueRef {
|
||||
// Normalize type so differences in regions and typedefs don't cause
|
||||
// duplicate declarations
|
||||
let function_type = erase_regions(ccx.tcx(), &function_type);
|
||||
let params = match function_type.sty {
|
||||
ty::TyClosure(_, substs, _) => &substs.types,
|
||||
_ => unreachable!()
|
||||
};
|
||||
let substs = erase_regions(ccx.tcx(), substs);
|
||||
let mono_id = MonoId {
|
||||
def: closure_id,
|
||||
params: params
|
||||
params: &substs.func_substs.types
|
||||
};
|
||||
|
||||
match ccx.closure_vals().borrow().get(&mono_id) {
|
||||
Some(&llfn) => {
|
||||
debug!("get_or_create_declaration_if_closure(): found closure {:?}: {:?}",
|
||||
mono_id, ccx.tn().val_to_string(llfn));
|
||||
return Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
|
||||
}
|
||||
None => {}
|
||||
if let Some(&llfn) = ccx.closure_vals().borrow().get(&mono_id) {
|
||||
debug!("get_or_create_declaration_if_closure(): found closure {:?}: {:?}",
|
||||
mono_id, ccx.tn().val_to_string(llfn));
|
||||
return llfn;
|
||||
}
|
||||
|
||||
let symbol = ccx.tcx().map.with_path(closure_id.node, |path| {
|
||||
mangle_internal_name_by_path_and_seq(path, "closure")
|
||||
});
|
||||
|
||||
// Currently there’s only a single user of
|
||||
// get_or_create_declaration_if_closure and it unconditionally defines the
|
||||
// function, therefore we use define_* here.
|
||||
let llfn = declare::define_internal_rust_fn(ccx, &symbol[..], function_type);
|
||||
let function_type = ccx.tcx().mk_closure_from_closure_substs(closure_id, Box::new(substs));
|
||||
let llfn = declare::define_internal_rust_fn(ccx, &symbol[..], function_type).unwrap_or_else(||{
|
||||
ccx.sess().bug(&format!("symbol `{}` already defined", symbol));
|
||||
});
|
||||
|
||||
// set an inline hint for all closures
|
||||
attributes::inline(llfn, attributes::InlineAttr::Hint);
|
||||
|
|
@ -179,7 +162,7 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
|
|||
ccx.tn().val_to_string(llfn));
|
||||
ccx.closure_vals().borrow_mut().insert(mono_id, llfn);
|
||||
|
||||
Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
|
||||
llfn
|
||||
}
|
||||
|
||||
pub enum Dest<'a, 'tcx: 'a> {
|
||||
|
|
@ -191,9 +174,11 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
|
|||
decl: &ast::FnDecl,
|
||||
body: &ast::Block,
|
||||
id: ast::NodeId,
|
||||
param_substs: &'tcx Substs<'tcx>)
|
||||
closure_substs: &'tcx ty::ClosureSubsts<'tcx>)
|
||||
-> Option<Block<'a, 'tcx>>
|
||||
{
|
||||
let param_substs = closure_substs.func_substs;
|
||||
|
||||
let ccx = match dest {
|
||||
Dest::SaveIn(bcx, _) => bcx.ccx(),
|
||||
Dest::Ignore(ccx) => ccx
|
||||
|
|
@ -204,10 +189,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
|
|||
debug!("trans_closure_expr()");
|
||||
|
||||
let closure_id = ast_util::local_def(id);
|
||||
let llfn = get_or_create_declaration_if_closure(
|
||||
ccx,
|
||||
closure_id,
|
||||
param_substs).unwrap();
|
||||
let llfn = get_or_create_closure_declaration(ccx, closure_id, closure_substs);
|
||||
|
||||
// Get the type of this closure. Use the current `param_substs` as
|
||||
// the closure substitutions. This makes sense because the closure
|
||||
|
|
@ -216,7 +198,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
|
|||
// of the closure expression.
|
||||
|
||||
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
|
||||
let function_type = infcx.closure_type(closure_id, param_substs);
|
||||
let function_type = infcx.closure_type(closure_id, closure_substs);
|
||||
|
||||
let freevars: Vec<ty::Freevar> =
|
||||
tcx.with_freevars(id, |fv| fv.iter().cloned().collect());
|
||||
|
|
@ -226,7 +208,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
|
|||
trans_closure(ccx,
|
||||
decl,
|
||||
body,
|
||||
llfn.val,
|
||||
llfn,
|
||||
param_substs,
|
||||
id,
|
||||
&[],
|
||||
|
|
@ -269,20 +251,12 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
|
|||
|
||||
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>,
|
||||
substs: ty::ClosureSubsts<'tcx>,
|
||||
trait_closure_kind: ty::ClosureKind)
|
||||
-> ValueRef
|
||||
{
|
||||
// The substitutions should have no type parameters remaining
|
||||
// after passing through fulfill_obligation
|
||||
let llfn = callee::trans_fn_ref_with_substs(ccx,
|
||||
closure_def_id,
|
||||
node,
|
||||
param_substs,
|
||||
substs.clone()).val;
|
||||
// If this is a closure, redirect to it.
|
||||
let llfn = get_or_create_closure_declaration(ccx, closure_def_id, &substs);
|
||||
|
||||
// If the closure is a Fn closure, but a FnOnce is needed (etc),
|
||||
// then adapt the self type
|
||||
|
|
@ -290,7 +264,6 @@ pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
|
|||
trans_closure_adapter_shim(ccx,
|
||||
closure_def_id,
|
||||
substs,
|
||||
upvar_tys,
|
||||
closure_kind,
|
||||
trait_closure_kind,
|
||||
llfn)
|
||||
|
|
@ -299,8 +272,7 @@ pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
|
|||
fn trans_closure_adapter_shim<'a, 'tcx>(
|
||||
ccx: &'a CrateContext<'a, 'tcx>,
|
||||
closure_def_id: ast::DefId,
|
||||
substs: Substs<'tcx>,
|
||||
upvar_tys: Vec<Ty<'tcx>>,
|
||||
substs: ty::ClosureSubsts<'tcx>,
|
||||
llfn_closure_kind: ty::ClosureKind,
|
||||
trait_closure_kind: ty::ClosureKind,
|
||||
llfn: ValueRef)
|
||||
|
|
@ -339,7 +311,7 @@ fn trans_closure_adapter_shim<'a, 'tcx>(
|
|||
// 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, upvar_tys, llfn)
|
||||
trans_fn_once_adapter_shim(ccx, closure_def_id, substs, llfn)
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.bug(&format!("trans_closure_adapter_shim: cannot convert {:?} to {:?}",
|
||||
|
|
@ -352,8 +324,7 @@ fn trans_closure_adapter_shim<'a, 'tcx>(
|
|||
fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
||||
ccx: &'a CrateContext<'a, 'tcx>,
|
||||
closure_def_id: ast::DefId,
|
||||
substs: Substs<'tcx>,
|
||||
upvar_tys: Vec<Ty<'tcx>>,
|
||||
substs: ty::ClosureSubsts<'tcx>,
|
||||
llreffn: ValueRef)
|
||||
-> ValueRef
|
||||
{
|
||||
|
|
@ -367,12 +338,11 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
|||
|
||||
// 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, upvar_tys);
|
||||
let closure_ty = tcx.mk_closure_from_closure_substs(closure_def_id, Box::new(substs.clone()));
|
||||
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.
|
||||
let ty::ClosureTy { unsafety, abi, mut sig } = infcx.closure_type(closure_def_id, substs);
|
||||
let ty::ClosureTy { unsafety, abi, mut sig } = infcx.closure_type(closure_def_id, &substs);
|
||||
sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet
|
||||
let llref_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
|
||||
abi: abi,
|
||||
|
|
@ -402,7 +372,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
|||
ast::DUMMY_NODE_ID,
|
||||
false,
|
||||
sig.output,
|
||||
substs,
|
||||
substs.func_substs,
|
||||
None,
|
||||
&block_arena);
|
||||
let mut bcx = init_function(&fcx, false, sig.output);
|
||||
|
|
|
|||
|
|
@ -882,11 +882,16 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
}
|
||||
},
|
||||
ast::ExprClosure(_, ref decl, ref body) => {
|
||||
closure::trans_closure_expr(closure::Dest::Ignore(cx),
|
||||
decl,
|
||||
body,
|
||||
e.id,
|
||||
param_substs);
|
||||
match ety.sty {
|
||||
ty::TyClosure(_, ref substs) => {
|
||||
closure::trans_closure_expr(closure::Dest::Ignore(cx), decl,
|
||||
body, e.id, substs);
|
||||
}
|
||||
_ =>
|
||||
cx.sess().span_bug(
|
||||
e.span,
|
||||
&format!("bad type for closure expr: {:?}", ety))
|
||||
}
|
||||
C_null(type_of::type_of(cx, ety))
|
||||
},
|
||||
_ => cx.sess().span_bug(e.span,
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ impl<'tcx> TypeMap<'tcx> {
|
|||
}
|
||||
}
|
||||
},
|
||||
ty::TyClosure(def_id, substs, _) => {
|
||||
ty::TyClosure(def_id, ref 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,
|
||||
|
|
@ -811,7 +811,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)
|
||||
|
||||
}
|
||||
ty::TyClosure(def_id, substs, _) => {
|
||||
ty::TyClosure(def_id, ref 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<_>>();
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
|
|||
ty::TyBareFn(_, ref f) => {
|
||||
(&f.sig, f.abi, None)
|
||||
}
|
||||
ty::TyClosure(closure_did, substs, _) => {
|
||||
ty::TyClosure(closure_did, ref 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);
|
||||
|
|
|
|||
|
|
@ -1146,8 +1146,14 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
SaveIn(lldest) => closure::Dest::SaveIn(bcx, lldest),
|
||||
Ignore => closure::Dest::Ignore(bcx.ccx())
|
||||
};
|
||||
closure::trans_closure_expr(dest, decl, body, expr.id, bcx.fcx.param_substs)
|
||||
.unwrap_or(bcx)
|
||||
let substs = match expr_ty(bcx, expr).sty {
|
||||
ty::TyClosure(_, ref substs) => substs,
|
||||
ref t =>
|
||||
bcx.tcx().sess.span_bug(
|
||||
expr.span,
|
||||
&format!("closure expr without closure type: {:?}", t)),
|
||||
};
|
||||
closure::trans_closure_expr(dest, decl, body, expr.id, substs).unwrap_or(bcx)
|
||||
}
|
||||
ast::ExprCall(ref f, ref args) => {
|
||||
if bcx.tcx().is_method_call(expr.id) {
|
||||
|
|
|
|||
|
|
@ -341,9 +341,6 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
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);
|
||||
Callee {
|
||||
bcx: bcx,
|
||||
|
|
@ -642,15 +639,11 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
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);
|
||||
vec![llfn].into_iter()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
return Some(CallStep::Builtin);
|
||||
}
|
||||
|
||||
ty::TyClosure(def_id, substs, _) => {
|
||||
ty::TyClosure(def_id, ref substs) => {
|
||||
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
|
||||
|
||||
// Check whether this is a call to a closure where we
|
||||
|
|
|
|||
|
|
@ -41,8 +41,7 @@ pub fn check_drop_impl(tcx: &ty::ctxt, drop_impl_did: ast::DefId) -> Result<(),
|
|||
let dtor_predicates = tcx.lookup_predicates(drop_impl_did);
|
||||
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::TyStruct(self_type_did, self_to_impl_substs) => {
|
||||
try!(ensure_drop_params_and_item_params_correspond(tcx,
|
||||
drop_impl_did,
|
||||
dtor_generics,
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
|||
}
|
||||
ty::TyEnum(did, _) |
|
||||
ty::TyStruct(did, _) |
|
||||
ty::TyClosure(did, _, _) => {
|
||||
ty::TyClosure(did, _) => {
|
||||
self.assemble_inherent_impl_candidates_for_type(did);
|
||||
}
|
||||
ty::TyBox(_) => {
|
||||
|
|
@ -711,7 +711,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
|||
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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ use middle::free_region::FreeRegionMap;
|
|||
use middle::implicator;
|
||||
use middle::mem_categorization as mc;
|
||||
use middle::region::CodeExtent;
|
||||
use middle::subst::Substs;
|
||||
use middle::traits;
|
||||
use middle::ty::{self, ReScope, Ty, MethodCall, HasTypeFlags};
|
||||
use middle::infer::{self, GenericKind};
|
||||
|
|
@ -1444,7 +1443,7 @@ fn closure_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
|
|||
origin: infer::SubregionOrigin<'tcx>,
|
||||
region: ty::Region,
|
||||
def_id: ast::DefId,
|
||||
substs: &'tcx Substs<'tcx>) {
|
||||
substs: &'tcx ty::ClosureSubsts<'tcx>) {
|
||||
debug!("closure_must_outlive(region={:?}, def_id={:?}, substs={:?})",
|
||||
region, def_id, substs);
|
||||
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
|||
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());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue