diff --git a/Makefile.in b/Makefile.in index b657ad6a6883..df9cb78ef8f1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -421,9 +421,9 @@ else TSREQS := \ $(foreach target,$(CFG_TARGET_TRIPLES), \ $(SREQ3_T_$(target)_H_$(CFG_HOST_TRIPLE))) -FUZZ := $(HBIN3_H_$(CFG_HOST_TRIPLE))/fuzzer$(X) -CARGO := $(HBIN3_H_$(CFG_HOST_TRIPLE))/cargo$(X) -RUSTDOC := $(HBIN3_H_$(CFG_HOST_TRIPLE))/rustdoc$(X) +FUZZ := $(HBIN2_H_$(CFG_HOST_TRIPLE))/fuzzer$(X) +CARGO := $(HBIN2_H_$(CFG_HOST_TRIPLE))/cargo$(X) +RUSTDOC := $(HBIN2_H_$(CFG_HOST_TRIPLE))/rustdoc$(X) all: rustc $(GENERATED) docs $(FUZZ) $(CARGO) $(RUSTDOC) diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs index eee76f24ec2c..ff099f3d007a 100644 --- a/src/cargo/cargo.rs +++ b/src/cargo/cargo.rs @@ -332,7 +332,7 @@ fn try_parse_sources(filename: str, sources: map::hashmap) { } } -fn load_one_source_package(&src: source, p: map::hashmap) { +fn load_one_source_package(&&src: source, p: map::hashmap) { let name = alt p.find("name") { some(json::string(_n)) { _n } _ { @@ -404,8 +404,8 @@ fn load_one_source_package(&src: source, p: map::hashmap) { log(debug, " loaded package: " + src.name + "/" + name); } -fn load_source_packages(&c: cargo, &src: source) { - log(debug, "loading source: " + src.name); +fn load_source_packages(&&c: cargo, &&src: source) { + log(debug, "Loading source: " + src.name); let dir = path::connect(c.sourcedir, src.name); let pkgfile = path::connect(dir, "packages.json"); if !os::path_exists(pkgfile) { ret; } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs new file mode 100644 index 000000000000..aea97cf1649f --- /dev/null +++ b/src/libcore/cmp.rs @@ -0,0 +1,10 @@ +#[doc="Interfaces used for comparison."] + +iface ord { + fn lt(&&other: self) -> bool; +} + +iface eq { + fn eq(&&other: self) -> bool; +} + diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 6b4c7ad7d3ca..efcd424024a1 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -44,6 +44,7 @@ export extfmt; export tuple; export to_str; export dvec, dvec_iter; +export cmp; // NDM seems to be necessary for resolve to work export option_iter; @@ -152,6 +153,7 @@ mod tuple; // Ubiquitous-utility-type modules +mod cmp; mod either; mod iter; mod logging; diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs index c7a31b39ad59..ccaab58553f7 100644 --- a/src/libcore/dvec.rs +++ b/src/libcore/dvec.rs @@ -57,6 +57,11 @@ fn dvec() -> dvec { {mut data: [mut]} } +#[doc = "Creates a new dvec with a single element"] +fn from_elt(+e: A) -> dvec { + {mut data: [mut e]} +} + #[doc = "Creates a new dvec with the contents of a vector"] fn from_vec(+v: [mut A]) -> dvec { {mut data: v} @@ -234,7 +239,9 @@ impl extensions for dvec { self.data[idx] = a; } - #[doc = "Overwrites the contents of the element at `idx` with `a`"] + #[doc = "Overwrites the contents of the element at `idx` with `a`, + growing the vector if necessary. New elements will be initialized + with `initval`"] fn grow_set_elt(idx: uint, initval: A, val: A) { self.swap { |v| let mut v <- v; @@ -242,4 +249,9 @@ impl extensions for dvec { v } } + + #[doc = "Returns the last element, failing if the vector is empty"] + fn last() -> A { + self.get_elt(self.len() - 1u) + } } \ No newline at end of file diff --git a/src/libcore/future.rs b/src/libcore/future.rs index e0321b452878..6152b83536a8 100644 --- a/src/libcore/future.rs +++ b/src/libcore/future.rs @@ -108,7 +108,7 @@ fn get(future: future) -> A { fn with(future: future, blk: fn(A) -> B) -> B { #[doc = "Work with the value without copying it"]; - let v = alt future.v { + let v = alt copy future.v { either::left(v) { v } either::right(f) { let v = @f(); diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs index 156724cb0617..4011ac1a18a7 100644 --- a/src/libcore/int-template.rs +++ b/src/libcore/int-template.rs @@ -1,4 +1,5 @@ import T = inst::T; +import cmp::{eq, ord}; export min_value, max_value; export min, max; @@ -10,6 +11,7 @@ export range; export compl; export abs; export parse_buf, from_str, to_str, to_str_bytes, str; +export ord, eq; const min_value: T = -1 as T << (inst::bits - 1 as T); const max_value: T = min_value - 1 as T; @@ -108,6 +110,18 @@ fn to_str_bytes(n: T, radix: uint, f: fn([u8]/&) -> U) -> U { #[doc = "Convert to a string"] fn str(i: T) -> str { ret to_str(i, 10u); } +impl ord of ord for T { + fn lt(&&other: T) -> bool { + ret self < other; + } +} + +impl eq of eq for T { + fn eq(&&other: T) -> bool { + ret self == other; + } +} + // FIXME: Has alignment issues on windows and 32-bit linux #[test] diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 02371ea7625d..b18be417019b 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -613,7 +613,7 @@ impl of writer for mem_buffer { // FIXME #2004--use memcpy here? let mut pos = self.pos, vpos = 0u; while vpos < vlen && pos < buf_len { - self.buf.set_elt(pos, v[vpos]); + self.buf.set_elt(pos, copy v[vpos]); pos += 1u; vpos += 1u; } diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index 26cf00bbcd10..71bd1025d1db 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -218,7 +218,7 @@ impl extensions for rng { } #[doc = "Shuffle a mutable vec in place"] - fn shuffle_mut(&values: [mut T]) { + fn shuffle_mut(&&values: [mut T]) { let mut i = values.len(); while i >= 2u { // invariant: elements with index >= i have been locked in place. diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 7f967ae373d7..6c24b6569884 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -122,7 +122,7 @@ Convert a vector of bytes to a UTF-8 string Fails if invalid UTF-8 "] -fn from_bytes(vv: [u8]) -> str unsafe { +pure fn from_bytes(vv: [u8]) -> str unsafe { assert is_utf8(vv); ret unsafe::from_bytes(vv); } @@ -134,7 +134,7 @@ Convert a byte to a UTF-8 string Fails if invalid UTF-8 "] -fn from_byte(b: u8) -> str unsafe { +pure fn from_byte(b: u8) -> str unsafe { assert b < 128u8; let mut v = [b, 0u8]; let s: str = ::unsafe::reinterpret_cast(v); @@ -217,22 +217,24 @@ fn push_char(&s: str, ch: char) unsafe { } #[doc = "Convert a char to a string"] -fn from_char(ch: char) -> str { +pure fn from_char(ch: char) -> str { let mut buf = ""; - push_char(buf, ch); + unchecked { push_char(buf, ch); } ret buf; } #[doc = "Convert a vector of chars to a string"] -fn from_chars(chs: [char]) -> str { +pure fn from_chars(chs: [char]) -> str { let mut buf = ""; - reserve(buf, chs.len()); - for vec::each(chs) {|ch| push_char(buf, ch); } + unchecked { + reserve(buf, chs.len()); + for vec::each(chs) {|ch| push_char(buf, ch); } + } ret buf; } #[doc = "Concatenate a vector of strings"] -fn concat(v: [str]) -> str { +pure fn concat(v: [str]) -> str { let mut s: str = ""; for vec::each(v) {|ss| s += ss; } ret s; @@ -241,7 +243,7 @@ fn concat(v: [str]) -> str { #[doc = " Concatenate a vector of strings, placing a given separator between each "] -fn connect(v: [str], sep: str) -> str { +pure fn connect(v: [str], sep: str) -> str { let mut s = "", first = true; for vec::each(v) {|ss| if first { first = false; } else { s += sep; } @@ -286,7 +288,7 @@ fn shift_char(&s: str) -> char unsafe { fn unshift_char(&s: str, ch: char) { s = from_char(ch) + s; } #[doc = "Returns a string with leading whitespace removed"] -fn trim_left(+s: str) -> str { +pure fn trim_left(+s: str) -> str { alt find(s, {|c| !char::is_whitespace(c)}) { none { "" } some(first) { @@ -297,7 +299,7 @@ fn trim_left(+s: str) -> str { } #[doc = "Returns a string with trailing whitespace removed"] -fn trim_right(+s: str) -> str { +pure fn trim_right(+s: str) -> str { alt rfind(s, {|c| !char::is_whitespace(c)}) { none { "" } some(last) { @@ -309,7 +311,7 @@ fn trim_right(+s: str) -> str { } #[doc = "Returns a string with leading and trailing whitespace removed"] -fn trim(+s: str) -> str { trim_left(trim_right(s)) } +pure fn trim(+s: str) -> str { trim_left(trim_right(s)) } /* Section: Transforming strings @@ -320,7 +322,7 @@ Converts a string to a vector of bytes The result vector is not null-terminated. "] -fn bytes(s: str) -> [u8] unsafe { +pure fn bytes(s: str) -> [u8] unsafe { let mut s_copy = s; let mut v: [u8] = ::unsafe::reinterpret_cast(s_copy); ::unsafe::forget(s_copy); @@ -332,14 +334,14 @@ fn bytes(s: str) -> [u8] unsafe { Work with the string as a byte slice, not including trailing null. "] #[inline(always)] -fn byte_slice(s: str/&, f: fn([u8]/&) -> T) -> T unsafe { +pure fn byte_slice(s: str/&, f: fn([u8]/&) -> T) -> T unsafe { unpack_slice(s) {|p,n| vec::unsafe::form_slice(p, n-1u, f) } } #[doc = "Convert a string to a vector of characters"] -fn chars(s: str) -> [char] { +pure fn chars(s: str) -> [char] { let mut buf = [], i = 0u; let len = len(s); while i < len { @@ -356,7 +358,7 @@ Take a substring of another. Returns a string containing `n` characters starting at byte offset `begin`. "] -fn substr(s: str, begin: uint, n: uint) -> str { +pure fn substr(s: str, begin: uint, n: uint) -> str { slice(s, begin, begin + count_bytes(s, begin, n)) } @@ -366,7 +368,7 @@ Returns a slice of the given string from the byte range [`begin`..`end`) Fails when `begin` and `end` do not point to valid characters or beyond the last character of the string "] -fn slice(s: str, begin: uint, end: uint) -> str unsafe { +pure fn slice(s: str, begin: uint, end: uint) -> str unsafe { assert is_char_boundary(s, begin); assert is_char_boundary(s, end); unsafe::slice_bytes(s, begin, end) @@ -375,7 +377,7 @@ fn slice(s: str, begin: uint, end: uint) -> str unsafe { #[doc = " Splits a string into substrings at each occurrence of a given character "] -fn split_char(s: str, sep: char) -> [str] { +pure fn split_char(s: str, sep: char) -> [str] { split_char_inner(s, sep, len(s), true) } @@ -385,18 +387,18 @@ character up to 'count' times The byte must be a valid UTF-8/ASCII byte "] -fn splitn_char(s: str, sep: char, count: uint) -> [str] { +pure fn splitn_char(s: str, sep: char, count: uint) -> [str] { split_char_inner(s, sep, count, true) } #[doc = " Like `split_char`, but omits empty strings from the returned vector "] -fn split_char_nonempty(s: str, sep: char) -> [str] { +pure fn split_char_nonempty(s: str, sep: char) -> [str] { split_char_inner(s, sep, len(s), false) } -fn split_char_inner(s: str, sep: char, count: uint, allow_empty: bool) +pure fn split_char_inner(s: str, sep: char, count: uint, allow_empty: bool) -> [str] unsafe { if sep < 128u as char { let b = sep as u8, l = len(s); @@ -423,7 +425,7 @@ fn split_char_inner(s: str, sep: char, count: uint, allow_empty: bool) #[doc = "Splits a string into substrings using a character function"] -fn split(s: str, sepfn: fn(char) -> bool) -> [str] { +pure fn split(s: str, sepfn: fn(char) -> bool) -> [str] { split_inner(s, sepfn, len(s), true) } @@ -431,16 +433,16 @@ fn split(s: str, sepfn: fn(char) -> bool) -> [str] { Splits a string into substrings using a character function, cutting at most `count` times. "] -fn splitn(s: str, sepfn: fn(char) -> bool, count: uint) -> [str] { +pure fn splitn(s: str, sepfn: fn(char) -> bool, count: uint) -> [str] { split_inner(s, sepfn, count, true) } #[doc = "Like `split`, but omits empty strings from the returned vector"] -fn split_nonempty(s: str, sepfn: fn(char) -> bool) -> [str] { +pure fn split_nonempty(s: str, sepfn: fn(char) -> bool) -> [str] { split_inner(s, sepfn, len(s), false) } -fn split_inner(s: str, sepfn: fn(cc: char) -> bool, count: uint, +pure fn split_inner(s: str, sepfn: fn(cc: char) -> bool, count: uint, allow_empty: bool) -> [str] unsafe { let l = len(s); let mut result = [], i = 0u, start = 0u, done = 0u; @@ -462,7 +464,7 @@ fn split_inner(s: str, sepfn: fn(cc: char) -> bool, count: uint, } // See Issue #1932 for why this is a naive search -fn iter_matches(s: str, sep: str, f: fn(uint, uint)) { +pure fn iter_matches(s: str, sep: str, f: fn(uint, uint)) { let sep_len = len(sep), l = len(s); assert sep_len > 0u; let mut i = 0u, match_start = 0u, match_i = 0u; @@ -489,7 +491,7 @@ fn iter_matches(s: str, sep: str, f: fn(uint, uint)) { } } -fn iter_between_matches(s: str, sep: str, f: fn(uint, uint)) { +pure fn iter_between_matches(s: str, sep: str, f: fn(uint, uint)) { let mut last_end = 0u; iter_matches(s, sep) {|from, to| f(last_end, from); @@ -507,7 +509,7 @@ Splits a string into a vector of the substrings separated by a given string assert [\"\", \"XXX\", \"YYY\", \"\"] == split_str(\".XXX.YYY.\", \".\") ~~~ "] -fn split_str(s: str, sep: str) -> [str] { +pure fn split_str(s: str, sep: str) -> [str] { let mut result = []; iter_between_matches(s, sep) {|from, to| unsafe { result += [unsafe::slice_bytes(s, from, to)]; } @@ -515,7 +517,7 @@ fn split_str(s: str, sep: str) -> [str] { result } -fn split_str_nonempty(s: str, sep: str) -> [str] { +pure fn split_str_nonempty(s: str, sep: str) -> [str] { let mut result = []; iter_between_matches(s, sep) {|from, to| if to > from { @@ -528,13 +530,13 @@ fn split_str_nonempty(s: str, sep: str) -> [str] { #[doc = " Splits a string into a vector of the substrings separated by LF ('\\n') "] -fn lines(s: str) -> [str] { split_char(s, '\n') } +pure fn lines(s: str) -> [str] { split_char(s, '\n') } #[doc = " Splits a string into a vector of the substrings separated by LF ('\\n') and/or CR LF ('\\r\\n') "] -fn lines_any(s: str) -> [str] { +pure fn lines_any(s: str) -> [str] { vec::map(lines(s), {|s| let l = len(s); let mut cp = s; @@ -548,18 +550,22 @@ fn lines_any(s: str) -> [str] { #[doc = " Splits a string into a vector of the substrings separated by whitespace "] -fn words(s: str) -> [str] { +pure fn words(s: str) -> [str] { split_nonempty(s, {|c| char::is_whitespace(c)}) } #[doc = "Convert a string to lowercase. ASCII only"] -fn to_lower(s: str) -> str { - map(s, {|c| (libc::tolower(c as libc::c_char)) as char}) +pure fn to_lower(s: str) -> str { + map(s, {|c| + unchecked{(libc::tolower(c as libc::c_char)) as char} + }) } #[doc = "Convert a string to uppercase. ASCII only"] -fn to_upper(s: str) -> str { - map(s, {|c| (libc::toupper(c as libc::c_char)) as char}) +pure fn to_upper(s: str) -> str { + map(s, {|c| + unchecked{(libc::toupper(c as libc::c_char)) as char} + }) } #[doc = " @@ -575,7 +581,7 @@ Replace all occurances of one string with another The original string with all occurances of `from` replaced with `to` "] -fn replace(s: str, from: str, to: str) -> str unsafe { +pure fn replace(s: str, from: str, to: str) -> str unsafe { let mut result = "", first = true; iter_between_matches(s, from) {|start, end| if first { first = false; } else { result += to; } @@ -595,7 +601,7 @@ pure fn eq(&&a: str, &&b: str) -> bool { a == b } pure fn le(&&a: str, &&b: str) -> bool { a <= b } #[doc = "String hash function"] -fn hash(&&s: str) -> uint { +pure fn hash(&&s: str) -> uint { // djb hash. // FIXME: replace with murmur. (see #859 and #1616) let mut u: uint = 5381u; @@ -611,7 +617,7 @@ Section: Iterating through strings Return true if a predicate matches all characters or if the string contains no characters "] -fn all(s: str, it: fn(char) -> bool) -> bool { +pure fn all(s: str, it: fn(char) -> bool) -> bool { all_between(s, 0u, len(s), it) } @@ -619,20 +625,24 @@ fn all(s: str, it: fn(char) -> bool) -> bool { Return true if a predicate matches any character (and false if it matches none or there are no characters) "] -fn any(ss: str, pred: fn(char) -> bool) -> bool { +pure fn any(ss: str, pred: fn(char) -> bool) -> bool { !all(ss, {|cc| !pred(cc)}) } #[doc = "Apply a function to each character"] -fn map(ss: str, ff: fn(char) -> char) -> str { +pure fn map(ss: str, ff: fn(char) -> char) -> str { let mut result = ""; - reserve(result, len(ss)); - chars_iter(ss) {|cc| str::push_char(result, ff(cc));} + unchecked { + reserve(result, len(ss)); + chars_iter(ss) {|cc| + str::push_char(result, ff(cc)); + } + } result } #[doc = "Iterate over the bytes in a string"] -fn bytes_iter(ss: str, it: fn(u8)) { +pure fn bytes_iter(ss: str, it: fn(u8)) { let mut pos = 0u; let len = len(ss); @@ -644,7 +654,7 @@ fn bytes_iter(ss: str, it: fn(u8)) { #[doc = "Iterate over the bytes in a string"] #[inline(always)] -fn each(s: str, it: fn(u8) -> bool) { +pure fn each(s: str, it: fn(u8) -> bool) { let mut i = 0u, l = len(s); while (i < l) { if !it(s[i]) { break; } @@ -654,7 +664,7 @@ fn each(s: str, it: fn(u8) -> bool) { #[doc = "Iterates over the chars in a string"] #[inline(always)] -fn each_char(s: str, it: fn(char) -> bool) { +pure fn each_char(s: str, it: fn(char) -> bool) { let mut pos = 0u; let len = len(s); while pos < len { @@ -665,7 +675,7 @@ fn each_char(s: str, it: fn(char) -> bool) { } #[doc = "Iterate over the characters in a string"] -fn chars_iter(s: str, it: fn(char)) { +pure fn chars_iter(s: str, it: fn(char)) { let mut pos = 0u; let len = len(s); while (pos < len) { @@ -678,7 +688,7 @@ fn chars_iter(s: str, it: fn(char)) { #[doc = " Apply a function to each substring after splitting by character "] -fn split_char_iter(ss: str, cc: char, ff: fn(&&str)) { +pure fn split_char_iter(ss: str, cc: char, ff: fn(&&str)) { vec::iter(split_char(ss, cc), ff) } @@ -686,17 +696,18 @@ fn split_char_iter(ss: str, cc: char, ff: fn(&&str)) { Apply a function to each substring after splitting by character, up to `count` times "] -fn splitn_char_iter(ss: str, sep: char, count: uint, ff: fn(&&str)) unsafe { +pure fn splitn_char_iter(ss: str, sep: char, count: uint, + ff: fn(&&str)) unsafe { vec::iter(splitn_char(ss, sep, count), ff) } #[doc = "Apply a function to each word"] -fn words_iter(ss: str, ff: fn(&&str)) { +pure fn words_iter(ss: str, ff: fn(&&str)) { vec::iter(words(ss), ff) } #[doc = "Apply a function to each line (by '\\n')"] -fn lines_iter(ss: str, ff: fn(&&str)) { +pure fn lines_iter(ss: str, ff: fn(&&str)) { vec::iter(lines(ss), ff) } @@ -717,7 +728,7 @@ Returns the byte index of the first matching character An `option` containing the byte index of the first matching character or `none` if there is no match "] -fn find_char(s: str, c: char) -> option { +pure fn find_char(s: str, c: char) -> option { find_char_between(s, c, 0u, len(s)) } @@ -741,7 +752,7 @@ or `none` if there is no match `start` must be less than or equal to `len(s)`. `start` must be the index of a character boundary, as defined by `is_char_boundary`. "] -fn find_char_from(s: str, c: char, start: uint) -> option { +pure fn find_char_from(s: str, c: char, start: uint) -> option { find_char_between(s, c, start, len(s)) } @@ -766,7 +777,7 @@ or `none` if there is no match or equal to `len(s)`. `start` must be the index of a character boundary, as defined by `is_char_boundary`. "] -fn find_char_between(s: str, c: char, start: uint, end: uint) +pure fn find_char_between(s: str, c: char, start: uint, end: uint) -> option { if c < 128u as char { assert start <= end; @@ -796,7 +807,7 @@ Returns the byte index of the last matching character An `option` containing the byte index of the last matching character or `none` if there is no match "] -fn rfind_char(s: str, c: char) -> option { +pure fn rfind_char(s: str, c: char) -> option { rfind_char_between(s, c, len(s), 0u) } @@ -820,7 +831,7 @@ or `none` if there is no match `start` must be less than or equal to `len(s)`. `start` must be the index of a character boundary, as defined by `is_char_boundary`. "] -fn rfind_char_from(s: str, c: char, start: uint) -> option { +pure fn rfind_char_from(s: str, c: char, start: uint) -> option { rfind_char_between(s, c, start, 0u) } @@ -845,7 +856,7 @@ or `none` if there is no match or equal to `len(s)`. `start` must be the index of a character boundary, as defined by `is_char_boundary`. "] -fn rfind_char_between(s: str, c: char, start: uint, end: uint) +pure fn rfind_char_between(s: str, c: char, start: uint, end: uint) -> option { if c < 128u as char { assert start >= end; @@ -876,7 +887,7 @@ the given predicate An `option` containing the byte index of the first matching character or `none` if there is no match "] -fn find(s: str, f: fn(char) -> bool) -> option { +pure fn find(s: str, f: fn(char) -> bool) -> option { find_between(s, 0u, len(s), f) } @@ -900,7 +911,7 @@ or `none` if there is no match `start` must be less than or equal to `len(s)`. `start` must be the index of a character boundary, as defined by `is_char_boundary`. "] -fn find_from(s: str, start: uint, f: fn(char) -> bool) -> option { +pure fn find_from(s: str, start: uint, f: fn(char) -> bool) -> option { find_between(s, start, len(s), f) } @@ -926,7 +937,7 @@ or `none` if there is no match or equal to `len(s)`. `start` must be the index of a character boundary, as defined by `is_char_boundary`. "] -fn find_between(s: str, start: uint, end: uint, f: fn(char) -> bool) +pure fn find_between(s: str, start: uint, end: uint, f: fn(char) -> bool) -> option { assert start <= end; assert end <= len(s); @@ -954,7 +965,7 @@ the given predicate An option containing the byte index of the last matching character or `none` if there is no match "] -fn rfind(s: str, f: fn(char) -> bool) -> option { +pure fn rfind(s: str, f: fn(char) -> bool) -> option { rfind_between(s, len(s), 0u, f) } @@ -978,7 +989,7 @@ or `none` if there is no match `start` must be less than or equal to `len(s)', `start` must be the index of a character boundary, as defined by `is_char_boundary` "] -fn rfind_from(s: str, start: uint, f: fn(char) -> bool) -> option { +pure fn rfind_from(s: str, start: uint, f: fn(char) -> bool) -> option { rfind_between(s, start, 0u, f) } @@ -1004,7 +1015,7 @@ or `none` if there is no match than or equal to `len(s)`. `start` must be the index of a character boundary, as defined by `is_char_boundary` "] -fn rfind_between(s: str, start: uint, end: uint, f: fn(char) -> bool) +pure fn rfind_between(s: str, start: uint, end: uint, f: fn(char) -> bool) -> option { assert start >= end; assert start <= len(s); @@ -1019,7 +1030,7 @@ fn rfind_between(s: str, start: uint, end: uint, f: fn(char) -> bool) } // Utility used by various searching functions -fn match_at(haystack: str, needle: str, at: uint) -> bool { +pure fn match_at(haystack: str, needle: str, at: uint) -> bool { let mut i = at; for each(needle) {|c| if haystack[i] != c { ret false; } i += 1u; } ret true; @@ -1038,7 +1049,7 @@ Returns the byte index of the first matching substring An `option` containing the byte index of the first matching substring or `none` if there is no match "] -fn find_str(haystack: str, needle: str) -> option { +pure fn find_str(haystack: str, needle: str) -> option { find_str_between(haystack, needle, 0u, len(haystack)) } @@ -1061,7 +1072,7 @@ or `none` if there is no match `start` must be less than or equal to `len(s)` "] -fn find_str_from(haystack: str, needle: str, start: uint) +pure fn find_str_from(haystack: str, needle: str, start: uint) -> option { find_str_between(haystack, needle, start, len(haystack)) } @@ -1086,7 +1097,7 @@ or `none` if there is no match `start` must be less than or equal to `end` and `end` must be less than or equal to `len(s)`. "] -fn find_str_between(haystack: str, needle: str, start: uint, end:uint) +pure fn find_str_between(haystack: str, needle: str, start: uint, end:uint) -> option { // See Issue #1932 for why this is a naive search assert end <= len(haystack); @@ -1111,7 +1122,7 @@ Returns true if one string contains another * haystack - The string to look in * needle - The string to look for "] -fn contains(haystack: str, needle: str) -> bool { +pure fn contains(haystack: str, needle: str) -> bool { option::is_some(find_str(haystack, needle)) } @@ -1123,7 +1134,7 @@ Returns true if one string starts with another * haystack - The string to look in * needle - The string to look for "] -fn starts_with(haystack: str, needle: str) -> bool unsafe { +pure fn starts_with(haystack: str, needle: str) -> bool unsafe { let haystack_len = len(haystack), needle_len = len(needle); if needle_len == 0u { true } else if needle_len > haystack_len { false } @@ -1138,7 +1149,7 @@ Returns true if one string ends with another * haystack - The string to look in * needle - The string to look for "] -fn ends_with(haystack: str, needle: str) -> bool { +pure fn ends_with(haystack: str, needle: str) -> bool { let haystack_len = len(haystack), needle_len = len(needle); if needle_len == 0u { true } else if needle_len > haystack_len { false } @@ -1150,7 +1161,7 @@ Section: String properties */ #[doc = "Determines if a string contains only ASCII characters"] -fn is_ascii(s: str) -> bool { +pure fn is_ascii(s: str) -> bool { let mut i: uint = len(s); while i > 0u { i -= 1u; if !u8::is_ascii(s[i]) { ret false; } } ret true; @@ -1167,7 +1178,7 @@ Returns true if the string contains only whitespace Whitespace characters are determined by `char::is_whitespace` "] -fn is_whitespace(s: str) -> bool { +pure fn is_whitespace(s: str) -> bool { ret all(s, char::is_whitespace); } @@ -1189,14 +1200,14 @@ pure fn len(s: str) -> uint unsafe { } #[doc = "Returns the number of characters that a string holds"] -fn char_len(s: str) -> uint { count_chars(s, 0u, len(s)) } +pure fn char_len(s: str) -> uint { count_chars(s, 0u, len(s)) } /* Section: Misc */ #[doc = "Determines if a vector of bytes contains valid UTF-8"] -fn is_utf8(v: [const u8]) -> bool { +pure fn is_utf8(v: [const u8]) -> bool { let mut i = 0u; let total = vec::len::(v); while i < total { @@ -1214,7 +1225,7 @@ fn is_utf8(v: [const u8]) -> bool { } #[doc = "Determines if a vector of `u16` contains valid UTF-16"] -fn is_utf16(v: [const u16]) -> bool { +pure fn is_utf16(v: [const u16]) -> bool { let len = vec::len(v); let mut i = 0u; while (i < len) { @@ -1235,7 +1246,7 @@ fn is_utf16(v: [const u16]) -> bool { } #[doc = "Converts to a vector of `u16` encoded as UTF-16"] -fn to_utf16(s: str) -> [u16] { +pure fn to_utf16(s: str) -> [u16] { let mut u = []; chars_iter(s) {|cch| // Arithmetic with u32 literals is easier on the eyes than chars. @@ -1257,7 +1268,7 @@ fn to_utf16(s: str) -> [u16] { ret u; } -fn utf16_chars(v: [const u16], f: fn(char)) { +pure fn utf16_chars(v: [const u16], f: fn(char)) { let len = vec::len(v); let mut i = 0u; while (i < len && v[i] != 0u16) { @@ -1282,10 +1293,12 @@ fn utf16_chars(v: [const u16], f: fn(char)) { } -fn from_utf16(v: [const u16]) -> str { +pure fn from_utf16(v: [const u16]) -> str { let mut buf = ""; - reserve(buf, vec::len(v)); - utf16_chars(v) {|ch| push_char(buf, ch); } + unchecked { + reserve(buf, vec::len(v)); + utf16_chars(v) {|ch| push_char(buf, ch); } + } ret buf; } @@ -1303,7 +1316,7 @@ As char_len but for a slice of a string The number of Unicode characters in `s` between the given indices. "] -fn count_chars(s: str, start: uint, end: uint) -> uint { +pure fn count_chars(s: str, start: uint, end: uint) -> uint { assert is_char_boundary(s, start); assert is_char_boundary(s, end); let mut i = start, len = 0u; @@ -1318,7 +1331,7 @@ fn count_chars(s: str, start: uint, end: uint) -> uint { #[doc = " Counts the number of bytes taken by the `n` in `s` starting from `start`. "] -fn count_bytes(s: str, start: uint, n: uint) -> uint { +pure fn count_bytes(s: str, start: uint, n: uint) -> uint { assert is_char_boundary(s, start); let mut end = start, cnt = n; let l = len(s); @@ -1403,7 +1416,7 @@ index of the next unicode character. If `i` is greater than or equal to the length of the string. If `i` is not the index of the beginning of a valid UTF-8 character. "] -fn char_range_at(s: str, i: uint) -> {ch: char, next: uint} { +pure fn char_range_at(s: str, i: uint) -> {ch: char, next: uint} { let b0 = s[i]; let w = utf8_char_width(b0); assert (w != 0u); @@ -1426,14 +1439,16 @@ fn char_range_at(s: str, i: uint) -> {ch: char, next: uint} { } #[doc = "Pluck a character out of a string"] -fn char_at(s: str, i: uint) -> char { ret char_range_at(s, i).ch; } +pure fn char_at(s: str, i: uint) -> char { ret char_range_at(s, i).ch; } #[doc = " Given a byte position and a str, return the previous char and its position This function can be used to iterate over a unicode string in reverse. "] -fn char_range_at_reverse(ss: str, start: uint) -> {ch: char, prev: uint} { +pure fn char_range_at_reverse(ss: str, start: uint) + -> {ch: char, prev: uint} { + let mut prev = start; // while there is a previous byte == 10...... @@ -1470,7 +1485,8 @@ Loop through a substring, char by char `true` If execution proceeded correctly, `false` if it was interrupted, that is if `it` returned `false` at any point. "] -fn all_between(s: str, start: uint, end: uint, it: fn(char) -> bool) -> bool { +pure fn all_between(s: str, start: uint, end: uint, + it: fn(char) -> bool) -> bool { assert is_char_boundary(s, start); let mut i = start; while i < end { @@ -1502,7 +1518,8 @@ Loop through a substring, char by char `true` if `it` returns `true` for any character "] -fn any_between(s: str, start: uint, end: uint, it: fn(char) -> bool) -> bool { +pure fn any_between(s: str, start: uint, end: uint, + it: fn(char) -> bool) -> bool { !all_between(s, start, end, {|c| !it(c)}) } @@ -1533,7 +1550,7 @@ interop. let i = str::as_bytes(\"Hello World\") { |bytes| vec::len(bytes) }; ~~~ "] -fn as_bytes(s: str, f: fn([u8]) -> T) -> T unsafe { +pure fn as_bytes(s: str, f: fn([u8]) -> T) -> T unsafe { let v: *[u8] = ::unsafe::reinterpret_cast(ptr::addr_of(s)); f(*v) } @@ -1544,7 +1561,7 @@ Work with the byte buffer of a string. Allows for unsafe manipulation of strings, which is useful for native interop. "] -fn as_buf(s: str, f: fn(*u8) -> T) -> T unsafe { +pure fn as_buf(s: str, f: fn(*u8) -> T) -> T unsafe { as_bytes(s) { |v| vec::as_buf(v, f) } } @@ -1560,7 +1577,7 @@ interop, without copying the original string. let s = str::as_buf(\"PATH\", { |path_buf| libc::getenv(path_buf) }); ~~~ "] -fn as_c_str(s: str, f: fn(*libc::c_char) -> T) -> T unsafe { +pure fn as_c_str(s: str, f: fn(*libc::c_char) -> T) -> T unsafe { as_buf(s) {|buf| f(buf as *libc::c_char) } } @@ -1574,7 +1591,7 @@ indexable area for a null byte, as is the case in slices pointing to full strings, or suffixes of them. "] #[inline(always)] -fn unpack_slice(s: str/&, f: fn(*u8, uint) -> T) -> T unsafe { +pure fn unpack_slice(s: str/&, f: fn(*u8, uint) -> T) -> T unsafe { let v : *(*u8,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s)); let (buf,len) = *v; f(buf, len) @@ -1639,18 +1656,22 @@ pure fn capacity(&&s: str) -> uint unsafe { } #[doc = "Escape each char in `s` with char::escape_default."] -fn escape_default(s: str) -> str { +pure fn escape_default(s: str) -> str { let mut out: str = ""; - reserve_at_least(out, str::len(s)); - chars_iter(s) {|c| out += char::escape_default(c); } + unchecked { + reserve_at_least(out, str::len(s)); + chars_iter(s) {|c| out += char::escape_default(c); } + } ret out; } #[doc = "Escape each char in `s` with char::escape_unicode."] -fn escape_unicode(s: str) -> str { +pure fn escape_unicode(s: str) -> str { let mut out: str = ""; - reserve_at_least(out, str::len(s)); - chars_iter(s) {|c| out += char::escape_unicode(c); } + unchecked { + reserve_at_least(out, str::len(s)); + chars_iter(s) {|c| out += char::escape_unicode(c); } + } ret out; } diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index 93f204cb58f5..e0fd21f6c4a1 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -17,9 +17,9 @@ enum type_desc = { #[abi = "cdecl"] native mod rustrt { - fn refcount(t: *()) -> libc::intptr_t; + pure fn refcount(t: *()) -> libc::intptr_t; fn unsupervise(); - fn shape_log_str(t: *sys::type_desc, data: *()) -> str; + pure fn shape_log_str(t: *sys::type_desc, data: *()) -> str; } #[abi = "rust-intrinsic"] @@ -36,13 +36,13 @@ Returns a pointer to a type descriptor. Useful for calling certain function in the Rust runtime or otherwise performing dark magick. "] -fn get_type_desc() -> *type_desc { - rusti::get_tydesc::() as *type_desc +pure fn get_type_desc() -> *type_desc { + unchecked { rusti::get_tydesc::() as *type_desc } } #[doc = "Returns the size of a type"] -fn size_of() -> uint unsafe { - rusti::size_of::() +pure fn size_of() -> uint unsafe { + unchecked { rusti::size_of::() } } #[doc = " @@ -51,23 +51,23 @@ Returns the ABI-required minimum alignment of a type This is the alignment used for struct fields. It may be smaller than the preferred alignment. "] -fn min_align_of() -> uint unsafe { - rusti::min_align_of::() +pure fn min_align_of() -> uint unsafe { + unchecked { rusti::min_align_of::() } } #[doc = "Returns the preferred alignment of a type"] -fn pref_align_of() -> uint unsafe { - rusti::pref_align_of::() +pure fn pref_align_of() -> uint unsafe { + unchecked { rusti::pref_align_of::() } } #[doc = "Returns the refcount of a shared box"] -fn refcount(t: @T) -> uint { +pure fn refcount(t: @T) -> uint { unsafe { ret rustrt::refcount(unsafe::reinterpret_cast(t)) as uint; } } -fn log_str(t: T) -> str { +pure fn log_str(t: T) -> str { unsafe { let data_ptr: *() = unsafe::reinterpret_cast(ptr::addr_of(t)); rustrt::shape_log_str(get_type_desc::(), data_ptr) diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs index a63d01e6e8e0..7126fb3d007d 100644 --- a/src/libcore/uint-template.rs +++ b/src/libcore/uint-template.rs @@ -1,4 +1,5 @@ import T = inst::T; +import cmp::{eq, ord}; export min_value, max_value; export min, max; @@ -10,6 +11,7 @@ export range; export compl; export to_str, to_str_bytes; export from_str, from_str_radix, str, parse_buf; +export ord, eq; const min_value: T = 0 as T; const max_value: T = 0 as T - 1 as T; @@ -49,6 +51,18 @@ pure fn compl(i: T) -> T { max_value ^ i } +impl ord of ord for T { + fn lt(&&other: T) -> bool { + ret self < other; + } +} + +impl eq of eq for T { + fn eq(&&other: T) -> bool { + ret self == other; + } +} + #[doc = " Parse a buffer of bytes diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index cce654f0e24b..4cfcd6b7517e 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -211,18 +211,18 @@ fn from_mut(+v: [mut T]) -> [T] unsafe { pure fn head(v: [const T]/&) -> T { v[0] } #[doc = "Returns a vector containing all but the first element of a slice"] -fn tail(v: [const T]/&) -> [T] { +pure fn tail(v: [const T]/&) -> [T] { ret slice(v, 1u, len(v)); } #[doc = "Returns a vector containing all but the first `n` \ elements of a slice"] -fn tailn(v: [const T]/&, n: uint) -> [T] { +pure fn tailn(v: [const T]/&, n: uint) -> [T] { slice(v, n, len(v)) } #[doc = "Returns a vector containing all but the last element of a slice"] -fn init(v: [const T]/&) -> [T] { +pure fn init(v: [const T]/&) -> [T] { assert len(v) != 0u; slice(v, 0u, len(v) - 1u) } @@ -798,7 +798,7 @@ Swaps two elements in a vector * a - The index of the first element * b - The index of the second element "] -fn swap(v: [mut T], a: uint, b: uint) { +fn swap(&&v: [mut T], a: uint, b: uint) { v[a] <-> v[b]; } @@ -1033,10 +1033,10 @@ pure fn unpack_mut_slice(s: [mut T]/&, impl extensions/& for [const T]/& { #[doc = "Returns true if a vector contains no elements"] #[inline] - fn is_empty() -> bool { is_empty(self) } + pure fn is_empty() -> bool { is_empty(self) } #[doc = "Returns true if a vector contains some elements"] #[inline] - fn is_not_empty() -> bool { is_not_empty(self) } + pure fn is_not_empty() -> bool { is_not_empty(self) } #[doc = "Returns the length of a vector"] #[inline] pure fn len() -> uint { len(self) } @@ -1046,28 +1046,28 @@ impl extensions/& for [const T]/& { impl extensions/& for [const T]/& { #[doc = "Returns the first element of a vector"] #[inline] - fn head() -> T { head(self) } + pure fn head() -> T { head(self) } #[doc = "Returns all but the last elemnt of a vector"] #[inline] - fn init() -> [T] { init(self) } + pure fn init() -> [T] { init(self) } #[doc = " Returns the last element of a `v`, failing if the vector is empty. "] #[inline] - fn last() -> T { last(self) } + pure fn last() -> T { last(self) } #[doc = "Returns a copy of the elements from [`start`..`end`) from `v`."] #[inline] - fn slice(start: uint, end: uint) -> [T] { slice(self, start, end) } + pure fn slice(start: uint, end: uint) -> [T] { slice(self, start, end) } #[doc = "Returns all but the first element of a vector"] #[inline] - fn tail() -> [T] { tail(self) } + pure fn tail() -> [T] { tail(self) } } #[doc = "Extension methods for vectors"] impl extensions/& for [T]/& { #[doc = "Reduce a vector from right to left"] #[inline] - fn foldr(z: U, p: fn(T, U) -> U) -> U { foldr(self, z, p) } + pure fn foldr(z: U, p: fn(T, U) -> U) -> U { foldr(self, z, p) } #[doc = " Iterates over a vector @@ -1075,7 +1075,7 @@ impl extensions/& for [T]/& { the element's value. "] #[inline] - fn iter(f: fn(T)) { iter(self, f) } + pure fn iter(f: fn(T)) { iter(self, f) } #[doc = " Iterates over a vector's elements and indexes @@ -1083,7 +1083,7 @@ impl extensions/& for [T]/& { the element's value and index. "] #[inline] - fn iteri(f: fn(uint, T)) { iteri(self, f) } + pure fn iteri(f: fn(uint, T)) { iteri(self, f) } #[doc = " Find the first index matching some predicate @@ -1092,10 +1092,10 @@ impl extensions/& for [T]/& { elements then none is returned. "] #[inline] - fn position(f: fn(T) -> bool) -> option { position(self, f) } + pure fn position(f: fn(T) -> bool) -> option { position(self, f) } #[doc = "Find the first index containing a matching value"] #[inline] - fn position_elem(x: T) -> option { position_elem(self, x) } + pure fn position_elem(x: T) -> option { position_elem(self, x) } #[doc = " Iterates over a vector in reverse @@ -1103,7 +1103,7 @@ impl extensions/& for [T]/& { the element's value. "] #[inline] - fn riter(f: fn(T)) { riter(self, f) } + pure fn riter(f: fn(T)) { riter(self, f) } #[doc =" Iterates over a vector's elements and indexes in reverse @@ -1111,7 +1111,7 @@ impl extensions/& for [T]/& { the element's value and index. "] #[inline] - fn riteri(f: fn(uint, T)) { riteri(self, f) } + pure fn riteri(f: fn(uint, T)) { riteri(self, f) } #[doc = " Find the last index matching some predicate @@ -1120,20 +1120,20 @@ impl extensions/& for [T]/& { matches no elements then none is returned. "] #[inline] - fn rposition(f: fn(T) -> bool) -> option { rposition(self, f) } + pure fn rposition(f: fn(T) -> bool) -> option { rposition(self, f) } #[doc = "Find the last index containing a matching value"] #[inline] - fn rposition_elem(x: T) -> option { rposition_elem(self, x) } + pure fn rposition_elem(x: T) -> option { rposition_elem(self, x) } #[doc = " Apply a function to each element of a vector and return the results "] #[inline] - fn map(f: fn(T) -> U) -> [U] { map(self, f) } + pure fn map(f: fn(T) -> U) -> [U] { map(self, f) } #[doc = " Apply a function to the index and value of each element in the vector and return the results "] - fn mapi(f: fn(uint, T) -> U) -> [U] { + pure fn mapi(f: fn(uint, T) -> U) -> [U] { mapi(self, f) } #[doc = "Returns true if the function returns true for all elements. @@ -1147,7 +1147,7 @@ impl extensions/& for [T]/& { of each result vector "] #[inline] - fn flat_map(f: fn(T) -> [U]) -> [U] { flat_map(self, f) } + pure fn flat_map(f: fn(T) -> [U]) -> [U] { flat_map(self, f) } #[doc = " Apply a function to each element of a vector and return the results @@ -1155,7 +1155,7 @@ impl extensions/& for [T]/& { the resulting vector. "] #[inline] - fn filter_map(f: fn(T) -> option) -> [U] { + pure fn filter_map(f: fn(T) -> option) -> [U] { filter_map(self, f) } } @@ -1170,7 +1170,7 @@ impl extensions/& for [T]/& { only those elements for which `f` returned true. "] #[inline] - fn filter(f: fn(T) -> bool) -> [T] { filter(self, f) } + pure fn filter(f: fn(T) -> bool) -> [T] { filter(self, f) } #[doc = " Search for the first element that matches a given predicate @@ -1179,7 +1179,7 @@ impl extensions/& for [T]/& { is returned. If `f` matches no elements then none is returned. "] #[inline] - fn find(f: fn(T) -> bool) -> option { find(self, f) } + pure fn find(f: fn(T) -> bool) -> option { find(self, f) } #[doc = " Search for the last element that matches a given predicate @@ -1188,7 +1188,7 @@ impl extensions/& for [T]/& { matches no elements then none is returned. "] #[inline] - fn rfind(f: fn(T) -> bool) -> option { rfind(self, f) } + pure fn rfind(f: fn(T) -> bool) -> option { rfind(self, f) } } #[doc = "Unsafe operations"] @@ -1221,12 +1221,12 @@ mod unsafe { #[doc = " Sets the length of a vector - This well explicitly set the size of the vector, without actually + This will explicitly set the size of the vector, without actually modifing its buffers, so it is up to the caller to ensure that the vector is actually the specified size. "] #[inline(always)] - unsafe fn set_len(&v: [const T], new_len: uint) { + unsafe fn set_len(&&v: [const T], new_len: uint) { let repr: **vec_repr = ::unsafe::reinterpret_cast(addr_of(v)); (**repr).fill = new_len * sys::size_of::(); } diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index 063fdd9b9a49..3445d7399afa 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -24,9 +24,7 @@ type arc_data = { resource arc_destruct(data: *libc::c_void) { unsafe { let data: ~arc_data = unsafe::reinterpret_cast(data); - let ref_ptr = &mut data.count; - - let new_count = rustrt::rust_atomic_decrement(ref_ptr); + let new_count = rustrt::rust_atomic_decrement(&mut data.count); assert new_count >= 0; if new_count == 0 { // drop glue takes over. diff --git a/src/libstd/deque.rs b/src/libstd/deque.rs index 0f30e5e6e12c..4cef32456618 100644 --- a/src/libstd/deque.rs +++ b/src/libstd/deque.rs @@ -1,6 +1,7 @@ #[doc = "A deque. Untested as of yet. Likely buggy"]; import option::{some, none}; +import dvec::{dvec, extensions}; iface t { fn size() -> uint; @@ -23,7 +24,7 @@ fn create() -> t { * Grow is only called on full elts, so nelts is also len(elts), unlike * elsewhere. */ - fn grow(nelts: uint, lo: uint, elts: [mut cell]) -> + fn grow(nelts: uint, lo: uint, -elts: [mut cell]) -> [mut cell] { assert (nelts == vec::len(elts)); let mut rv = [mut]; @@ -39,38 +40,38 @@ fn create() -> t { ret rv; } - fn get(elts: [mut cell], i: uint) -> T { - ret alt elts[i] { some(t) { t } _ { fail } }; + fn get(elts: dvec>, i: uint) -> T { + alt elts.get_elt(i) { some(t) { t } _ { fail } } } type repr = {mut nelts: uint, mut lo: uint, mut hi: uint, - mut elts: [mut cell]}; + elts: dvec>}; impl of t for repr { fn size() -> uint { ret self.nelts; } fn add_front(t: T) { let oldlo: uint = self.lo; if self.lo == 0u { - self.lo = vec::len(self.elts) - 1u; + self.lo = self.elts.len() - 1u; } else { self.lo -= 1u; } if self.lo == self.hi { - self.elts = grow(self.nelts, oldlo, self.elts); - self.lo = vec::len(self.elts) - 1u; + self.elts.swap({ |v| grow(self.nelts, oldlo, v) }); + self.lo = self.elts.len() - 1u; self.hi = self.nelts; } - self.elts[self.lo] = some(t); + self.elts.set_elt(self.lo, some(t)); self.nelts += 1u; } fn add_back(t: T) { if self.lo == self.hi && self.nelts != 0u { - self.elts = grow(self.nelts, self.lo, self.elts); + self.elts.swap({ |v| grow(self.nelts, self.lo, v) }); self.lo = 0u; self.hi = self.nelts; } - self.elts[self.hi] = some(t); - self.hi = (self.hi + 1u) % vec::len(self.elts); + self.elts.set_elt(self.hi, some(t)); + self.hi = (self.hi + 1u) % self.elts.len(); self.nelts += 1u; } /** @@ -79,24 +80,24 @@ fn create() -> t { */ fn pop_front() -> T { let t: T = get(self.elts, self.lo); - self.elts[self.lo] = none; - self.lo = (self.lo + 1u) % vec::len(self.elts); + self.elts.set_elt(self.lo, none); + self.lo = (self.lo + 1u) % self.elts.len(); self.nelts -= 1u; ret t; } fn pop_back() -> T { if self.hi == 0u { - self.hi = vec::len(self.elts) - 1u; + self.hi = self.elts.len() - 1u; } else { self.hi -= 1u; } let t: T = get(self.elts, self.hi); - self.elts[self.hi] = none; + self.elts.set_elt(self.hi, none); self.nelts -= 1u; ret t; } fn peek_front() -> T { ret get(self.elts, self.lo); } fn peek_back() -> T { ret get(self.elts, self.hi - 1u); } fn get(i: int) -> T { - let idx = (self.lo + (i as uint)) % vec::len(self.elts); + let idx = (self.lo + (i as uint)) % self.elts.len(); ret get(self.elts, idx); } } @@ -105,7 +106,10 @@ fn create() -> t { mut nelts: 0u, mut lo: 0u, mut hi: 0u, - mut elts: vec::to_mut(vec::from_elem(initial_capacity, none)) + elts: + dvec::from_vec( + vec::to_mut( + vec::from_elem(initial_capacity, none))) }; repr as t:: } diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 7e16578fd9c8..76c71d7ed2aa 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -1,5 +1,6 @@ #[doc = "Sorting methods"]; import vec::len; +import int::{eq, ord}; export le; export merge_sort; @@ -141,7 +142,6 @@ fn qsort3(compare_func_lt: le, compare_func_eq: le, qsort3::(compare_func_lt, compare_func_eq, arr, i, right); } -// FIXME: This should take lt and eq types (#2348) #[doc = " Fancy quicksort. Sorts a mut vector in place. @@ -152,10 +152,9 @@ According to these slides this is the algorithm of choice for This is an unstable sort. "] -fn quick_sort3(compare_func_lt: le, compare_func_eq: le, - arr: [mut T]) { +fn quick_sort3(arr: [mut T]) { if len::(arr) == 0u { ret; } - qsort3::(compare_func_lt, compare_func_eq, arr, 0, + qsort3::({ |x, y| x.lt(y) }, { |x, y| x.eq(y) }, arr, 0, (len::(arr) as int) - 1); } @@ -163,11 +162,7 @@ fn quick_sort3(compare_func_lt: le, compare_func_eq: le, mod test_qsort3 { fn check_sort(v1: [mut int], v2: [mut int]) { let len = vec::len::(v1); - fn lt(&&a: int, &&b: int) -> bool { ret a < b; } - fn equal(&&a: int, &&b: int) -> bool { ret a == b; } - let f1 = lt; - let f2 = equal; - quick_sort3::(f1, f2, v1); + quick_sort3::(v1); let mut i = 0u; while i < len { log(debug, v2[i]); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f0a3006b8c67..ab458931b0c0 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -313,7 +313,7 @@ enum expr_ { expr_fn(proto, fn_decl, blk, capture_clause), expr_fn_block(fn_decl, blk, capture_clause), // Inner expr is always an expr_fn_block. We need the wrapping node to - // sanely type this (a function returning nil on the inside but bool on + // easily type this (a function returning nil on the inside but bool on // the outside). expr_loop_body(@expr), expr_block(blk), diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 76feba3954c7..cc4593d4af86 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -21,17 +21,17 @@ pure fn mk_sp(lo: uint, hi: uint) -> span { // make this a const, once the compiler supports it pure fn dummy_sp() -> span { ret mk_sp(0u, 0u); } -fn path_name(p: @path) -> str { path_name_i(p.idents) } +pure fn path_name(p: @path) -> str { path_name_i(p.idents) } -fn path_name_i(idents: [ident]) -> str { str::connect(idents, "::") } +pure fn path_name_i(idents: [ident]) -> str { str::connect(idents, "::") } -fn path_to_ident(p: @path) -> ident { vec::last(p.idents) } +pure fn path_to_ident(p: @path) -> ident { vec::last(p.idents) } -fn local_def(id: node_id) -> def_id { {crate: local_crate, node: id} } +pure fn local_def(id: node_id) -> def_id { {crate: local_crate, node: id} } pure fn is_local(did: ast::def_id) -> bool { did.crate == local_crate } -fn stmt_id(s: stmt) -> node_id { +pure fn stmt_id(s: stmt) -> node_id { alt s.node { stmt_decl(_, id) { id } stmt_expr(_, id) { id } @@ -45,7 +45,7 @@ fn variant_def_ids(d: def) -> {enm: def_id, var: def_id} { _ { fail "non-variant in variant_def_ids"; } } } -fn def_id_of_def(d: def) -> def_id { +pure fn def_id_of_def(d: def) -> def_id { alt d { def_fn(id, _) | def_mod(id) | def_native_mod(id) | def_const(id) | @@ -60,7 +60,7 @@ fn def_id_of_def(d: def) -> def_id { } } -fn binop_to_str(op: binop) -> str { +pure fn binop_to_str(op: binop) -> str { alt op { add { ret "+"; } subtract { ret "-"; } @@ -95,7 +95,7 @@ pure fn is_shift_binop(b: binop) -> bool { } } -fn unop_to_str(op: unop) -> str { +pure fn unop_to_str(op: unop) -> str { alt op { box(mt) { if mt == m_mutbl { ret "@mut "; } ret "@"; } uniq(mt) { if mt == m_mutbl { ret "~mut "; } ret "~"; } @@ -105,11 +105,11 @@ fn unop_to_str(op: unop) -> str { } } -fn is_path(e: @expr) -> bool { +pure fn is_path(e: @expr) -> bool { ret alt e.node { expr_path(_) { true } _ { false } }; } -fn int_ty_to_str(t: int_ty) -> str { +pure fn int_ty_to_str(t: int_ty) -> str { alt t { ty_char { "u8" } // ??? ty_i { "" } ty_i8 { "i8" } ty_i16 { "i16" } @@ -117,7 +117,7 @@ fn int_ty_to_str(t: int_ty) -> str { } } -fn int_ty_max(t: int_ty) -> u64 { +pure fn int_ty_max(t: int_ty) -> u64 { alt t { ty_i8 { 0x80u64 } ty_i16 { 0x8000u64 } @@ -126,14 +126,14 @@ fn int_ty_max(t: int_ty) -> u64 { } } -fn uint_ty_to_str(t: uint_ty) -> str { +pure fn uint_ty_to_str(t: uint_ty) -> str { alt t { ty_u { "u" } ty_u8 { "u8" } ty_u16 { "u16" } ty_u32 { "u32" } ty_u64 { "u64" } } } -fn uint_ty_max(t: uint_ty) -> u64 { +pure fn uint_ty_max(t: uint_ty) -> u64 { alt t { ty_u8 { 0xffu64 } ty_u16 { 0xffffu64 } @@ -142,7 +142,7 @@ fn uint_ty_max(t: uint_ty) -> u64 { } } -fn float_ty_to_str(t: float_ty) -> str { +pure fn float_ty_to_str(t: float_ty) -> str { alt t { ty_f { "" } ty_f32 { "f32" } ty_f64 { "f64" } } } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 259041959d4c..0fa419cd4a96 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -77,7 +77,7 @@ fn next_line(file: filemap, chpos: uint, byte_pos: uint) { file.lines += [{ch: chpos, byte: byte_pos + file.start_pos.byte}]; } -type lookup_fn = fn@(file_pos) -> uint; +type lookup_fn = pure fn(file_pos) -> uint; fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn) -> {fm: filemap, line: uint} @@ -108,12 +108,12 @@ fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc { } fn lookup_char_pos(map: codemap, pos: uint) -> loc { - fn lookup(pos: file_pos) -> uint { ret pos.ch; } + pure fn lookup(pos: file_pos) -> uint { ret pos.ch; } ret lookup_pos(map, pos, lookup); } fn lookup_byte_pos(map: codemap, pos: uint) -> loc { - fn lookup(pos: file_pos) -> uint { ret pos.byte; } + pure fn lookup(pos: file_pos) -> uint { ret pos.byte; } ret lookup_pos(map, pos, lookup); } @@ -139,7 +139,7 @@ fn lookup_char_pos_adj(map: codemap, pos: uint) } fn adjust_span(map: codemap, sp: span) -> span { - fn lookup(pos: file_pos) -> uint { ret pos.ch; } + pure fn lookup(pos: file_pos) -> uint { ret pos.ch; } let line = lookup_line(map, sp.lo, lookup); alt (line.fm.substr) { fss_none {sp} @@ -198,7 +198,8 @@ fn get_line(fm: filemap, line: int) -> str unsafe { fn lookup_byte_offset(cm: codemap::codemap, chpos: uint) -> {fm: filemap, pos: uint} { - let {fm, line} = lookup_line(cm, chpos, {|pos| pos.ch}); + pure fn lookup(pos: file_pos) -> uint { ret pos.ch; } + let {fm, line} = lookup_line(cm, chpos, lookup); let line_offset = fm.lines[line].byte - fm.start_pos.byte; let col = chpos - fm.lines[line].ch; let col_offset = str::count_bytes(*fm.src, line_offset, col); diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 6d54615e8272..f58333c5599b 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -86,11 +86,14 @@ impl codemap_handler of handler for handler_t { } fn has_errors() -> bool { self.err_count > 0u } fn abort_if_errors() { - if self.err_count > 0u { - let s = #fmt["aborting due to %u previous errors", - self.err_count]; - self.fatal(s); + let s; + alt self.err_count { + 0u { ret; } + 1u { s = "aborting due to previous error"; } + _ { s = #fmt["aborting due to %u previous errors", + self.err_count]; } } + self.fatal(s); } fn warn(msg: str) { self.emit(none, msg, warning); diff --git a/src/libsyntax/ext/qquote.rs b/src/libsyntax/ext/qquote.rs index f3c7de97865a..1a7ae69e79df 100644 --- a/src/libsyntax/ext/qquote.rs +++ b/src/libsyntax/ext/qquote.rs @@ -212,7 +212,7 @@ fn finish state = skip(str::char_len(repl)); str2 += repl; } - alt state { + alt copy state { active {str::push_char(str2, ch);} skip(1u) {state = blank;} skip(sk) {state = skip (sk-1u);} diff --git a/src/libsyntax/ext/simplext.rs b/src/libsyntax/ext/simplext.rs index 76b78cb2b86c..764c484c8e39 100644 --- a/src/libsyntax/ext/simplext.rs +++ b/src/libsyntax/ext/simplext.rs @@ -1,5 +1,6 @@ import codemap::span; import std::map::{hashmap, str_hash}; +import dvec::{dvec, extensions}; import base::*; @@ -134,7 +135,7 @@ fn compose_sels(s1: selector, s2: selector) -> selector { type binders = {real_binders: hashmap, - mut literal_ast_matchers: [selector]}; + literal_ast_matchers: dvec}; type bindings = hashmap>; fn acumm_bindings(_cx: ext_ctxt, _b_dest: bindings, _b_src: bindings) { } @@ -146,7 +147,7 @@ fn acumm_bindings(_cx: ext_ctxt, _b_dest: bindings, _b_src: bindings) { } fn pattern_to_selectors(cx: ext_ctxt, e: @expr) -> binders { let res: binders = {real_binders: str_hash::(), - mut literal_ast_matchers: []}; + literal_ast_matchers: dvec()}; //this oughta return binders instead, but macro args are a sequence of //expressions, rather than a single expression fn trivial_selector(m: matchable) -> match_result { ret some(leaf(m)); } @@ -474,7 +475,7 @@ fn p_t_s_rec(cx: ext_ctxt, m: matchable, s: selector, b: binders) { _ { cx.bug("broken traversal in p_t_s_r") } } } - b.literal_ast_matchers += [bind select(cx, _, e)]; + b.literal_ast_matchers.push(bind select(cx, _, e)); } } } @@ -640,8 +641,8 @@ fn p_t_s_r_length(cx: ext_ctxt, len: uint, at_least: bool, s: selector, _ { none } } } - b.literal_ast_matchers += - [compose_sels(s, bind len_select(cx, _, at_least, len))]; + b.literal_ast_matchers.push( + compose_sels(s, bind len_select(cx, _, at_least, len))); } fn p_t_s_r_actual_vector(cx: ext_ctxt, elts: [@expr], _repeat_after: bool, diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index 4bfba482c4f5..35afb79ce63f 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -18,7 +18,7 @@ fn seq_sep_none() -> seq_sep { } -fn token_to_str(reader: reader, token: token::token) -> str { +fn token_to_str(reader: reader, ++token: token::token) -> str { token::to_str(*reader.interner, token) } @@ -27,8 +27,9 @@ fn token_to_str(reader: reader, token: token::token) -> str { impl parser_common for parser { fn unexpected_last(t: token::token) -> ! { - self.span_fatal(self.last_span, "unexpected token: '" - + token_to_str(self.reader, t) + "'"); + self.span_fatal( + copy self.last_span, + "unexpected token: '" + token_to_str(self.reader, t) + "'"); } fn unexpected() -> ! { @@ -49,7 +50,7 @@ impl parser_common for parser { } fn parse_ident() -> ast::ident { - alt self.token { + alt copy self.token { token::IDENT(i, _) { self.bump(); ret self.get_str(i); } _ { self.fatal("expecting ident, found " + token_to_str(self.reader, self.token)); } @@ -79,7 +80,7 @@ impl parser_common for parser { } } - fn token_is_keyword(word: str, tok: token::token) -> bool { + fn token_is_keyword(word: str, ++tok: token::token) -> bool { self.require_keyword(word); alt tok { token::IDENT(sid, false) { str::eq(word, self.get_str(sid)) } @@ -93,8 +94,11 @@ impl parser_common for parser { fn eat_keyword(word: str) -> bool { self.require_keyword(word); - alt self.token { - token::IDENT(sid, false) { + + // FIXME: this gratuitous use of @ is to + // workaround LLVM bug #13042 + alt @self.token { + @token::IDENT(sid, false) { if str::eq(word, self.get_str(sid)) { self.bump(); ret true; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8b40e2a8a973..33e7d082bfb0 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -121,16 +121,16 @@ class parser { ret self.buffer[distance - 1u].tok; } fn fatal(m: str) -> ! { - self.sess.span_diagnostic.span_fatal(self.span, m) + self.sess.span_diagnostic.span_fatal(copy self.span, m) } fn span_fatal(sp: span, m: str) -> ! { self.sess.span_diagnostic.span_fatal(sp, m) } fn bug(m: str) -> ! { - self.sess.span_diagnostic.span_bug(self.span, m) + self.sess.span_diagnostic.span_bug(copy self.span, m) } fn warn(m: str) { - self.sess.span_diagnostic.span_warn(self.span, m) + self.sess.span_diagnostic.span_warn(copy self.span, m) } fn get_str(i: token::str_num) -> str { interner::get(*self.reader.interner, i) @@ -307,7 +307,7 @@ class parser { // Parses something like "&x" fn parse_region() -> @region { self.expect(token::BINOP(token::AND)); - alt self.token { + alt copy self.token { token::IDENT(sid, _) { self.bump(); let n = self.get_str(sid); @@ -322,7 +322,7 @@ class parser { // Parses something like "&x." (note the trailing dot) fn parse_region_dot() -> @region { let name = - alt self.token { + alt copy self.token { token::IDENT(sid, _) if self.look_ahead(1u) == token::DOT { self.bump(); self.bump(); some(self.get_str(sid)) @@ -483,11 +483,11 @@ class parser { } fn maybe_parse_dollar_mac() -> option { - alt self.token { + alt copy self.token { token::DOLLAR { let lo = self.span.lo; self.bump(); - alt self.token { + alt copy self.token { token::LIT_INT(num, ty_i) { self.bump(); some(mac_var(num as uint)) @@ -511,7 +511,7 @@ class parser { fn maybe_parse_vstore() -> option { if self.token == token::BINOP(token::SLASH) { self.bump(); - alt self.token { + alt copy self.token { token::AT { self.bump(); some(vstore_box) } @@ -968,7 +968,7 @@ class parser { loop { // expr.f if self.eat(token::DOT) { - alt self.token { + alt copy self.token { token::IDENT(i, _) { hi = self.span.hi; self.bump(); @@ -986,7 +986,7 @@ class parser { cont; } if self.expr_is_complete(e) { break; } - alt self.token { + alt copy self.token { // expr(...) token::LPAREN if self.permits_call() { let es_opt = self.parse_seq(token::LPAREN, token::RPAREN, @@ -1042,7 +1042,7 @@ class parser { let mut hi; let mut ex; - alt self.token { + alt copy self.token { token::NOT { self.bump(); let e = self.to_expr(self.parse_prefix_expr()); @@ -1134,7 +1134,7 @@ class parser { fn parse_assign_expr() -> @expr { let lo = self.span.lo; let lhs = self.parse_binops(); - alt self.token { + alt copy self.token { token::EQ { self.bump(); let rhs = self.parse_expr(); @@ -1831,7 +1831,7 @@ class parser { } fn parse_method_name() -> ident { - alt self.token { + alt copy self.token { token::BINOP(op) { self.bump(); token::binop_to_str(op) } token::NOT { self.bump(); "!" } token::LBRACKET { self.bump(); self.expect(token::RBRACKET); "[]" } @@ -2375,7 +2375,7 @@ class parser { while self.token == token::MOD_SEP { self.bump(); - alt self.token { + alt copy self.token { token::IDENT(i, _) { self.bump(); @@ -2477,7 +2477,7 @@ class parser { } fn parse_str() -> str { - alt self.token { + alt copy self.token { token::LIT_STR(s) { self.bump(); self.get_str(s) } _ { self.fatal("expected string literal") diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index cb92aad04c70..bbbd09632ef8 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -184,16 +184,16 @@ fn is_lit(t: token::token) -> bool { } } -fn is_ident(t: token::token) -> bool { +pure fn is_ident(t: token::token) -> bool { alt t { token::IDENT(_, _) { ret true; } _ { } } ret false; } -fn is_plain_ident(t: token::token) -> bool { +pure fn is_plain_ident(t: token::token) -> bool { ret alt t { token::IDENT(_, false) { true } _ { false } }; } -fn is_bar(t: token::token) -> bool { +pure fn is_bar(t: token::token) -> bool { alt t { token::BINOP(token::OR) | token::OROR { true } _ { false } } } diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 882ce7b6461f..329dff0c4c1b 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -59,11 +59,11 @@ type break_t = {offset: int, blank_space: int}; type begin_t = {offset: int, breaks: breaks}; -enum token { STRING(str, int), BREAK(break_t), BEGIN(begin_t), END, EOF, } +enum token { STRING(@str, int), BREAK(break_t), BEGIN(begin_t), END, EOF, } -fn tok_str(t: token) -> str { +fn tok_str(++t: token) -> str { alt t { - STRING(s, len) { ret #fmt["STR(%s,%d)", s, len]; } + STRING(s, len) { ret #fmt["STR(%s,%d)", *s, len]; } BREAK(_) { ret "BREAK"; } BEGIN(_) { ret "BEGIN"; } END { ret "END"; } @@ -109,8 +109,8 @@ fn mk_printer(out: io::writer, linewidth: uint) -> printer { mut space: linewidth as int, mut left: 0u, mut right: 0u, - mut token: token, - mut size: size, + token: token, + size: size, mut left_total: 0, mut right_total: 0, mut scan_stack: scan_stack, @@ -206,8 +206,8 @@ type printer = @{ mut space: int, // number of spaces left on line mut left: uint, // index of left side of input stream mut right: uint, // index of right side of input stream - mut token: [mut token], // ring-buffr stream goes through - mut size: [mut int], // ring-buffer of calculated sizes + token: [mut token], // ring-buffr stream goes through + size: [mut int], // ring-buffer of calculated sizes mut left_total: int, // running size of stream "...left" mut right_total: int, // running size of stream "...right" // pseudo-stack, really a ring too. Holds the @@ -346,7 +346,7 @@ impl printer for printer { self.right %= self.buf_len; assert (self.right != self.left); } - fn advance_left(x: token, L: int) { + fn advance_left(++x: token, L: int) { #debug("advnce_left [%u,%u], sizeof(%u)=%d", self.left, self.right, self.left, L); if L >= 0 { @@ -367,7 +367,7 @@ impl printer for printer { fn check_stack(k: int) { if !self.scan_stack_empty { let x = self.scan_top(); - alt self.token[x] { + alt copy self.token[x] { BEGIN(b) { if k > 0 { self.size[self.scan_pop()] = self.size[x] + @@ -465,7 +465,7 @@ impl printer for printer { assert (L == len); // assert L <= space; self.space -= len; - self.write_str(s); + self.write_str(*s); } EOF { // EOF should never get here. @@ -493,14 +493,14 @@ fn end(p: printer) { p.pretty_print(END); } fn eof(p: printer) { p.pretty_print(EOF); } fn word(p: printer, wrd: str) { - p.pretty_print(STRING(wrd, str::len(wrd) as int)); + p.pretty_print(STRING(@wrd, str::len(wrd) as int)); } fn huge_word(p: printer, wrd: str) { - p.pretty_print(STRING(wrd, size_infinity)); + p.pretty_print(STRING(@wrd, size_infinity)); } -fn zero_word(p: printer, wrd: str) { p.pretty_print(STRING(wrd, 0)); } +fn zero_word(p: printer, wrd: str) { p.pretty_print(STRING(@wrd, 0)); } fn spaces(p: printer, n: uint) { break_offset(p, n, 0); } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index dd935533b7fc..d4e66137d675 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -539,6 +539,7 @@ fn print_item(s: ps, &&item: @ast::item) { print_block(s, ctor.node.body); option::iter(m_dtor) {|dtor| hardbreak_if_not_bol(s); + maybe_print_comment(s, dtor.span.lo); head(s, "drop"); print_block(s, dtor.node.body); } @@ -1703,7 +1704,7 @@ fn print_comment(s: ps, cmnt: comments::cmnt) { // We need to do at least one, possibly two hardbreaks. let is_semi = alt s.s.last_token() { - pp::STRING(s, _) { s == ";" } + pp::STRING(s, _) { *s == ";" } _ { false } }; if is_semi || is_begin(s) || is_end(s) { hardbreak(s.s); } diff --git a/src/rustc/back/link.rs b/src/rustc/back/link.rs index db87084fc1ba..c3e1b4da7727 100644 --- a/src/rustc/back/link.rs +++ b/src/rustc/back/link.rs @@ -637,6 +637,11 @@ fn link_binary(sess: session, // and binutils 2.22+ won't add them automatically if sess.targ_cfg.os == session::os_linux { cc_args += ["-lrt", "-ldl"]; + + // LLVM implements the `frem` instruction as a call to `fmod`, + // which lives in libm. Similar to above, on some linuxes we + // have to be explicit about linking to it. See #2510 + cc_args += ["-lm"]; } if sess.targ_cfg.os == session::os_freebsd { diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index 6d4f48595d25..e769455376a5 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -194,7 +194,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, bind middle::check_loop::check_crate(ty_cx, crate)); time(time_passes, "alt checking", bind middle::check_alt::check_crate(ty_cx, crate)); - let (last_use_map, spill_map) = + let last_use_map = time(time_passes, "liveness checking", bind middle::liveness::check_crate(ty_cx, method_map, crate)); time(time_passes, "typestate checking", @@ -216,7 +216,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, let maps = {mutbl_map: mutbl_map, root_map: root_map, copy_map: copy_map, last_use_map: last_use_map, impl_map: impl_map, method_map: method_map, - vtable_map: vtable_map, spill_map: spill_map}; + vtable_map: vtable_map}; let (llmod, link_meta) = time(time_passes, "translation", diff --git a/src/rustc/driver/rustc.rs b/src/rustc/driver/rustc.rs index db185215bea5..5e88df1de5ec 100644 --- a/src/rustc/driver/rustc.rs +++ b/src/rustc/driver/rustc.rs @@ -15,7 +15,8 @@ import std::map::hashmap; import getopts::{opt_present}; import rustc::driver::driver::*; import syntax::codemap; -import rustc::driver::{diagnostic, session}; +import syntax::diagnostic; +import rustc::driver::session; import rustc::middle::lint; import io::reader_util; diff --git a/src/rustc/front/test.rs b/src/rustc/front/test.rs index b410cb75ad6f..2cb144a60b5c 100644 --- a/src/rustc/front/test.rs +++ b/src/rustc/front/test.rs @@ -9,6 +9,7 @@ import syntax::codemap::span; import driver::session; import session::session; import syntax::attr; +import dvec::{dvec, extensions}; export modify_for_testing; @@ -20,7 +21,7 @@ type test_ctxt = @{sess: session::session, crate: @ast::crate, mut path: [ast::ident], - mut testfns: [test]}; + testfns: dvec}; // Traverse the crate, collecting all the test functions, eliding any // existing main functions, and synthesizing a main test harness @@ -40,7 +41,7 @@ fn generate_test_harness(sess: session::session, @{sess: sess, crate: crate, mut path: [], - mut testfns: []}; + testfns: dvec()}; let precursor = @{fold_crate: fold::wrap(bind fold_crate(cx, _, _)), @@ -110,8 +111,8 @@ fn fold_item(cx: test_ctxt, &&i: @ast::item, fld: fold::ast_fold) -> let test = {span: i.span, path: cx.path, ignore: is_ignored(cx, i), should_fail: should_fail(i)}; - cx.testfns += [test]; - #debug("have %u test functions", vec::len(cx.testfns)); + cx.testfns.push(test); + #debug("have %u test functions", cx.testfns.len()); } } } @@ -269,11 +270,10 @@ fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::ty { } fn mk_test_desc_vec(cx: test_ctxt) -> @ast::expr { - #debug("building test vector from %u tests", vec::len(cx.testfns)); + #debug("building test vector from %u tests", cx.testfns.len()); let mut descs = []; for cx.testfns.each {|test| - let test_ = test; // Satisfy alias analysis - descs += [mk_test_desc_rec(cx, test_)]; + descs += [mk_test_desc_rec(cx, test)]; } ret @{id: cx.sess.next_node_id(), diff --git a/src/rustc/metadata/creader.rs b/src/rustc/metadata/creader.rs index 2aacd87cbe85..3356e8cdd652 100644 --- a/src/rustc/metadata/creader.rs +++ b/src/rustc/metadata/creader.rs @@ -13,6 +13,7 @@ import std::map::{hashmap, int_hash}; import syntax::print::pprust; import filesearch::filesearch; import common::*; +import dvec::{dvec, extensions}; export read_crates; @@ -26,7 +27,7 @@ fn read_crates(diag: span_handler, crate: ast::crate, cstore: cstore, os: os, static: static, - mut crate_cache: [], + crate_cache: dvec(), mut next_crate_num: 1}; let v = visit::mk_simple_visitor(@{visit_view_item: @@ -35,7 +36,7 @@ fn read_crates(diag: span_handler, crate: ast::crate, with *visit::default_simple_visitor()}); visit::visit_crate(crate, (), v); dump_crates(e.crate_cache); - warn_if_multiple_versions(diag, copy e.crate_cache); + warn_if_multiple_versions(diag, e.crate_cache.get()); } type cache_entry = { @@ -45,7 +46,7 @@ type cache_entry = { metas: @[@ast::meta_item] }; -fn dump_crates(crate_cache: [cache_entry]) { +fn dump_crates(crate_cache: dvec) { #debug("resolved crates:"); for crate_cache.each {|entry| #debug("cnum: %?", entry.cnum); @@ -64,10 +65,10 @@ fn warn_if_multiple_versions(diag: span_handler, crate_cache: [cache_entry]) { import either::*; - if crate_cache.is_not_empty() { + if crate_cache.len() != 0u { let name = loader::crate_name_from_metas(*crate_cache.last().metas); let {lefts: matches, rights: non_matches} = - partition(crate_cache.map {|entry| + partition(crate_cache.map_to_vec {|entry| let othername = loader::crate_name_from_metas(*entry.metas); if name == othername { left(entry) @@ -99,7 +100,7 @@ type env = @{diag: span_handler, cstore: cstore::cstore, os: loader::os, static: bool, - mut crate_cache: [cache_entry], + crate_cache: dvec, mut next_crate_num: ast::crate_num}; fn visit_view_item(e: env, i: @ast::view_item) { @@ -176,12 +177,14 @@ fn metas_with_ident(ident: ast::ident, fn existing_match(e: env, metas: [@ast::meta_item], hash: str) -> option { - let maybe_entry = e.crate_cache.find {|c| - loader::metadata_matches(*c.metas, metas) && - (hash.is_empty() || c.hash == hash) - }; - maybe_entry.map {|c| c.cnum } + for e.crate_cache.each {|c| + if loader::metadata_matches(*c.metas, metas) + && (hash.is_empty() || c.hash == hash) { + ret some(c.cnum); + } + } + ret none; } fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item], @@ -211,8 +214,8 @@ fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item], // Claim this crate number and cache it let cnum = e.next_crate_num; - e.crate_cache += [{cnum: cnum, span: span, - hash: hash, metas: @linkage_metas}]; + e.crate_cache.push({cnum: cnum, span: span, + hash: hash, metas: @linkage_metas}); e.next_crate_num += 1; // Now resolve the crates referenced by this crate diff --git a/src/rustc/metadata/cstore.rs b/src/rustc/metadata/cstore.rs index 22d19f81c868..0bbbeafdb54a 100644 --- a/src/rustc/metadata/cstore.rs +++ b/src/rustc/metadata/cstore.rs @@ -63,7 +63,9 @@ type cstore_private = type use_crate_map = map::hashmap; // Internal method to retrieve the data from the cstore -fn p(cstore: cstore) -> cstore_private { alt cstore { private(p) { p } } } +pure fn p(cstore: cstore) -> cstore_private { + alt cstore { private(p) { p } } +} fn mk_cstore() -> cstore { let meta_cache = map::int_hash::(); diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 644d519fc0f2..4df45033a77c 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -7,7 +7,6 @@ import syntax::{ast, ast_util}; import syntax::attr; import middle::ty; import syntax::ast_map; -import common::*; import tydecode::{parse_ty_data, parse_def_id, parse_bounds_data, parse_ident}; import syntax::print::pprust; @@ -15,6 +14,7 @@ import cmd=cstore::crate_metadata; import util::ppaux::ty_to_str; import ebml::deserializer; import syntax::diagnostic::span_handler; +import common::*; export class_dtor; export get_class_fields; diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index 2fd59cb21662..6ebf0ed9ec65 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -57,7 +57,6 @@ type maps = { impl_map: middle::resolve::impl_map, method_map: middle::typeck::method_map, vtable_map: middle::typeck::vtable_map, - spill_map: middle::liveness::spill_map }; type decode_ctxt = @{ @@ -839,12 +838,6 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, } } - option::iter(maps.spill_map.find(id)) {|_m| - ebml_w.tag(c::tag_table_spill) {|| - ebml_w.id(id); - } - } - option::iter(maps.last_use_map.find(id)) {|m| ebml_w.tag(c::tag_table_last_use) {|| ebml_w.id(id); @@ -953,8 +946,6 @@ fn decode_side_tables(xcx: extended_decode_ctxt, dcx.maps.mutbl_map.insert(id, ()); } else if tag == (c::tag_table_copy as uint) { dcx.maps.copy_map.insert(id, ()); - } else if tag == (c::tag_table_spill as uint) { - dcx.maps.spill_map.insert(id, ()); } else { let val_doc = entry_doc[c::tag_table_val]; let val_dsr = ebml::ebml_deserializer(val_doc); diff --git a/src/rustc/middle/borrowck.rs b/src/rustc/middle/borrowck.rs index 2b52cd675a66..d106c2b23d86 100644 --- a/src/rustc/middle/borrowck.rs +++ b/src/rustc/middle/borrowck.rs @@ -164,6 +164,7 @@ import util::common::indenter; import ast_util::op_expr_callee_id; import ty::to_str; import driver::session::session; +import dvec::{dvec, extensions}; export check_crate, root_map, mutbl_map; @@ -298,7 +299,7 @@ type loan = {lp: @loan_path, cmt: cmt, mutbl: ast::mutability}; // maps computed by `gather_loans` that are then used by `check_loans` type req_maps = { - req_loan_map: hashmap, + req_loan_map: hashmap>>, pure_map: hashmap }; diff --git a/src/rustc/middle/borrowck/categorization.rs b/src/rustc/middle/borrowck/categorization.rs index c7103b6899c4..ff9d51196c91 100644 --- a/src/rustc/middle/borrowck/categorization.rs +++ b/src/rustc/middle/borrowck/categorization.rs @@ -7,7 +7,15 @@ determine what kind of memory is used in evaluating it (for example, where dereferences occur and what kind of pointer is dereferenced; whether the memory is mutable; etc) +Categorization effectively transforms all of our expressions into +expressions of the following forms (the actual enum has many more +possibilities, naturally, but they are all variants of these base +forms): + E = rvalue // some computed rvalue + | x // address of a local variable, arg, or upvar + | *E // deref of a ptr + | E.comp // access to an interior component Imagine a routine ToAddr(Expr) that evaluates an expression and returns an address where the result is to be found. If Expr is an lvalue, then this diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index 615a6737c834..04a37d327cda 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -7,6 +7,7 @@ // 3. assignments do not affect things loaned out as immutable // 4. moves to dnot affect things loaned out in any way +import dvec::{dvec, extensions}; import categorization::public_methods; export check_loans; @@ -22,7 +23,7 @@ enum check_loan_ctxt = @{ // we are in a ctor, we track the self id mut in_ctor: bool, mut declared_purity: ast::purity, - mut fn_args: [ast::node_id] + mut fn_args: @[ast::node_id] }; // if we are enforcing purity, why are we doing so? @@ -44,7 +45,7 @@ fn check_loans(bccx: borrowck_ctxt, reported: int_hash(), mut in_ctor: false, mut declared_purity: ast::impure_fn, - mut fn_args: []}); + mut fn_args: @[]}); let vt = visit::mk_vt(@{visit_expr: check_loans_in_expr, visit_block: check_loans_in_block, visit_fn: check_loans_in_fn @@ -179,7 +180,7 @@ impl methods for check_loan_ctxt { let did = ast_util::def_id_of_def(def); let is_fn_arg = did.crate == ast::local_crate && - self.fn_args.contains(did.node); + (*self.fn_args).contains(did.node); if is_fn_arg { ret; } // case (a) above } ast::expr_fn_block(*) | ast::expr_fn(*) | @@ -225,7 +226,8 @@ impl methods for check_loan_ctxt { ast::expr_path(_) { let def = self.tcx().def_map.get(expr.id); let did = ast_util::def_id_of_def(def); - did.crate == ast::local_crate && self.fn_args.contains(did.node) + did.crate == ast::local_crate && + (*self.fn_args).contains(did.node) } ast::expr_fn_block(*) | ast::expr_fn(*) { self.is_stack_closure(expr.id) @@ -484,7 +486,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, sp: span, id: ast::node_id, &&self: check_loan_ctxt, visitor: visit::vt) { - #debug["purity on entry=%?", self.declared_purity]; + #debug["purity on entry=%?", copy self.declared_purity]; save_and_restore(self.in_ctor) {|| save_and_restore(self.declared_purity) {|| save_and_restore(self.fn_args) {|| @@ -500,7 +502,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, visit::fk_ctor(*) { self.in_ctor = true; self.declared_purity = decl.purity; - self.fn_args = decl.inputs.map({|i| i.id}); + self.fn_args = @decl.inputs.map({|i| i.id}); } visit::fk_anon(*) | visit::fk_fn_block(*) if is_stack_closure { @@ -512,7 +514,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, visit::fk_res(*) | visit::fk_dtor(*) { self.in_ctor = false; self.declared_purity = decl.purity; - self.fn_args = decl.inputs.map({|i| i.id}); + self.fn_args = @decl.inputs.map({|i| i.id}); } } @@ -520,7 +522,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, } } } - #debug["purity on exit=%?", self.declared_purity]; + #debug["purity on exit=%?", copy self.declared_purity]; } fn check_loans_in_expr(expr: @ast::expr, diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs index 1b18ff3f94b1..fe59d771042f 100644 --- a/src/rustc/middle/borrowck/gather_loans.rs +++ b/src/rustc/middle/borrowck/gather_loans.rs @@ -84,15 +84,24 @@ fn req_loans_in_expr(ex: @ast::expr, // the pointer to be borrowed as immutable even if it // is mutable in the caller's frame, thus effectively // passing the buck onto us to enforce this) + // + // FIXME---this handling is not really adequate. For + // example, if there is a type like, {f: [int]}, we + // will ignore it, but we ought to be requiring it to + // be immutable (whereas something like {f:int} would + // be fine). alt opt_deref_kind(arg_ty.ty) { - some(deref_ptr(region_ptr)) { + some(deref_ptr(region_ptr)) | + some(deref_ptr(unsafe_ptr)) { /* region pointers are (by induction) guaranteed */ + /* unsafe pointers are the user's problem */ } + some(deref_comp(_)) | none { /* not a pointer, no worries */ } - some(_) { + some(deref_ptr(_)) { let arg_cmt = self.bccx.cat_borrow_of_expr(arg); self.guarantee_valid(arg_cmt, m_const, scope_r); } @@ -264,13 +273,14 @@ impl methods for gather_loan_ctxt { } } - fn add_loans(scope_id: ast::node_id, loans: @const [loan]) { + fn add_loans(scope_id: ast::node_id, loans: @dvec) { alt self.req_maps.req_loan_map.find(scope_id) { some(l) { - *l += [loans]; + (*l).push(loans); } none { - self.req_maps.req_loan_map.insert(scope_id, @mut [loans]); + self.req_maps.req_loan_map.insert( + scope_id, @dvec::from_vec([mut loans])); } } } diff --git a/src/rustc/middle/borrowck/loan.rs b/src/rustc/middle/borrowck/loan.rs index e54ac388f0f3..c0e6f4accf70 100644 --- a/src/rustc/middle/borrowck/loan.rs +++ b/src/rustc/middle/borrowck/loan.rs @@ -5,8 +5,8 @@ export public_methods; impl public_methods for borrowck_ctxt { - fn loan(cmt: cmt, mutbl: ast::mutability) -> @const [loan] { - let lc = @{bccx: self, loans: @mut []}; + fn loan(cmt: cmt, mutbl: ast::mutability) -> @dvec { + let lc = @{bccx: self, loans: @dvec()}; lc.loan(cmt, mutbl); ret lc.loans; } @@ -14,7 +14,7 @@ impl public_methods for borrowck_ctxt { type loan_ctxt = @{ bccx: borrowck_ctxt, - loans: @mut [loan] + loans: @dvec }; impl loan_methods for loan_ctxt { @@ -23,9 +23,9 @@ impl loan_methods for loan_ctxt { // Note: all cmt's that we deal with will have a non-none lp, because // the entry point into this routine, `borrowck_ctxt::loan()`, rejects // any cmt with a none-lp. - *self.loans += [{lp:option::get(cmt.lp), - cmt:cmt, - mutbl:mutbl}]; + (*self.loans).push({lp:option::get(cmt.lp), + cmt:cmt, + mutbl:mutbl}); } fn loan(cmt: cmt, req_mutbl: ast::mutability) { diff --git a/src/rustc/middle/check_const.rs b/src/rustc/middle/check_const.rs index 4fbab3879d0c..6c2032c9c34d 100644 --- a/src/rustc/middle/check_const.rs +++ b/src/rustc/middle/check_const.rs @@ -2,6 +2,7 @@ import syntax::ast::*; import syntax::{visit, ast_util, ast_map}; import driver::session::session; import std::map::hashmap; +import dvec::{dvec, extensions}; fn check_crate(sess: session, crate: @crate, ast_map: ast_map::map, def_map: resolve::def_map, @@ -130,7 +131,7 @@ fn check_item_recursion(sess: session, ast_map: ast_map::map, sess: session, ast_map: ast_map::map, def_map: resolve::def_map, - idstack: @mut [node_id], + idstack: @dvec, }; let env = { @@ -138,7 +139,7 @@ fn check_item_recursion(sess: session, ast_map: ast_map::map, sess: sess, ast_map: ast_map, def_map: def_map, - idstack: @mut [] + idstack: @dvec() }; let visitor = visit::mk_vt(@{ @@ -152,9 +153,9 @@ fn check_item_recursion(sess: session, ast_map: ast_map::map, if (*env.idstack).contains(it.id) { env.sess.span_fatal(env.root_it.span, "recursive constant"); } - vec::push(*env.idstack, it.id); + (*env.idstack).push(it.id); visit::visit_item(it, env, v); - vec::pop(*env.idstack); + (*env.idstack).pop(); } fn visit_expr(e: @expr, &&env: env, v: visit::vt) { diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 3f82e647ab6b..0f1edb0c4158 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -57,7 +57,6 @@ import capture::{cap_move, cap_drop, cap_copy, cap_ref}; export check_crate; export last_use_map; -export spill_map; // Maps from an expr id to a list of variable ids for which this expr // is the last use. Typically, the expr is a path and the node id is @@ -66,13 +65,6 @@ export spill_map; // list of closed over variables that can be moved into the closure. type last_use_map = hashmap>; -// A set of variable ids which must be spilled (stored on the stack). -// We add in any variables or arguments where: -// (1) the variables are moved; -// (2) the address of the variable/argument is taken; -// or (3) we find a last use (as they may be moved). -type spill_map = hashmap; - enum variable = uint; enum live_node = uint; @@ -85,7 +77,7 @@ enum live_node_kind { fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map, - crate: @crate) -> (last_use_map, spill_map) { + crate: @crate) -> last_use_map { let visitor = visit::mk_vt(@{ visit_fn: visit_fn, visit_local: visit_local, @@ -94,12 +86,11 @@ fn check_crate(tcx: ty::ctxt, }); let last_use_map = int_hash(); - let spill_map = int_hash(); let initial_maps = @ir_maps(tcx, method_map, - last_use_map, spill_map); + last_use_map); visit::visit_crate(*crate, initial_maps, visitor); tcx.sess.abort_if_errors(); - ret (last_use_map, spill_map); + ret last_use_map; } impl of to_str::to_str for live_node { @@ -133,7 +124,7 @@ impl of to_str::to_str for variable { // assignment. And so forth. impl methods for live_node { - fn is_valid() -> bool { *self != uint::max_value } + pure fn is_valid() -> bool { *self != uint::max_value } } fn invalid_node() -> live_node { live_node(uint::max_value) } @@ -162,7 +153,6 @@ class ir_maps { let tcx: ty::ctxt; let method_map: typeck::method_map; let last_use_map: last_use_map; - let spill_map: spill_map; let mut num_live_nodes: uint; let mut num_vars: uint; @@ -174,11 +164,10 @@ class ir_maps { let mut lnks: [live_node_kind]; new(tcx: ty::ctxt, method_map: typeck::method_map, - last_use_map: last_use_map, spill_map: spill_map) { + last_use_map: last_use_map) { self.tcx = tcx; self.method_map = method_map; self.last_use_map = last_use_map; - self.spill_map = spill_map; self.num_live_nodes = 0u; self.num_vars = 0u; @@ -264,17 +253,6 @@ class ir_maps { self.lnks[*ln] } - fn add_spill(var: variable) { - let vk = self.var_kinds[*var]; - alt vk { - vk_local(id, _) | vk_arg(id, _, by_val) { - #debug["adding spill for %?", vk]; - self.spill_map.insert(id, ()); - } - vk_arg(*) | vk_field(_) | vk_self | vk_implicit_ret {} - } - } - fn add_last_use(expr_id: node_id, var: variable) { let vk = self.var_kinds[*var]; #debug["Node %d is a last use of variable %?", expr_id, vk]; @@ -308,7 +286,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, // swap in a new set of IR maps for this function body: let fn_maps = @ir_maps(self.tcx, self.method_map, - self.last_use_map, self.spill_map); + self.last_use_map); #debug["creating fn_maps: %x", ptr::addr_of(*fn_maps) as uint]; @@ -571,7 +549,7 @@ class liveness { fn live_on_exit(ln: live_node, var: variable) -> option { - self.live_on_entry(self.successors[*ln], var) + self.live_on_entry(copy self.successors[*ln], var) } fn used_on_entry(ln: live_node, var: variable) -> bool { @@ -590,7 +568,7 @@ class liveness { fn assigned_on_exit(ln: live_node, var: variable) -> option { - self.assigned_on_entry(self.successors[*ln], var) + self.assigned_on_entry(copy self.successors[*ln], var) } fn indices(ln: live_node, op: fn(uint)) { @@ -627,14 +605,14 @@ class liveness { wr.write_str("[ln("); wr.write_uint(*ln); wr.write_str(") of kind "); - wr.write_str(#fmt["%?", self.ir.lnks[*ln]]); + wr.write_str(#fmt["%?", copy self.ir.lnks[*ln]]); wr.write_str(" reads"); self.write_vars(wr, ln, {|idx| self.users[idx].reader}); wr.write_str(" writes"); self.write_vars(wr, ln, {|idx| self.users[idx].writer}); wr.write_str(" "); wr.write_str(" precedes "); - wr.write_str(self.successors[*ln].to_str()); + wr.write_str((copy self.successors[*ln]).to_str()); wr.write_str("]"); } } @@ -668,9 +646,9 @@ class liveness { let mut changed = false; self.indices2(ln, succ_ln) { |idx, succ_idx| - changed |= copy_if_invalid(self.users[succ_idx].reader, + changed |= copy_if_invalid(copy self.users[succ_idx].reader, self.users[idx].reader); - changed |= copy_if_invalid(self.users[succ_idx].writer, + changed |= copy_if_invalid(copy self.users[succ_idx].writer, self.users[idx].writer); if self.users[succ_idx].used && !self.users[idx].used { self.users[idx].used = true; @@ -1407,11 +1385,7 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) { vt.visit_expr(f, self, vt); vec::iter2(args, targs) { |arg_expr, arg_ty| alt ty::resolved_mode(self.tcx, arg_ty.mode) { - by_val | by_copy { - vt.visit_expr(arg_expr, self, vt); - } - by_ref | by_mutbl_ref { - self.spill_expr(arg_expr); + by_val | by_copy | by_ref | by_mutbl_ref{ vt.visit_expr(arg_expr, self, vt); } by_move { @@ -1421,10 +1395,6 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) { } } - expr_addr_of(_, arg_expr) { - self.spill_expr(arg_expr); - } - // no correctness conditions related to liveness expr_if_check(*) | expr_if(*) | expr_alt(*) | expr_while(*) | expr_loop(*) | @@ -1434,7 +1404,7 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) { expr_assert(*) | expr_check(*) | expr_copy(*) | expr_loop_body(*) | expr_cast(*) | expr_unary(*) | expr_fail(*) | expr_ret(*) | expr_break | expr_cont | expr_lit(_) | - expr_block(*) | expr_swap(*) | expr_mac(*) { + expr_block(*) | expr_swap(*) | expr_mac(*) | expr_addr_of(*) { visit::visit_expr(expr, self, vt); } } @@ -1501,10 +1471,7 @@ impl check_methods for @liveness { ln.to_str(), var.to_str()]; alt (*self).live_on_exit(ln, var) { - none { - // update spill map to include this variable, as it is moved: - (*self.ir).add_spill(var); - } + none { } some(lnk) { self.report_illegal_move(span, lnk, var); } @@ -1516,20 +1483,10 @@ impl check_methods for @liveness { some(_) {} none { (*self.ir).add_last_use(expr.id, var); - - // update spill map to include this variable, as it may be moved: - (*self.ir).add_spill(var); } } } - fn spill_expr(expr: @expr) { - alt (*self).variable_from_path(expr) { - some(var) {(*self.ir).add_spill(var)} - none {} - } - } - fn check_move_from_expr(expr: @expr, vt: vt<@liveness>) { #debug["check_move_from_expr(node %d: %s)", expr.id, expr_to_str(expr)]; @@ -1775,4 +1732,4 @@ impl check_methods for @liveness { } } } - } \ No newline at end of file + } diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index a92db033c229..6c75e470c0a8 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -100,7 +100,7 @@ type glob_imp_def = {def: def, path: @ast::view_path}; type indexed_mod = { m: option, index: mod_index, - mut glob_imports: [glob_imp_def], + glob_imports: dvec, mut globbed_exports: [ident], glob_imported_names: hashmap, path: str @@ -123,7 +123,7 @@ type env = def_map: def_map, ast_map: ast_map::map, imports: hashmap, - mut exp_map: exp_map, + exp_map: exp_map, mod_map: hashmap, block_map: hashmap, ext_map: ext_map, @@ -132,7 +132,7 @@ type env = ext_cache: ext_hash, used_imports: {mut track: bool, mut data: [node_id]}, - mut reported: [{ident: str, sc: scope}], + reported: dvec<{ident: str, sc: scope}>, mut ignored_imports: [node_id], mut current_tp: option, mut resolve_unexported: bool, @@ -174,7 +174,7 @@ fn create_env(sess: session, amap: ast_map::map) -> @env { def_map: int_hash(), ast_map: amap, imports: int_hash(), - mut exp_map: int_hash(), + exp_map: int_hash(), mod_map: int_hash(), block_map: int_hash(), ext_map: new_def_hash(), @@ -182,7 +182,7 @@ fn create_env(sess: session, amap: ast_map::map) -> @env { impl_cache: new_def_hash(), ext_cache: new_ext_hash(), used_imports: {mut track: false, mut data: []}, - mut reported: [], + reported: dvec(), mut ignored_imports: [], mut current_tp: none, mut resolve_unexported: false, @@ -270,7 +270,7 @@ fn map_crate(e: @env, c: @ast::crate) { e.mod_map.insert(i.id, @{m: some(md), index: index_mod(md), - mut glob_imports: [], + glob_imports: dvec(), mut globbed_exports: [], glob_imported_names: str_hash(), path: path_from_scope(sc, i.ident)}); @@ -279,7 +279,7 @@ fn map_crate(e: @env, c: @ast::crate) { e.mod_map.insert(i.id, @{m: none::, index: index_nmod(nmd), - mut glob_imports: [], + glob_imports: dvec(), mut globbed_exports: [], glob_imported_names: str_hash(), path: path_from_scope(sc, i.ident)}); @@ -301,7 +301,7 @@ fn map_crate(e: @env, c: @ast::crate) { let glob = {def: imp, path: vp}; alt list::head(sc) { scope_item(i) { - e.mod_map.get(i.id).glob_imports += [glob]; + e.mod_map.get(i.id).glob_imports.push(glob); } scope_block(b, _, _) { let globs = alt e.block_map.find(b.node.id) { @@ -311,8 +311,8 @@ fn map_crate(e: @env, c: @ast::crate) { e.block_map.insert(b.node.id, globs); } scope_crate { - e.mod_map.get(ast::crate_node_id).glob_imports - += [glob]; + e.mod_map.get(ast::crate_node_id). + glob_imports.push(glob); } _ { e.sess.span_bug(vi.span, "unexpected scope in a \ glob import"); } @@ -338,7 +338,7 @@ fn map_crate(e: @env, c: @ast::crate) { e.mod_map.insert(ast::crate_node_id, @{m: some(c.node.module), index: index_mod(c.node.module), - mut glob_imports: [], + glob_imports: dvec(), mut globbed_exports: [], glob_imported_names: str_hash(), path: ""}); @@ -899,7 +899,7 @@ fn unresolved_err(e: env, cx: ctxt, sp: span, name: ident, kind: str) { for e.reported.each {|rs| if str::eq(rs.ident, name) && err_scope == rs.sc { ret; } } - e.reported += [{ident: name, sc: err_scope}]; + e.reported.push({ident: name, sc: err_scope}); } _ {} } @@ -1536,7 +1536,7 @@ fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident, // absence takes the place of todo() if !info.glob_imported_names.contains_key(id) { info.glob_imported_names.insert(id, glob_resolving(sp)); - let globs = info.glob_imports; + let globs = info.glob_imports.get(); let val = lookup_in_globs(e, globs, sp, id, ns_val, dr); let typ = lookup_in_globs(e, globs, sp, id, ns_type, dr); let md = lookup_in_globs(e, globs, sp, id, ns_module, dr); diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 62c3134e9abd..c1d05bf39da1 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -62,6 +62,12 @@ enum dest { ignore, } +// Heap selectors. Indicate which heap something should go on. +enum heap { + heap_shared, + heap_exchange, +} + fn dest_str(ccx: @crate_ctxt, d: dest) -> str { alt d { by_val(v) { #fmt["by_val(%s)", val_str(ccx.tn, *v)] } @@ -341,75 +347,61 @@ fn opaque_box_body(bcx: block, PointerCast(bcx, bodyptr, T_ptr(type_of(ccx, body_t))) } -// trans_malloc_boxed_raw: expects an unboxed type and returns a pointer to +// malloc_raw: expects an unboxed type and returns a pointer to // enough space for a box of that type. This includes a rust_opaque_box // header. -fn malloc_boxed_raw(bcx: block, t: ty::t, - &static_ti: option<@tydesc_info>) -> ValueRef { - let _icx = bcx.insn_ctxt("trans_malloc_boxed_raw"); +fn malloc_raw(bcx: block, t: ty::t, heap: heap) -> ValueRef { + let _icx = bcx.insn_ctxt("malloc_raw"); let ccx = bcx.ccx(); - // Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc - // wants. - let box_ptr = ty::mk_imm_box(ccx.tcx, t); - let llty = type_of(ccx, box_ptr); + let (mk_fn, upcall) = alt heap { + heap_shared { (ty::mk_imm_box, ccx.upcalls.malloc) } + heap_exchange { + (ty::mk_imm_uniq, ccx.upcalls.exchange_malloc ) + } + }; - // Get the tydesc for the body: - let lltydesc = get_tydesc(ccx, t, static_ti); - lazily_emit_all_tydesc_glue(ccx, copy static_ti); - - // Allocate space: - let rval = Call(bcx, ccx.upcalls.malloc, [lltydesc]); - ret PointerCast(bcx, rval, llty); -} - -// trans_malloc_boxed: usefully wraps trans_malloc_box_raw; allocates a box, -// initializes the reference count to 1, and pulls out the body and rc -fn malloc_boxed(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} { - let _icx = bcx.insn_ctxt("trans_malloc_boxed"); - let mut ti = none; - let box = malloc_boxed_raw(bcx, t, ti); - let box_no_addrspace = non_gc_box_cast( - bcx, box, ty::mk_imm_box(bcx.tcx(), t)); - let body = GEPi(bcx, box_no_addrspace, [0u, abi::box_field_body]); - ret {box: box, body: body}; -} - -fn malloc_unique_raw(bcx: block, t: ty::t) -> ValueRef { - let _icx = bcx.insn_ctxt("malloc_unique_box_raw"); - let ccx = bcx.ccx(); - - // Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc - // wants. - let box_ptr = ty::mk_imm_uniq(ccx.tcx, t); - let llty = type_of(ccx, box_ptr); + // Grab the TypeRef type of box_ptr_ty. + let box_ptr_ty = mk_fn(bcx.tcx(), t); + let llty = type_of(ccx, box_ptr_ty); // Get the tydesc for the body: let mut static_ti = none; let lltydesc = get_tydesc(ccx, t, static_ti); - lazily_emit_all_tydesc_glue(ccx, static_ti); + lazily_emit_all_tydesc_glue(ccx, copy static_ti); // Allocate space: - let rval = Call(bcx, ccx.upcalls.exchange_malloc, [lltydesc]); + let rval = Call(bcx, upcall, [lltydesc]); ret PointerCast(bcx, rval, llty); } -fn malloc_unique(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} { - let _icx = bcx.insn_ctxt("malloc_unique_box"); - let box = malloc_unique_raw(bcx, t); - let non_gc_box = non_gc_box_cast(bcx, box, ty::mk_imm_uniq(bcx.tcx(), t)); +// malloc_general: usefully wraps malloc_raw; allocates a box, +// and pulls out the body +fn malloc_general(bcx: block, t: ty::t, heap: heap) -> + {box: ValueRef, body: ValueRef} { + let _icx = bcx.insn_ctxt("malloc_general"); + let mk_ty = alt heap { heap_shared { ty::mk_imm_box } + heap_exchange { ty::mk_imm_uniq } }; + let box = malloc_raw(bcx, t, heap); + let non_gc_box = non_gc_box_cast(bcx, box, mk_ty(bcx.tcx(), t)); let body = GEPi(bcx, non_gc_box, [0u, abi::box_field_body]); ret {box: box, body: body}; } +fn malloc_boxed(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} { + malloc_general(bcx, t, heap_shared) +} +fn malloc_unique(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} { + malloc_general(bcx, t, heap_exchange) +} + fn malloc_unique_dyn_raw(bcx: block, t: ty::t, size: ValueRef) -> ValueRef { - let _icx = bcx.insn_ctxt("malloc_unique_box_raw"); + let _icx = bcx.insn_ctxt("malloc_unique_dyn_raw"); let ccx = bcx.ccx(); - // Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc - // wants. - let box_ptr = ty::mk_imm_uniq(ccx.tcx, t); - let llty = type_of(ccx, box_ptr); + // Grab the TypeRef type of box_ptr_ty. + let box_ptr_ty = ty::mk_imm_uniq(ccx.tcx, t); + let llty = type_of(ccx, box_ptr_ty); // Get the tydesc for the body: let mut static_ti = none; @@ -423,7 +415,7 @@ fn malloc_unique_dyn_raw(bcx: block, t: ty::t, size: ValueRef) -> ValueRef { fn malloc_unique_dyn(bcx: block, t: ty::t, size: ValueRef ) -> {box: ValueRef, body: ValueRef} { - let _icx = bcx.insn_ctxt("malloc_unique_box"); + let _icx = bcx.insn_ctxt("malloc_unique_dyn"); let box = malloc_unique_dyn_raw(bcx, t, size); let body = GEPi(bcx, box, [0u, abi::box_field_body]); ret {box: box, body: body}; @@ -1194,7 +1186,7 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint, } } } else if field == abi::tydesc_field_visit_glue { - alt ti.free_glue { + alt ti.visit_glue { some(_) { } none { #debug("+++ lazily_emit_tydesc_glue VISIT %s", @@ -1230,6 +1222,8 @@ fn call_tydesc_glue_full(cx: block, v: ValueRef, tydesc: ValueRef, static_glue_fn = sti.drop_glue; } else if field == abi::tydesc_field_free_glue { static_glue_fn = sti.free_glue; + } else if field == abi::tydesc_field_visit_glue { + static_glue_fn = sti.visit_glue; } } } @@ -3749,6 +3743,8 @@ fn lval_to_dps(bcx: block, e: @ast::expr, dest: dest) -> block { let ty = expr_ty(bcx, e); let lv = trans_lval(bcx, e); let last_use = (lv.kind == owned && last_use_map.contains_key(e.id)); + #debug["is last use (%s) = %b, %d", expr_to_str(e), last_use, + lv.kind as int]; lval_result_to_dps(lv, ty, last_use, dest) } @@ -4039,29 +4035,10 @@ fn init_local(bcx: block, local: @ast::local) -> block { let ty = node_id_type(bcx, local.node.id); let llptr = alt bcx.fcx.lllocals.find(local.node.id) { some(local_mem(v)) { v } - some(_) { bcx.tcx().sess.span_bug(local.span, + _ { bcx.tcx().sess.span_bug(local.span, "init_local: Someone forgot to document why it's\ safe to assume local.node.init must be local_mem!"); - } - // This is a local that is kept immediate - none { - let initexpr = alt local.node.init { - some({expr, _}) { expr } - none { bcx.tcx().sess.span_bug(local.span, - "init_local: late-initialized var appears to \ - be an immediate -- possibly init_local was called \ - without calling alloc_local"); } - }; - let mut {bcx, val, kind} = trans_temp_lval(bcx, initexpr); - if kind != temporary { - if kind == owned { val = Load(bcx, val); } - let rs = take_ty_immediate(bcx, val, ty); - bcx = rs.bcx; val = rs.val; - add_clean_temp(bcx, val, ty); } - bcx.fcx.lllocals.insert(local.node.pat.id, local_imm(val)); - ret bcx; - } }; let mut bcx = bcx; @@ -4341,17 +4318,6 @@ fn alloc_local(cx: block, local: @ast::local) -> block { ast::pat_ident(pth, none) { some(path_to_ident(pth)) } _ { none } }; - // Do not allocate space for locals that can be kept immediate. - let ccx = cx.ccx(); - if option::is_some(simple_name) && - !ccx.maps.mutbl_map.contains_key(local.node.pat.id) && - !ccx.maps.spill_map.contains_key(local.node.pat.id) && - ty::type_is_immediate(t) { - alt local.node.init { - some({op: ast::init_assign, _}) { ret cx; } - _ {} - } - } let val = alloc_ty(cx, t); if cx.sess().opts.debuginfo { option::iter(simple_name) {|name| diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs index 9057c9ef6302..88cd126b1e4d 100644 --- a/src/rustc/middle/trans/closure.rs +++ b/src/rustc/middle/trans/closure.rs @@ -175,11 +175,12 @@ fn allocate_cbox(bcx: block, let mut temp_cleanups = []; let (bcx, box) = alt ck { ty::ck_box { - let box = malloc_boxed_raw(bcx, cdata_ty, ti); + get_tydesc(ccx, cdata_ty, ti); + let box = malloc_raw(bcx, cdata_ty, heap_shared); (bcx, box) } ty::ck_uniq { - let box = malloc_unique_raw(bcx, cdata_ty); + let box = malloc_raw(bcx, cdata_ty, heap_exchange); (bcx, box) } ty::ck_block { diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index 336cb897ed3b..09c5ebbf96aa 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -24,29 +24,30 @@ fn visit_ty_steps(bcx: block, t: ty::t, ty::ty_bool { step(bcx, "visit_bool", []) } ty::ty_int(ast::ty_i) { step(bcx, "visit_int", []) } ty::ty_int(ast::ty_char) { step(bcx, "visit_char", []) } - ty::ty_int(ast::ty_i8) { step(bcx, "visit_i8", []) } - ty::ty_int(ast::ty_i16) { step(bcx, "visit_i16", []) } - ty::ty_int(ast::ty_i32) { step(bcx, "visit_i32", []) } - ty::ty_int(ast::ty_i64) { step(bcx, "visit_i64", []) } - ty::ty_uint(ast::ty_u) { step(bcx, "visit_uint", []) } - ty::ty_uint(ast::ty_u8) { step(bcx, "visit_u8", []) } - ty::ty_uint(ast::ty_u16) { step(bcx, "visit_u16", []) } - ty::ty_uint(ast::ty_u32) { step(bcx, "visit_u32", []) } - ty::ty_uint(ast::ty_u64) { step(bcx, "visit_u64", []) } - ty::ty_float(ast::ty_f) { step(bcx, "visit_float", []) } - ty::ty_float(ast::ty_f32) { step(bcx, "visit_f32", []) } - ty::ty_float(ast::ty_f64) { step(bcx, "visit_f64", []) } - ty::ty_str { step(bcx, "visit_str", []) } + ty::ty_int(ast::ty_i8) { step(bcx, "visit_i8", []) } + ty::ty_int(ast::ty_i16) { step(bcx, "visit_i16", []) } + ty::ty_int(ast::ty_i32) { step(bcx, "visit_i32", []) } + ty::ty_int(ast::ty_i64) { step(bcx, "visit_i64", []) } + ty::ty_uint(ast::ty_u) { step(bcx, "visit_uint", []) } + ty::ty_uint(ast::ty_u8) { step(bcx, "visit_u8", []) } + ty::ty_uint(ast::ty_u16) { step(bcx, "visit_u16", []) } + ty::ty_uint(ast::ty_u32) { step(bcx, "visit_u32", []) } + ty::ty_uint(ast::ty_u64) { step(bcx, "visit_u64", []) } + ty::ty_float(ast::ty_f) { step(bcx, "visit_float", []) } + ty::ty_float(ast::ty_f32) { step(bcx, "visit_f32", []) } + ty::ty_float(ast::ty_f64) { step(bcx, "visit_f64", []) } + ty::ty_str { step(bcx, "visit_str", []) } - ty::ty_vec(mt) { - let bcx = step(bcx, "visit_vec_of", - [C_uint(ccx, mt.mutbl as uint)]); - sub(bcx, mt.ty) - } + ty::ty_vec(mt) { + let bcx = step(bcx, "visit_vec_of", + [C_uint(ccx, mt.mutbl as uint)]); + sub(bcx, mt.ty) + } _ { - bcx.sess().unimpl("trans::reflect::visit_ty_args on " - + ty_to_str(bcx.ccx().tcx, t)); + // Ideally this would be an unimpl, but sadly we have + // to pretend we can visit everything at this point. + step(bcx, "visit_bot", []) } } } diff --git a/src/rustc/middle/tstate/auxiliary.rs b/src/rustc/middle/tstate/auxiliary.rs index c34953ac33e6..6d6848336d49 100644 --- a/src/rustc/middle/tstate/auxiliary.rs +++ b/src/rustc/middle/tstate/auxiliary.rs @@ -13,9 +13,9 @@ import tstate::ann::{pre_and_post, pre_and_post_state, empty_ann, prestate, set_postcondition, ts_ann, clear_in_postcond, clear_in_poststate_}; -import tritv::*; -import bitvectors::promises_; import driver::session::session; +import dvec::{dvec, extensions}; +import tritv::{dont_care, tfalse, tritv_get, ttrue}; import syntax::print::pprust::{constr_args_to_str, lit_to_str}; @@ -197,7 +197,7 @@ type constraint = { path: @path, // FIXME: really only want it to be mut during collect_locals. // freeze it after that. - descs: @mut [pred_args] + descs: @dvec }; type tsconstr = { @@ -473,8 +473,7 @@ fn node_id_to_def(ccx: crate_ctxt, id: node_id) -> option { fn norm_a_constraint(id: def_id, c: constraint) -> [norm_constraint] { let mut rslt: [norm_constraint] = []; - let descs = *c.descs; - for vec::each(descs) {|pd| + for (*c.descs).each {|pd| rslt += [{bit_num: pd.node.bit_num, c: respan(pd.span, {path: c.path, @@ -498,11 +497,11 @@ fn constraints(fcx: fn_ctxt) -> [norm_constraint] { // FIXME // Would rather take an immutable vec as an argument, // should freeze it at some earlier point. -fn match_args(fcx: fn_ctxt, occs: @mut [pred_args], +fn match_args(fcx: fn_ctxt, occs: @dvec, occ: [@constr_arg_use]) -> uint { #debug("match_args: looking at %s", constr_args_to_str(fn@(i: inst) -> str { ret i.ident; }, occ)); - for vec::each(*occs) {|pd| + for (*occs).each {|pd| log(debug, "match_args: candidate " + pred_args_to_str(pd)); fn eq(p: inst, q: inst) -> bool { ret p.node == q.node; } @@ -613,7 +612,8 @@ fn substitute_arg(cx: ty::ctxt, actuals: [@expr], a: @constr_arg) -> } } -fn pred_args_matches(pattern: [constr_arg_general_], desc: pred_args) -> +fn pred_args_matches(pattern: [constr_arg_general_], + desc: pred_args) -> bool { let mut i = 0u; for desc.node.args.each {|c| @@ -638,7 +638,8 @@ fn pred_args_matches(pattern: [constr_arg_general_], desc: pred_args) -> ret true; } -fn find_instance_(pattern: [constr_arg_general_], descs: [pred_args]) -> +fn find_instance_(pattern: [constr_arg_general_], + descs: [pred_args]) -> option { for descs.each {|d| if pred_args_matches(pattern, d) { ret some(d.node.bit_num); } @@ -660,15 +661,19 @@ fn find_instances(_fcx: fn_ctxt, subst: subst, if vec::len(subst) == 0u { ret []; } let mut res = []; - for (*c.descs).each { |d| - if args_mention(d.node.args, find_in_subst_bool, subst) { - let old_bit_num = d.node.bit_num; - let newv = replace(subst, d); - alt find_instance_(newv, *c.descs) { - some(d1) {res += [{from: old_bit_num, to: d1}]} - _ {} - } - } else {} + (*c.descs).swap { |v| + let v <- vec::from_mut(v); + for v.each { |d| + if args_mention(d.node.args, find_in_subst_bool, subst) { + let old_bit_num = d.node.bit_num; + let newv = replace(subst, d); + alt find_instance_(newv, v) { + some(d1) {res += [{from: old_bit_num, to: d1}]} + _ {} + } + } else {} + } + vec::to_mut(v) } ret res; } @@ -811,7 +816,7 @@ fn copy_in_poststate_two(fcx: fn_ctxt, src_post: poststate, // dest def_id let insts = find_instances(fcx, subst, val); for insts.each {|p| - if promises_(p.from, src_post) { + if bitvectors::promises_(p.from, src_post) { set_in_poststate_(p.to, target_post); } } @@ -897,12 +902,6 @@ fn args_mention(args: [@constr_arg_use], fn use_var(fcx: fn_ctxt, v: node_id) { *fcx.enclosing.used_vars += [v]; } -// FIXME: This should be a function in vec::. -fn vec_contains(v: @mut [node_id], i: node_id) -> bool { - for vec::each(*v) {|d| if d == i { ret true; } } - ret false; -} - fn op_to_oper_ty(io: init_op) -> oper_type { alt io { init_move { oper_move } _ { oper_assign } } } diff --git a/src/rustc/middle/tstate/collect_locals.rs b/src/rustc/middle/tstate/collect_locals.rs index f8575569c5ac..0d3ab5321df3 100644 --- a/src/rustc/middle/tstate/collect_locals.rs +++ b/src/rustc/middle/tstate/collect_locals.rs @@ -8,6 +8,7 @@ import syntax::ast_util::respan; import driver::session::session; import aux::*; import std::map::hashmap; +import dvec::{dvec, extensions}; type ctxt = {cs: @mut [sp_constr], tcx: ty::ctxt}; @@ -57,12 +58,11 @@ fn add_constraint(tcx: ty::ctxt, c: sp_constr, next: uint, tbl: constr_map) -> let {path: p, def_id: d_id, args: args} = c.node; alt tbl.find(d_id) { some(ct) { - let {path: _, descs: pds} = ct; - *pds += [respan(c.span, {args: args, bit_num: next})]; + (*ct.descs).push(respan(c.span, {args: args, bit_num: next})); } none { - let rslt: @mut [pred_args] = - @mut [respan(c.span, {args: args, bit_num: next})]; + let rslt = @dvec(); + (*rslt).push(respan(c.span, {args: args, bit_num: next})); tbl.insert(d_id, {path:p, descs:rslt}); } } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index b4d2e86e7c68..ca70c7d70a62 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -4,19 +4,19 @@ import std::map::hashmap; import driver::session; import session::session; import syntax::{ast, ast_map}; -import syntax::ast::*; import syntax::ast_util; import syntax::ast_util::{is_local, local_def, split_class_items, new_def_hash}; import syntax::codemap::span; import metadata::csearch; -import util::common::*; import util::ppaux::region_to_str; import util::ppaux::vstore_to_str; import util::ppaux::{ty_to_str, tys_to_str, ty_constr_to_str}; -import syntax::print::pprust::*; import middle::lint::{get_warning_level, vecs_not_implicitly_copyable, ignore}; +import syntax::ast::*; +import syntax::print::pprust::*; + export ty_vid, region_vid, vid; export br_hashmap; export is_instantiable; @@ -63,7 +63,6 @@ export mt; export node_type_table; export pat_ty; export sequence_element_type; -export sort_methods; export stmt_node_id; export sty; export subst, subst_tps, substs_is_noop, substs_to_str, substs; @@ -2311,13 +2310,6 @@ fn method_idx(id: ast::ident, meths: [method]) -> option { ret none; } -fn sort_methods(meths: [method]) -> [method] { - fn method_lteq(a: method, b: method) -> bool { - ret str::le(a.ident, b.ident); - } - ret std::sort::merge_sort(bind method_lteq(_, _), meths); -} - fn occurs_check(tcx: ctxt, sp: span, vid: ty_vid, rt: t) { // Fast path if !type_needs_infer(rt) { ret; } diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index d8ce3d83a603..476ef9d3ba55 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -45,7 +45,8 @@ an rptr (`&r.T`) use the region `r` that appears in the rptr. "]; import check::fn_ctxt; -import rscope::*; +import rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope}; +import rscope::{in_binding_rscope, region_scope, type_rscope}; iface ast_conv { fn tcx() -> ty::ctxt; diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 2649dc6c6756..b3f7c5a93885 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -71,7 +71,8 @@ import collect::{methods}; // ccx.to_ty() import method::{methods}; // methods for method::lookup import middle::ty::tys_in_fn_ty; import regionmanip::{replace_bound_regions_in_fn_ty, region_of}; -import rscope::*; +import rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope}; +import rscope::{in_binding_rscope, region_scope, type_rscope}; type fn_ctxt = // var_bindings, locals and next_var_id are shared @@ -386,6 +387,12 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) { }; // typecheck the members for members.each {|m| check_class_member(class_ccx, class_t, m); } + // Check that there's at least one field + let (fields,_) = split_class_items(members); + if fields.len() < 1u { + ccx.tcx.sess.span_err(it.span, "A class must have at least one \ + field"); + } // Check that the class is instantiable check_instantiable(ccx.tcx, it.span, it.id); } diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index e97629a823b6..e81bd9d35478 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -369,31 +369,23 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) { let t_ctor = ty::mk_fn( tcx, - ty_of_fn_decl(ccx, - empty_rscope, - ast::proto_any, - ctor.node.dec, - none)); + ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_any, + ctor.node.dec, none)); write_ty_to_tcx(tcx, ctor.node.id, t_ctor); tcx.tcache.insert(local_def(ctor.node.id), {bounds: tpt.bounds, - rp: ast::rp_none, + rp: rp, ty: t_ctor}); option::iter(m_dtor) {|dtor| // Write the dtor type let t_dtor = ty::mk_fn( tcx, - // not sure about empty_rscope - // FIXME - ty_of_fn_decl(ccx, - empty_rscope, - ast::proto_any, - ast_util::dtor_dec(), - none)); + ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_any, + ast_util::dtor_dec(), none)); write_ty_to_tcx(tcx, dtor.node.id, t_dtor); tcx.tcache.insert(local_def(dtor.node.id), {bounds: tpt.bounds, - rp: ast::rp_none, + rp: rp, ty: t_dtor}); }; ensure_iface_methods(ccx, it.id); diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs index 60f4ea8dabff..c5c445702d51 100644 --- a/src/rustc/util/ppaux.rs +++ b/src/rustc/util/ppaux.rs @@ -1,6 +1,14 @@ import std::map::hashmap; import middle::ty; -import middle::ty::*; +import middle::ty::{arg, bound_region, br_anon, br_named, canon_mode}; +import middle::ty::{ck_block, ck_box, ck_uniq, constr, ctxt, field, method}; +import middle::ty::{mt, re_bound, re_free, re_scope, re_var, region, t}; +import middle::ty::{ty_bool, ty_bot, ty_box, ty_class, ty_constr, ty_enum}; +import middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_iface, ty_int}; +import middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param}; +import middle::ty::{ty_ptr, ty_rec, ty_res, ty_rptr, ty_self, ty_str, ty_tup}; +import middle::ty::{ty_type, ty_uniq, ty_uint, ty_var, ty_var_integral}; +import middle::ty::{ty_vec, vid}; import metadata::encoder; import syntax::codemap; import syntax::print::pprust; diff --git a/src/snapshots.txt b/src/snapshots.txt index 457c35cd737a..7b6938e6133e 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -6,6 +6,14 @@ S 2012-06-06 db31969 macos-x86_64 bd99c6745ae0b41b2ac749fdc58fe76a3ccb50a6 macos-i386 cba5620bbfe9195917799dd02fac5b9e2be997cd +S 2012-06-05 fec3b91 + winnt-i386 36348a2b016f25d9e3b7e1a8814a352c18123839 + linux-x86_64 7308f0eb3d6a9985c14dfbbde7e1f9eb901cc966 + linux-i386 d4c1e1733fd30945f96ae67dbc10289f2a9ec380 + freebsd-x86_64 d0ee6054d7d8320d64aa4dbb9b041537fa2665d5 + macos-x86_64 652501172b4fee6631f595c90538fd95914ef444 + macos-i386 5c54b5ecf54cc2631fdd48caa326ab44b5a2e494 + S 2012-06-04 7213274 winnt-i386 94b9414433fd83c086b349ded3159f0541aace16 linux-x86_64 eb9cf0de4cc09e8b8bfcf741eff4b20510e13a5b diff --git a/src/test/auxiliary/cci_nested_lib.rs b/src/test/auxiliary/cci_nested_lib.rs index 9c26221960ca..87ab9bbcfea3 100644 --- a/src/test/auxiliary/cci_nested_lib.rs +++ b/src/test/auxiliary/cci_nested_lib.rs @@ -1,14 +1,16 @@ -type alist = { eq_fn: fn@(A,A) -> bool, mut data: [(A,B)] }; +import dvec::{dvec,extensions}; + +type entry = {key: A, value: B}; +type alist = { eq_fn: fn@(A,A) -> bool, data: dvec> }; fn alist_add(lst: alist, k: A, v: B) { - lst.data += [(k, v)]; + lst.data.push({key:k, value:v}); } fn alist_get(lst: alist, k: A) -> B { let eq_fn = lst.eq_fn; - for lst.data.each {|pair| - let (ki, vi) = pair; // copy req'd for alias analysis - if eq_fn(k, ki) { ret vi; } + for lst.data.each {|entry| + if eq_fn(entry.key, k) { ret entry.value; } } fail; } @@ -16,14 +18,12 @@ fn alist_get(lst: alist, k: A) -> B { #[inline] fn new_int_alist() -> alist { fn eq_int(&&a: int, &&b: int) -> bool { a == b } - ret {eq_fn: eq_int, - mut data: []}; + ret {eq_fn: eq_int, data: dvec()}; } #[inline] fn new_int_alist_2() -> alist { #[inline] fn eq_int(&&a: int, &&b: int) -> bool { a == b } - ret {eq_fn: eq_int, - mut data: []}; + ret {eq_fn: eq_int, data: dvec()}; } \ No newline at end of file diff --git a/src/test/compile-fail/issue-2487-b.rs b/src/test/compile-fail/issue-2487-b.rs new file mode 100644 index 000000000000..a1438c531876 --- /dev/null +++ b/src/test/compile-fail/issue-2487-b.rs @@ -0,0 +1,19 @@ +class socket { + let sock: int; + + new() { self.sock = 1; } + + drop { } + + fn set_identity() { + closure { || + setsockopt_bytes(self.sock) //! ERROR copying a noncopyable value + } + } +} + +fn closure(f: fn@()) { f() } + +fn setsockopt_bytes(+_sock: int) { } + +fn main() {} diff --git a/src/test/compile-fail/issue-2509-a.rs b/src/test/compile-fail/issue-2509-a.rs new file mode 100644 index 000000000000..a500d249c07a --- /dev/null +++ b/src/test/compile-fail/issue-2509-a.rs @@ -0,0 +1,9 @@ +class c { //! ERROR A class must have at least one field + new() { } +} + +fn main() { + let a = c(); + let x = [a]; + let _y = x[0]; +} diff --git a/src/test/compile-fail/issue-511.rs b/src/test/compile-fail/issue-511.rs index f2ef8c90c3f6..40d25a375668 100644 --- a/src/test/compile-fail/issue-511.rs +++ b/src/test/compile-fail/issue-511.rs @@ -8,4 +8,8 @@ fn f(&o: option) { fn main() { f::(option::none); //!^ ERROR taking mut reference to static item + + // Additional errors reported by borrowck: + //^^ ERROR illegal borrow unless pure: creating mutable alias to aliasable, immutable memory + //^^^ NOTE impure due to access to impure function } \ No newline at end of file diff --git a/src/test/compile-fail/noncopyable-class.rs b/src/test/compile-fail/noncopyable-class.rs index da0a0a488f50..736fee0f66cb 100644 --- a/src/test/compile-fail/noncopyable-class.rs +++ b/src/test/compile-fail/noncopyable-class.rs @@ -3,14 +3,15 @@ // Test that a class with a non-copyable field can't be // copied class bar { - new() {} + let x: int; + new(x:int) {self.x = x;} drop {} } class foo { let i: int; let j: bar; - new(i:int) { self.i = i; self.j = bar(); } + new(i:int) { self.i = i; self.j = bar(5); } } fn main() { let x <- foo(10); let y = x; log(error, x); } diff --git a/src/test/compile-fail/regions-bounds.rs b/src/test/compile-fail/regions-bounds.rs index 1582c8a049fc..c62db9b8fff2 100644 --- a/src/test/compile-fail/regions-bounds.rs +++ b/src/test/compile-fail/regions-bounds.rs @@ -4,7 +4,7 @@ enum an_enum/& { } iface an_iface/& { } -class a_class/& { new() { } } +class a_class/& { let x:int; new(x:int) { self.x = x; } } fn a_fn1(e: an_enum/&a) -> an_enum/&b { ret e; //! ERROR mismatched types: expected `an_enum/&b` but found `an_enum/&a` diff --git a/src/test/compile-fail/vec-res-add.rs b/src/test/compile-fail/vec-res-add.rs index ea411ca27a2f..f6388b197983 100644 --- a/src/test/compile-fail/vec-res-add.rs +++ b/src/test/compile-fail/vec-res-add.rs @@ -1,7 +1,8 @@ // error-pattern: copying a noncopyable value class r { - new(_i:int) {} + let i:int; + new(i:int) {self.i = i;} drop {} } diff --git a/src/test/run-fail/bug-2470-bounds-check-overflow-2.rs b/src/test/run-fail/bug-2470-bounds-check-overflow-2.rs new file mode 100644 index 000000000000..215fd53ce5ed --- /dev/null +++ b/src/test/run-fail/bug-2470-bounds-check-overflow-2.rs @@ -0,0 +1,17 @@ +// xfail-test +// error-pattern:bounds check + +fn main() { + let x = [1u,2u,3u]; + + // This should cause a bounds-check failure, but may not if we do our + // bounds checking by comparing a scaled index value to the vector's + // length (in bytes), because the scaling of the index will cause it to + // wrap around to a small number. + + let idx = uint::max_value & !(uint::max_value >> 1u); + #error("ov2 idx = 0x%x", idx); + + // This should fail. + #error("ov2 0x%x", x[idx]); +} \ No newline at end of file diff --git a/src/test/run-fail/bug-2470-bounds-check-overflow-3.rs b/src/test/run-fail/bug-2470-bounds-check-overflow-3.rs new file mode 100644 index 000000000000..26737f8a9fab --- /dev/null +++ b/src/test/run-fail/bug-2470-bounds-check-overflow-3.rs @@ -0,0 +1,28 @@ +// xfail-test +// error-pattern:bounds check + +#[cfg(target_arch="x86")] +fn main() { + let x = [1u,2u,3u]; + + // This should cause a bounds-check failure, but may not if we do our + // bounds checking by truncating the index value to the size of the + // machine word, losing relevant bits of the index value. + + // This test is only meaningful on 32-bit hosts. + + let idx = u64::max_value & !(u64::max_value >> 1u); + #error("ov3 idx = 0x%8.8x%8.8x", + (idx >> 32) as uint, + idx as uint); + + // This should fail. + #error("ov3 0x%x", x[idx]); +} + +#[cfg(target_arch="x86_64")] +fn main() { + // This version just fails anyways, for symmetry on 64-bit hosts. + let x = [1u,2u,3u]; + #error("ov3 0x%x", x[200]); +} diff --git a/src/test/run-fail/bug-2470-bounds-check-overflow.rs b/src/test/run-fail/bug-2470-bounds-check-overflow.rs new file mode 100644 index 000000000000..84bd9ab5c76e --- /dev/null +++ b/src/test/run-fail/bug-2470-bounds-check-overflow.rs @@ -0,0 +1,24 @@ +// error-pattern:bounds check + +fn main() { + + // This should cause a bounds-check failure, but may not if we do our + // bounds checking by comparing the scaled index to the vector's + // address-bounds, since we've scaled the index to wrap around to the + // address of the 0th cell in the array (even though the index is + // huge). + + let x = [1u,2u,3u]; + vec::unpack_slice(x) {|p, _len| + let base = p as uint; // base = 0x1230 say + let idx = base / sys::size_of::(); // idx = 0x0246 say + #error("ov1 base = 0x%x", base); + #error("ov1 idx = 0x%x", idx); + #error("ov1 sizeof::() = 0x%x", sys::size_of::()); + #error("ov1 idx * sizeof::() = 0x%x", + idx * sys::size_of::()); + + // This should fail. + #error("ov1 0x%x", x[idx]); + } +} \ No newline at end of file diff --git a/src/test/run-fail/morestack2.rs b/src/test/run-fail/morestack2.rs index 736d0d81a5dd..d68e9c497895 100644 --- a/src/test/run-fail/morestack2.rs +++ b/src/test/run-fail/morestack2.rs @@ -21,7 +21,8 @@ fn getbig_call_c_and_fail(i: int) { } class and_then_get_big_again { - new() {} + let x:int; + new(x:int) {self.x = x;} drop { fn getbig(i: int) { if i != 0 { @@ -34,7 +35,7 @@ class and_then_get_big_again { fn main() { task::spawn {|| - let r = and_then_get_big_again(); + let r = and_then_get_big_again(4); getbig_call_c_and_fail(10000); }; } \ No newline at end of file diff --git a/src/test/run-fail/morestack3.rs b/src/test/run-fail/morestack3.rs index 61b0b824d25a..0f0aea5ccd12 100644 --- a/src/test/run-fail/morestack3.rs +++ b/src/test/run-fail/morestack3.rs @@ -5,7 +5,7 @@ use std; fn getbig_and_fail(&&i: int) { - let _r = and_then_get_big_again(); + let _r = and_then_get_big_again(5); if i != 0 { getbig_and_fail(i - 1); } else { @@ -14,7 +14,8 @@ fn getbig_and_fail(&&i: int) { } class and_then_get_big_again { - new() {} + let x:int; + new(x:int) {self.x = x;} drop { fn getbig(i: int) { if i != 0 { diff --git a/src/test/run-fail/morestack4.rs b/src/test/run-fail/morestack4.rs index 63155b50de15..b1c86d5110a9 100644 --- a/src/test/run-fail/morestack4.rs +++ b/src/test/run-fail/morestack4.rs @@ -5,7 +5,7 @@ use std; fn getbig_and_fail(&&i: int) { - let r = and_then_get_big_again(); + let r = and_then_get_big_again(5); if i != 0 { getbig_and_fail(i - 1); } else { @@ -14,7 +14,8 @@ fn getbig_and_fail(&&i: int) { } class and_then_get_big_again { - new() {} + let x:int; + new(x:int) {self.x = x;} drop {} } diff --git a/src/test/run-fail/rt-set-exit-status-fail2.rs b/src/test/run-fail/rt-set-exit-status-fail2.rs index 680df73d62e4..2c2665446cdf 100644 --- a/src/test/run-fail/rt-set-exit-status-fail2.rs +++ b/src/test/run-fail/rt-set-exit-status-fail2.rs @@ -1,19 +1,20 @@ // error-pattern:whatever class r { + let x:int; // Setting the exit status after the runtime has already // failed has no effect and the process exits with the // runtime's exit code drop { os::set_exit_status(50); } - new() {} + new(x:int) {self.x = x;} } fn main() { log(error, "whatever"); task::spawn {|| - let i = r(); + let i = r(5); }; fail; } \ No newline at end of file diff --git a/src/test/run-pass/alt-pattern-drop.rs b/src/test/run-pass/alt-pattern-drop.rs index 81ea2a2d7749..0af65bd18270 100644 --- a/src/test/run-pass/alt-pattern-drop.rs +++ b/src/test/run-pass/alt-pattern-drop.rs @@ -25,8 +25,10 @@ fn foo(s: @int) { fn main() { let s: @int = @0; // ref up + let count = dbg::refcount(s); + foo(s); // ref up then down log(debug, dbg::refcount(s)); - assert (dbg::refcount(s) == 1u); + assert (dbg::refcount(s) == count); } diff --git a/src/test/run-pass/class-implements-multiple-ifaces.rs b/src/test/run-pass/class-implements-multiple-ifaces.rs index 44cd125e1963..1a8f77776720 100644 --- a/src/test/run-pass/class-implements-multiple-ifaces.rs +++ b/src/test/run-pass/class-implements-multiple-ifaces.rs @@ -1,6 +1,7 @@ use std; import std::map::*; import vec::*; +import dvec::{dvec, extensions}; enum furniture { chair, couch, bed } enum body_part { finger, toe, nose, ear } @@ -26,7 +27,7 @@ fn vec_includes(xs: [T], x: T) -> bool { class cat implements noisy, scratchy, bitey { priv { let meows : @mut uint; - let scratched : @mut [furniture]; + let scratched : dvec; let bite_counts : hashmap; fn meow() -> uint { @@ -44,7 +45,7 @@ class cat implements noisy, scratchy, bitey { new(in_x : uint, in_y : int, in_name: str) { self.meows = @mut in_x; self.how_hungry = @mut in_y; - self.name = in_name; self.scratched = @mut []; + self.name = in_name; self.scratched = dvec(); let hsher: hashfn = fn@(p: body_part) -> uint { int::hash(p as int) }; let eqer : eqfn = @@ -61,10 +62,10 @@ class cat implements noisy, scratchy, bitey { fn meow_count() -> uint { *self.meows } fn scratch() -> option { let all = [chair, couch, bed]; - log(error, *(self.scratched)); + log(error, self.scratched); let mut rslt = none; - for each(all) {|thing| if !vec_includes(*(self.scratched), thing) { - *self.scratched += [thing]; + for each(all) {|thing| if !self.scratched.contains(thing) { + self.scratched.push(thing); ret some(thing); }} rslt } diff --git a/src/test/run-pass/conditional-compile.rs b/src/test/run-pass/conditional-compile.rs index 8f4bd22f75dd..2b64840d8301 100644 --- a/src/test/run-pass/conditional-compile.rs +++ b/src/test/run-pass/conditional-compile.rs @@ -26,11 +26,13 @@ enum tg { bar, } #[cfg(bogus)] class r { - new(i:int) {} + let i: int; + new(i:int) { self.i = i; } } class r { - new(i:int) {} + let i: int; + new(i:int) { self.i = i; } } #[cfg(bogus)] diff --git a/src/test/run-pass/iface-cast.rs b/src/test/run-pass/iface-cast.rs index b771eca4be80..1377bb2a2790 100644 --- a/src/test/run-pass/iface-cast.rs +++ b/src/test/run-pass/iface-cast.rs @@ -26,10 +26,9 @@ impl of to_str for int { impl of to_str for Tree { fn to_str() -> str { - #fmt["[%s, %s, %s]", - self.val.to_str(), - self.left.to_str(), - self.right.to_str()] + let l = self.left, r = self.right; + #fmt["[%s, %s, %s]", self.val.to_str(), + l.to_str(), r.to_str()] } } diff --git a/src/test/run-pass/issue-2487-a.rs b/src/test/run-pass/issue-2487-a.rs new file mode 100644 index 000000000000..ab1d9ccb3bea --- /dev/null +++ b/src/test/run-pass/issue-2487-a.rs @@ -0,0 +1,19 @@ +class socket { + let sock: int; + + new() { self.sock = 1; } + + drop { } + + fn set_identity() { + closure { || + setsockopt_bytes(copy self.sock) + } + } +} + +fn closure(f: fn()) { f() } + +fn setsockopt_bytes(_sock: int) { } + +fn main() {} diff --git a/src/test/run-pass/issue-2502.rs b/src/test/run-pass/issue-2502.rs new file mode 100644 index 000000000000..6aa35169dd5c --- /dev/null +++ b/src/test/run-pass/issue-2502.rs @@ -0,0 +1,13 @@ +class font/& { + let fontbuf: &self.[u8]; + + new(fontbuf: &self.[u8]) { + self.fontbuf = fontbuf; + } + + fn buf() -> &self.[u8] { + self.fontbuf + } +} + +fn main() { } diff --git a/src/test/run-pass/maybe-mutable.rs b/src/test/run-pass/maybe-mutable.rs index 8c9d63922a6f..4f305ff83788 100644 --- a/src/test/run-pass/maybe-mutable.rs +++ b/src/test/run-pass/maybe-mutable.rs @@ -4,7 +4,7 @@ // -*- rust -*- fn len(v: [const int]) -> uint { let mut i = 0u; - for v.each {|x| i += 1u; } + while i < vec::len(v) { i += 1u; } ret i; } diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index e9caa5f1d4b7..4b92e518b2e4 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -1,7 +1,3 @@ -// xfail-test -// -// This doesn't work quite yet in check-fast mode. Not sure why. Crashes. - enum my_visitor = @{ mut types: [str] }; impl of intrinsic::ty_visitor for my_visitor {