rustc: unbox closures used in function arguments

This commit is contained in:
Jorge Aparicio 2014-12-30 19:59:09 -05:00
parent 70ce68eed4
commit 5de9f47e49
2 changed files with 59 additions and 53 deletions

View File

@ -1122,11 +1122,15 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
})
}
// FIXME(#19596) unbox `op`
pub fn cat_pattern(&self,
cmt: cmt<'tcx>,
pat: &ast::Pat,
op: |&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat|)
pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, mut op: F) where
F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
{
self.cat_pattern_(cmt, pat, &mut op)
}
// FIXME(#19596) This is a workaround, but there should be a better way to do this
fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F) where
F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
{
// Here, `cmt` is the categorization for the value being
// matched and pat is the pattern it is being matched against.
@ -1177,7 +1181,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
pat.id, pprust::pat_to_string(pat),
cmt.repr(self.tcx()));
op(self, cmt.clone(), pat);
(*op)(self, cmt.clone(), pat);
let def_map = self.tcx().def_map.borrow();
let opt_def = def_map.get(&pat.id);
@ -1214,7 +1218,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
pat, cmt.clone(), subpat_ty,
InteriorField(PositionalField(i)));
self.cat_pattern(subcmt, &**subpat, |x,y,z| op(x,y,z));
self.cat_pattern_(subcmt, &**subpat, op);
}
}
Some(&def::DefStruct(..)) => {
@ -1224,13 +1228,12 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
self.cat_imm_interior(
pat, cmt.clone(), subpat_ty,
InteriorField(PositionalField(i)));
self.cat_pattern(cmt_field, &**subpat,
|x,y,z| op(x,y,z));
self.cat_pattern_(cmt_field, &**subpat, op);
}
}
Some(&def::DefConst(..)) => {
for subpat in subpats.iter() {
self.cat_pattern(cmt.clone(), &**subpat, |x,y,z| op(x,y,z));
self.cat_pattern_(cmt.clone(), &**subpat, op);
}
}
_ => {
@ -1242,7 +1245,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
}
ast::PatIdent(_, _, Some(ref subpat)) => {
self.cat_pattern(cmt, &**subpat, op);
self.cat_pattern_(cmt, &**subpat, op);
}
ast::PatIdent(_, _, None) => {
@ -1254,7 +1257,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
for fp in field_pats.iter() {
let field_ty = self.pat_ty(&*fp.node.pat); // see (*2)
let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.ident.name, field_ty);
self.cat_pattern(cmt_field, &*fp.node.pat, |x,y,z| op(x,y,z));
self.cat_pattern_(cmt_field, &*fp.node.pat, op);
}
}
@ -1266,29 +1269,28 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
self.cat_imm_interior(
pat, cmt.clone(), subpat_ty,
InteriorField(PositionalField(i)));
self.cat_pattern(subcmt, &**subpat, |x,y,z| op(x,y,z));
self.cat_pattern_(subcmt, &**subpat, op);
}
}
ast::PatBox(ref subpat) | ast::PatRegion(ref subpat) => {
// @p1, ~p1, ref p1
let subcmt = self.cat_deref(pat, cmt, 0, false);
self.cat_pattern(subcmt, &**subpat, op);
self.cat_pattern_(subcmt, &**subpat, op);
}
ast::PatVec(ref before, ref slice, ref after) => {
let elt_cmt = self.cat_index(pat, self.deref_vec(pat, cmt));
for before_pat in before.iter() {
self.cat_pattern(elt_cmt.clone(), &**before_pat,
|x,y,z| op(x,y,z));
self.cat_pattern_(elt_cmt.clone(), &**before_pat, op);
}
for slice_pat in slice.iter() {
let slice_ty = self.pat_ty(&**slice_pat);
let slice_cmt = self.cat_rvalue_node(pat.id(), pat.span(), slice_ty);
self.cat_pattern(slice_cmt, &**slice_pat, |x,y,z| op(x,y,z));
self.cat_pattern_(slice_cmt, &**slice_pat, op);
}
for after_pat in after.iter() {
self.cat_pattern(elt_cmt.clone(), &**after_pat, |x,y,z| op(x,y,z));
self.cat_pattern_(elt_cmt.clone(), &**after_pat, op);
}
}

View File

@ -2812,49 +2812,53 @@ pub fn walk_ty<'tcx, F>(ty: Ty<'tcx>, mut f: F) where
maybe_walk_ty(ty, |ty| { f(ty); true });
}
// FIXME(#19596) unbox `f`
pub fn maybe_walk_ty<'tcx>(ty: Ty<'tcx>, f: |Ty<'tcx>| -> bool) {
if !f(ty) {
return;
}
match ty.sty {
ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str | ty_infer(_) | ty_param(_) | ty_err => {}
ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty(ty, f),
ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
maybe_walk_ty(tm.ty, f);
pub fn maybe_walk_ty<'tcx, F>(ty: Ty<'tcx>, mut f: F) where F: FnMut(Ty<'tcx>) -> bool {
// FIXME(#19596) This is a workaround, but there should be a better way to do this
fn maybe_walk_ty_<'tcx, F>(ty: Ty<'tcx>, f: &mut F) where F: FnMut(Ty<'tcx>) -> bool {
if !(*f)(ty) {
return;
}
ty_trait(box TyTrait { ref principal, .. }) => {
for subty in principal.0.substs.types.iter() {
maybe_walk_ty(*subty, |x| f(x));
match ty.sty {
ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str | ty_infer(_) | ty_param(_) | ty_err => {}
ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty_(ty, f),
ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
maybe_walk_ty_(tm.ty, f);
}
}
ty_projection(ProjectionTy { ref trait_ref, .. }) => {
for subty in trait_ref.substs.types.iter() {
maybe_walk_ty(*subty, |x| f(x));
ty_trait(box TyTrait { ref principal, .. }) => {
for subty in principal.0.substs.types.iter() {
maybe_walk_ty_(*subty, f);
}
}
}
ty_enum(_, ref substs) |
ty_struct(_, ref substs) |
ty_unboxed_closure(_, _, ref substs) => {
for subty in substs.types.iter() {
maybe_walk_ty(*subty, |x| f(x));
ty_projection(ProjectionTy { ref trait_ref, .. }) => {
for subty in trait_ref.substs.types.iter() {
maybe_walk_ty_(*subty, f);
}
}
}
ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
ty_bare_fn(_, ref ft) => {
for a in ft.sig.0.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
if let ty::FnConverging(output) = ft.sig.0.output {
maybe_walk_ty(output, f);
ty_enum(_, ref substs) |
ty_struct(_, ref substs) |
ty_unboxed_closure(_, _, ref substs) => {
for subty in substs.types.iter() {
maybe_walk_ty_(*subty, f);
}
}
}
ty_closure(ref ft) => {
for a in ft.sig.0.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
if let ty::FnConverging(output) = ft.sig.0.output {
maybe_walk_ty(output, f);
ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty_(*tt, f); } }
ty_bare_fn(_, ref ft) => {
for a in ft.sig.0.inputs.iter() { maybe_walk_ty_(*a, f); }
if let ty::FnConverging(output) = ft.sig.0.output {
maybe_walk_ty_(output, f);
}
}
ty_closure(ref ft) => {
for a in ft.sig.0.inputs.iter() { maybe_walk_ty_(*a, f); }
if let ty::FnConverging(output) = ft.sig.0.output {
maybe_walk_ty_(output, f);
}
}
}
}
maybe_walk_ty_(ty, &mut f);
}
// Folds types from the bottom up.