From 0a26edca75a53839d63c0227d62f863dfb717e1b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 23 Sep 2012 05:39:39 -0700 Subject: [PATCH] Fix trans for region patterns (&P) --- src/libsyntax/parse/token.rs | 2 +- src/rustc/middle/trans/alt.rs | 82 +++++++++++++------ src/rustdoc/extract.rs | 2 +- src/rustdoc/markdown_writer.rs | 2 +- src/test/run-pass/borrowed-ptr-pattern-2.rs | 11 +-- src/test/run-pass/borrowed-ptr-pattern-3.rs | 11 +-- .../borrowed-ptr-pattern-infallible.rs | 6 ++ .../run-pass/borrowed-ptr-pattern-option.rs | 13 +++ src/test/run-pass/borrowed-ptr-pattern.rs | 10 ++- 9 files changed, 99 insertions(+), 40 deletions(-) create mode 100644 src/test/run-pass/borrowed-ptr-pattern-infallible.rs create mode 100644 src/test/run-pass/borrowed-ptr-pattern-option.rs diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 9bf612c588a..37f2e6bd189 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -331,7 +331,7 @@ type ident_interner = util::interner::interner<@~str>; * so we have to use a unique number. See taskgroup_key! in task.rs * for another case of this. */ macro_rules! interner_key ( - () => (cast::transmute::<(uint, uint), &fn(+@@token::ident_interner)>( + () => (cast::transmute::<(uint, uint), &fn(+v: @@token::ident_interner)>( (-3 as uint, 0u))) ) diff --git a/src/rustc/middle/trans/alt.rs b/src/rustc/middle/trans/alt.rs index c7abed19c59..07727113741 100644 --- a/src/rustc/middle/trans/alt.rs +++ b/src/rustc/middle/trans/alt.rs @@ -487,6 +487,31 @@ fn enter_uniq(bcx: block, dm: DefMap, m: &[@Match/&r], } } +fn enter_region(bcx: block, dm: DefMap, m: &[@Match/&r], + col: uint, val: ValueRef) + -> ~[@Match/&r] +{ + debug!("enter_region(bcx=%s, m=%s, col=%u, val=%?)", + bcx.to_str(), + matches_to_str(bcx, m), + col, + bcx.val_str(val)); + let _indenter = indenter(); + + let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()}; + do enter_match(bcx, dm, m, col, val) |p| { + match p.node { + ast::pat_region(sub) => { + Some(~[sub]) + } + _ => { + assert_is_binding_or_wild(bcx, p); + Some(~[dummy]) + } + } + } +} + fn get_options(ccx: @crate_ctxt, m: &[@Match], col: uint) -> ~[Opt] { fn add_to_set(tcx: ty::ctxt, set: &DVec, val: Opt) { if set.any(|l| opt_eq(tcx, &l, &val)) {return;} @@ -585,34 +610,35 @@ fn root_pats_as_necessary(bcx: block, m: &[@Match], } } -fn any_box_pat(m: &[@Match], col: uint) -> bool { - for vec::each(m) |br| { - match br.pats[col].node { - ast::pat_box(_) => return true, - _ => () - } +// Macro for deciding whether any of the remaining matches fit a given kind of +// pattern. Note that, because the macro is well-typed, either ALL of the +// matches should fit that sort of pattern or NONE (however, some of the +// matches may be wildcards like _ or identifiers). +macro_rules! any_pat ( + ($m:expr, $pattern:pat) => { + vec::any($m, |br| { + match br.pats[col].node { + $pattern => true, + _ => false + } + }) } - return false; +) + +fn any_box_pat(m: &[@Match], col: uint) -> bool { + any_pat!(m, ast::pat_box(_)) } fn any_uniq_pat(m: &[@Match], col: uint) -> bool { - for vec::each(m) |br| { - match br.pats[col].node { - ast::pat_uniq(_) => return true, - _ => () - } - } - return false; + any_pat!(m, ast::pat_uniq(_)) +} + +fn any_region_pat(m: &[@Match], col: uint) -> bool { + any_pat!(m, ast::pat_region(_)) } fn any_tup_pat(m: &[@Match], col: uint) -> bool { - for vec::each(m) |br| { - match br.pats[col].node { - ast::pat_tup(_) => return true, - _ => () - } - } - return false; + any_pat!(m, ast::pat_tup(_)) } type mk_fail = fn@() -> BasicBlockRef; @@ -940,6 +966,13 @@ fn compile_submatch(bcx: block, return; } + if any_region_pat(m, col) { + let loaded_val = Load(bcx, val); + compile_submatch(bcx, enter_region(bcx, dm, m, col, val), + vec::append(~[loaded_val], vals_left), chk); + return; + } + // Decide what kind of branch we need let opts = get_options(ccx, m, col); let mut kind = no_branch; @@ -1248,12 +1281,15 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef, bcx = bind_irrefutable_pat(bcx, *elem, fldptr, make_copy); } } - ast::pat_box(inner) | ast::pat_uniq(inner) | - ast::pat_region(inner) => { + ast::pat_box(inner) | ast::pat_uniq(inner) => { let llbox = Load(bcx, val); let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]); bcx = bind_irrefutable_pat(bcx, inner, unboxed, true); } + ast::pat_region(inner) => { + let loaded_val = Load(bcx, val); + bcx = bind_irrefutable_pat(bcx, inner, loaded_val, true); + } ast::pat_wild | ast::pat_lit(_) | ast::pat_range(_, _) => () } return bcx; diff --git a/src/rustdoc/extract.rs b/src/rustdoc/extract.rs index 0f7728d60f0..b8a13b712e5 100644 --- a/src/rustdoc/extract.rs +++ b/src/rustdoc/extract.rs @@ -10,7 +10,7 @@ export from_srv, extract, to_str, interner; * there. */ macro_rules! interner_key ( () => (cast::transmute::<(uint, uint), - &fn(+@@syntax::parse::token::ident_interner)>((-3 as uint, 0u))) + &fn(+v: @@syntax::parse::token::ident_interner)>((-3 as uint, 0u))) ) // Hack; rather than thread an interner through everywhere, rely on diff --git a/src/rustdoc/markdown_writer.rs b/src/rustdoc/markdown_writer.rs index 5749e4dcb23..99849263067 100644 --- a/src/rustdoc/markdown_writer.rs +++ b/src/rustdoc/markdown_writer.rs @@ -14,7 +14,7 @@ enum WriteInstr { Done } -type Writer = fn~(+WriteInstr); +type Writer = fn~(+v: WriteInstr); type WriterFactory = fn~(page: doc::Page) -> Writer; trait WriterUtils { diff --git a/src/test/run-pass/borrowed-ptr-pattern-2.rs b/src/test/run-pass/borrowed-ptr-pattern-2.rs index 8e31bc38e32..1cfe037c729 100644 --- a/src/test/run-pass/borrowed-ptr-pattern-2.rs +++ b/src/test/run-pass/borrowed-ptr-pattern-2.rs @@ -1,10 +1,11 @@ -fn foo(s: &str) { +fn foo(s: &~str) -> bool { match s { - &"kitty" => fail ~"cat", - _ => () + &~"kitty" => true, + _ => false } } fn main() { - -} \ No newline at end of file + assert foo(&~"kitty"); + assert !foo(&~"gata"); +} diff --git a/src/test/run-pass/borrowed-ptr-pattern-3.rs b/src/test/run-pass/borrowed-ptr-pattern-3.rs index 844e36ccf3b..8d95d84966e 100644 --- a/src/test/run-pass/borrowed-ptr-pattern-3.rs +++ b/src/test/run-pass/borrowed-ptr-pattern-3.rs @@ -1,10 +1,11 @@ -fn foo(s: &r/uint) { +fn foo(s: &r/uint) -> bool { match s { - &3 => fail ~"oh", - _ => () + &3 => true, + _ => false } } fn main() { - -} \ No newline at end of file + assert foo(&3); + assert !foo(&4); +} diff --git a/src/test/run-pass/borrowed-ptr-pattern-infallible.rs b/src/test/run-pass/borrowed-ptr-pattern-infallible.rs new file mode 100644 index 00000000000..4b2006f51a2 --- /dev/null +++ b/src/test/run-pass/borrowed-ptr-pattern-infallible.rs @@ -0,0 +1,6 @@ +fn main() { + let (&x, &y, &z) = (&3, &'a', &@"No pets!"); + assert x == 3; + assert y == 'a'; + assert z == @"No pets!"; +} diff --git a/src/test/run-pass/borrowed-ptr-pattern-option.rs b/src/test/run-pass/borrowed-ptr-pattern-option.rs new file mode 100644 index 00000000000..9da88ff0006 --- /dev/null +++ b/src/test/run-pass/borrowed-ptr-pattern-option.rs @@ -0,0 +1,13 @@ +fn select(x: &r/Option, y: &r/Option) -> &r/Option { + match (x, y) { + (&None, &None) => x, + (&Some(_), _) => x, + (&None, &Some(_)) => y + } +} + +fn main() { + let x = None; + let y = Some(3); + assert select(&x, &y).get() == 3; +} \ No newline at end of file diff --git a/src/test/run-pass/borrowed-ptr-pattern.rs b/src/test/run-pass/borrowed-ptr-pattern.rs index afe1f34fac4..ae1c955be69 100644 --- a/src/test/run-pass/borrowed-ptr-pattern.rs +++ b/src/test/run-pass/borrowed-ptr-pattern.rs @@ -1,9 +1,11 @@ -fn foo(x: &T) { +fn foo(x: &T) -> T{ match x { - &a => fail #fmt("%?", a) + &a => a } } fn main() { - -} \ No newline at end of file + assert foo(&3) == 3; + assert foo(&'a') == 'a'; + assert foo(&@"Dogs rule, cats drool") == @"Dogs rule, cats drool"; +}