rustc: Implement "mutable?". Add a test case and XFAIL it in rustboot for now.
This commit is contained in:
@@ -456,6 +456,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \
|
|||||||
test/run-pass/iter-ret.rs \
|
test/run-pass/iter-ret.rs \
|
||||||
test/run-pass/leak-tag-copy.rs \
|
test/run-pass/leak-tag-copy.rs \
|
||||||
test/run-pass/lib-io.rs \
|
test/run-pass/lib-io.rs \
|
||||||
|
test/run-pass/maybe-mutable.rs \
|
||||||
test/run-pass/mlist-cycle.rs \
|
test/run-pass/mlist-cycle.rs \
|
||||||
test/run-pass/obj-as.rs \
|
test/run-pass/obj-as.rs \
|
||||||
test/run-pass/seq-compare.rs \
|
test/run-pass/seq-compare.rs \
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ tag pat_ {
|
|||||||
tag mutability {
|
tag mutability {
|
||||||
mut;
|
mut;
|
||||||
imm;
|
imm;
|
||||||
|
maybe_mut;
|
||||||
}
|
}
|
||||||
|
|
||||||
tag opacity {
|
tag opacity {
|
||||||
|
|||||||
@@ -615,6 +615,10 @@ impure fn parse_path(parser p, greed g) -> ast.path {
|
|||||||
impure fn parse_mutability(parser p) -> ast.mutability {
|
impure fn parse_mutability(parser p) -> ast.mutability {
|
||||||
if (p.peek() == token.MUTABLE) {
|
if (p.peek() == token.MUTABLE) {
|
||||||
p.bump();
|
p.bump();
|
||||||
|
if (p.peek() == token.QUES) {
|
||||||
|
p.bump();
|
||||||
|
ret ast.maybe_mut;
|
||||||
|
}
|
||||||
ret ast.mut;
|
ret ast.mut;
|
||||||
}
|
}
|
||||||
ret ast.imm;
|
ret ast.imm;
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ fn ty_to_str(&@t typ) -> str {
|
|||||||
alt (m.mut) {
|
alt (m.mut) {
|
||||||
case (ast.mut) { mstr = "mutable "; }
|
case (ast.mut) { mstr = "mutable "; }
|
||||||
case (ast.imm) { mstr = ""; }
|
case (ast.imm) { mstr = ""; }
|
||||||
|
case (ast.maybe_mut) { mstr = "mutable? "; }
|
||||||
}
|
}
|
||||||
|
|
||||||
ret mstr + ty_to_str(m.ty);
|
ret mstr + ty_to_str(m.ty);
|
||||||
@@ -858,6 +859,21 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
ret ures_err(terr_mismatch, expected, actual);
|
ret ures_err(terr_mismatch, expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unifies two mutability flags.
|
||||||
|
fn unify_mut(ast.mutability expected, ast.mutability actual)
|
||||||
|
-> option.t[ast.mutability] {
|
||||||
|
if (expected == actual) {
|
||||||
|
ret some[ast.mutability](expected);
|
||||||
|
}
|
||||||
|
if (expected == ast.maybe_mut) {
|
||||||
|
ret some[ast.mutability](actual);
|
||||||
|
}
|
||||||
|
if (actual == ast.maybe_mut) {
|
||||||
|
ret some[ast.mutability](expected);
|
||||||
|
}
|
||||||
|
ret none[ast.mutability];
|
||||||
|
}
|
||||||
|
|
||||||
tag fn_common_res {
|
tag fn_common_res {
|
||||||
fn_common_res_err(unify_result);
|
fn_common_res_err(unify_result);
|
||||||
fn_common_res_ok(vec[arg], @t);
|
fn_common_res_ok(vec[arg], @t);
|
||||||
@@ -1158,10 +1174,14 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
case (ty.ty_box(?expected_mt)) {
|
case (ty.ty_box(?expected_mt)) {
|
||||||
alt (actual.struct) {
|
alt (actual.struct) {
|
||||||
case (ty.ty_box(?actual_mt)) {
|
case (ty.ty_box(?actual_mt)) {
|
||||||
if (expected_mt.mut != actual_mt.mut) {
|
auto mut;
|
||||||
|
alt (unify_mut(expected_mt.mut, actual_mt.mut)) {
|
||||||
|
case (none[ast.mutability]) {
|
||||||
ret ures_err(terr_box_mutability, expected,
|
ret ures_err(terr_box_mutability, expected,
|
||||||
actual);
|
actual);
|
||||||
}
|
}
|
||||||
|
case (some[ast.mutability](?m)) { mut = m; }
|
||||||
|
}
|
||||||
|
|
||||||
auto result = unify_step(bindings,
|
auto result = unify_step(bindings,
|
||||||
expected_mt.ty,
|
expected_mt.ty,
|
||||||
@@ -1169,8 +1189,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
handler);
|
handler);
|
||||||
alt (result) {
|
alt (result) {
|
||||||
case (ures_ok(?result_sub)) {
|
case (ures_ok(?result_sub)) {
|
||||||
auto mt = rec(ty=result_sub,
|
auto mt = rec(ty=result_sub, mut=mut);
|
||||||
mut=expected_mt.mut);
|
|
||||||
ret ures_ok(plain_ty(ty.ty_box(mt)));
|
ret ures_ok(plain_ty(ty.ty_box(mt)));
|
||||||
}
|
}
|
||||||
case (_) {
|
case (_) {
|
||||||
@@ -1188,10 +1207,14 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
case (ty.ty_vec(?expected_mt)) {
|
case (ty.ty_vec(?expected_mt)) {
|
||||||
alt (actual.struct) {
|
alt (actual.struct) {
|
||||||
case (ty.ty_vec(?actual_mt)) {
|
case (ty.ty_vec(?actual_mt)) {
|
||||||
if (expected_mt.mut != actual_mt.mut) {
|
auto mut;
|
||||||
|
alt (unify_mut(expected_mt.mut, actual_mt.mut)) {
|
||||||
|
case (none[ast.mutability]) {
|
||||||
ret ures_err(terr_vec_mutability, expected,
|
ret ures_err(terr_vec_mutability, expected,
|
||||||
actual);
|
actual);
|
||||||
}
|
}
|
||||||
|
case (some[ast.mutability](?m)) { mut = m; }
|
||||||
|
}
|
||||||
|
|
||||||
auto result = unify_step(bindings,
|
auto result = unify_step(bindings,
|
||||||
expected_mt.ty,
|
expected_mt.ty,
|
||||||
@@ -1199,8 +1222,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
handler);
|
handler);
|
||||||
alt (result) {
|
alt (result) {
|
||||||
case (ures_ok(?result_sub)) {
|
case (ures_ok(?result_sub)) {
|
||||||
auto mt = rec(ty=result_sub,
|
auto mt = rec(ty=result_sub, mut=mut);
|
||||||
mut=expected_mt.mut);
|
|
||||||
ret ures_ok(plain_ty(ty.ty_vec(mt)));
|
ret ures_ok(plain_ty(ty.ty_vec(mt)));
|
||||||
}
|
}
|
||||||
case (_) {
|
case (_) {
|
||||||
@@ -1279,10 +1301,16 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
while (i < expected_len) {
|
while (i < expected_len) {
|
||||||
auto expected_elem = expected_elems.(i);
|
auto expected_elem = expected_elems.(i);
|
||||||
auto actual_elem = actual_elems.(i);
|
auto actual_elem = actual_elems.(i);
|
||||||
if (expected_elem.mut != actual_elem.mut) {
|
|
||||||
|
auto mut;
|
||||||
|
alt (unify_mut(expected_elem.mut,
|
||||||
|
actual_elem.mut)) {
|
||||||
|
case (none[ast.mutability]) {
|
||||||
auto err = terr_tuple_mutability;
|
auto err = terr_tuple_mutability;
|
||||||
ret ures_err(err, expected, actual);
|
ret ures_err(err, expected, actual);
|
||||||
}
|
}
|
||||||
|
case (some[ast.mutability](?m)) { mut = m; }
|
||||||
|
}
|
||||||
|
|
||||||
auto result = unify_step(bindings,
|
auto result = unify_step(bindings,
|
||||||
expected_elem.ty,
|
expected_elem.ty,
|
||||||
@@ -1290,8 +1318,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
handler);
|
handler);
|
||||||
alt (result) {
|
alt (result) {
|
||||||
case (ures_ok(?rty)) {
|
case (ures_ok(?rty)) {
|
||||||
auto mt = rec(ty=rty,
|
auto mt = rec(ty=rty, mut=mut);
|
||||||
mut=expected_elem.mut);
|
|
||||||
result_elems += vec(mt);
|
result_elems += vec(mt);
|
||||||
}
|
}
|
||||||
case (_) {
|
case (_) {
|
||||||
@@ -1329,10 +1356,15 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
while (i < expected_len) {
|
while (i < expected_len) {
|
||||||
auto expected_field = expected_fields.(i);
|
auto expected_field = expected_fields.(i);
|
||||||
auto actual_field = actual_fields.(i);
|
auto actual_field = actual_fields.(i);
|
||||||
if (expected_field.mt.mut
|
|
||||||
!= actual_field.mt.mut) {
|
auto mut;
|
||||||
auto err = terr_record_mutability;
|
alt (unify_mut(expected_field.mt.mut,
|
||||||
ret ures_err(err, expected, actual);
|
actual_field.mt.mut)) {
|
||||||
|
case (none[ast.mutability]) {
|
||||||
|
ret ures_err(terr_record_mutability,
|
||||||
|
expected, actual);
|
||||||
|
}
|
||||||
|
case (some[ast.mutability](?m)) { mut = m; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_str.eq(expected_field.ident,
|
if (!_str.eq(expected_field.ident,
|
||||||
@@ -1349,8 +1381,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
handler);
|
handler);
|
||||||
alt (result) {
|
alt (result) {
|
||||||
case (ures_ok(?rty)) {
|
case (ures_ok(?rty)) {
|
||||||
auto mt = rec(ty=rty,
|
auto mt = rec(ty=rty, mut=mut);
|
||||||
mut=expected_field.mt.mut);
|
|
||||||
_vec.push[field]
|
_vec.push[field]
|
||||||
(result_fields,
|
(result_fields,
|
||||||
rec(mt=mt with expected_field));
|
rec(mt=mt with expected_field));
|
||||||
@@ -1490,6 +1521,12 @@ fn type_err_to_str(&ty.type_err err) -> str {
|
|||||||
case (terr_mismatch) {
|
case (terr_mismatch) {
|
||||||
ret "types differ";
|
ret "types differ";
|
||||||
}
|
}
|
||||||
|
case (terr_box_mutability) {
|
||||||
|
ret "boxed values differ in mutability";
|
||||||
|
}
|
||||||
|
case (terr_vec_mutability) {
|
||||||
|
ret "vectors differ in mutability";
|
||||||
|
}
|
||||||
case (terr_tuple_size(?e_sz, ?a_sz)) {
|
case (terr_tuple_size(?e_sz, ?a_sz)) {
|
||||||
ret "expected a tuple with " + _uint.to_str(e_sz, 10u) +
|
ret "expected a tuple with " + _uint.to_str(e_sz, 10u) +
|
||||||
" elements but found one with " + _uint.to_str(a_sz, 10u) +
|
" elements but found one with " + _uint.to_str(a_sz, 10u) +
|
||||||
|
|||||||
@@ -58,8 +58,10 @@ impure fn commasep[IN](ps s, vec[IN] elts, impure fn (ps, &IN) op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impure fn print_mt(ps s, &ast.mt mt) {
|
impure fn print_mt(ps s, &ast.mt mt) {
|
||||||
if (mt.mut == ast.mut) {
|
alt (mt.mut) {
|
||||||
wrd1(s, "mutable");
|
case (ast.mut) { wrd1(s, "mutable"); }
|
||||||
|
case (ast.maybe_mut) { wrd1(s, "mutable?"); }
|
||||||
|
case (ast.imm) { /* nothing */ }
|
||||||
}
|
}
|
||||||
print_type(s, mt.ty);
|
print_type(s, mt.ty);
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/test/run-pass/maybe-mutable.rs
Normal file
17
src/test/run-pass/maybe-mutable.rs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// -*- rust -*-
|
||||||
|
|
||||||
|
fn len(vec[mutable? int] v) -> uint {
|
||||||
|
auto i = 0u;
|
||||||
|
for (int x in v) {
|
||||||
|
i += 1u;
|
||||||
|
}
|
||||||
|
ret i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
auto v0 = vec(1, 2, 3, 4, 5);
|
||||||
|
log len(v0);
|
||||||
|
auto v1 = vec(mutable 1, 2, 3, 4, 5);
|
||||||
|
log len(v1);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user