auto merge of #12244 : pcwalton/rust/deuniquevectorpatterns, r=pcwalton

Preparatory work for removing unique vectors from the language, which is
itself preparatory work for dynamically sized types.

r? @brson
This commit is contained in:
bors 2014-02-19 21:56:51 -08:00
commit 0cc8ba0c20
25 changed files with 229 additions and 198 deletions

View File

@ -315,12 +315,15 @@ pub fn opt_shard(maybestr: Option<~str>) -> Option<(uint,uint)> {
match maybestr {
None => None,
Some(s) => {
match s.split('.').to_owned_vec() {
[a, b] => match (from_str::<uint>(a), from_str::<uint>(b)) {
(Some(a), Some(b)) => Some((a,b)),
let vector = s.split('.').to_owned_vec();
if vector.len() == 2 {
match (from_str::<uint>(vector[0]),
from_str::<uint>(vector[1])) {
(Some(a), Some(b)) => Some((a, b)),
_ => None
},
_ => None
}
} else {
None
}
}
}

View File

@ -130,27 +130,25 @@ fn helper(input: libc::c_int, messages: Port<Req>) {
}
'outer: loop {
let timeout = match active {
let timeout = if active.len() == 0 {
// Empty array? no timeout (wait forever for the next request)
[] => ptr::null(),
[~Inner { target, .. }, ..] => {
let now = now();
// If this request has already expired, then signal it and go
// through another iteration
if target <= now {
signal(&mut active, &mut dead);
continue;
}
// The actual timeout listed in the requests array is an
// absolute date, so here we translate the absolute time to a
// relative time.
let tm = target - now;
timeout.tv_sec = (tm / 1000) as libc::time_t;
timeout.tv_usec = ((tm % 1000) * 1000) as libc::suseconds_t;
&timeout as *libc::timeval
ptr::null()
} else {
let now = now();
// If this request has already expired, then signal it and go
// through another iteration
if active[0].target <= now {
signal(&mut active, &mut dead);
continue;
}
// The actual timeout listed in the requests array is an
// absolute date, so here we translate the absolute time to a
// relative time.
let tm = active[0].target - now;
timeout.tv_sec = (tm / 1000) as libc::time_t;
timeout.tv_usec = ((tm % 1000) * 1000) as libc::suseconds_t;
&timeout as *libc::timeval
};
imp::fd_set(&mut set, input);

View File

@ -495,24 +495,23 @@ impl ToPrimitive for BigUint {
#[cfg(target_word_size = "32")]
#[inline]
fn to_u64(&self) -> Option<u64> {
match self.data {
[] => {
Some(0)
match self.data.len() {
0 => Some(0),
1 => Some(self.data[0] as u64),
2 => {
Some(BigDigit::to_uint(self.data[1], self.data[0]) as u64)
}
[n0] => {
Some(n0 as u64)
}
[n0, n1] => {
Some(BigDigit::to_uint(n1, n0) as u64)
}
[n0, n1, n2] => {
let n_lo = BigDigit::to_uint(n1, n0) as u64;
let n_hi = n2 as u64;
3 => {
let n_lo = BigDigit::to_uint(self.data[1], self.data[0]) as
u64;
let n_hi = self.data[2] as u64;
Some((n_hi << 32) + n_lo)
}
[n0, n1, n2, n3] => {
let n_lo = BigDigit::to_uint(n1, n0) as u64;
let n_hi = BigDigit::to_uint(n3, n2) as u64;
4 => {
let n_lo = BigDigit::to_uint(self.data[1], self.data[0])
as u64;
let n_hi = BigDigit::to_uint(self.data[3], self.data[2])
as u64;
Some((n_hi << 32) + n_lo)
}
_ => None
@ -522,16 +521,10 @@ impl ToPrimitive for BigUint {
#[cfg(target_word_size = "64")]
#[inline]
fn to_u64(&self) -> Option<u64> {
match self.data {
[] => {
Some(0)
}
[n0] => {
Some(n0 as u64)
}
[n0, n1] => {
Some(BigDigit::to_uint(n1, n0) as u64)
}
match self.data.len() {
0 => Some(0),
1 => Some(self.data[0] as u64),
2 => Some(BigDigit::to_uint(self.data[1], self.data[0]) as u64),
_ => None
}
}

View File

@ -1213,15 +1213,13 @@ fn check_unused_mut_pat(cx: &Context, p: &ast::Pat) {
ast::PatIdent(ast::BindByValue(ast::MutMutable),
ref path, _) if pat_util::pat_is_binding(cx.tcx.def_map, p)=> {
// `let mut _a = 1;` doesn't need a warning.
let initial_underscore = match path.segments {
[ast::PathSegment { identifier: id, .. }] => {
token::get_ident(id).get().starts_with("_")
}
_ => {
cx.tcx.sess.span_bug(p.span,
"mutable binding that doesn't \
consist of exactly one segment");
}
let initial_underscore = if path.segments.len() == 1 {
token::get_ident(path.segments[0].identifier).get()
.starts_with("_")
} else {
cx.tcx.sess.span_bug(p.span,
"mutable binding that doesn't consist \
of exactly one segment")
};
let used_mut_nodes = cx.tcx.used_mut_nodes.borrow();

View File

@ -603,7 +603,17 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
ty::ty_vec(mt, vstore) => {
let region_var = match vstore {
ty::vstore_slice(r) => r,
ty::vstore_uniq | ty::vstore_fixed(_) => {
ty::vstore_uniq => {
fcx.type_error_message(pat.span,
|_| {
~"unique vector patterns are no \
longer supported"
},
expected,
None);
default_region_var
}
ty::vstore_fixed(_) => {
default_region_var
}
};

View File

@ -3894,8 +3894,11 @@ pub fn ast_expr_vstore_to_vstore(fcx: @FnCtxt,
ast::ExprVstoreUniq => ty::vstore_uniq,
ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
match e.node {
ast::ExprLit(..) |
ast::ExprVec([], _) => {
ast::ExprLit(..) => {
// string literals and *empty slices* live in static memory
ty::vstore_slice(ty::ReStatic)
}
ast::ExprVec(ref elements, _) if elements.len() == 0 => {
// string literals and *empty slices* live in static memory
ty::vstore_slice(ty::ReStatic)
}

View File

@ -311,20 +311,19 @@ pub fn unindent(s: &str) -> ~str {
}
});
match lines {
[head, .. tail] => {
let mut unindented = ~[ head.trim() ];
unindented.push_all(tail.map(|&line| {
if line.is_whitespace() {
line
} else {
assert!(line.len() >= min_indent);
line.slice_from(min_indent)
}
}));
unindented.connect("\n")
}
[] => s.to_owned()
if lines.len() >= 1 {
let mut unindented = ~[ lines[0].trim() ];
unindented.push_all(lines.tail().map(|&line| {
if line.is_whitespace() {
line
} else {
assert!(line.len() >= min_indent);
line.slice_from(min_indent)
}
}));
unindented.connect("\n")
} else {
s.to_owned()
}
}

View File

@ -97,30 +97,27 @@ fn cs_clone(
name))
}
match *all_fields {
[FieldInfo { name: None, .. }, ..] => {
// enum-like
let subcalls = all_fields.map(subcall);
cx.expr_call_ident(trait_span, ctor_ident, subcalls)
},
_ => {
// struct-like
let fields = all_fields.map(|field| {
let ident = match field.name {
Some(i) => i,
None => cx.span_bug(trait_span,
format!("unnamed field in normal struct in `deriving({})`",
name))
};
cx.field_imm(field.span, ident, subcall(field))
});
if all_fields.len() >= 1 && all_fields[0].name.is_none() {
// enum-like
let subcalls = all_fields.map(subcall);
cx.expr_call_ident(trait_span, ctor_ident, subcalls)
} else {
// struct-like
let fields = all_fields.map(|field| {
let ident = match field.name {
Some(i) => i,
None => cx.span_bug(trait_span,
format!("unnamed field in normal struct in `deriving({})`",
name))
};
cx.field_imm(field.span, ident, subcall(field))
});
if fields.is_empty() {
// no fields, so construct like `None`
cx.expr_ident(trait_span, ctor_ident)
} else {
cx.expr_struct_ident(trait_span, ctor_ident, fields)
}
if fields.is_empty() {
// no fields, so construct like `None`
cx.expr_ident(trait_span, ctor_ident)
} else {
cx.expr_struct_ident(trait_span, ctor_ident, fields)
}
}
}

View File

@ -663,25 +663,26 @@ impl<'a> MethodDef<'a> {
}
// transpose raw_fields
let fields = match raw_fields {
[ref self_arg, .. rest] => {
self_arg.iter().enumerate().map(|(i, &(span, opt_id, field))| {
let other_fields = rest.map(|l| {
match &l[i] {
&(_, _, ex) => ex
}
});
FieldInfo {
span: span,
name: opt_id,
self_: field,
other: other_fields
let fields = if raw_fields.len() > 0 {
raw_fields[0].iter()
.enumerate()
.map(|(i, &(span, opt_id, field))| {
let other_fields = raw_fields.tail().map(|l| {
match &l[i] {
&(_, _, ex) => ex
}
}).collect()
}
[] => { cx.span_bug(trait_.span,
"no self arguments to non-static method \
in generic `deriving`") }
});
FieldInfo {
span: span,
name: opt_id,
self_: field,
other: other_fields
}
}).collect()
} else {
cx.span_bug(trait_.span,
"no self arguments to non-static method in generic \
`deriving`")
};
// body of the inner most destructuring match

View File

@ -54,7 +54,10 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt,
MetaNameValue(_, ref l) => {
cx.span_err(l.span, "unexpected value in `deriving`");
}
MetaWord(_) | MetaList(_, []) => {
MetaWord(_) => {
cx.span_warn(mitem.span, "empty trait list in `deriving`");
}
MetaList(_, ref titems) if titems.len() == 0 => {
cx.span_warn(mitem.span, "empty trait list in `deriving`");
}
MetaList(_, ref titems) => {

View File

@ -74,7 +74,8 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
// Getting harder... making the format string:
match *substr.fields {
// unit struct/nullary variant: no work necessary!
Struct([]) | EnumMatching(_, _, []) => {}
Struct(ref fields) if fields.len() == 0 => {}
EnumMatching(_, _, ref fields) if fields.len() == 0 => {}
Struct(ref fields) | EnumMatching(_, _, ref fields) => {
if fields[0].name.is_none() {

View File

@ -40,7 +40,7 @@ pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> base::MacResult {
let exprs = match get_exprs_from_tts(cx, sp, tts) {
Some([]) => {
Some(ref exprs) if exprs.len() == 0 => {
cx.span_err(sp, "env! takes 1 or 2 arguments");
return MacResult::dummy_expr(sp);
}

View File

@ -647,14 +647,10 @@ impl Visitor<()> for NewNameFinderContext {
&ast::Path {
global: false,
span: _,
segments: [
ast::PathSegment {
identifier: id,
lifetimes: _,
types: _
}
]
} => self.ident_accumulator.push(id),
segments: ref segments
} if segments.len() == 1 => {
self.ident_accumulator.push(segments[0].identifier)
}
// I believe these must be enums...
_ => ()
}
@ -1187,7 +1183,12 @@ foo_module!()
let bindings = name_finder.ident_accumulator;
let cxbinds: ~[&ast::Ident] =
bindings.iter().filter(|b| "xx" == token::get_ident(**b).get()).collect();
bindings.iter().filter(|b| {
let ident = token::get_ident(**b);
let string = ident.get();
"xx" == string
}).collect();
let cxbinds: &[&ast::Ident] = cxbinds;
let cxbind = match cxbinds {
[b] => b,
_ => fail!("expected just one binding for ext_cx")

View File

@ -363,40 +363,48 @@ mod test {
// check the token-tree-ization of macros
#[test] fn string_to_tts_macro () {
let tts = string_to_tts(~"macro_rules! zip (($a)=>($a))");
let tts: &[ast::TokenTree] = tts;
match tts {
[ast::TTTok(_,_),
ast::TTTok(_,token::NOT),
ast::TTTok(_,_),
ast::TTDelim(delim_elts)] =>
match *delim_elts {
[ast::TTTok(_,token::LPAREN),
ast::TTDelim(first_set),
ast::TTTok(_,token::FAT_ARROW),
ast::TTDelim(second_set),
ast::TTTok(_,token::RPAREN)] =>
match *first_set {
ast::TTDelim(delim_elts)] => {
let delim_elts: &[ast::TokenTree] = *delim_elts;
match delim_elts {
[ast::TTTok(_,token::LPAREN),
ast::TTTok(_,token::DOLLAR),
ast::TTTok(_,_),
ast::TTTok(_,token::RPAREN)] =>
match *second_set {
[ast::TTTok(_,token::LPAREN),
ast::TTTok(_,token::DOLLAR),
ast::TTTok(_,_),
ast::TTTok(_,token::RPAREN)] =>
assert_eq!("correct","correct"),
_ => assert_eq!("wrong 4","correct")
ast::TTDelim(first_set),
ast::TTTok(_,token::FAT_ARROW),
ast::TTDelim(second_set),
ast::TTTok(_,token::RPAREN)] => {
let first_set: &[ast::TokenTree] = *first_set;
match first_set {
[ast::TTTok(_,token::LPAREN),
ast::TTTok(_,token::DOLLAR),
ast::TTTok(_,_),
ast::TTTok(_,token::RPAREN)] => {
let second_set: &[ast::TokenTree] =
*second_set;
match second_set {
[ast::TTTok(_,token::LPAREN),
ast::TTTok(_,token::DOLLAR),
ast::TTTok(_,_),
ast::TTTok(_,token::RPAREN)] => {
assert_eq!("correct","correct")
}
_ => assert_eq!("wrong 4","correct")
}
},
_ => {
error!("failing value 3: {:?}",first_set);
assert_eq!("wrong 3","correct")
}
}
},
_ => {
error!("failing value 3: {:?}",first_set);
assert_eq!("wrong 3","correct")
error!("failing value 2: {:?}",delim_elts);
assert_eq!("wrong","correct");
}
},
_ => {
error!("failing value 2: {:?}",delim_elts);
assert_eq!("wrong","correct");
}
},
_ => {
error!("failing value: {:?}",tts);

View File

@ -81,7 +81,13 @@ impl<T> SmallVector<T> {
pub fn expect_one(self, err: &'static str) -> T {
match self {
One(v) => v,
Many([v]) => v,
Many(v) => {
if v.len() == 1 {
v.move_iter().next().unwrap()
} else {
fail!(err)
}
}
_ => fail!(err)
}
}

View File

@ -21,6 +21,7 @@ pub fn main() {
Foo { string: ~"bar" },
Foo { string: ~"baz" }
];
let x: &[Foo] = x;
match x {
[_, ..tail] => {
match tail {

View File

@ -10,8 +10,9 @@
fn a() -> &[int] {
let vec = ~[1, 2, 3, 4];
let vec: &[int] = vec; //~ ERROR does not live long enough
let tail = match vec {
[_, ..tail] => tail, //~ ERROR does not live long enough
[_, ..tail] => tail,
_ => fail!("a")
};
tail
@ -19,8 +20,9 @@ fn a() -> &[int] {
fn b() -> &[int] {
let vec = ~[1, 2, 3, 4];
let vec: &[int] = vec; //~ ERROR does not live long enough
let init = match vec {
[..init, _] => init, //~ ERROR does not live long enough
[..init, _] => init,
_ => fail!("b")
};
init
@ -28,8 +30,9 @@ fn b() -> &[int] {
fn c() -> &[int] {
let vec = ~[1, 2, 3, 4];
let vec: &[int] = vec; //~ ERROR does not live long enough
let slice = match vec {
[_, ..slice, _] => slice, //~ ERROR does not live long enough
[_, ..slice, _] => slice,
_ => fail!("c")
};
slice

View File

@ -10,7 +10,8 @@
fn a() {
let mut v = ~[1, 2, 3];
match v {
let vb: &mut [int] = v;
match vb {
[_a, ..tail] => {
v.push(tail[0] + tail[1]); //~ ERROR cannot borrow
}

View File

@ -9,17 +9,17 @@
// except according to those terms.
fn a() {
let mut vec = ~[~1, ~2, ~3];
let mut vec = [~1, ~2, ~3];
match vec {
[~ref _a] => {
[~ref _a, _, _] => {
vec[0] = ~4; //~ ERROR cannot assign
}
_ => fail!("foo")
}
}
fn b() {
let mut vec = ~[~1, ~2, ~3];
let vec: &mut [~int] = vec;
match vec {
[.._b] => {
vec[0] = ~4; //~ ERROR cannot assign
@ -29,6 +29,7 @@ fn b() {
fn c() {
let mut vec = ~[~1, ~2, ~3];
let vec: &mut [~int] = vec;
match vec {
[_a, .._b] => {
//~^ ERROR cannot move out
@ -41,27 +42,31 @@ fn c() {
}
_ => {}
}
let a = vec[0]; //~ ERROR use of partially moved value: `vec`
let a = vec[0]; //~ ERROR cannot move out
}
fn d() {
let mut vec = ~[~1, ~2, ~3];
let vec: &mut [~int] = vec;
match vec {
[.._a, _b] => {
//~^ ERROR cannot move out
}
_ => {}
}
let a = vec[0]; //~ ERROR use of partially moved value: `vec`
let a = vec[0]; //~ ERROR cannot move out
}
fn e() {
let mut vec = ~[~1, ~2, ~3];
let vec: &mut [~int] = vec;
match vec {
[_a, _b, _c] => {}
[_a, _b, _c] => {} //~ ERROR cannot move out
//~^ ERROR cannot move out
//~^^ ERROR cannot move out
_ => {}
}
let a = vec[0]; //~ ERROR use of partially moved value: `vec`
let a = vec[0]; //~ ERROR cannot move out
}
fn main() {}

View File

@ -10,8 +10,9 @@
fn a() -> &int {
let vec = ~[1, 2, 3, 4];
let vec: &[int] = vec; //~ ERROR `vec[..]` does not live long enough
let tail = match vec {
[_a, ..tail] => &tail[0], //~ ERROR `vec[..]` does not live long enough
[_a, ..tail] => &tail[0],
_ => fail!("foo")
};
tail

View File

@ -10,19 +10,24 @@
fn main() {
let x: ~[(int, int)] = ~[];
let x: &[(int, int)] = x;
match x {
[a, (2, 3), _] => (),
[(1, 2), (2, 3), b] => (), //~ ERROR unreachable pattern
_ => ()
}
match ~[~"foo", ~"bar", ~"baz"] {
let x: ~[~str] = ~[~"foo", ~"bar", ~"baz"];
let x: &[~str] = x;
match x {
[a, _, _, ..] => { println!("{}", a); }
[~"foo", ~"bar", ~"baz", ~"foo", ~"bar"] => { } //~ ERROR unreachable pattern
_ => { }
}
match ~['a', 'b', 'c'] {
let x: ~[char] = ~['a', 'b', 'c'];
let x: &[char] = x;
match x {
['a', 'b', 'c', .._tail] => {}
['a', 'b', 'c'] => {} //~ ERROR unreachable pattern
_ => {}

View File

@ -35,23 +35,31 @@ fn main() {
(_, a) => {}
(b, b) => {}
}
match ~[Some(42), None, Some(21)] {
let vec = ~[Some(42), None, Some(21)];
let vec: &[Option<int>] = vec;
match vec {
//~^ ERROR non-exhaustive patterns: vectors of length 0 not covered
[Some(..), None, ..tail] => {}
[Some(..), Some(..), ..tail] => {}
[None] => {}
}
match ~[1] {
let vec = ~[1];
let vec: &[int] = vec;
match vec {
[_, ..tail] => (),
[] => ()
}
match ~[0.5] { //~ ERROR non-exhaustive patterns: vectors of length 4 not covered
let vec = ~[0.5];
let vec: &[f32] = vec;
match vec { //~ ERROR non-exhaustive patterns: vectors of length 4 not covered
[0.1, 0.2, 0.3] => (),
[0.1, 0.2] => (),
[0.1] => (),
[] => ()
}
match ~[Some(42), None, Some(21)] {
let vec = ~[Some(42), None, Some(21)];
let vec: &[Option<int>] = vec;
match vec {
[Some(..), None, ..tail] => {}
[Some(..), Some(..), ..tail] => {}
[None, None, ..tail] => {}

View File

@ -9,24 +9,22 @@
// except according to those terms.
pub fn main() {
let x = ~[1, 2, 3];
let x = [1, 2, 3];
match x {
[2, ..] => fail!(),
[1, ..tail] => {
assert_eq!(tail, [2, 3]);
[2, _, _] => fail!(),
[1, a, b] => {
assert_eq!([a, b], [2, 3]);
}
[_] => fail!(),
[] => fail!()
[_, _, _] => fail!(),
}
let y = (~[(1, true), (2, false)], 0.5);
let y = ([(1, true), (2, false)], 0.5);
match y {
([_, _, _], 0.5) => fail!(),
([(1, a), (b, false), ..tail], _) => {
([(1, a), (b, false)], _) => {
assert_eq!(a, true);
assert_eq!(b, 2);
assert!(tail.is_empty());
}
([.._tail], _) => fail!()
([_, _], 0.5) => fail!(),
([_, _], _) => fail!(),
}
}

View File

@ -9,28 +9,22 @@
// except according to those terms.
fn a() {
let x = ~[1];
let x = [1];
match x {
[_, _, _, _, _, ..] => fail!(),
[.., _, _, _, _] => fail!(),
[_, .., _, _] => fail!(),
[_, _] => fail!(),
[a] => {
assert_eq!(a, 1);
}
[] => fail!()
}
}
fn b() {
let x = ~[1, 2, 3];
let x = [1, 2, 3];
match x {
[a, b, ..c] => {
assert_eq!(a, 1);
assert_eq!(b, 2);
assert_eq!(c, &[3]);
}
_ => fail!()
}
match x {
[..a, b, c] => {
@ -38,7 +32,6 @@ fn b() {
assert_eq!(b, 2);
assert_eq!(c, 3);
}
_ => fail!()
}
match x {
[a, ..b, c] => {
@ -46,7 +39,6 @@ fn b() {
assert_eq!(b, &[2]);
assert_eq!(c, 3);
}
_ => fail!()
}
match x {
[a, b, c] => {
@ -54,7 +46,6 @@ fn b() {
assert_eq!(b, 2);
assert_eq!(c, 3);
}
_ => fail!()
}
}

View File

@ -14,7 +14,7 @@ struct Foo {
}
pub fn main() {
let x = ~[
let x = [
Foo { string: ~"foo" },
Foo { string: ~"bar" },
Foo { string: ~"baz" }
@ -39,8 +39,5 @@ pub fn main() {
}
}
}
_ => {
unreachable!();
}
}
}