about summary refs log tree commit diff
path: root/src/comp/syntax/parse
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-09-15 16:15:17 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-09-15 16:15:17 +0200
commit3abe3671bd39a359de3421b062b98d3adaa1942d (patch)
treea6a95df9c3ab53b55cc902cf736b0a282be98da0 /src/comp/syntax/parse
parent75eee8b194231c2fe808242a9828253125b854c8 (diff)
downloadrust-3abe3671bd39a359de3421b062b98d3adaa1942d.tar.gz
rust-3abe3671bd39a359de3421b062b98d3adaa1942d.zip
Require the parameter that will be referenced to be noted
Issue #918
Diffstat (limited to 'src/comp/syntax/parse')
-rw-r--r--src/comp/syntax/parse/parser.rs21
1 files changed, 17 insertions, 4 deletions
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs
index 4a449c25a97..b2da68b0cd9 100644
--- a/src/comp/syntax/parse/parser.rs
+++ b/src/comp/syntax/parse/parser.rs
@@ -285,7 +285,7 @@ fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
     // FIXME: there's no syntax for this right now anyway
     //  auto constrs = parse_constrs(~[], p);
     let constrs: [@ast::constr] = [];
-    let (ret_style, ret_ty) = parse_ret_ty(p);
+    let (ret_style, ret_ty) = parse_ret_ty(p, vec::len(inputs.node));
     ret ast::ty_fn(proto, inputs.node, ret_ty, ret_style, constrs);
 }
 
@@ -437,7 +437,7 @@ fn parse_ty_postfix(orig_t: ast::ty_, p: parser, colons_before_params: bool)
     }
 }
 
-fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
+fn parse_ret_ty(p: parser, n_args: uint) -> (ast::ret_style, @ast::ty) {
     ret if eat(p, token::RARROW) {
         let lo = p.get_lo_pos();
         if eat(p, token::NOT) {
@@ -445,7 +445,20 @@ fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
         } else {
             let style = ast::return_val;
             if eat(p, token::BINOP(token::AND)) {
-                style = ast::return_ref(eat(p, token::NOT));
+                if n_args == 0u {
+                    p.fatal("can not return reference from argument-less fn");
+                }
+                let mut_root = eat(p, token::NOT), arg = 0u;
+                alt p.peek() {
+                  token::LIT_INT(val) { p.bump(); arg = val as uint; }
+                  _ { if n_args > 1u {
+                      p.fatal("must specify referenced parameter");
+                  } }
+                }
+                if arg >= n_args {
+                    p.fatal("referenced argument does not exist");
+                }
+                style = ast::return_ref(mut_root, arg);
             };
             (style, parse_ty(p, false))
         }
@@ -1734,7 +1747,7 @@ fn parse_fn_decl(p: parser, purity: ast::purity, il: ast::inlineness) ->
         p.bump();
         constrs = parse_constrs(bind parse_ty_constr(inputs.node, _), p);
     }
-    let (ret_style, ret_ty) = parse_ret_ty(p);
+    let (ret_style, ret_ty) = parse_ret_ty(p, vec::len(inputs.node));
     ret {inputs: inputs.node,
          output: ret_ty,
          purity: purity,