auto merge of #5002 : catamorphism/rust/one-tuples, r=graydon
r? @graydon - This is for greater uniformity (for example, macros that generate tuples). rustc already supported 1-tuple patterns, but there was no way to construct a 1-tuple term. @graydon , as far as your comment on #4898 - it did turn out to be solvable inside the macro (since @luqmana already fixed it using structs instead), but I still think it's a good idea to allow 1-tuples, for uniformity. I don't think anyone is likely to trip over it, and I'm not too worried that it changes the amount of ambiguity.
This commit is contained in:
commit
f68335113b
6 changed files with 69 additions and 11 deletions
|
@ -43,6 +43,8 @@ impl ToStr for @str {
|
||||||
pure fn to_str(&self) -> ~str { ::str::from_slice(*self) }
|
pure fn to_str(&self) -> ~str { ::str::from_slice(*self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME #4898: impl for one-tuples
|
||||||
|
|
||||||
impl<A: ToStr, B: ToStr> ToStr for (A, B) {
|
impl<A: ToStr, B: ToStr> ToStr for (A, B) {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pure fn to_str(&self) -> ~str {
|
pure fn to_str(&self) -> ~str {
|
||||||
|
|
|
@ -111,6 +111,8 @@ impl<A: Copy, B: Copy> ExtendedTupleOps<A,B> for (~[A], ~[B]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME #4898: impl for one-tuples
|
||||||
|
|
||||||
#[cfg(notest)]
|
#[cfg(notest)]
|
||||||
impl<A: Eq, B: Eq> Eq for (A, B) {
|
impl<A: Eq, B: Eq> Eq for (A, B) {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
|
@ -576,12 +576,21 @@ pub impl Parser {
|
||||||
self.bump();
|
self.bump();
|
||||||
ty_nil
|
ty_nil
|
||||||
} else {
|
} else {
|
||||||
|
// (t) is a parenthesized ty
|
||||||
|
// (t,) is the type of a tuple with only one field,
|
||||||
|
// of type t
|
||||||
let mut ts = ~[self.parse_ty(false)];
|
let mut ts = ~[self.parse_ty(false)];
|
||||||
|
let mut one_tuple = false;
|
||||||
while self.token == token::COMMA {
|
while self.token == token::COMMA {
|
||||||
self.bump();
|
self.bump();
|
||||||
ts.push(self.parse_ty(false));
|
if self.token != token::RPAREN {
|
||||||
|
ts.push(self.parse_ty(false));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
one_tuple = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let t = if vec::len(ts) == 1u { ts[0].node }
|
let t = if ts.len() == 1 && !one_tuple { ts[0].node }
|
||||||
else { ty_tup(ts) };
|
else { ty_tup(ts) };
|
||||||
self.expect(token::RPAREN);
|
self.expect(token::RPAREN);
|
||||||
t
|
t
|
||||||
|
@ -1061,6 +1070,9 @@ pub impl Parser {
|
||||||
|
|
||||||
if self.token == token::LPAREN {
|
if self.token == token::LPAREN {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
// (e) is parenthesized e
|
||||||
|
// (e,) is a tuple with only one field, e
|
||||||
|
let mut one_tuple = false;
|
||||||
if self.token == token::RPAREN {
|
if self.token == token::RPAREN {
|
||||||
hi = self.span.hi;
|
hi = self.span.hi;
|
||||||
self.bump();
|
self.bump();
|
||||||
|
@ -1069,12 +1081,18 @@ pub impl Parser {
|
||||||
}
|
}
|
||||||
let mut es = ~[self.parse_expr()];
|
let mut es = ~[self.parse_expr()];
|
||||||
while self.token == token::COMMA {
|
while self.token == token::COMMA {
|
||||||
self.bump(); es.push(self.parse_expr());
|
self.bump();
|
||||||
|
if self.token != token::RPAREN {
|
||||||
|
es.push(self.parse_expr());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
one_tuple = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
hi = self.span.hi;
|
hi = self.span.hi;
|
||||||
self.expect(token::RPAREN);
|
self.expect(token::RPAREN);
|
||||||
|
|
||||||
return if es.len() == 1 {
|
return if es.len() == 1 && !one_tuple {
|
||||||
self.mk_expr(lo, self.span.hi, expr_paren(es[0]))
|
self.mk_expr(lo, self.span.hi, expr_paren(es[0]))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2158,11 +2176,13 @@ pub impl Parser {
|
||||||
pat = pat_lit(expr);
|
pat = pat_lit(expr);
|
||||||
} else {
|
} else {
|
||||||
let mut fields = ~[self.parse_pat(refutable)];
|
let mut fields = ~[self.parse_pat(refutable)];
|
||||||
while self.token == token::COMMA {
|
if self.look_ahead(1) != token::RPAREN {
|
||||||
self.bump();
|
while self.token == token::COMMA {
|
||||||
fields.push(self.parse_pat(refutable));
|
self.bump();
|
||||||
|
fields.push(self.parse_pat(refutable));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if vec::len(fields) == 1u { self.expect(token::COMMA); }
|
if fields.len() == 1 { self.expect(token::COMMA); }
|
||||||
hi = self.span.hi;
|
hi = self.span.hi;
|
||||||
self.expect(token::RPAREN);
|
self.expect(token::RPAREN);
|
||||||
pat = pat_tup(fields);
|
pat = pat_tup(fields);
|
||||||
|
|
|
@ -414,6 +414,9 @@ pub fn print_type_ex(s: @ps, &&ty: @ast::Ty, print_colons: bool) {
|
||||||
ast::ty_tup(elts) => {
|
ast::ty_tup(elts) => {
|
||||||
popen(s);
|
popen(s);
|
||||||
commasep(s, inconsistent, elts, print_type);
|
commasep(s, inconsistent, elts, print_type);
|
||||||
|
if elts.len() == 1 {
|
||||||
|
word(s.s, ~",");
|
||||||
|
}
|
||||||
pclose(s);
|
pclose(s);
|
||||||
}
|
}
|
||||||
ast::ty_bare_fn(f) => {
|
ast::ty_bare_fn(f) => {
|
||||||
|
@ -1199,6 +1202,9 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
|
||||||
ast::expr_tup(exprs) => {
|
ast::expr_tup(exprs) => {
|
||||||
popen(s);
|
popen(s);
|
||||||
commasep_exprs(s, inconsistent, exprs);
|
commasep_exprs(s, inconsistent, exprs);
|
||||||
|
if exprs.len() == 1 {
|
||||||
|
word(s.s, ~",");
|
||||||
|
}
|
||||||
pclose(s);
|
pclose(s);
|
||||||
}
|
}
|
||||||
ast::expr_call(func, args, sugar) => {
|
ast::expr_call(func, args, sugar) => {
|
||||||
|
@ -1634,6 +1640,9 @@ pub fn print_pat(s: @ps, &&pat: @ast::pat, refutable: bool) {
|
||||||
ast::pat_tup(elts) => {
|
ast::pat_tup(elts) => {
|
||||||
popen(s);
|
popen(s);
|
||||||
commasep(s, inconsistent, elts, |s, p| print_pat(s, p, refutable));
|
commasep(s, inconsistent, elts, |s, p| print_pat(s, p, refutable));
|
||||||
|
if elts.len() == 1 {
|
||||||
|
word(s.s, ~",");
|
||||||
|
}
|
||||||
pclose(s);
|
pclose(s);
|
||||||
}
|
}
|
||||||
ast::pat_box(inner) => {
|
ast::pat_box(inner) => {
|
||||||
|
|
24
src/test/run-pass/one-tuple.rs
Normal file
24
src/test/run-pass/one-tuple.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Why one-tuples? Because macros.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match ('c',) {
|
||||||
|
(x,) => {
|
||||||
|
assert x == 'c';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// test the 1-tuple type too
|
||||||
|
let x: (char,) = ('d',);
|
||||||
|
let (y,) = x;
|
||||||
|
assert y == 'd';
|
||||||
|
}
|
||||||
|
|
|
@ -636,11 +636,12 @@ struct Triple { x: int, y: int, z: int }
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let r = (1,2,3,true,false, Triple {x:5,y:4,z:3});
|
let r = (1,2,3,true,false, Triple {x:5,y:4,z:3}, (12,));
|
||||||
let p = ptr::addr_of(&r) as *c_void;
|
let p = ptr::addr_of(&r) as *c_void;
|
||||||
let u = my_visitor(@Stuff {mut ptr1: p,
|
let u = my_visitor(@Stuff {mut ptr1: p,
|
||||||
mut ptr2: p,
|
mut ptr2: p,
|
||||||
mut vals: ~[]});
|
mut vals: ~[]
|
||||||
|
});
|
||||||
let v = ptr_visit_adaptor(Inner {inner: u});
|
let v = ptr_visit_adaptor(Inner {inner: u});
|
||||||
let td = get_tydesc_for(r);
|
let td = get_tydesc_for(r);
|
||||||
unsafe { error!("tydesc sz: %u, align: %u",
|
unsafe { error!("tydesc sz: %u, align: %u",
|
||||||
|
@ -653,7 +654,7 @@ pub fn main() {
|
||||||
}
|
}
|
||||||
error!("%?", copy u.vals);
|
error!("%?", copy u.vals);
|
||||||
assert u.vals == ~[
|
assert u.vals == ~[
|
||||||
~"1", ~"2", ~"3", ~"true", ~"false", ~"5", ~"4", ~"3"
|
~"1", ~"2", ~"3", ~"true", ~"false", ~"5", ~"4", ~"3", ~"12"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue