Skip to content

Commit a6a5c48

Browse files
committed
make ref x bindings produce region ptrs and fix various minor bugs
we now detect inconsistent modes, binding names, and various other errors. typeck/trans integration is mostly done. borrowck not so much. more tests needed.
1 parent ecaf9e3 commit a6a5c48

File tree

19 files changed

+339
-176
lines changed

19 files changed

+339
-176
lines changed

src/libsyntax/ast.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,8 @@ type field_pat = {ident: ident, pat: @pat};
148148
#[auto_serialize]
149149
enum binding_mode {
150150
bind_by_value,
151-
bind_by_ref
151+
bind_by_ref(ast::mutability),
152+
bind_by_implicit_ref
152153
}
153154

154155
#[auto_serialize]

src/libsyntax/ext/auto_serialize.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,9 @@ impl helpers of ext_ctxt_helpers for ext_ctxt {
228228
let path = @{span: span, global: false, idents: ~[nm],
229229
rp: none, types: ~[]};
230230
@{id: self.next_id(),
231-
node: ast::pat_ident(ast::bind_by_ref, path, none),
231+
node: ast::pat_ident(ast::bind_by_implicit_ref,
232+
path,
233+
none),
232234
span: span}
233235
}
234236

@@ -834,7 +836,7 @@ fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: ast::ident,
834836
// Generate pattern var(v1, v2, v3)
835837
|pats| {
836838
if vec::is_empty(pats) {
837-
ast::pat_ident(ast::bind_by_ref,
839+
ast::pat_ident(ast::bind_by_implicit_ref,
838840
cx.path(v_span, ~[v_name]),
839841
none)
840842
} else {

src/libsyntax/ext/pipes/ast_builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt {
116116
@{node: {is_mutbl: false,
117117
ty: self.ty_infer(),
118118
pat: @{id: self.next_id(),
119-
node: ast::pat_ident(ast::bind_by_ref,
119+
node: ast::pat_ident(ast::bind_by_implicit_ref,
120120
path(ident,
121121
self.empty_span()),
122122
none),

src/libsyntax/parse/parser.rs

Lines changed: 85 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed,
1616
import dvec::{dvec, extensions};
1717
import vec::{push};
1818
import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
19-
bind_by_ref, bind_by_value, bitand, bitor, bitxor, blk,
19+
bind_by_ref, bind_by_implicit_ref, bind_by_value,
20+
bitand, bitor, bitxor, blk,
2021
blk_check_mode, bound_const, bound_copy, bound_send, bound_trait,
2122
bound_owned, box, by_copy, by_move, by_mutbl_ref, by_ref, by_val,
2223
capture_clause, capture_item, cdir_dir_mod, cdir_src_mod,
@@ -1718,7 +1719,9 @@ class parser {
17181719
} else {
17191720
subpat = @{
17201721
id: self.get_id(),
1721-
node: pat_ident(bind_by_ref, fieldpath, none),
1722+
node: pat_ident(bind_by_implicit_ref,
1723+
fieldpath,
1724+
none),
17221725
span: mk_sp(lo, hi)
17231726
};
17241727
}
@@ -1749,88 +1752,101 @@ class parser {
17491752
}
17501753
}
17511754
tok => {
1752-
if !is_ident_or_path(tok) ||
1753-
self.is_keyword(~"true") || self.is_keyword(~"false") {
1755+
if !is_ident_or_path(tok)
1756+
|| self.is_keyword(~"true")
1757+
|| self.is_keyword(~"false")
1758+
{
17541759
let val = self.parse_expr_res(RESTRICT_NO_BAR_OP);
17551760
if self.eat_keyword(~"to") {
17561761
let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
1757-
hi = end.span.hi;
17581762
pat = pat_range(val, end);
17591763
} else {
1760-
hi = val.span.hi;
17611764
pat = pat_lit(val);
17621765
}
1766+
} else if self.eat_keyword(~"ref") {
1767+
let mutbl = self.parse_mutability();
1768+
pat = self.parse_pat_ident(refutable, bind_by_ref(mutbl));
1769+
} else if self.eat_keyword(~"copy") {
1770+
pat = self.parse_pat_ident(refutable, bind_by_value);
1771+
} else if !is_plain_ident(self.token) {
1772+
pat = self.parse_enum_variant(refutable);
17631773
} else {
1764-
let binding_mode;
1765-
if self.eat_keyword(~"ref") {
1766-
binding_mode = bind_by_ref;
1767-
} else if self.eat_keyword(~"copy") {
1768-
binding_mode = bind_by_value;
1769-
} else if refutable {
1770-
// XXX: Should be bind_by_value, but that's not
1771-
// backward compatible.
1772-
binding_mode = bind_by_ref;
1773-
} else {
1774-
binding_mode = bind_by_value;
1775-
}
1776-
1777-
if is_plain_ident(self.token) &&
1778-
match self.look_ahead(1) {
1779-
token::LPAREN | token::LBRACKET | token::LT => {
1780-
false
1781-
}
1782-
_ => {
1783-
true
1784-
}
1785-
} {
1786-
let name = self.parse_value_path();
1787-
let sub = if self.eat(token::AT) {
1788-
some(self.parse_pat(refutable))
1789-
}
1790-
else { none };
1791-
pat = pat_ident(binding_mode, name, sub);
1792-
} else {
1793-
let enum_path = self.parse_path_with_tps(true);
1794-
hi = enum_path.span.hi;
1795-
let mut args: ~[@pat] = ~[];
1796-
let mut star_pat = false;
1797-
match self.token {
1798-
token::LPAREN => match self.look_ahead(1u) {
1799-
token::BINOP(token::STAR) => {
1800-
// This is a "top constructor only" pat
1801-
self.bump(); self.bump();
1802-
star_pat = true;
1803-
self.expect(token::RPAREN);
1804-
}
1805-
_ => {
1806-
args = self.parse_unspanned_seq(
1807-
token::LPAREN, token::RPAREN,
1808-
seq_sep_trailing_disallowed(token::COMMA),
1809-
|p| p.parse_pat(refutable));
1810-
hi = self.span.hi;
1811-
}
1812-
}
1813-
_ => ()
1814-
}
1815-
// at this point, we're not sure whether it's a enum or a
1816-
// bind
1817-
if star_pat {
1818-
pat = pat_enum(enum_path, none);
1819-
}
1820-
else if vec::is_empty(args) &&
1821-
vec::len(enum_path.idents) == 1u {
1822-
pat = pat_ident(binding_mode, enum_path, none);
1823-
}
1824-
else {
1825-
pat = pat_enum(enum_path, some(args));
1826-
}
1774+
// this is a plain identifier, like `x` or `x(...)`
1775+
match self.look_ahead(1) {
1776+
token::LPAREN | token::LBRACKET | token::LT => {
1777+
pat = self.parse_enum_variant(refutable);
1778+
}
1779+
_ => {
1780+
let binding_mode = if refutable {
1781+
// XXX: Should be bind_by_value, but that's not
1782+
// backward compatible.
1783+
bind_by_implicit_ref
1784+
} else {
1785+
bind_by_value
1786+
};
1787+
pat = self.parse_pat_ident(refutable, binding_mode);
1788+
}
18271789
}
18281790
}
1791+
hi = self.span.hi;
18291792
}
18301793
}
18311794
return @{id: self.get_id(), node: pat, span: mk_sp(lo, hi)};
18321795
}
18331796

1797+
fn parse_pat_ident(refutable: bool,
1798+
binding_mode: ast::binding_mode) -> ast::pat_ {
1799+
if !is_plain_ident(self.token) {
1800+
self.span_fatal(
1801+
copy self.last_span,
1802+
~"expected identifier, found path");
1803+
}
1804+
let name = self.parse_value_path();
1805+
let sub = if self.eat(token::AT) {
1806+
some(self.parse_pat(refutable))
1807+
} else { none };
1808+
1809+
// just to be friendly, if they write something like
1810+
// ref some(i)
1811+
// we end up here with ( as the current token. This shortly
1812+
// leads to a parse error. Note that if there is no explicit
1813+
// binding mode then we do not end up here, because the lookahead
1814+
// will direct us over to parse_enum_variant()
1815+
if self.token == token::LPAREN {
1816+
self.span_fatal(
1817+
copy self.last_span,
1818+
~"expected identifier, found enum pattern");
1819+
}
1820+
1821+
pat_ident(binding_mode, name, sub)
1822+
}
1823+
1824+
fn parse_enum_variant(refutable: bool) -> ast::pat_ {
1825+
let enum_path = self.parse_path_with_tps(true);
1826+
match self.token {
1827+
token::LPAREN => {
1828+
match self.look_ahead(1u) {
1829+
token::BINOP(token::STAR) => { // foo(*)
1830+
self.expect(token::LPAREN);
1831+
self.expect(token::BINOP(token::STAR));
1832+
self.expect(token::RPAREN);
1833+
pat_enum(enum_path, none)
1834+
}
1835+
_ => { // foo(a, ..., z)
1836+
let args = self.parse_unspanned_seq(
1837+
token::LPAREN, token::RPAREN,
1838+
seq_sep_trailing_disallowed(token::COMMA),
1839+
|p| p.parse_pat(refutable));
1840+
pat_enum(enum_path, some(args))
1841+
}
1842+
}
1843+
}
1844+
_ => { // option::none
1845+
pat_enum(enum_path, some(~[]))
1846+
}
1847+
}
1848+
}
1849+
18341850
fn parse_local(is_mutbl: bool,
18351851
allow_init: bool) -> @local {
18361852
let lo = self.span.lo;

src/libsyntax/print/pprust.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,8 +1332,12 @@ fn print_pat(s: ps, &&pat: @ast::pat) {
13321332
ast::pat_wild => word(s.s, ~"_"),
13331333
ast::pat_ident(binding_mode, path, sub) => {
13341334
match binding_mode {
1335-
ast::bind_by_ref => word_space(s, ~"ref"),
1336-
ast::bind_by_value => ()
1335+
ast::bind_by_ref(mutbl) => {
1336+
word_nbsp(s, ~"ref");
1337+
print_mutability(s, mutbl);
1338+
}
1339+
ast::bind_by_implicit_ref |
1340+
ast::bind_by_value => {}
13371341
}
13381342
print_path(s, path, true);
13391343
match sub {

src/rustc/middle/borrowck/categorization.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,15 +264,17 @@ impl public_methods for borrowck_ctxt {
264264
mutbl:m, ty:expr_ty}
265265
}
266266

267-
ast::def_binding(vid, ast::bind_by_value) => {
268-
// by-value bindings are basically local variables
267+
ast::def_binding(vid, ast::bind_by_value) |
268+
ast::def_binding(vid, ast::bind_by_ref(_)) => {
269+
// by-value/by-ref bindings are local variables
269270
@{id:id, span:span,
270271
cat:cat_local(vid), lp:some(@lp_local(vid)),
271272
mutbl:m_imm, ty:expr_ty}
272273
}
273274

274-
ast::def_binding(pid, ast::bind_by_ref) => {
275-
// bindings are "special" since they are implicit pointers.
275+
ast::def_binding(pid, ast::bind_by_implicit_ref) => {
276+
// implicit-by-ref bindings are "special" since they are
277+
// implicit pointers.
276278

277279
// lookup the mutability for this binding that we found in
278280
// gather_loans when we categorized it

src/rustc/middle/liveness.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ fn add_class_fields(self: @ir_maps, did: def_id) {
404404

405405
fn visit_local(local: @local, &&self: @ir_maps, vt: vt<@ir_maps>) {
406406
let def_map = self.tcx.def_map;
407-
do pat_util::pat_bindings(def_map, local.node.pat) |p_id, sp, path| {
407+
do pat_util::pat_bindings(def_map, local.node.pat) |_bm, p_id, sp, path| {
408408
debug!{"adding local variable %d", p_id};
409409
let name = ast_util::path_to_ident(path);
410410
(*self).add_live_node_for_node(p_id, lnk_vdef(sp));
@@ -587,7 +587,7 @@ class liveness {
587587

588588
fn pat_bindings(pat: @pat, f: fn(live_node, variable, span)) {
589589
let def_map = self.tcx.def_map;
590-
do pat_util::pat_bindings(def_map, pat) |p_id, sp, _n| {
590+
do pat_util::pat_bindings(def_map, pat) |_bm, p_id, sp, _n| {
591591
let ln = self.live_node(p_id, sp);
592592
let var = self.variable(p_id, sp);
593593
f(ln, var, sp);

src/rustc/middle/pat_util.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type pat_id_map = std::map::hashmap<ident, node_id>;
1515
// use the node_id of their namesake in the first pattern.
1616
fn pat_id_map(dm: resolve3::DefMap, pat: @pat) -> pat_id_map {
1717
let map = std::map::box_str_hash();
18-
do pat_bindings(dm, pat) |p_id, _s, n| {
18+
do pat_bindings(dm, pat) |_bm, p_id, _s, n| {
1919
map.insert(path_to_ident(n), p_id);
2020
};
2121
return map;
@@ -33,11 +33,11 @@ fn pat_is_variant(dm: resolve3::DefMap, pat: @pat) -> bool {
3333
}
3434

3535
fn pat_bindings(dm: resolve3::DefMap, pat: @pat,
36-
it: fn(node_id, span, @path)) {
36+
it: fn(binding_mode, node_id, span, @path)) {
3737
do walk_pat(pat) |p| {
3838
match p.node {
39-
pat_ident(_, pth, _) if !pat_is_variant(dm, p) => {
40-
it(p.id, p.span, pth);
39+
pat_ident(binding_mode, pth, _) if !pat_is_variant(dm, p) => {
40+
it(binding_mode, p.id, p.span, pth);
4141
}
4242
_ => {}
4343
}
@@ -46,6 +46,6 @@ fn pat_bindings(dm: resolve3::DefMap, pat: @pat,
4646

4747
fn pat_binding_ids(dm: resolve3::DefMap, pat: @pat) -> ~[node_id] {
4848
let mut found = ~[];
49-
pat_bindings(dm, pat, |b_id, _sp, _pt| vec::push(found, b_id) );
49+
pat_bindings(dm, pat, |_bm, b_id, _sp, _pt| vec::push(found, b_id) );
5050
return found;
5151
}

0 commit comments

Comments
 (0)