aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile1
-rw-r--r--src/boot/me/trans.ml45
-rw-r--r--src/test/run-pass/alt-pattern-drop.rs19
3 files changed, 55 insertions, 10 deletions
diff --git a/src/Makefile b/src/Makefile
index 77045777..62fe0bee 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -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 \
diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml
index 39cfd0f4..edb86294 100644
--- a/src/boot/me/trans.ml
+++ b/src/boot/me/trans.ml
@@ -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
@@ -4173,7 +4185,8 @@ 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
@@ -4181,8 +4194,10 @@ let trans_visitor
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
@@ -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;
diff --git a/src/test/run-pass/alt-pattern-drop.rs b/src/test/run-pass/alt-pattern-drop.rs
new file mode 100644
index 00000000..d1f1440f
--- /dev/null
+++ b/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);
+}