Skip to content

Commit

Permalink
Have alt-pattern drop the slots it initializes when binding slot patt…
Browse files Browse the repository at this point in the history
…erns. Add a testcase for this as well.
  • Loading branch information
froystig committed Aug 27, 2010
1 parent 1428b59 commit 5e77e78
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/Makefile
Expand Up @@ -425,6 +425,7 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
$(addprefix test/run-pass/, \
arith-1.rs \
acyclic-unwind.rs \
alt-pattern-drop.rs \
alt-pattern-simple.rs \
alt-tag.rs \
append-units.rs \
Expand Down
45 changes: 35 additions & 10 deletions src/boot/me/trans.ml
Expand Up @@ -4138,12 +4138,24 @@ let trans_visitor

let trans_arm arm : quad_idx =
let (pat, block) = arm.node in
(* Translates the pattern and returns the addresses of the branch
* instructions, which are taken if the match fails. *)
let rec trans_pat pat src_cell src_ty =

(* Translates the pattern and returns the following pair.
*
* fst: The addresses of the branch instructions that are taken if
* the match fails.
* snd: The (cell, slot) pairs of any slots bound and initialized
* in PAT_slot pattern leaves.
*)
let rec trans_pat
(pat:Ast.pat)
(src_cell:Il.cell)
(src_ty:Ast.ty)
: (quad_idx list) * ((Il.cell * Ast.slot) list) =

match pat with
Ast.PAT_lit lit ->
trans_compare_simple Il.JNE (trans_lit lit) (Il.Cell src_cell)
(trans_compare_simple Il.JNE (trans_lit lit) (Il.Cell src_cell),
[])

| Ast.PAT_tag (lval, pats) ->
let tag_name = tag_ctor_name_to_tag_name (lval_to_name lval) in
Expand Down Expand Up @@ -4173,16 +4185,19 @@ let trans_visitor

let tup_cell:Il.cell = get_variant_ptr union_cell tag_number in

let trans_elem_pat i elem_pat : quad_idx list =
let trans_elem_pat i elem_pat
: (quad_idx list) * ((Il.cell * Ast.slot) list) =
let elem_cell =
get_element_ptr_dyn_in_current_frame tup_cell i
in
let elem_ty = ty_tup.(i) in
trans_pat elem_pat elem_cell elem_ty
in

let elem_jumps = Array.mapi trans_elem_pat pats in
next_jumps @ (List.concat (Array.to_list elem_jumps))
let (elem_jumps, bindings) =
List.split (Array.to_list (Array.mapi trans_elem_pat pats))
in
(next_jumps @ (List.concat elem_jumps), List.concat bindings)

| Ast.PAT_slot (dst, _) ->
let dst_slot = get_slot cx dst.id in
Expand All @@ -4191,14 +4206,24 @@ let trans_visitor
(get_ty_params_of_current_frame())
CLONE_none dst_cell dst_slot
src_cell src_ty;
[] (* irrefutable *)
([], [(dst_cell, dst_slot)]) (* irrefutable *)

| Ast.PAT_wild -> [] (* irrefutable *)
| Ast.PAT_wild -> ([], []) (* irrefutable *)
in

let (lval_cell, lval_ty) = trans_lval at.Ast.alt_tag_lval in
let next_jumps = trans_pat pat lval_cell lval_ty in
let (next_jumps, bindings) = trans_pat pat lval_cell lval_ty in
trans_block block;

(* Drop any slots we initialized in the leaf slot bindings of
* this arm's pattern.
*
* FIXME: Is `None` really correct to pass as the curr_iso?
*)
List.iter
(fun (cell, slot) -> drop_slot_in_current_frame cell slot None)
bindings;

let last_jump = mark() in
emit (Il.jmp Il.JMP Il.CodeNone);
List.iter patch next_jumps;
Expand Down
19 changes: 19 additions & 0 deletions src/test/run-pass/alt-pattern-drop.rs
@@ -0,0 +1,19 @@
// -*- rust -*-

use std;
import std._str;

type t = tag(make_t(str), clam());

fn main() {
let str s = "hi"; // ref up
let t x = make_t(s); // ref up

alt (x) {
case (make_t(y)) { log y; } // ref up and ref down
case (_) { log "?"; }
}

log _str.refcount(s);
check (_str.refcount(s) == 2u);
}

0 comments on commit 5e77e78

Please sign in to comment.