merge
This commit is contained in:
commit
cd02046de4
76 changed files with 749 additions and 574 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ fn try_parse_sources(filename: str, sources: map::hashmap<str, source>) {
|
|||
}
|
||||
}
|
||||
|
||||
fn load_one_source_package(&src: source, p: map::hashmap<str, json::json>) {
|
||||
fn load_one_source_package(&&src: source, p: map::hashmap<str, json::json>) {
|
||||
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<str, json::json>) {
|
|||
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; }
|
||||
|
|
|
|||
10
src/libcore/cmp.rs
Normal file
10
src/libcore/cmp.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#[doc="Interfaces used for comparison."]
|
||||
|
||||
iface ord {
|
||||
fn lt(&&other: self) -> bool;
|
||||
}
|
||||
|
||||
iface eq {
|
||||
fn eq(&&other: self) -> bool;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,11 @@ fn dvec<A>() -> dvec<A> {
|
|||
{mut data: [mut]}
|
||||
}
|
||||
|
||||
#[doc = "Creates a new dvec with a single element"]
|
||||
fn from_elt<A>(+e: A) -> dvec<A> {
|
||||
{mut data: [mut e]}
|
||||
}
|
||||
|
||||
#[doc = "Creates a new dvec with the contents of a vector"]
|
||||
fn from_vec<A>(+v: [mut A]) -> dvec<A> {
|
||||
{mut data: v}
|
||||
|
|
@ -234,7 +239,9 @@ impl extensions<A:copy> for dvec<A> {
|
|||
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<A:copy> for dvec<A> {
|
|||
v
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = "Returns the last element, failing if the vector is empty"]
|
||||
fn last() -> A {
|
||||
self.get_elt(self.len() - 1u)
|
||||
}
|
||||
}
|
||||
|
|
@ -108,7 +108,7 @@ fn get<A:copy>(future: future<A>) -> A {
|
|||
fn with<A,B>(future: future<A>, 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();
|
||||
|
|
|
|||
|
|
@ -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<U>(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]
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ impl extensions for rng {
|
|||
}
|
||||
|
||||
#[doc = "Shuffle a mutable vec in place"]
|
||||
fn shuffle_mut<T>(&values: [mut T]) {
|
||||
fn shuffle_mut<T>(&&values: [mut T]) {
|
||||
let mut i = values.len();
|
||||
while i >= 2u {
|
||||
// invariant: elements with index >= i have been locked in place.
|
||||
|
|
|
|||
|
|
@ -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<T>(s: str/&, f: fn([u8]/&) -> T) -> T unsafe {
|
||||
pure fn byte_slice<T>(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<uint> {
|
||||
pure fn find_char(s: str, c: char) -> option<uint> {
|
||||
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<uint> {
|
||||
pure fn find_char_from(s: str, c: char, start: uint) -> option<uint> {
|
||||
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<uint> {
|
||||
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<uint> {
|
||||
pure fn rfind_char(s: str, c: char) -> option<uint> {
|
||||
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<uint> {
|
||||
pure fn rfind_char_from(s: str, c: char, start: uint) -> option<uint> {
|
||||
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<uint> {
|
||||
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<uint> {
|
||||
pure fn find(s: str, f: fn(char) -> bool) -> option<uint> {
|
||||
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<uint> {
|
||||
pure fn find_from(s: str, start: uint, f: fn(char) -> bool) -> option<uint> {
|
||||
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<uint> {
|
||||
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<uint> {
|
||||
pure fn rfind(s: str, f: fn(char) -> bool) -> option<uint> {
|
||||
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<uint> {
|
||||
pure fn rfind_from(s: str, start: uint, f: fn(char) -> bool) -> option<uint> {
|
||||
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<uint> {
|
||||
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<uint> {
|
||||
pure fn find_str(haystack: str, needle: str) -> option<uint> {
|
||||
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<uint> {
|
||||
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<uint> {
|
||||
// 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::<u8>(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<T>(s: str, f: fn([u8]) -> T) -> T unsafe {
|
||||
pure fn as_bytes<T>(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<T>(s: str, f: fn(*u8) -> T) -> T unsafe {
|
||||
pure fn as_buf<T>(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<T>(s: str, f: fn(*libc::c_char) -> T) -> T unsafe {
|
||||
pure fn as_c_str<T>(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<T>(s: str/&, f: fn(*u8, uint) -> T) -> T unsafe {
|
||||
pure fn unpack_slice<T>(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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<T>() -> *type_desc {
|
||||
rusti::get_tydesc::<T>() as *type_desc
|
||||
pure fn get_type_desc<T>() -> *type_desc {
|
||||
unchecked { rusti::get_tydesc::<T>() as *type_desc }
|
||||
}
|
||||
|
||||
#[doc = "Returns the size of a type"]
|
||||
fn size_of<T>() -> uint unsafe {
|
||||
rusti::size_of::<T>()
|
||||
pure fn size_of<T>() -> uint unsafe {
|
||||
unchecked { rusti::size_of::<T>() }
|
||||
}
|
||||
|
||||
#[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<T>() -> uint unsafe {
|
||||
rusti::min_align_of::<T>()
|
||||
pure fn min_align_of<T>() -> uint unsafe {
|
||||
unchecked { rusti::min_align_of::<T>() }
|
||||
}
|
||||
|
||||
#[doc = "Returns the preferred alignment of a type"]
|
||||
fn pref_align_of<T>() -> uint unsafe {
|
||||
rusti::pref_align_of::<T>()
|
||||
pure fn pref_align_of<T>() -> uint unsafe {
|
||||
unchecked { rusti::pref_align_of::<T>() }
|
||||
}
|
||||
|
||||
#[doc = "Returns the refcount of a shared box"]
|
||||
fn refcount<T>(t: @T) -> uint {
|
||||
pure fn refcount<T>(t: @T) -> uint {
|
||||
unsafe {
|
||||
ret rustrt::refcount(unsafe::reinterpret_cast(t)) as uint;
|
||||
}
|
||||
}
|
||||
|
||||
fn log_str<T>(t: T) -> str {
|
||||
pure fn log_str<T>(t: T) -> str {
|
||||
unsafe {
|
||||
let data_ptr: *() = unsafe::reinterpret_cast(ptr::addr_of(t));
|
||||
rustrt::shape_log_str(get_type_desc::<T>(), data_ptr)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -211,18 +211,18 @@ fn from_mut<T>(+v: [mut T]) -> [T] unsafe {
|
|||
pure fn head<T: copy>(v: [const T]/&) -> T { v[0] }
|
||||
|
||||
#[doc = "Returns a vector containing all but the first element of a slice"]
|
||||
fn tail<T: copy>(v: [const T]/&) -> [T] {
|
||||
pure fn tail<T: copy>(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<T: copy>(v: [const T]/&, n: uint) -> [T] {
|
||||
pure fn tailn<T: copy>(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<T: copy>(v: [const T]/&) -> [T] {
|
||||
pure fn init<T: copy>(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<T>(v: [mut T], a: uint, b: uint) {
|
||||
fn swap<T>(&&v: [mut T], a: uint, b: uint) {
|
||||
v[a] <-> v[b];
|
||||
}
|
||||
|
||||
|
|
@ -1033,10 +1033,10 @@ pure fn unpack_mut_slice<T,U>(s: [mut T]/&,
|
|||
impl extensions/&<T> 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/&<T> for [const T]/& {
|
|||
impl extensions/&<T: copy> 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/&<T> for [T]/& {
|
||||
#[doc = "Reduce a vector from right to left"]
|
||||
#[inline]
|
||||
fn foldr<U: copy>(z: U, p: fn(T, U) -> U) -> U { foldr(self, z, p) }
|
||||
pure fn foldr<U: copy>(z: U, p: fn(T, U) -> U) -> U { foldr(self, z, p) }
|
||||
#[doc = "
|
||||
Iterates over a vector
|
||||
|
||||
|
|
@ -1075,7 +1075,7 @@ impl extensions/&<T> 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/&<T> 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/&<T> for [T]/& {
|
|||
elements then none is returned.
|
||||
"]
|
||||
#[inline]
|
||||
fn position(f: fn(T) -> bool) -> option<uint> { position(self, f) }
|
||||
pure fn position(f: fn(T) -> bool) -> option<uint> { position(self, f) }
|
||||
#[doc = "Find the first index containing a matching value"]
|
||||
#[inline]
|
||||
fn position_elem(x: T) -> option<uint> { position_elem(self, x) }
|
||||
pure fn position_elem(x: T) -> option<uint> { position_elem(self, x) }
|
||||
#[doc = "
|
||||
Iterates over a vector in reverse
|
||||
|
||||
|
|
@ -1103,7 +1103,7 @@ impl extensions/&<T> 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/&<T> 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/&<T> for [T]/& {
|
|||
matches no elements then none is returned.
|
||||
"]
|
||||
#[inline]
|
||||
fn rposition(f: fn(T) -> bool) -> option<uint> { rposition(self, f) }
|
||||
pure fn rposition(f: fn(T) -> bool) -> option<uint> { rposition(self, f) }
|
||||
#[doc = "Find the last index containing a matching value"]
|
||||
#[inline]
|
||||
fn rposition_elem(x: T) -> option<uint> { rposition_elem(self, x) }
|
||||
pure fn rposition_elem(x: T) -> option<uint> { rposition_elem(self, x) }
|
||||
#[doc = "
|
||||
Apply a function to each element of a vector and return the results
|
||||
"]
|
||||
#[inline]
|
||||
fn map<U>(f: fn(T) -> U) -> [U] { map(self, f) }
|
||||
pure fn map<U>(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<U>(f: fn(uint, T) -> U) -> [U] {
|
||||
pure fn mapi<U>(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/&<T> for [T]/& {
|
|||
of each result vector
|
||||
"]
|
||||
#[inline]
|
||||
fn flat_map<U>(f: fn(T) -> [U]) -> [U] { flat_map(self, f) }
|
||||
pure fn flat_map<U>(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/&<T> for [T]/& {
|
|||
the resulting vector.
|
||||
"]
|
||||
#[inline]
|
||||
fn filter_map<U: copy>(f: fn(T) -> option<U>) -> [U] {
|
||||
pure fn filter_map<U: copy>(f: fn(T) -> option<U>) -> [U] {
|
||||
filter_map(self, f)
|
||||
}
|
||||
}
|
||||
|
|
@ -1170,7 +1170,7 @@ impl extensions/&<T: copy> 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/&<T: copy> for [T]/& {
|
|||
is returned. If `f` matches no elements then none is returned.
|
||||
"]
|
||||
#[inline]
|
||||
fn find(f: fn(T) -> bool) -> option<T> { find(self, f) }
|
||||
pure fn find(f: fn(T) -> bool) -> option<T> { find(self, f) }
|
||||
#[doc = "
|
||||
Search for the last element that matches a given predicate
|
||||
|
||||
|
|
@ -1188,7 +1188,7 @@ impl extensions/&<T: copy> for [T]/& {
|
|||
matches no elements then none is returned.
|
||||
"]
|
||||
#[inline]
|
||||
fn rfind(f: fn(T) -> bool) -> option<T> { rfind(self, f) }
|
||||
pure fn rfind(f: fn(T) -> bool) -> option<T> { 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<T>(&v: [const T], new_len: uint) {
|
||||
unsafe fn set_len<T>(&&v: [const T], new_len: uint) {
|
||||
let repr: **vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
|
||||
(**repr).fill = new_len * sys::size_of::<T>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,7 @@ type arc_data<T: const> = {
|
|||
resource arc_destruct<T: const>(data: *libc::c_void) {
|
||||
unsafe {
|
||||
let data: ~arc_data<T> = 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.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#[doc = "A deque. Untested as of yet. Likely buggy"];
|
||||
|
||||
import option::{some, none};
|
||||
import dvec::{dvec, extensions};
|
||||
|
||||
iface t<T> {
|
||||
fn size() -> uint;
|
||||
|
|
@ -23,7 +24,7 @@ fn create<T: copy>() -> t<T> {
|
|||
* Grow is only called on full elts, so nelts is also len(elts), unlike
|
||||
* elsewhere.
|
||||
*/
|
||||
fn grow<T: copy>(nelts: uint, lo: uint, elts: [mut cell<T>]) ->
|
||||
fn grow<T: copy>(nelts: uint, lo: uint, -elts: [mut cell<T>]) ->
|
||||
[mut cell<T>] {
|
||||
assert (nelts == vec::len(elts));
|
||||
let mut rv = [mut];
|
||||
|
|
@ -39,38 +40,38 @@ fn create<T: copy>() -> t<T> {
|
|||
|
||||
ret rv;
|
||||
}
|
||||
fn get<T: copy>(elts: [mut cell<T>], i: uint) -> T {
|
||||
ret alt elts[i] { some(t) { t } _ { fail } };
|
||||
fn get<T: copy>(elts: dvec<cell<T>>, i: uint) -> T {
|
||||
alt elts.get_elt(i) { some(t) { t } _ { fail } }
|
||||
}
|
||||
|
||||
type repr<T> = {mut nelts: uint,
|
||||
mut lo: uint,
|
||||
mut hi: uint,
|
||||
mut elts: [mut cell<T>]};
|
||||
elts: dvec<cell<T>>};
|
||||
|
||||
impl <T: copy> of t<T> for repr<T> {
|
||||
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: copy>() -> t<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: copy>() -> t<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::<T>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
|
|||
qsort3::<T>(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<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
|
||||
arr: [mut T]) {
|
||||
fn quick_sort3<T: copy ord eq>(arr: [mut T]) {
|
||||
if len::<T>(arr) == 0u { ret; }
|
||||
qsort3::<T>(compare_func_lt, compare_func_eq, arr, 0,
|
||||
qsort3::<T>({ |x, y| x.lt(y) }, { |x, y| x.eq(y) }, arr, 0,
|
||||
(len::<T>(arr) as int) - 1);
|
||||
}
|
||||
|
||||
|
|
@ -163,11 +162,7 @@ fn quick_sort3<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
|
|||
mod test_qsort3 {
|
||||
fn check_sort(v1: [mut int], v2: [mut int]) {
|
||||
let len = vec::len::<int>(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::<int>(f1, f2, v1);
|
||||
quick_sort3::<int>(v1);
|
||||
let mut i = 0u;
|
||||
while i < len {
|
||||
log(debug, v2[i]);
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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" } }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ fn finish<T: qq_helper>
|
|||
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);}
|
||||
|
|
|
|||
|
|
@ -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<ident, selector>,
|
||||
mut literal_ast_matchers: [selector]};
|
||||
literal_ast_matchers: dvec<selector>};
|
||||
type bindings = hashmap<ident, arb_depth<matchable>>;
|
||||
|
||||
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::<selector>(),
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<mac_> {
|
||||
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<vstore> {
|
||||
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")
|
||||
|
|
|
|||
|
|
@ -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 } }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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<test>};
|
||||
|
||||
// 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(),
|
||||
|
|
|
|||
|
|
@ -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<cache_entry>) {
|
||||
#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<cache_entry>,
|
||||
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<int> {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -63,7 +63,9 @@ type cstore_private =
|
|||
type use_crate_map = map::hashmap<ast::node_id, ast::crate_num>;
|
||||
|
||||
// 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::<crate_metadata>();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<ast::node_id, @mut [@const [loan]]>,
|
||||
req_loan_map: hashmap<ast::node_id, @dvec<@dvec<loan>>>,
|
||||
pure_map: hashmap<ast::node_id, bckerr>
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<check_loan_ctxt>) {
|
||||
|
||||
#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,
|
||||
|
|
|
|||
|
|
@ -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<loan>) {
|
||||
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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<loan> {
|
||||
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<loan>
|
||||
};
|
||||
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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<node_id>,
|
||||
};
|
||||
|
||||
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<env>) {
|
||||
|
|
|
|||
|
|
@ -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<node_id, @dvec<node_id>>;
|
||||
|
||||
// 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<node_id, ()>;
|
||||
|
||||
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<live_node_kind> {
|
||||
|
||||
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<live_node_kind> {
|
||||
|
||||
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 {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ type glob_imp_def = {def: def, path: @ast::view_path};
|
|||
type indexed_mod = {
|
||||
m: option<ast::_mod>,
|
||||
index: mod_index,
|
||||
mut glob_imports: [glob_imp_def],
|
||||
glob_imports: dvec<glob_imp_def>,
|
||||
mut globbed_exports: [ident],
|
||||
glob_imported_names: hashmap<str, glob_import_state>,
|
||||
path: str
|
||||
|
|
@ -123,7 +123,7 @@ type env =
|
|||
def_map: def_map,
|
||||
ast_map: ast_map::map,
|
||||
imports: hashmap<node_id, import_state>,
|
||||
mut exp_map: exp_map,
|
||||
exp_map: exp_map,
|
||||
mod_map: hashmap<node_id, @indexed_mod>,
|
||||
block_map: hashmap<node_id, [glob_imp_def]>,
|
||||
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<uint>,
|
||||
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::<ast::_mod>,
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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|
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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", [])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<pred_args>
|
||||
};
|
||||
|
||||
type tsconstr = {
|
||||
|
|
@ -473,8 +473,7 @@ fn node_id_to_def(ccx: crate_ctxt, id: node_id) -> option<def> {
|
|||
|
||||
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<pred_args>,
|
||||
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_<inst>], desc: pred_args) ->
|
||||
fn pred_args_matches(pattern: [constr_arg_general_<inst>],
|
||||
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_<inst>], desc: pred_args) ->
|
|||
ret true;
|
||||
}
|
||||
|
||||
fn find_instance_(pattern: [constr_arg_general_<inst>], descs: [pred_args]) ->
|
||||
fn find_instance_(pattern: [constr_arg_general_<inst>],
|
||||
descs: [pred_args]) ->
|
||||
option<uint> {
|
||||
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<T>(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 } }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<uint> {
|
|||
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; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
type alist<A,B> = { eq_fn: fn@(A,A) -> bool, mut data: [(A,B)] };
|
||||
import dvec::{dvec,extensions};
|
||||
|
||||
type entry<A,B> = {key: A, value: B};
|
||||
type alist<A,B> = { eq_fn: fn@(A,A) -> bool, data: dvec<entry<A,B>> };
|
||||
|
||||
fn alist_add<A: copy, B: copy>(lst: alist<A,B>, k: A, v: B) {
|
||||
lst.data += [(k, v)];
|
||||
lst.data.push({key:k, value:v});
|
||||
}
|
||||
|
||||
fn alist_get<A: copy, B: copy>(lst: alist<A,B>, 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<A: copy, B: copy>(lst: alist<A,B>, k: A) -> B {
|
|||
#[inline]
|
||||
fn new_int_alist<B: copy>() -> alist<int, B> {
|
||||
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<B: copy>() -> alist<int, B> {
|
||||
#[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()};
|
||||
}
|
||||
19
src/test/compile-fail/issue-2487-b.rs
Normal file
19
src/test/compile-fail/issue-2487-b.rs
Normal file
|
|
@ -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() {}
|
||||
9
src/test/compile-fail/issue-2509-a.rs
Normal file
9
src/test/compile-fail/issue-2509-a.rs
Normal file
|
|
@ -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];
|
||||
}
|
||||
|
|
@ -8,4 +8,8 @@ fn f<T>(&o: option<T>) {
|
|||
fn main() {
|
||||
f::<int>(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
|
||||
}
|
||||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
}
|
||||
|
||||
|
|
|
|||
17
src/test/run-fail/bug-2470-bounds-check-overflow-2.rs
Normal file
17
src/test/run-fail/bug-2470-bounds-check-overflow-2.rs
Normal file
|
|
@ -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]);
|
||||
}
|
||||
28
src/test/run-fail/bug-2470-bounds-check-overflow-3.rs
Normal file
28
src/test/run-fail/bug-2470-bounds-check-overflow-3.rs
Normal file
|
|
@ -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]);
|
||||
}
|
||||
24
src/test/run-fail/bug-2470-bounds-check-overflow.rs
Normal file
24
src/test/run-fail/bug-2470-bounds-check-overflow.rs
Normal file
|
|
@ -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::<uint>(); // idx = 0x0246 say
|
||||
#error("ov1 base = 0x%x", base);
|
||||
#error("ov1 idx = 0x%x", idx);
|
||||
#error("ov1 sizeof::<uint>() = 0x%x", sys::size_of::<uint>());
|
||||
#error("ov1 idx * sizeof::<uint>() = 0x%x",
|
||||
idx * sys::size_of::<uint>());
|
||||
|
||||
// This should fail.
|
||||
#error("ov1 0x%x", x[idx]);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T>(xs: [T], x: T) -> bool {
|
|||
class cat implements noisy, scratchy, bitey {
|
||||
priv {
|
||||
let meows : @mut uint;
|
||||
let scratched : @mut [furniture];
|
||||
let scratched : dvec<furniture>;
|
||||
let bite_counts : hashmap<body_part, uint>;
|
||||
|
||||
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<body_part> =
|
||||
fn@(p: body_part) -> uint { int::hash(p as int) };
|
||||
let eqer : eqfn<body_part> =
|
||||
|
|
@ -61,10 +62,10 @@ class cat implements noisy, scratchy, bitey {
|
|||
fn meow_count() -> uint { *self.meows }
|
||||
fn scratch() -> option<furniture> {
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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()]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
19
src/test/run-pass/issue-2487-a.rs
Normal file
19
src/test/run-pass/issue-2487-a.rs
Normal file
|
|
@ -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() {}
|
||||
13
src/test/run-pass/issue-2502.rs
Normal file
13
src/test/run-pass/issue-2502.rs
Normal file
|
|
@ -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() { }
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue