Skip to content

Commit 53ce42d

Browse files
committed
Implement &-patterns
Closes #2855
1 parent e9f5a09 commit 53ce42d

File tree

13 files changed

+88
-18
lines changed

13 files changed

+88
-18
lines changed

src/libsyntax/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ enum pat_ {
360360
pat_tup(~[@pat]),
361361
pat_box(@pat),
362362
pat_uniq(@pat),
363+
pat_region(@pat), // borrowed pointer pattern
363364
pat_lit(@expr),
364365
pat_range(@expr, @expr),
365366
}

src/libsyntax/ast_util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ fn walk_pat(pat: @pat, it: fn(@pat)) {
595595
pat_enum(_, Some(s)) | pat_tup(s) => for s.each |p| {
596596
walk_pat(p, it)
597597
},
598-
pat_box(s) | pat_uniq(s) => walk_pat(s, it),
598+
pat_box(s) | pat_uniq(s) | pat_region(s) => walk_pat(s, it),
599599
pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _, _)
600600
| pat_enum(_, _) => ()
601601
}

src/libsyntax/fold.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ {
384384
pat_tup(elts) => pat_tup(vec::map(elts, |x| fld.fold_pat(x))),
385385
pat_box(inner) => pat_box(fld.fold_pat(inner)),
386386
pat_uniq(inner) => pat_uniq(fld.fold_pat(inner)),
387+
pat_region(inner) => pat_region(fld.fold_pat(inner)),
387388
pat_range(e1, e2) => {
388389
pat_range(fld.fold_expr(e1), fld.fold_expr(e2))
389390
}

src/libsyntax/parse/parser.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
4242
mac_invoc_tt, mac_var, matcher, match_nonterminal, match_seq,
4343
match_tok, method, mode, module_ns, mt, mul, mutability,
4444
named_field, neg, noreturn, not, pat, pat_box, pat_enum,
45-
pat_ident, pat_lit, pat_range, pat_rec, pat_struct, pat_tup,
46-
pat_uniq, pat_wild, path, private, proto, proto_bare,
45+
pat_ident, pat_lit, pat_range, pat_rec, pat_region, pat_struct,
46+
pat_tup, pat_uniq, pat_wild, path, private, proto, proto_bare,
4747
proto_block, proto_box, proto_uniq, provided, public, pure_fn,
4848
purity, re_anon, re_named, region, rem, required, ret_style,
4949
return_val, self_ty, shl, shr, stmt, stmt_decl, stmt_expr,
@@ -1844,6 +1844,25 @@ struct parser {
18441844
};
18451845

18461846
}
1847+
token::BINOP(token::AND) => {
1848+
let lo = self.span.lo;
1849+
self.bump();
1850+
let sub = self.parse_pat(refutable);
1851+
hi = sub.span.hi;
1852+
// HACK: parse &"..." as a literal of a borrowed str
1853+
pat = match sub.node {
1854+
pat_lit(e@@{
1855+
node: expr_lit(@{node: lit_str(_), span: _}), _
1856+
}) => {
1857+
let vst = @{id: self.get_id(), callee_id: self.get_id(),
1858+
node: expr_vstore(e,
1859+
vstore_slice(self.region_from_name(None))),
1860+
span: mk_sp(lo, hi)};
1861+
pat_lit(vst)
1862+
}
1863+
_ => pat_region(sub)
1864+
};
1865+
}
18471866
token::LBRACE => {
18481867
self.bump();
18491868
let (fields, etc) = self.parse_pat_fields(refutable);

src/libsyntax/print/pprust.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,10 @@ fn print_pat(s: ps, &&pat: @ast::pat) {
15371537
}
15381538
ast::pat_box(inner) => { word(s.s, ~"@"); print_pat(s, inner); }
15391539
ast::pat_uniq(inner) => { word(s.s, ~"~"); print_pat(s, inner); }
1540+
ast::pat_region(inner) => {
1541+
word(s.s, ~"&");
1542+
print_pat(s, inner);
1543+
}
15401544
ast::pat_lit(e) => print_expr(s, e),
15411545
ast::pat_range(begin, end) => {
15421546
print_expr(s, begin);

src/libsyntax/visit.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
237237
pat_tup(elts) => for elts.each |elt| {
238238
v.visit_pat(elt, e, v)
239239
},
240-
pat_box(inner) | pat_uniq(inner) => v.visit_pat(inner, e, v),
240+
pat_box(inner) | pat_uniq(inner) | pat_region(inner) =>
241+
v.visit_pat(inner, e, v),
241242
pat_ident(_, path, inner) => {
242243
visit_path(path, e, v);
243244
do option::iter(inner) |subpat| { v.visit_pat(subpat, e, v)};

src/rustc/middle/check_alt.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ fn pat_ctor_id(tcx: ty::ctxt, p: @pat) -> Option<ctor> {
235235
pat_range(lo, hi) => {
236236
Some(range(eval_const_expr(tcx, lo), eval_const_expr(tcx, hi)))
237237
}
238-
pat_box(_) | pat_uniq(_) | pat_rec(_, _) | pat_tup(_) |
238+
pat_box(_) | pat_uniq(_) | pat_rec(_, _) | pat_tup(_) | pat_region(*) |
239239
pat_struct(*) => {
240240
Some(single)
241241
}
@@ -258,8 +258,8 @@ fn is_wild(tcx: ty::ctxt, p: @pat) -> bool {
258258

259259
fn missing_ctor(tcx: ty::ctxt, m: matrix, left_ty: ty::t) -> Option<ctor> {
260260
match ty::get(left_ty).struct {
261-
ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_tup(_) | ty::ty_rec(_) |
262-
ty::ty_class(*) => {
261+
ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(*) | ty::ty_tup(_) |
262+
ty::ty_rec(_) | ty::ty_class(*) => {
263263
for m.each |r| {
264264
if !is_wild(tcx, r[0]) { return None; }
265265
}
@@ -305,7 +305,7 @@ fn ctor_arity(tcx: ty::ctxt, ctor: ctor, ty: ty::t) -> uint {
305305
match ty::get(ty).struct {
306306
ty::ty_tup(fs) => fs.len(),
307307
ty::ty_rec(fs) => fs.len(),
308-
ty::ty_box(_) | ty::ty_uniq(_) => 1u,
308+
ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(*) => 1u,
309309
ty::ty_enum(eid, _) => {
310310
let id = match ctor { variant(id) => id,
311311
_ => fail ~"impossible case" };
@@ -386,7 +386,8 @@ fn specialize(tcx: ty::ctxt, r: ~[@pat], ctor_id: ctor, arity: uint,
386386
Some(vec::append(args, vec::tail(r)))
387387
}
388388
pat_tup(args) => Some(vec::append(args, vec::tail(r))),
389-
pat_box(a) | pat_uniq(a) => Some(vec::append(~[a], vec::tail(r))),
389+
pat_box(a) | pat_uniq(a) | pat_region(a) =>
390+
Some(vec::append(~[a], vec::tail(r))),
390391
pat_lit(expr) => {
391392
let e_v = eval_const_expr(tcx, expr);
392393
let match_ = match ctor_id {
@@ -440,7 +441,8 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
440441
}
441442

442443
match pat.node {
443-
pat_box(sub) | pat_uniq(sub) | pat_ident(_, _, Some(sub)) => {
444+
pat_box(sub) | pat_uniq(sub) | pat_region(sub) |
445+
pat_ident(_, _, Some(sub)) => {
444446
is_refutable(tcx, sub)
445447
}
446448
pat_wild | pat_ident(_, _, None) => { false }

src/rustc/middle/mem_categorization.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -898,8 +898,9 @@ impl &mem_categorization_ctxt {
898898
}
899899
}
900900

901-
ast::pat_box(subpat) | ast::pat_uniq(subpat) => {
902-
// @p1, ~p1
901+
ast::pat_box(subpat) | ast::pat_uniq(subpat) |
902+
ast::pat_region(subpat) => {
903+
// @p1, ~p1, &p1
903904
match self.cat_deref(subpat, cmt, 0u, true) {
904905
Some(subcmt) => {
905906
self.cat_pattern(subcmt, subpat, op);

src/rustc/middle/trans/alt.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -914,12 +914,8 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
914914
bcx = bind_irrefutable_pat(bcx, elem, fldptr, make_copy);
915915
}
916916
}
917-
ast::pat_box(inner) => {
918-
let llbox = Load(bcx, val);
919-
let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
920-
bcx = bind_irrefutable_pat(bcx, inner, unboxed, true);
921-
}
922-
ast::pat_uniq(inner) => {
917+
ast::pat_box(inner) | ast::pat_uniq(inner) |
918+
ast::pat_region(inner) => {
923919
let llbox = Load(bcx, val);
924920
let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
925921
bcx = bind_irrefutable_pat(bcx, inner, unboxed, true);

src/rustc/middle/typeck/check/alt.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,22 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
447447
}
448448
}
449449
}
450+
ast::pat_region(inner) => {
451+
match structure_of(fcx, pat.span, expected) {
452+
ty::ty_rptr(_, e_inner) => {
453+
check_pat(pcx, inner, e_inner.ty);
454+
fcx.write_ty(pat.id, expected);
455+
}
456+
_ => {
457+
tcx.sess.span_fatal(
458+
pat.span,
459+
~"mismatched types: expected `" +
460+
fcx.infcx().ty_to_str(expected) +
461+
~"` found borrowed pointer");
462+
}
463+
}
464+
}
465+
450466
}
451467
}
452468

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
fn foo<T>(s: &str) {
2+
match s {
3+
&"kitty" => fail ~"cat",
4+
_ => ()
5+
}
6+
}
7+
8+
fn main() {
9+
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
fn foo<T>(s: &r/uint) {
2+
match s {
3+
&3 => fail ~"oh",
4+
_ => ()
5+
}
6+
}
7+
8+
fn main() {
9+
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fn foo<T>(x: &T) {
2+
match x {
3+
&a => fail #fmt("%?", a)
4+
}
5+
}
6+
7+
fn main() {
8+
9+
}

0 commit comments

Comments
 (0)