Begin to support pattern matching on unique boxes

Issue #409
This commit is contained in:
Brian Anderson 2011-09-23 11:15:17 -07:00
parent 87700adb2f
commit 2082f67765
10 changed files with 72 additions and 0 deletions

View File

@ -665,6 +665,13 @@ fn pattern_roots(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat)
}; };
walk(tcx, m ? some(contains(ty)) : mut, p, set); walk(tcx, m ? some(contains(ty)) : mut, p, set);
} }
ast::pat_uniq(p) {
let ty = ty::node_id_to_type(tcx, pat.id);
let m = alt ty::struct(tcx, ty) {
ty::ty_uniq(mt) { mt.mut != ast::imm }
};
walk(tcx, m ? some(contains(ty)) : mut, p, set);
}
} }
} }
let set = []; let set = [];

View File

@ -98,6 +98,12 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
_ { ret pattern_supersedes(tcx, suba, b); } _ { ret pattern_supersedes(tcx, suba, b); }
} }
} }
pat_uniq(suba) {
alt b.node {
pat_uniq(subb) { ret pattern_supersedes(tcx, suba, subb); }
_ { ret pattern_supersedes(tcx, suba, b); }
}
}
} }
} }

View File

@ -176,6 +176,17 @@ fn enter_box(m: match, col: uint, val: ValueRef) -> match {
ret enter_match(m, col, val, bind e(dummy, _)); ret enter_match(m, col, val, bind e(dummy, _));
} }
fn enter_uniq(m: match, col: uint, val: ValueRef) -> match {
let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
fn e(dummy: @ast::pat, p: @ast::pat) -> option::t<[@ast::pat]> {
alt p.node {
ast::pat_uniq(sub) { ret some([sub]); }
_ { ret some([dummy]); }
}
}
ret enter_match(m, col, val, bind e(dummy, _));
}
fn get_options(ccx: @crate_ctxt, m: match, col: uint) -> [opt] { fn get_options(ccx: @crate_ctxt, m: match, col: uint) -> [opt] {
fn add_to_set(&set: [opt], val: opt) { fn add_to_set(&set: [opt], val: opt) {
for l: opt in set { if opt_eq(l, val) { ret; } } for l: opt in set { if opt_eq(l, val) { ret; } }
@ -249,6 +260,13 @@ fn any_box_pat(m: match, col: uint) -> bool {
ret false; ret false;
} }
fn any_uniq_pat(m: match, col: uint) -> bool {
for br: match_branch in m {
alt br.pats[col].node { ast::pat_uniq(_) { ret true; } _ { } }
}
ret false;
}
fn any_tup_pat(m: match, col: uint) -> bool { fn any_tup_pat(m: match, col: uint) -> bool {
for br: match_branch in m { for br: match_branch in m {
alt br.pats[col].node { ast::pat_tup(_) { ret true; } _ { } } alt br.pats[col].node { ast::pat_tup(_) { ret true; } _ { } }
@ -386,6 +404,13 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
ret; ret;
} }
if any_uniq_pat(m, col) {
let unboxed = Load(bcx, val);
compile_submatch(bcx, enter_uniq(m, col, val),
[unboxed] + vals_left, f, exits);
ret;
}
// Decide what kind of branch we need // Decide what kind of branch we need
let opts = get_options(ccx, m, col); let opts = get_options(ccx, m, col);
tag branch_kind { no_branch; single; switch; compare; } tag branch_kind { no_branch; single; switch; compare; }

View File

@ -1435,6 +1435,20 @@ fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat,
} }
} }
} }
ast::pat_uniq(inner) {
alt structure_of(fcx, pat.span, expected) {
ty::ty_uniq(e_inner) {
check_pat(fcx, map, inner, e_inner.ty);
write::ty_only_fixup(fcx, pat.id, expected);
}
_ {
fcx.ccx.tcx.sess.span_fatal(pat.span,
"mismatched types: expected " +
ty_to_str(fcx.ccx.tcx, expected) +
" found uniq");
}
}
}
} }
} }

View File

@ -92,6 +92,7 @@ tag pat_ {
pat_rec([field_pat], bool); pat_rec([field_pat], bool);
pat_tup([@pat]); pat_tup([@pat]);
pat_box(@pat); pat_box(@pat);
pat_uniq(@pat);
} }
tag mutability { mut; imm; maybe_mut; } tag mutability { mut; imm; maybe_mut; }

View File

@ -69,6 +69,7 @@ iter pat_bindings(pat: @pat) -> @pat {
for elt in elts { for each b in pat_bindings(elt) { put b; } } for elt in elts { for each b in pat_bindings(elt) { put b; } }
} }
pat_box(sub) { for each b in pat_bindings(sub) { put b; } } pat_box(sub) { for each b in pat_bindings(sub) { put b; } }
pat_uniq(sub) { for each b in pat_bindings(sub) { put b; } }
pat_wild. | pat_lit(_) { } pat_wild. | pat_lit(_) { }
} }
} }

View File

@ -291,6 +291,7 @@ fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ {
} }
pat_tup(elts) { pat_tup(vec::map(fld.fold_pat, elts)) } pat_tup(elts) { pat_tup(vec::map(fld.fold_pat, elts)) }
pat_box(inner) { pat_box(fld.fold_pat(inner)) } pat_box(inner) { pat_box(fld.fold_pat(inner)) }
pat_uniq(inner) { pat_uniq(fld.fold_pat(inner)) }
}; };
} }

View File

@ -1425,6 +1425,12 @@ fn parse_pat(p: parser) -> @ast::pat {
pat = ast::pat_box(sub); pat = ast::pat_box(sub);
hi = sub.span.hi; hi = sub.span.hi;
} }
token::TILDE. {
p.bump();
let sub = parse_pat(p);
pat = ast::pat_uniq(sub);
hi = sub.span.hi;
}
token::LBRACE. { token::LBRACE. {
p.bump(); p.bump();
let fields = []; let fields = [];

View File

@ -1113,6 +1113,7 @@ fn print_pat(s: ps, pat: @ast::pat) {
pclose(s); pclose(s);
} }
ast::pat_box(inner) { word(s.s, "@"); print_pat(s, inner); } ast::pat_box(inner) { word(s.s, "@"); print_pat(s, inner); }
ast::pat_uniq(inner) { word(s.s, "~"); print_pat(s, inner); }
} }
s.ann.post(ann_node); s.ann.post(ann_node);
} }

View File

@ -0,0 +1,10 @@
fn simple() {
alt ~true {
~true { }
_ { fail; }
}
}
fn main() {
simple();
}