Merge remote-tracking branch 'mozilla/master'
Conflicts: src/libextra/test.rs src/libstd/rt/global_heap.rs src/libstd/unstable/lang.rs src/libstd/vec.rs
This commit is contained in:
commit
fae3336769
247 changed files with 5152 additions and 5749 deletions
|
@ -139,11 +139,11 @@ endif
|
||||||
|
|
||||||
# version-string calculation
|
# version-string calculation
|
||||||
CFG_GIT_DIR := $(CFG_SRC_DIR).git
|
CFG_GIT_DIR := $(CFG_SRC_DIR).git
|
||||||
CFG_RELEASE = 0.7
|
CFG_RELEASE = 0.8-pre
|
||||||
CFG_VERSION = $(CFG_RELEASE)
|
CFG_VERSION = $(CFG_RELEASE)
|
||||||
# windows exe's need numeric versions - don't use anything but
|
# windows exe's need numeric versions - don't use anything but
|
||||||
# numbers and dots here
|
# numbers and dots here
|
||||||
CFG_VERSION_WIN = 0.7
|
CFG_VERSION_WIN = 0.8
|
||||||
|
|
||||||
ifneq ($(wildcard $(CFG_GIT)),)
|
ifneq ($(wildcard $(CFG_GIT)),)
|
||||||
ifneq ($(wildcard $(CFG_GIT_DIR)),)
|
ifneq ($(wildcard $(CFG_GIT_DIR)),)
|
||||||
|
|
2
configure
vendored
2
configure
vendored
|
@ -402,7 +402,7 @@ fi
|
||||||
step_msg "looking for build programs"
|
step_msg "looking for build programs"
|
||||||
|
|
||||||
probe_need CFG_PERL perl
|
probe_need CFG_PERL perl
|
||||||
probe_need CFG_CURL curl
|
probe_need CFG_CURLORWGET curl wget
|
||||||
probe_need CFG_PYTHON python2.7 python2.6 python2 python
|
probe_need CFG_PYTHON python2.7 python2.6 python2 python
|
||||||
|
|
||||||
python_version=$($CFG_PYTHON -V 2>&1)
|
python_version=$($CFG_PYTHON -V 2>&1)
|
||||||
|
|
21
doc/rust.md
21
doc/rust.md
|
@ -207,7 +207,7 @@ The keywords are the following strings:
|
||||||
as
|
as
|
||||||
break
|
break
|
||||||
copy
|
copy
|
||||||
do drop
|
do
|
||||||
else enum extern
|
else enum extern
|
||||||
false fn for
|
false fn for
|
||||||
if impl
|
if impl
|
||||||
|
@ -1107,11 +1107,11 @@ The derived types are borrowed pointers with the `'static` lifetime,
|
||||||
fixed-size arrays, tuples, and structs.
|
fixed-size arrays, tuples, and structs.
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
static bit1: uint = 1 << 0;
|
static BIT1: uint = 1 << 0;
|
||||||
static bit2: uint = 1 << 1;
|
static BIT2: uint = 1 << 1;
|
||||||
|
|
||||||
static bits: [uint, ..2] = [bit1, bit2];
|
static BITS: [uint, ..2] = [BIT1, BIT2];
|
||||||
static string: &'static str = "bitstring";
|
static STRING: &'static str = "bitstring";
|
||||||
|
|
||||||
struct BitsNStrings<'self> {
|
struct BitsNStrings<'self> {
|
||||||
mybits: [uint, ..2],
|
mybits: [uint, ..2],
|
||||||
|
@ -1119,8 +1119,8 @@ struct BitsNStrings<'self> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bits_n_strings: BitsNStrings<'static> = BitsNStrings {
|
static bits_n_strings: BitsNStrings<'static> = BitsNStrings {
|
||||||
mybits: bits,
|
mybits: BITS,
|
||||||
mystring: string
|
mystring: STRING
|
||||||
};
|
};
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
@ -2869,9 +2869,6 @@ The kinds are:
|
||||||
: Types of this kind can be safely sent between tasks.
|
: Types of this kind can be safely sent between tasks.
|
||||||
This kind includes scalars, owning pointers, owned closures, and
|
This kind includes scalars, owning pointers, owned closures, and
|
||||||
structural types containing only other owned types. All `Send` types are `Static`.
|
structural types containing only other owned types. All `Send` types are `Static`.
|
||||||
`Static`
|
|
||||||
: Types of this kind do not contain any borrowed pointers;
|
|
||||||
this can be a useful guarantee for code that breaks borrowing assumptions using [`unsafe` operations](#unsafe-functions).
|
|
||||||
`Copy`
|
`Copy`
|
||||||
: This kind includes all types that can be copied. All types with
|
: This kind includes all types that can be copied. All types with
|
||||||
sendable kind are copyable, as are managed boxes, managed closures,
|
sendable kind are copyable, as are managed boxes, managed closures,
|
||||||
|
@ -2879,14 +2876,12 @@ The kinds are:
|
||||||
Types with destructors (types that implement `Drop`) can not implement `Copy`.
|
Types with destructors (types that implement `Drop`) can not implement `Copy`.
|
||||||
`Drop`
|
`Drop`
|
||||||
: This is not strictly a kind, but its presence interacts with kinds: the `Drop`
|
: This is not strictly a kind, but its presence interacts with kinds: the `Drop`
|
||||||
trait provides a single method `finalize` that takes no parameters, and is run
|
trait provides a single method `drop` that takes no parameters, and is run
|
||||||
when values of the type are dropped. Such a method is called a "destructor",
|
when values of the type are dropped. Such a method is called a "destructor",
|
||||||
and are always executed in "top-down" order: a value is completely destroyed
|
and are always executed in "top-down" order: a value is completely destroyed
|
||||||
before any of the values it owns run their destructors. Only `Send` types
|
before any of the values it owns run their destructors. Only `Send` types
|
||||||
that do not implement `Copy` can implement `Drop`.
|
that do not implement `Copy` can implement `Drop`.
|
||||||
|
|
||||||
> **Note:** The `finalize` method may be renamed in future versions of Rust.
|
|
||||||
|
|
||||||
_Default_
|
_Default_
|
||||||
: Types with destructors, closure environments,
|
: Types with destructors, closure environments,
|
||||||
and various other _non-first-class_ types,
|
and various other _non-first-class_ types,
|
||||||
|
|
|
@ -108,7 +108,7 @@ impl Iterator<int> for ZeroStream {
|
||||||
## Container iterators
|
## Container iterators
|
||||||
|
|
||||||
Containers implement iteration over the contained elements by returning an
|
Containers implement iteration over the contained elements by returning an
|
||||||
iterator object. For example, vectors have four iterators available:
|
iterator object. For example, vector slices have four iterators available:
|
||||||
|
|
||||||
* `vector.iter()`, for immutable references to the elements
|
* `vector.iter()`, for immutable references to the elements
|
||||||
* `vector.mut_iter()`, for mutable references to the elements
|
* `vector.mut_iter()`, for mutable references to the elements
|
||||||
|
|
|
@ -237,8 +237,8 @@ can specify a variable's type by following it with a colon, then the type
|
||||||
name. Static items, on the other hand, always require a type annotation.
|
name. Static items, on the other hand, always require a type annotation.
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
static monster_factor: float = 57.8;
|
static MONSTER_FACTOR: float = 57.8;
|
||||||
let monster_size = monster_factor * 10.0;
|
let monster_size = MONSTER_FACTOR * 10.0;
|
||||||
let monster_size: int = 50;
|
let monster_size: int = 50;
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
|
|
@ -323,9 +323,9 @@ AR_i686-pc-mingw32=$(AR)
|
||||||
CFG_LIB_NAME_i686-pc-mingw32=$(1).dll
|
CFG_LIB_NAME_i686-pc-mingw32=$(1).dll
|
||||||
CFG_LIB_GLOB_i686-pc-mingw32=$(1)-*.dll
|
CFG_LIB_GLOB_i686-pc-mingw32=$(1)-*.dll
|
||||||
CFG_LIB_DSYM_GLOB_i686-pc-mingw32=$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_i686-pc-mingw32=$(1)-*.dylib.dSYM
|
||||||
CFG_GCCISH_CFLAGS_i686-pc-mingw32 := -Wall -Werror -g -march=i686
|
CFG_GCCISH_CFLAGS_i686-pc-mingw32 := -Wall -Werror -g -m32 -march=i686 -D_WIN32_WINNT=0x0600
|
||||||
CFG_GCCISH_CXXFLAGS_i686-pc-mingw32 := -fno-rtti
|
CFG_GCCISH_CXXFLAGS_i686-pc-mingw32 := -fno-rtti
|
||||||
CFG_GCCISH_LINK_FLAGS_i686-pc-mingw32 := -shared -fPIC -g
|
CFG_GCCISH_LINK_FLAGS_i686-pc-mingw32 := -shared -fPIC -g -m32
|
||||||
CFG_GCCISH_DEF_FLAG_i686-pc-mingw32 :=
|
CFG_GCCISH_DEF_FLAG_i686-pc-mingw32 :=
|
||||||
CFG_GCCISH_PRE_LIB_FLAGS_i686-pc-mingw32 :=
|
CFG_GCCISH_PRE_LIB_FLAGS_i686-pc-mingw32 :=
|
||||||
CFG_GCCISH_POST_LIB_FLAGS_i686-pc-mingw32 :=
|
CFG_GCCISH_POST_LIB_FLAGS_i686-pc-mingw32 :=
|
||||||
|
@ -367,6 +367,31 @@ CFG_LDPATH_i586-mingw32msvc :=
|
||||||
CFG_RUN_i586-mingw32msvc=
|
CFG_RUN_i586-mingw32msvc=
|
||||||
CFG_RUN_TARG_i586-mingw32msvc=
|
CFG_RUN_TARG_i586-mingw32msvc=
|
||||||
|
|
||||||
|
# x86_64-w64-mingw32 configuration
|
||||||
|
CC_x86_64-w64-mingw32=$(CC)
|
||||||
|
CXX_x86_64-w64-mingw32=$(CXX)
|
||||||
|
CPP_x86_64-w64-mingw32=$(CPP)
|
||||||
|
AR_x86_64-w64-mingw32=$(AR)
|
||||||
|
CFG_LIB_NAME_x86_64-w64-mingw32=$(1).dll
|
||||||
|
CFG_LIB_GLOB_x86_64-w64-mingw32=$(1)-*.dll
|
||||||
|
CFG_LIB_DSYM_GLOB_x86_64-w64-mingw32=$(1)-*.dylib.dSYM
|
||||||
|
CFG_GCCISH_CFLAGS_x86_64-w64-mingw32 := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600
|
||||||
|
CFG_GCCISH_CXXFLAGS_x86_64-w64-mingw32 := -fno-rtti
|
||||||
|
CFG_GCCISH_LINK_FLAGS_x86_64-w64-mingw32 := -shared -fPIC -g -m64
|
||||||
|
CFG_GCCISH_DEF_FLAG_x86_64-w64-mingw32 :=
|
||||||
|
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-w64-mingw32 :=
|
||||||
|
CFG_GCCISH_POST_LIB_FLAGS_x86_64-w64-mingw32 :=
|
||||||
|
CFG_DEF_SUFFIX_x86_64-w64-mingw32 := .mingw32.def
|
||||||
|
CFG_INSTALL_NAME_x86_64-w64-mingw32 =
|
||||||
|
CFG_LIBUV_LINK_FLAGS_x86_64-w64-mingw32 := -lWs2_32 -lpsapi -liphlpapi
|
||||||
|
CFG_EXE_SUFFIX_x86_64-w64-mingw32 := .exe
|
||||||
|
CFG_WINDOWSY_x86_64-w64-mingw32 := 1
|
||||||
|
CFG_UNIXY_x86_64-w64-mingw32 :=
|
||||||
|
CFG_PATH_MUNGE_x86_64-w64-mingw32 :=
|
||||||
|
CFG_LDPATH_x86_64-w64-mingw32 :=$(CFG_LDPATH_x86_64-w64-mingw32):$(PATH)
|
||||||
|
CFG_RUN_x86_64-w64-mingw32=PATH="$(CFG_LDPATH_x86_64-w64-mingw32):$(1)" $(2)
|
||||||
|
CFG_RUN_TARG_x86_64-w64-mingw32=$(call CFG_RUN_x86_64-w64-mingw32,$(HLIB$(1)_H_$(CFG_BUILD_TRIPLE)),$(2))
|
||||||
|
|
||||||
# x86_64-unknown-freebsd configuration
|
# x86_64-unknown-freebsd configuration
|
||||||
CC_x86_64-unknown-freebsd=$(CC)
|
CC_x86_64-unknown-freebsd=$(CC)
|
||||||
CXX_x86_64-unknown-freebsd=$(CXX)
|
CXX_x86_64-unknown-freebsd=$(CXX)
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
# The names of crates that must be tested
|
# The names of crates that must be tested
|
||||||
TEST_TARGET_CRATES = std extra
|
TEST_TARGET_CRATES = std extra
|
||||||
TEST_HOST_CRATES = syntax rustc rustdoc rusti rust rustpkg
|
TEST_HOST_CRATES = syntax rustc rustdoc rust rustpkg rusti
|
||||||
TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES)
|
TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES)
|
||||||
|
|
||||||
# Markdown files under doc/ that should have their code extracted and run
|
# Markdown files under doc/ that should have their code extracted and run
|
||||||
|
@ -157,6 +157,7 @@ check-test: cleantestlibs cleantmptestlogs all check-stage2-rfail
|
||||||
|
|
||||||
check-lite: cleantestlibs cleantmptestlogs \
|
check-lite: cleantestlibs cleantmptestlogs \
|
||||||
check-stage2-std check-stage2-extra check-stage2-rpass \
|
check-stage2-std check-stage2-extra check-stage2-rpass \
|
||||||
|
check-stage2-rustpkg check-stage2-rusti \
|
||||||
check-stage2-rfail check-stage2-cfail
|
check-stage2-rfail check-stage2-cfail
|
||||||
$(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
|
$(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTPKG_$(4)): \
|
||||||
$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_EXTRALIB_$(4)) \
|
$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_EXTRALIB_$(4)) \
|
||||||
$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4))
|
$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4))
|
||||||
@$$(call E, compile_and_link: $$@)
|
@$$(call E, compile_and_link: $$@)
|
||||||
$$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$< && touch $$@
|
$$(STAGE$(1)_T_$(4)_H_$(3)) $$(WFLAGS_ST$(1)) -o $$@ $$< && touch $$@
|
||||||
|
|
||||||
$$(TBIN$(1)_T_$(4)_H_$(3))/rustpkg$$(X_$(4)): \
|
$$(TBIN$(1)_T_$(4)_H_$(3))/rustpkg$$(X_$(4)): \
|
||||||
$$(DRIVER_CRATE) \
|
$$(DRIVER_CRATE) \
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use core::prelude::*;
|
|
||||||
|
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
pub enum mode {
|
pub enum mode {
|
||||||
mode_compile_fail,
|
mode_compile_fail,
|
||||||
|
|
|
@ -11,21 +11,16 @@
|
||||||
#[crate_type = "bin"];
|
#[crate_type = "bin"];
|
||||||
|
|
||||||
#[allow(non_camel_case_types)];
|
#[allow(non_camel_case_types)];
|
||||||
|
#[allow(unrecognized_lint)]; // NOTE: remove after snapshot
|
||||||
|
#[deny(warnings)];
|
||||||
|
|
||||||
#[no_core]; // XXX: Remove after snapshot
|
extern mod extra;
|
||||||
#[no_std];
|
|
||||||
|
|
||||||
extern mod core(name = "std", vers = "0.7");
|
use std::os;
|
||||||
extern mod extra(name = "extra", vers = "0.7");
|
|
||||||
|
|
||||||
use core::prelude::*;
|
|
||||||
use core::*;
|
|
||||||
|
|
||||||
use extra::getopts;
|
use extra::getopts;
|
||||||
use extra::test;
|
use extra::test;
|
||||||
|
|
||||||
use core::result::{Ok, Err};
|
|
||||||
|
|
||||||
use common::config;
|
use common::config;
|
||||||
use common::mode_run_pass;
|
use common::mode_run_pass;
|
||||||
use common::mode_run_fail;
|
use common::mode_run_fail;
|
||||||
|
@ -42,13 +37,6 @@ pub mod runtest;
|
||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
|
||||||
mod std {
|
|
||||||
pub use core::cmp;
|
|
||||||
pub use core::str;
|
|
||||||
pub use core::sys;
|
|
||||||
pub use core::unstable;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let args = os::args();
|
let args = os::args();
|
||||||
let config = parse_config(args);
|
let config = parse_config(args);
|
||||||
|
@ -98,8 +86,8 @@ pub fn parse_config(args: ~[~str]) -> config {
|
||||||
run_ignored: getopts::opt_present(matches, "ignored"),
|
run_ignored: getopts::opt_present(matches, "ignored"),
|
||||||
filter:
|
filter:
|
||||||
if !matches.free.is_empty() {
|
if !matches.free.is_empty() {
|
||||||
option::Some(copy matches.free[0])
|
Some(copy matches.free[0])
|
||||||
} else { option::None },
|
} else { None },
|
||||||
logfile: getopts::opt_maybe_str(matches, "logfile").map(|s| Path(*s)),
|
logfile: getopts::opt_maybe_str(matches, "logfile").map(|s| Path(*s)),
|
||||||
runtool: getopts::opt_maybe_str(matches, "runtool"),
|
runtool: getopts::opt_maybe_str(matches, "runtool"),
|
||||||
rustcflags: getopts::opt_maybe_str(matches, "rustcflags"),
|
rustcflags: getopts::opt_maybe_str(matches, "rustcflags"),
|
||||||
|
@ -148,8 +136,8 @@ pub fn log_config(config: &config) {
|
||||||
|
|
||||||
pub fn opt_str<'a>(maybestr: &'a Option<~str>) -> &'a str {
|
pub fn opt_str<'a>(maybestr: &'a Option<~str>) -> &'a str {
|
||||||
match *maybestr {
|
match *maybestr {
|
||||||
option::None => "(none)",
|
None => "(none)",
|
||||||
option::Some(ref s) => {
|
Some(ref s) => {
|
||||||
let s: &'a str = *s;
|
let s: &'a str = *s;
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
@ -161,7 +149,7 @@ pub fn opt_str2(maybestr: Option<~str>) -> ~str {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn str_opt(maybestr: ~str) -> Option<~str> {
|
pub fn str_opt(maybestr: ~str) -> Option<~str> {
|
||||||
if maybestr != ~"(none)" { option::Some(maybestr) } else { option::None }
|
if maybestr != ~"(none)" { Some(maybestr) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn str_mode(s: ~str) -> mode {
|
pub fn str_mode(s: ~str) -> mode {
|
||||||
|
@ -199,8 +187,8 @@ pub fn test_opts(config: &config) -> test::TestOpts {
|
||||||
logfile: copy config.logfile,
|
logfile: copy config.logfile,
|
||||||
run_tests: true,
|
run_tests: true,
|
||||||
run_benchmarks: false,
|
run_benchmarks: false,
|
||||||
save_results: option::None,
|
save_results: None,
|
||||||
compare_results: option::None
|
compare_results: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +256,7 @@ pub fn make_test_name(config: &config, testfile: &Path) -> test::TestName {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_test_closure(config: &config, testfile: &Path) -> test::TestFn {
|
pub fn make_test_closure(config: &config, testfile: &Path) -> test::TestFn {
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
let config = Cell::new(copy *config);
|
let config = Cell::new(copy *config);
|
||||||
let testfile = Cell::new(testfile.to_str());
|
let testfile = Cell::new(testfile.to_str());
|
||||||
test::DynTestFn(|| { runtest::run(config.take(), testfile.take()) })
|
test::DynTestFn(|| { runtest::run(config.take(), testfile.take()) })
|
||||||
|
|
|
@ -8,9 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use core::prelude::*;
|
use std::io;
|
||||||
|
|
||||||
use core::io;
|
|
||||||
|
|
||||||
pub struct ExpectedError { line: uint, kind: ~str, msg: ~str }
|
pub struct ExpectedError { line: uint, kind: ~str, msg: ~str }
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,11 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use core::prelude::*;
|
|
||||||
|
|
||||||
use common::config;
|
use common::config;
|
||||||
use common;
|
use common;
|
||||||
|
|
||||||
use core::io;
|
use std::io;
|
||||||
use core::os;
|
use std::os;
|
||||||
|
|
||||||
pub struct TestProps {
|
pub struct TestProps {
|
||||||
// Lines that should be expected, in order, on standard out
|
// Lines that should be expected, in order, on standard out
|
||||||
|
|
|
@ -8,11 +8,9 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use core::prelude::*;
|
use std::os;
|
||||||
|
use std::run;
|
||||||
use core::os;
|
use std::str;
|
||||||
use core::run;
|
|
||||||
use core::str;
|
|
||||||
|
|
||||||
#[cfg(target_os = "win32")]
|
#[cfg(target_os = "win32")]
|
||||||
fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] {
|
fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] {
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use core::prelude::*;
|
|
||||||
|
|
||||||
use common::mode_run_pass;
|
use common::mode_run_pass;
|
||||||
use common::mode_run_fail;
|
use common::mode_run_fail;
|
||||||
use common::mode_compile_fail;
|
use common::mode_compile_fail;
|
||||||
|
@ -22,10 +20,10 @@ use procsrv;
|
||||||
use util;
|
use util;
|
||||||
use util::logv;
|
use util::logv;
|
||||||
|
|
||||||
use core::io;
|
use std::io;
|
||||||
use core::os;
|
use std::os;
|
||||||
use core::uint;
|
use std::uint;
|
||||||
use core::vec;
|
use std::vec;
|
||||||
|
|
||||||
pub fn run(config: config, testfile: ~str) {
|
pub fn run(config: config, testfile: ~str) {
|
||||||
if config.verbose {
|
if config.verbose {
|
||||||
|
@ -79,8 +77,8 @@ fn run_rfail_test(config: &config, props: &TestProps, testfile: &Path) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// The value our Makefile configures valgrind to return on failure
|
// The value our Makefile configures valgrind to return on failure
|
||||||
static valgrind_err: int = 100;
|
static VALGRIND_ERR: int = 100;
|
||||||
if ProcRes.status == valgrind_err {
|
if ProcRes.status == VALGRIND_ERR {
|
||||||
fatal_ProcRes(~"run-fail test isn't valgrind-clean!", &ProcRes);
|
fatal_ProcRes(~"run-fail test isn't valgrind-clean!", &ProcRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,8 +100,8 @@ fn run_rfail_test(config: &config, props: &TestProps, testfile: &Path) {
|
||||||
|
|
||||||
fn check_correct_failure_status(ProcRes: &ProcRes) {
|
fn check_correct_failure_status(ProcRes: &ProcRes) {
|
||||||
// The value the rust runtime returns on failure
|
// The value the rust runtime returns on failure
|
||||||
static rust_err: int = 101;
|
static RUST_ERR: int = 101;
|
||||||
if ProcRes.status != rust_err {
|
if ProcRes.status != RUST_ERR {
|
||||||
fatal_ProcRes(
|
fatal_ProcRes(
|
||||||
fmt!("failure produced the wrong error code: %d",
|
fmt!("failure produced the wrong error code: %d",
|
||||||
ProcRes.status),
|
ProcRes.status),
|
||||||
|
@ -601,9 +599,8 @@ fn make_run_args(config: &config, _props: &TestProps, testfile: &Path) ->
|
||||||
ProcArgs {
|
ProcArgs {
|
||||||
// If we've got another tool to run under (valgrind),
|
// If we've got another tool to run under (valgrind),
|
||||||
// then split apart its command
|
// then split apart its command
|
||||||
let toolargs = split_maybe_args(&config.runtool);
|
let mut args = split_maybe_args(&config.runtool);
|
||||||
|
args.push(make_exe_name(config, testfile).to_str());
|
||||||
let mut args = toolargs + [make_exe_name(config, testfile).to_str()];
|
|
||||||
let prog = args.shift();
|
let prog = args.shift();
|
||||||
return ProcArgs {prog: prog, args: args};
|
return ProcArgs {prog: prog, args: args};
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,10 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use core::prelude::*;
|
|
||||||
|
|
||||||
use common::config;
|
use common::config;
|
||||||
|
|
||||||
use core::io;
|
use std::io;
|
||||||
use core::os::getenv;
|
use std::os::getenv;
|
||||||
|
|
||||||
pub fn make_new_path(path: &str) -> ~str {
|
pub fn make_new_path(path: &str) -> ~str {
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#[no_core];
|
|
||||||
#[no_std];
|
|
||||||
|
|
||||||
extern mod core(name = "std", vers = "0.7");
|
|
||||||
|
|
||||||
#[cfg(rustpkg)]
|
#[cfg(rustpkg)]
|
||||||
extern mod this(name = "rustpkg");
|
extern mod this(name = "rustpkg");
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<!ENTITY rustIdent "[a-zA-Z_][a-zA-Z_0-9]*">
|
<!ENTITY rustIdent "[a-zA-Z_][a-zA-Z_0-9]*">
|
||||||
<!ENTITY rustIntSuf "([iu](8|16|32|64)?)?">
|
<!ENTITY rustIntSuf "([iu](8|16|32|64)?)?">
|
||||||
]>
|
]>
|
||||||
<language name="Rust" version="0.7" kateversion="2.4" section="Sources" extensions="*.rs;*.rc" mimetype="text/x-rust" priority="15">
|
<language name="Rust" version="0.8-pre" kateversion="2.4" section="Sources" extensions="*.rs;*.rc" mimetype="text/x-rust" priority="15">
|
||||||
<highlighting>
|
<highlighting>
|
||||||
<list name="fn">
|
<list name="fn">
|
||||||
<item> fn </item>
|
<item> fn </item>
|
||||||
|
|
|
@ -43,7 +43,7 @@ fi
|
||||||
|
|
||||||
cp ${PREFIX}/bin/rustc ${TARG_DIR}/stage0/bin/
|
cp ${PREFIX}/bin/rustc ${TARG_DIR}/stage0/bin/
|
||||||
cp ${PREFIX}/lib/rustc/${TARG_DIR}/${LIBDIR}/* ${TARG_DIR}/stage0/${LIBDIR}/
|
cp ${PREFIX}/lib/rustc/${TARG_DIR}/${LIBDIR}/* ${TARG_DIR}/stage0/${LIBDIR}/
|
||||||
|
cp ${PREFIX}/lib/libextra*${LIB_SUF} ${TARG_DIR}/stage0/${LIBDIR}/
|
||||||
cp ${PREFIX}/lib/librust*${LIB_SUF} ${TARG_DIR}/stage0/${LIBDIR}/
|
cp ${PREFIX}/lib/librust*${LIB_SUF} ${TARG_DIR}/stage0/${LIBDIR}/
|
||||||
cp ${PREFIX}/lib/libcore*${LIB_SUF} ${TARG_DIR}/stage0/${LIBDIR}/
|
|
||||||
cp ${PREFIX}/lib/libstd*${LIB_SUF} ${TARG_DIR}/stage0/${LIBDIR}/
|
cp ${PREFIX}/lib/libstd*${LIB_SUF} ${TARG_DIR}/stage0/${LIBDIR}/
|
||||||
cp ${PREFIX}/lib/libsyntax*${LIB_SUF} ${TARG_DIR}/stage0/${LIBDIR}/
|
cp ${PREFIX}/lib/libsyntax*${LIB_SUF} ${TARG_DIR}/stage0/${LIBDIR}/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# xfail-license
|
# xfail-license
|
||||||
|
|
||||||
import re, os, sys, glob, tarfile, shutil, subprocess, tempfile
|
import re, os, sys, glob, tarfile, shutil, subprocess, tempfile, distutils.spawn
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -132,7 +132,13 @@ def local_rev_committer_date():
|
||||||
def get_url_to_file(u,f):
|
def get_url_to_file(u,f):
|
||||||
# no security issue, just to stop partial download leaving a stale file
|
# no security issue, just to stop partial download leaving a stale file
|
||||||
tmpf = f + '.tmp'
|
tmpf = f + '.tmp'
|
||||||
returncode = subprocess.call(["curl", "-o", tmpf, u])
|
|
||||||
|
returncode = -1
|
||||||
|
if distutils.spawn.find_executable("curl"):
|
||||||
|
returncode = subprocess.call(["curl", "-o", tmpf, u])
|
||||||
|
elif distutils.spawn.find_executable("wget"):
|
||||||
|
returncode = subprocess.call(["wget", "-O", tmpf, u])
|
||||||
|
|
||||||
if returncode != 0:
|
if returncode != 0:
|
||||||
os.unlink(tmpf)
|
os.unlink(tmpf)
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -250,6 +250,7 @@ rf.write('''// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGH
|
||||||
// The following code was generated by "src/etc/unicode.py"
|
// The following code was generated by "src/etc/unicode.py"
|
||||||
|
|
||||||
#[allow(missing_doc)];
|
#[allow(missing_doc)];
|
||||||
|
#[allow(non_uppercase_statics)];
|
||||||
|
|
||||||
''')
|
''')
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ syn region rustDeriving start="deriving(" end=")" contains=rustTrait
|
||||||
" Number literals
|
" Number literals
|
||||||
syn match rustNumber display "\<[0-9][0-9_]*\>"
|
syn match rustNumber display "\<[0-9][0-9_]*\>"
|
||||||
syn match rustNumber display "\<[0-9][0-9_]*\(u\|u8\|u16\|u32\|u64\)\>"
|
syn match rustNumber display "\<[0-9][0-9_]*\(u\|u8\|u16\|u32\|u64\)\>"
|
||||||
syn match rustNumber display "\<[0-9][0-9_]*\(i8\|i16\|i32\|i64\)\>"
|
syn match rustNumber display "\<[0-9][0-9_]*\(i\|i8\|i16\|i32\|i64\)\>"
|
||||||
|
|
||||||
syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\>"
|
syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\>"
|
||||||
syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\(u\|u8\|u16\|u32\|u64\)\>"
|
syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\(u\|u8\|u16\|u32\|u64\)\>"
|
||||||
|
|
|
@ -10,17 +10,37 @@
|
||||||
|
|
||||||
//! Base64 binary-to-text encoding
|
//! Base64 binary-to-text encoding
|
||||||
|
|
||||||
|
/// Available encoding character sets
|
||||||
use std::vec;
|
pub enum CharacterSet {
|
||||||
|
/// The standard character set (uses '+' and '/')
|
||||||
/// A trait for converting a value to base64 encoding.
|
Standard,
|
||||||
pub trait ToBase64 {
|
/// The URL safe character set (uses '-' and '_')
|
||||||
/// Converts the value of `self` to a base64 value, returning the owned
|
UrlSafe
|
||||||
/// string
|
|
||||||
fn to_base64(&self) -> ~str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static CHARS: [char, ..64] = [
|
/// Contains configuration parameters for to_base64
|
||||||
|
pub struct Config {
|
||||||
|
/// Character set to use
|
||||||
|
char_set: CharacterSet,
|
||||||
|
/// True to pad output with '=' characters
|
||||||
|
pad: bool,
|
||||||
|
/// Some(len) to wrap lines at len, None to disable line wrapping
|
||||||
|
line_length: Option<uint>
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configuration for RFC 4648 standard base64 encoding
|
||||||
|
pub static STANDARD: Config =
|
||||||
|
Config {char_set: Standard, pad: true, line_length: None};
|
||||||
|
|
||||||
|
/// Configuration for RFC 4648 base64url encoding
|
||||||
|
pub static URL_SAFE: Config =
|
||||||
|
Config {char_set: UrlSafe, pad: false, line_length: None};
|
||||||
|
|
||||||
|
/// Configuration for RFC 2045 MIME base64 encoding
|
||||||
|
pub static MIME: Config =
|
||||||
|
Config {char_set: Standard, pad: true, line_length: Some(76)};
|
||||||
|
|
||||||
|
static STANDARD_CHARS: [char, ..64] = [
|
||||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||||
|
@ -28,6 +48,21 @@ static CHARS: [char, ..64] = [
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static URLSAFE_CHARS: [char, ..64] = [
|
||||||
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||||
|
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||||
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||||
|
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
|
||||||
|
];
|
||||||
|
|
||||||
|
/// A trait for converting a value to base64 encoding.
|
||||||
|
pub trait ToBase64 {
|
||||||
|
/// Converts the value of `self` to a base64 value following the specified
|
||||||
|
/// format configuration, returning the owned string.
|
||||||
|
fn to_base64(&self, config: Config) -> ~str;
|
||||||
|
}
|
||||||
|
|
||||||
impl<'self> ToBase64 for &'self [u8] {
|
impl<'self> ToBase64 for &'self [u8] {
|
||||||
/**
|
/**
|
||||||
* Turn a vector of `u8` bytes into a base64 string.
|
* Turn a vector of `u8` bytes into a base64 string.
|
||||||
|
@ -36,55 +71,81 @@ impl<'self> ToBase64 for &'self [u8] {
|
||||||
*
|
*
|
||||||
* ~~~ {.rust}
|
* ~~~ {.rust}
|
||||||
* extern mod extra;
|
* extern mod extra;
|
||||||
* use extra::base64::ToBase64;
|
* use extra::base64::{ToBase64, standard};
|
||||||
*
|
*
|
||||||
* fn main () {
|
* fn main () {
|
||||||
* let str = [52,32].to_base64();
|
* let str = [52,32].to_base64(standard);
|
||||||
* println(fmt!("%s", str));
|
* println(fmt!("%s", str));
|
||||||
* }
|
* }
|
||||||
* ~~~
|
* ~~~
|
||||||
*/
|
*/
|
||||||
fn to_base64(&self) -> ~str {
|
fn to_base64(&self, config: Config) -> ~str {
|
||||||
|
let chars = match config.char_set {
|
||||||
|
Standard => STANDARD_CHARS,
|
||||||
|
UrlSafe => URLSAFE_CHARS
|
||||||
|
};
|
||||||
|
|
||||||
let mut s = ~"";
|
let mut s = ~"";
|
||||||
|
let mut i = 0;
|
||||||
|
let mut cur_length = 0;
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
s.reserve(((len + 3u) / 4u) * 3u);
|
while i < len - (len % 3) {
|
||||||
|
match config.line_length {
|
||||||
|
Some(line_length) =>
|
||||||
|
if cur_length >= line_length {
|
||||||
|
s.push_str("\r\n");
|
||||||
|
cur_length = 0;
|
||||||
|
},
|
||||||
|
None => ()
|
||||||
|
}
|
||||||
|
|
||||||
let mut i = 0u;
|
let n = (self[i] as u32) << 16 |
|
||||||
|
(self[i + 1] as u32) << 8 |
|
||||||
while i < len - (len % 3u) {
|
(self[i + 2] as u32);
|
||||||
let n = (self[i] as uint) << 16u |
|
|
||||||
(self[i + 1u] as uint) << 8u |
|
|
||||||
(self[i + 2u] as uint);
|
|
||||||
|
|
||||||
// This 24-bit number gets separated into four 6-bit numbers.
|
// This 24-bit number gets separated into four 6-bit numbers.
|
||||||
s.push_char(CHARS[(n >> 18u) & 63u]);
|
s.push_char(chars[(n >> 18) & 63]);
|
||||||
s.push_char(CHARS[(n >> 12u) & 63u]);
|
s.push_char(chars[(n >> 12) & 63]);
|
||||||
s.push_char(CHARS[(n >> 6u) & 63u]);
|
s.push_char(chars[(n >> 6 ) & 63]);
|
||||||
s.push_char(CHARS[n & 63u]);
|
s.push_char(chars[n & 63]);
|
||||||
|
|
||||||
i += 3u;
|
cur_length += 4;
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if len % 3 != 0 {
|
||||||
|
match config.line_length {
|
||||||
|
Some(line_length) =>
|
||||||
|
if cur_length >= line_length {
|
||||||
|
s.push_str("\r\n");
|
||||||
|
},
|
||||||
|
None => ()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Heh, would be cool if we knew this was exhaustive
|
// Heh, would be cool if we knew this was exhaustive
|
||||||
// (the dream of bounded integer types)
|
// (the dream of bounded integer types)
|
||||||
match len % 3 {
|
match len % 3 {
|
||||||
0 => (),
|
0 => (),
|
||||||
1 => {
|
1 => {
|
||||||
let n = (self[i] as uint) << 16u;
|
let n = (self[i] as u32) << 16;
|
||||||
s.push_char(CHARS[(n >> 18u) & 63u]);
|
s.push_char(chars[(n >> 18) & 63]);
|
||||||
s.push_char(CHARS[(n >> 12u) & 63u]);
|
s.push_char(chars[(n >> 12) & 63]);
|
||||||
s.push_char('=');
|
if config.pad {
|
||||||
s.push_char('=');
|
s.push_str("==");
|
||||||
}
|
}
|
||||||
2 => {
|
}
|
||||||
let n = (self[i] as uint) << 16u |
|
2 => {
|
||||||
(self[i + 1u] as uint) << 8u;
|
let n = (self[i] as u32) << 16 |
|
||||||
s.push_char(CHARS[(n >> 18u) & 63u]);
|
(self[i + 1u] as u32) << 8;
|
||||||
s.push_char(CHARS[(n >> 12u) & 63u]);
|
s.push_char(chars[(n >> 18) & 63]);
|
||||||
s.push_char(CHARS[(n >> 6u) & 63u]);
|
s.push_char(chars[(n >> 12) & 63]);
|
||||||
s.push_char('=');
|
s.push_char(chars[(n >> 6 ) & 63]);
|
||||||
}
|
if config.pad {
|
||||||
_ => fail!("Algebra is broken, please alert the math police")
|
s.push_char('=');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => fail!("Algebra is broken, please alert the math police")
|
||||||
}
|
}
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
@ -99,23 +160,25 @@ impl<'self> ToBase64 for &'self str {
|
||||||
*
|
*
|
||||||
* ~~~ {.rust}
|
* ~~~ {.rust}
|
||||||
* extern mod extra;
|
* extern mod extra;
|
||||||
* use extra::base64::ToBase64;
|
* use extra::base64::{ToBase64, standard};
|
||||||
*
|
*
|
||||||
* fn main () {
|
* fn main () {
|
||||||
* let str = "Hello, World".to_base64();
|
* let str = "Hello, World".to_base64(standard);
|
||||||
* println(fmt!("%s",str));
|
* println(fmt!("%s",str));
|
||||||
* }
|
* }
|
||||||
* ~~~
|
* ~~~
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
fn to_base64(&self) -> ~str {
|
fn to_base64(&self, config: Config) -> ~str {
|
||||||
self.as_bytes().to_base64()
|
self.as_bytes().to_base64(config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_doc)]
|
/// A trait for converting from base64 encoded values.
|
||||||
pub trait FromBase64 {
|
pub trait FromBase64 {
|
||||||
fn from_base64(&self) -> ~[u8];
|
/// Converts the value of `self`, interpreted as base64 encoded data, into
|
||||||
|
/// an owned vector of bytes, returning the vector.
|
||||||
|
fn from_base64(&self) -> Result<~[u8], ~str>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'self> FromBase64 for &'self [u8] {
|
impl<'self> FromBase64 for &'self [u8] {
|
||||||
|
@ -127,69 +190,64 @@ impl<'self> FromBase64 for &'self [u8] {
|
||||||
*
|
*
|
||||||
* ~~~ {.rust}
|
* ~~~ {.rust}
|
||||||
* extern mod extra;
|
* extern mod extra;
|
||||||
* use extra::base64::ToBase64;
|
* use extra::base64::{ToBase64, FromBase64, standard};
|
||||||
* use extra::base64::FromBase64;
|
|
||||||
*
|
*
|
||||||
* fn main () {
|
* fn main () {
|
||||||
* let str = [52,32].to_base64();
|
* let str = [52,32].to_base64(standard);
|
||||||
* println(fmt!("%s", str));
|
* println(fmt!("%s", str));
|
||||||
* let bytes = str.from_base64();
|
* let bytes = str.from_base64();
|
||||||
* println(fmt!("%?",bytes));
|
* println(fmt!("%?",bytes));
|
||||||
* }
|
* }
|
||||||
* ~~~
|
* ~~~
|
||||||
*/
|
*/
|
||||||
fn from_base64(&self) -> ~[u8] {
|
fn from_base64(&self) -> Result<~[u8], ~str> {
|
||||||
if self.len() % 4u != 0u { fail!("invalid base64 length"); }
|
let mut r = ~[];
|
||||||
|
let mut buf: u32 = 0;
|
||||||
|
let mut modulus = 0;
|
||||||
|
|
||||||
let len = self.len();
|
let mut it = self.iter();
|
||||||
let mut padding = 0u;
|
for it.advance |&byte| {
|
||||||
|
let ch = byte as char;
|
||||||
|
let val = byte as u32;
|
||||||
|
|
||||||
if len != 0u {
|
match ch {
|
||||||
if self[len - 1u] == '=' as u8 { padding += 1u; }
|
'A'..'Z' => buf |= val - 0x41,
|
||||||
if self[len - 2u] == '=' as u8 { padding += 1u; }
|
'a'..'z' => buf |= val - 0x47,
|
||||||
|
'0'..'9' => buf |= val + 0x04,
|
||||||
|
'+'|'-' => buf |= 0x3E,
|
||||||
|
'/'|'_' => buf |= 0x3F,
|
||||||
|
'\r'|'\n' => loop,
|
||||||
|
'=' => break,
|
||||||
|
_ => return Err(~"Invalid Base64 character")
|
||||||
|
}
|
||||||
|
|
||||||
|
buf <<= 6;
|
||||||
|
modulus += 1;
|
||||||
|
if modulus == 4 {
|
||||||
|
modulus = 0;
|
||||||
|
r.push((buf >> 22) as u8);
|
||||||
|
r.push((buf >> 14) as u8);
|
||||||
|
r.push((buf >> 6 ) as u8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut r = vec::with_capacity((len / 4u) * 3u - padding);
|
if !it.all(|&byte| {byte as char == '='}) {
|
||||||
|
return Err(~"Invalid Base64 character");
|
||||||
let mut i = 0u;
|
|
||||||
while i < len {
|
|
||||||
let mut n = 0u;
|
|
||||||
|
|
||||||
for 4u.times {
|
|
||||||
let ch = self[i] as char;
|
|
||||||
n <<= 6u;
|
|
||||||
|
|
||||||
match ch {
|
|
||||||
'A'..'Z' => n |= (ch as uint) - 0x41,
|
|
||||||
'a'..'z' => n |= (ch as uint) - 0x47,
|
|
||||||
'0'..'9' => n |= (ch as uint) + 0x04,
|
|
||||||
'+' => n |= 0x3E,
|
|
||||||
'/' => n |= 0x3F,
|
|
||||||
'=' => {
|
|
||||||
match len - i {
|
|
||||||
1u => {
|
|
||||||
r.push(((n >> 16u) & 0xFFu) as u8);
|
|
||||||
r.push(((n >> 8u ) & 0xFFu) as u8);
|
|
||||||
return copy r;
|
|
||||||
}
|
|
||||||
2u => {
|
|
||||||
r.push(((n >> 10u) & 0xFFu) as u8);
|
|
||||||
return copy r;
|
|
||||||
}
|
|
||||||
_ => fail!("invalid base64 padding")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => fail!("invalid base64 character")
|
|
||||||
}
|
|
||||||
|
|
||||||
i += 1u;
|
|
||||||
};
|
|
||||||
|
|
||||||
r.push(((n >> 16u) & 0xFFu) as u8);
|
|
||||||
r.push(((n >> 8u ) & 0xFFu) as u8);
|
|
||||||
r.push(((n ) & 0xFFu) as u8);
|
|
||||||
}
|
}
|
||||||
r
|
|
||||||
|
match modulus {
|
||||||
|
2 => {
|
||||||
|
r.push((buf >> 10) as u8);
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
r.push((buf >> 16) as u8);
|
||||||
|
r.push((buf >> 8 ) as u8);
|
||||||
|
}
|
||||||
|
0 => (),
|
||||||
|
_ => return Err(~"Invalid Base64 length")
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +257,8 @@ impl<'self> FromBase64 for &'self str {
|
||||||
* to the byte values it encodes.
|
* to the byte values it encodes.
|
||||||
*
|
*
|
||||||
* You can use the `from_bytes` function in `std::str`
|
* You can use the `from_bytes` function in `std::str`
|
||||||
* to turn a `[u8]` into a string with characters corresponding to those values.
|
* to turn a `[u8]` into a string with characters corresponding to those
|
||||||
|
* values.
|
||||||
*
|
*
|
||||||
* # Example
|
* # Example
|
||||||
*
|
*
|
||||||
|
@ -207,12 +266,11 @@ impl<'self> FromBase64 for &'self str {
|
||||||
*
|
*
|
||||||
* ~~~ {.rust}
|
* ~~~ {.rust}
|
||||||
* extern mod extra;
|
* extern mod extra;
|
||||||
* use extra::base64::ToBase64;
|
* use extra::base64::{ToBase64, FromBase64, standard};
|
||||||
* use extra::base64::FromBase64;
|
|
||||||
* use std::str;
|
* use std::str;
|
||||||
*
|
*
|
||||||
* fn main () {
|
* fn main () {
|
||||||
* let hello_str = "Hello, World".to_base64();
|
* let hello_str = "Hello, World".to_base64(standard);
|
||||||
* println(fmt!("%s",hello_str));
|
* println(fmt!("%s",hello_str));
|
||||||
* let bytes = hello_str.from_base64();
|
* let bytes = hello_str.from_base64();
|
||||||
* println(fmt!("%?",bytes));
|
* println(fmt!("%?",bytes));
|
||||||
|
@ -221,32 +279,86 @@ impl<'self> FromBase64 for &'self str {
|
||||||
* }
|
* }
|
||||||
* ~~~
|
* ~~~
|
||||||
*/
|
*/
|
||||||
fn from_base64(&self) -> ~[u8] {
|
fn from_base64(&self) -> Result<~[u8], ~str> {
|
||||||
self.as_bytes().from_base64()
|
self.as_bytes().from_base64()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[test]
|
||||||
mod tests {
|
fn test_to_base64_basic() {
|
||||||
#[test]
|
assert_eq!("".to_base64(STANDARD), ~"");
|
||||||
fn test_to_base64() {
|
assert_eq!("f".to_base64(STANDARD), ~"Zg==");
|
||||||
assert_eq!("".to_base64(), ~"");
|
assert_eq!("fo".to_base64(STANDARD), ~"Zm8=");
|
||||||
assert_eq!("f".to_base64(), ~"Zg==");
|
assert_eq!("foo".to_base64(STANDARD), ~"Zm9v");
|
||||||
assert_eq!("fo".to_base64(), ~"Zm8=");
|
assert_eq!("foob".to_base64(STANDARD), ~"Zm9vYg==");
|
||||||
assert_eq!("foo".to_base64(), ~"Zm9v");
|
assert_eq!("fooba".to_base64(STANDARD), ~"Zm9vYmE=");
|
||||||
assert_eq!("foob".to_base64(), ~"Zm9vYg==");
|
assert_eq!("foobar".to_base64(STANDARD), ~"Zm9vYmFy");
|
||||||
assert_eq!("fooba".to_base64(), ~"Zm9vYmE=");
|
}
|
||||||
assert_eq!("foobar".to_base64(), ~"Zm9vYmFy");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_base64() {
|
fn test_to_base64_line_break() {
|
||||||
assert_eq!("".from_base64(), "".as_bytes().to_owned());
|
assert!(![0u8, 1000].to_base64(Config {line_length: None, ..STANDARD})
|
||||||
assert_eq!("Zg==".from_base64(), "f".as_bytes().to_owned());
|
.contains("\r\n"));
|
||||||
assert_eq!("Zm8=".from_base64(), "fo".as_bytes().to_owned());
|
assert_eq!("foobar".to_base64(Config {line_length: Some(4), ..STANDARD}),
|
||||||
assert_eq!("Zm9v".from_base64(), "foo".as_bytes().to_owned());
|
~"Zm9v\r\nYmFy");
|
||||||
assert_eq!("Zm9vYg==".from_base64(), "foob".as_bytes().to_owned());
|
}
|
||||||
assert_eq!("Zm9vYmE=".from_base64(), "fooba".as_bytes().to_owned());
|
|
||||||
assert_eq!("Zm9vYmFy".from_base64(), "foobar".as_bytes().to_owned());
|
#[test]
|
||||||
|
fn test_to_base64_padding() {
|
||||||
|
assert_eq!("f".to_base64(Config {pad: false, ..STANDARD}), ~"Zg");
|
||||||
|
assert_eq!("fo".to_base64(Config {pad: false, ..STANDARD}), ~"Zm8");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_to_base64_url_safe() {
|
||||||
|
assert_eq!([251, 255].to_base64(URL_SAFE), ~"-_8");
|
||||||
|
assert_eq!([251, 255].to_base64(STANDARD), ~"+/8=");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_base64_basic() {
|
||||||
|
assert_eq!("".from_base64().get(), "".as_bytes().to_owned());
|
||||||
|
assert_eq!("Zg==".from_base64().get(), "f".as_bytes().to_owned());
|
||||||
|
assert_eq!("Zm8=".from_base64().get(), "fo".as_bytes().to_owned());
|
||||||
|
assert_eq!("Zm9v".from_base64().get(), "foo".as_bytes().to_owned());
|
||||||
|
assert_eq!("Zm9vYg==".from_base64().get(), "foob".as_bytes().to_owned());
|
||||||
|
assert_eq!("Zm9vYmE=".from_base64().get(), "fooba".as_bytes().to_owned());
|
||||||
|
assert_eq!("Zm9vYmFy".from_base64().get(), "foobar".as_bytes().to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_base64_newlines() {
|
||||||
|
assert_eq!("Zm9v\r\nYmFy".from_base64().get(),
|
||||||
|
"foobar".as_bytes().to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_base64_urlsafe() {
|
||||||
|
assert_eq!("-_8".from_base64().get(), "+/8=".from_base64().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_base64_invalid_char() {
|
||||||
|
assert!("Zm$=".from_base64().is_err())
|
||||||
|
assert!("Zg==$".from_base64().is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_base64_invalid_padding() {
|
||||||
|
assert!("Z===".from_base64().is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_base64_random() {
|
||||||
|
use std::rand::{task_rng, random, RngUtil};
|
||||||
|
use std::vec;
|
||||||
|
|
||||||
|
for 1000.times {
|
||||||
|
let v: ~[u8] = do vec::build |push| {
|
||||||
|
for task_rng().gen_uint_range(1, 100).times {
|
||||||
|
push(random());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
assert_eq!(v.to_base64(STANDARD).from_base64().get(), v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -872,7 +872,7 @@ mod tests {
|
||||||
use std::rand;
|
use std::rand;
|
||||||
use std::rand::Rng;
|
use std::rand::Rng;
|
||||||
|
|
||||||
static bench_bits : uint = 1 << 14;
|
static BENCH_BITS : uint = 1 << 14;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_to_str() {
|
fn test_to_str() {
|
||||||
|
@ -1452,19 +1452,19 @@ mod tests {
|
||||||
fn bench_big_bitv_big(b: &mut BenchHarness) {
|
fn bench_big_bitv_big(b: &mut BenchHarness) {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let mut storage = ~[];
|
let mut storage = ~[];
|
||||||
storage.grow(bench_bits / uint::bits, &0);
|
storage.grow(BENCH_BITS / uint::bits, &0);
|
||||||
let mut bitv = BigBitv::new(storage);
|
let mut bitv = BigBitv::new(storage);
|
||||||
do b.iter {
|
do b.iter {
|
||||||
bitv.set((r.next() as uint) % bench_bits, true);
|
bitv.set((r.next() as uint) % BENCH_BITS, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_bitv_big(b: &mut BenchHarness) {
|
fn bench_bitv_big(b: &mut BenchHarness) {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let mut bitv = Bitv::new(bench_bits, false);
|
let mut bitv = Bitv::new(BENCH_BITS, false);
|
||||||
do b.iter {
|
do b.iter {
|
||||||
bitv.set((r.next() as uint) % bench_bits, true);
|
bitv.set((r.next() as uint) % BENCH_BITS, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1491,14 +1491,14 @@ mod tests {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let mut bitv = BitvSet::new();
|
let mut bitv = BitvSet::new();
|
||||||
do b.iter {
|
do b.iter {
|
||||||
bitv.insert((r.next() as uint) % bench_bits);
|
bitv.insert((r.next() as uint) % BENCH_BITS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_bitv_big_union(b: &mut BenchHarness) {
|
fn bench_bitv_big_union(b: &mut BenchHarness) {
|
||||||
let mut b1 = Bitv::new(bench_bits, false);
|
let mut b1 = Bitv::new(BENCH_BITS, false);
|
||||||
let b2 = Bitv::new(bench_bits, false);
|
let b2 = Bitv::new(BENCH_BITS, false);
|
||||||
do b.iter {
|
do b.iter {
|
||||||
b1.union(&b2);
|
b1.union(&b2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,7 +240,6 @@ impl Digest for Sha1 {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::vec;
|
|
||||||
|
|
||||||
use digest::{Digest, DigestUtil};
|
use digest::{Digest, DigestUtil};
|
||||||
use sha1::Sha1;
|
use sha1::Sha1;
|
||||||
|
@ -337,7 +336,7 @@ mod tests {
|
||||||
for tests.iter().advance |t| {
|
for tests.iter().advance |t| {
|
||||||
(*sh).input_str(t.input);
|
(*sh).input_str(t.input);
|
||||||
sh.result(out);
|
sh.result(out);
|
||||||
assert!(vec::eq(t.output, out));
|
assert!(t.output.as_slice() == out);
|
||||||
|
|
||||||
let out_str = (*sh).result_str();
|
let out_str = (*sh).result_str();
|
||||||
assert_eq!(out_str.len(), 40);
|
assert_eq!(out_str.len(), 40);
|
||||||
|
@ -357,7 +356,7 @@ mod tests {
|
||||||
left = left - take;
|
left = left - take;
|
||||||
}
|
}
|
||||||
sh.result(out);
|
sh.result(out);
|
||||||
assert!(vec::eq(t.output, out));
|
assert!(t.output.as_slice() == out);
|
||||||
|
|
||||||
let out_str = (*sh).result_str();
|
let out_str = (*sh).result_str();
|
||||||
assert_eq!(out_str.len(), 40);
|
assert_eq!(out_str.len(), 40);
|
||||||
|
|
|
@ -11,17 +11,17 @@
|
||||||
//! A double-ended queue implemented as a circular buffer
|
//! A double-ended queue implemented as a circular buffer
|
||||||
|
|
||||||
use std::uint;
|
use std::uint;
|
||||||
use std::util::replace;
|
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use std::cast::transmute;
|
use std::iterator::FromIterator;
|
||||||
|
|
||||||
static initial_capacity: uint = 32u; // 2^5
|
static INITIAL_CAPACITY: uint = 8u; // 2^3
|
||||||
|
static MINIMUM_CAPACITY: uint = 2u;
|
||||||
|
|
||||||
#[allow(missing_doc)]
|
#[allow(missing_doc)]
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct Deque<T> {
|
pub struct Deque<T> {
|
||||||
priv nelts: uint,
|
priv nelts: uint,
|
||||||
priv lo: uint,
|
priv lo: uint,
|
||||||
priv hi: uint,
|
|
||||||
priv elts: ~[Option<T>]
|
priv elts: ~[Option<T>]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,26 +39,36 @@ impl<T> Mutable for Deque<T> {
|
||||||
for self.elts.mut_iter().advance |x| { *x = None }
|
for self.elts.mut_iter().advance |x| { *x = None }
|
||||||
self.nelts = 0;
|
self.nelts = 0;
|
||||||
self.lo = 0;
|
self.lo = 0;
|
||||||
self.hi = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Deque<T> {
|
impl<T> Deque<T> {
|
||||||
/// Create an empty Deque
|
/// Create an empty Deque
|
||||||
pub fn new() -> Deque<T> {
|
pub fn new() -> Deque<T> {
|
||||||
Deque{nelts: 0, lo: 0, hi: 0,
|
Deque::with_capacity(INITIAL_CAPACITY)
|
||||||
elts: vec::from_fn(initial_capacity, |_| None)}
|
}
|
||||||
|
|
||||||
|
/// Create an empty Deque with space for at least `n` elements.
|
||||||
|
pub fn with_capacity(n: uint) -> Deque<T> {
|
||||||
|
Deque{nelts: 0, lo: 0,
|
||||||
|
elts: vec::from_fn(uint::max(MINIMUM_CAPACITY, n), |_| None)}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a reference to the first element in the deque
|
/// Return a reference to the first element in the deque
|
||||||
///
|
///
|
||||||
/// Fails if the deque is empty
|
/// Fails if the deque is empty
|
||||||
pub fn peek_front<'a>(&'a self) -> &'a T { get(self.elts, self.lo) }
|
pub fn peek_front<'a>(&'a self) -> &'a T { get(self.elts, self.raw_index(0)) }
|
||||||
|
|
||||||
/// Return a reference to the last element in the deque
|
/// Return a reference to the last element in the deque
|
||||||
///
|
///
|
||||||
/// Fails if the deque is empty
|
/// Fails if the deque is empty
|
||||||
pub fn peek_back<'a>(&'a self) -> &'a T { get(self.elts, self.hi - 1u) }
|
pub fn peek_back<'a>(&'a self) -> &'a T {
|
||||||
|
if self.nelts > 0 {
|
||||||
|
get(self.elts, self.raw_index(self.nelts - 1))
|
||||||
|
} else {
|
||||||
|
fail!("peek_back: empty deque");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Retrieve an element in the deque by index
|
/// Retrieve an element in the deque by index
|
||||||
///
|
///
|
||||||
|
@ -68,16 +78,6 @@ impl<T> Deque<T> {
|
||||||
get(self.elts, idx)
|
get(self.elts, idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over the elements in the deque
|
|
||||||
pub fn each(&self, f: &fn(&T) -> bool) -> bool {
|
|
||||||
self.eachi(|_i, e| f(e))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterate over the elements in the deque by index
|
|
||||||
pub fn eachi(&self, f: &fn(uint, &T) -> bool) -> bool {
|
|
||||||
uint::range(0, self.nelts, |i| f(i, self.get(i as int)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Remove and return the first element in the deque
|
/// Remove and return the first element in the deque
|
||||||
///
|
///
|
||||||
/// Fails if the deque is empty
|
/// Fails if the deque is empty
|
||||||
|
@ -88,43 +88,39 @@ impl<T> Deque<T> {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return index in underlying vec for a given logical element index
|
||||||
|
fn raw_index(&self, idx: uint) -> uint {
|
||||||
|
raw_index(self.lo, self.elts.len(), idx)
|
||||||
|
}
|
||||||
|
|
||||||
/// Remove and return the last element in the deque
|
/// Remove and return the last element in the deque
|
||||||
///
|
///
|
||||||
/// Fails if the deque is empty
|
/// Fails if the deque is empty
|
||||||
pub fn pop_back(&mut self) -> T {
|
pub fn pop_back(&mut self) -> T {
|
||||||
if self.hi == 0u {
|
self.nelts -= 1;
|
||||||
self.hi = self.elts.len() - 1u;
|
let hi = self.raw_index(self.nelts);
|
||||||
} else { self.hi -= 1u; }
|
self.elts[hi].swap_unwrap()
|
||||||
let result = self.elts[self.hi].swap_unwrap();
|
|
||||||
self.elts[self.hi] = None;
|
|
||||||
self.nelts -= 1u;
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepend an element to the deque
|
/// Prepend an element to the deque
|
||||||
pub fn add_front(&mut self, t: T) {
|
pub fn add_front(&mut self, t: T) {
|
||||||
let oldlo = self.lo;
|
if self.nelts == self.elts.len() {
|
||||||
|
grow(self.nelts, &mut self.lo, &mut self.elts);
|
||||||
|
}
|
||||||
if self.lo == 0u {
|
if self.lo == 0u {
|
||||||
self.lo = self.elts.len() - 1u;
|
self.lo = self.elts.len() - 1u;
|
||||||
} else { self.lo -= 1u; }
|
} else { self.lo -= 1u; }
|
||||||
if self.lo == self.hi {
|
|
||||||
self.elts = grow(self.nelts, oldlo, self.elts);
|
|
||||||
self.lo = self.elts.len() - 1u;
|
|
||||||
self.hi = self.nelts;
|
|
||||||
}
|
|
||||||
self.elts[self.lo] = Some(t);
|
self.elts[self.lo] = Some(t);
|
||||||
self.nelts += 1u;
|
self.nelts += 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Append an element to the deque
|
/// Append an element to the deque
|
||||||
pub fn add_back(&mut self, t: T) {
|
pub fn add_back(&mut self, t: T) {
|
||||||
if self.lo == self.hi && self.nelts != 0u {
|
if self.nelts == self.elts.len() {
|
||||||
self.elts = grow(self.nelts, self.lo, self.elts);
|
grow(self.nelts, &mut self.lo, &mut self.elts);
|
||||||
self.lo = 0u;
|
|
||||||
self.hi = self.nelts;
|
|
||||||
}
|
}
|
||||||
self.elts[self.hi] = Some(t);
|
let hi = self.raw_index(self.nelts);
|
||||||
self.hi = (self.hi + 1u) % self.elts.len();
|
self.elts[hi] = Some(t);
|
||||||
self.nelts += 1u;
|
self.nelts += 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,42 +151,39 @@ impl<T> Deque<T> {
|
||||||
|
|
||||||
/// Front-to-back iterator.
|
/// Front-to-back iterator.
|
||||||
pub fn iter<'a>(&'a self) -> DequeIterator<'a, T> {
|
pub fn iter<'a>(&'a self) -> DequeIterator<'a, T> {
|
||||||
DequeIterator { idx: self.lo, nelts: self.nelts, used: 0, vec: self.elts }
|
DequeIterator{index: 0, nelts: self.nelts, elts: self.elts, lo: self.lo}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Front-to-back iterator which returns mutable values.
|
/// Front-to-back iterator which returns mutable values.
|
||||||
pub fn mut_iter<'a>(&'a mut self) -> DequeMutIterator<'a, T> {
|
pub fn mut_iter<'a>(&'a mut self) -> DequeMutIterator<'a, T> {
|
||||||
DequeMutIterator { idx: self.lo, nelts: self.nelts, used: 0, vec: self.elts }
|
DequeMutIterator{index: 0, nelts: self.nelts, elts: self.elts, lo: self.lo}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Back-to-front iterator.
|
/// Back-to-front iterator.
|
||||||
pub fn rev_iter<'a>(&'a self) -> DequeRevIterator<'a, T> {
|
pub fn rev_iter<'a>(&'a self) -> DequeRevIterator<'a, T> {
|
||||||
DequeRevIterator { idx: self.hi - 1u, nelts: self.nelts, used: 0, vec: self.elts }
|
DequeRevIterator{index: self.nelts-1, nelts: self.nelts, elts: self.elts,
|
||||||
|
lo: self.lo}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Back-to-front iterator which returns mutable values.
|
/// Back-to-front iterator which returns mutable values.
|
||||||
pub fn mut_rev_iter<'a>(&'a mut self) -> DequeMutRevIterator<'a, T> {
|
pub fn mut_rev_iter<'a>(&'a mut self) -> DequeMutRevIterator<'a, T> {
|
||||||
DequeMutRevIterator { idx: self.hi - 1u, nelts: self.nelts, used: 0, vec: self.elts }
|
DequeMutRevIterator{index: self.nelts-1, nelts: self.nelts, elts: self.elts,
|
||||||
|
lo: self.lo}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! iterator {
|
macro_rules! iterator {
|
||||||
(impl $name:ident -> $elem:ty, $step:expr) => {
|
(impl $name:ident -> $elem:ty, $getter:ident, $step:expr) => {
|
||||||
impl<'self, T> Iterator<$elem> for $name<'self, T> {
|
impl<'self, T> Iterator<$elem> for $name<'self, T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<$elem> {
|
fn next(&mut self) -> Option<$elem> {
|
||||||
if self.used >= self.nelts {
|
if self.nelts == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let ret = unsafe {
|
let raw_index = raw_index(self.lo, self.elts.len(), self.index);
|
||||||
match self.vec[self.idx % self.vec.len()] {
|
self.index += $step;
|
||||||
Some(ref e) => Some(transmute(e)),
|
self.nelts -= 1;
|
||||||
None => None
|
Some(self.elts[raw_index]. $getter ())
|
||||||
}
|
|
||||||
};
|
|
||||||
self.idx += $step;
|
|
||||||
self.used += 1;
|
|
||||||
ret
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,64 +191,115 @@ macro_rules! iterator {
|
||||||
|
|
||||||
/// Deque iterator
|
/// Deque iterator
|
||||||
pub struct DequeIterator<'self, T> {
|
pub struct DequeIterator<'self, T> {
|
||||||
priv idx: uint,
|
priv lo: uint,
|
||||||
priv nelts: uint,
|
priv nelts: uint,
|
||||||
priv used: uint,
|
priv index: uint,
|
||||||
priv vec: &'self [Option<T>]
|
priv elts: &'self [Option<T>],
|
||||||
}
|
}
|
||||||
iterator!{impl DequeIterator -> &'self T, 1}
|
iterator!{impl DequeIterator -> &'self T, get_ref, 1}
|
||||||
|
|
||||||
/// Deque reverse iterator
|
/// Deque reverse iterator
|
||||||
pub struct DequeRevIterator<'self, T> {
|
pub struct DequeRevIterator<'self, T> {
|
||||||
priv idx: uint,
|
priv lo: uint,
|
||||||
priv nelts: uint,
|
priv nelts: uint,
|
||||||
priv used: uint,
|
priv index: uint,
|
||||||
priv vec: &'self [Option<T>]
|
priv elts: &'self [Option<T>],
|
||||||
}
|
}
|
||||||
iterator!{impl DequeRevIterator -> &'self T, -1}
|
iterator!{impl DequeRevIterator -> &'self T, get_ref, -1}
|
||||||
|
|
||||||
/// Deque mutable iterator
|
/// Deque mutable iterator
|
||||||
pub struct DequeMutIterator<'self, T> {
|
pub struct DequeMutIterator<'self, T> {
|
||||||
priv idx: uint,
|
priv lo: uint,
|
||||||
priv nelts: uint,
|
priv nelts: uint,
|
||||||
priv used: uint,
|
priv index: uint,
|
||||||
priv vec: &'self mut [Option<T>]
|
priv elts: &'self mut [Option<T>],
|
||||||
|
|
||||||
}
|
}
|
||||||
iterator!{impl DequeMutIterator -> &'self mut T, 1}
|
iterator!{impl DequeMutIterator -> &'self mut T, get_mut_ref, 1}
|
||||||
|
|
||||||
/// Deque mutable reverse iterator
|
/// Deque mutable reverse iterator
|
||||||
pub struct DequeMutRevIterator<'self, T> {
|
pub struct DequeMutRevIterator<'self, T> {
|
||||||
priv idx: uint,
|
priv lo: uint,
|
||||||
priv nelts: uint,
|
priv nelts: uint,
|
||||||
priv used: uint,
|
priv index: uint,
|
||||||
priv vec: &'self mut [Option<T>]
|
priv elts: &'self mut [Option<T>],
|
||||||
}
|
}
|
||||||
iterator!{impl DequeMutRevIterator -> &'self mut T, -1}
|
iterator!{impl DequeMutRevIterator -> &'self mut T, get_mut_ref, -1}
|
||||||
|
|
||||||
/// Grow is only called on full elts, so nelts is also len(elts), unlike
|
/// Grow is only called on full elts, so nelts is also len(elts), unlike
|
||||||
/// elsewhere.
|
/// elsewhere.
|
||||||
fn grow<T>(nelts: uint, lo: uint, elts: &mut [Option<T>]) -> ~[Option<T>] {
|
fn grow<T>(nelts: uint, loptr: &mut uint, elts: &mut ~[Option<T>]) {
|
||||||
assert_eq!(nelts, elts.len());
|
assert_eq!(nelts, elts.len());
|
||||||
let mut rv = ~[];
|
let lo = *loptr;
|
||||||
|
let newlen = nelts * 2;
|
||||||
|
elts.reserve(newlen);
|
||||||
|
|
||||||
do rv.grow_fn(nelts + 1) |i| {
|
/* fill with None */
|
||||||
replace(&mut elts[(lo + i) % nelts], None)
|
for uint::range(elts.len(), elts.capacity()) |_| {
|
||||||
|
elts.push(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
rv
|
/*
|
||||||
|
Move the shortest half into the newly reserved area.
|
||||||
|
lo ---->|
|
||||||
|
nelts ----------->|
|
||||||
|
[o o o|o o o o o]
|
||||||
|
A [. . .|o o o o o o o o|. . . . .]
|
||||||
|
B [o o o|. . . . . . . .|o o o o o]
|
||||||
|
*/
|
||||||
|
|
||||||
|
assert!(newlen - nelts/2 >= nelts);
|
||||||
|
if lo <= (nelts - lo) { // A
|
||||||
|
for uint::range(0, lo) |i| {
|
||||||
|
elts.swap(i, nelts + i);
|
||||||
|
}
|
||||||
|
} else { // B
|
||||||
|
for uint::range(lo, nelts) |i| {
|
||||||
|
elts.swap(i, newlen - nelts + i);
|
||||||
|
}
|
||||||
|
*loptr += newlen - nelts;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get<'r, T>(elts: &'r [Option<T>], i: uint) -> &'r T {
|
fn get<'r, T>(elts: &'r [Option<T>], i: uint) -> &'r T {
|
||||||
match elts[i] { Some(ref t) => t, _ => fail!() }
|
match elts[i] { Some(ref t) => t, _ => fail!() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return index in underlying vec for a given logical element index
|
||||||
|
fn raw_index(lo: uint, len: uint, index: uint) -> uint {
|
||||||
|
if lo >= len - index {
|
||||||
|
lo + index - len
|
||||||
|
} else {
|
||||||
|
lo + index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Eq> Eq for Deque<A> {
|
||||||
|
fn eq(&self, other: &Deque<A>) -> bool {
|
||||||
|
self.nelts == other.nelts &&
|
||||||
|
self.iter().zip(other.iter()).all(|(a, b)| a.eq(b))
|
||||||
|
}
|
||||||
|
fn ne(&self, other: &Deque<A>) -> bool {
|
||||||
|
!self.eq(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A, T: Iterator<A>> FromIterator<A, T> for Deque<A> {
|
||||||
|
fn from_iterator(iterator: &mut T) -> Deque<A> {
|
||||||
|
let mut deq = Deque::new();
|
||||||
|
for iterator.advance |elt| {
|
||||||
|
deq.add_back(elt);
|
||||||
|
}
|
||||||
|
deq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::cmp::Eq;
|
use std::cmp::Eq;
|
||||||
use std::kinds::Copy;
|
use std::kinds::Copy;
|
||||||
use std::int;
|
use std::{int, uint};
|
||||||
|
use extra::test;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_simple() {
|
fn test_simple() {
|
||||||
|
@ -369,6 +413,61 @@ mod tests {
|
||||||
assert_eq!(copy *deq.get(3), copy d);
|
assert_eq!(copy *deq.get(3), copy d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_front_grow() {
|
||||||
|
let mut deq = Deque::new();
|
||||||
|
for int::range(0, 66) |i| {
|
||||||
|
deq.add_front(i);
|
||||||
|
}
|
||||||
|
assert_eq!(deq.len(), 66);
|
||||||
|
|
||||||
|
for int::range(0, 66) |i| {
|
||||||
|
assert_eq!(*deq.get(i), 65 - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut deq = Deque::new();
|
||||||
|
for int::range(0, 66) |i| {
|
||||||
|
deq.add_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for int::range(0, 66) |i| {
|
||||||
|
assert_eq!(*deq.get(i), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_new(b: &mut test::BenchHarness) {
|
||||||
|
do b.iter {
|
||||||
|
let _ = Deque::new::<u64>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_add_back(b: &mut test::BenchHarness) {
|
||||||
|
let mut deq = Deque::new();
|
||||||
|
do b.iter {
|
||||||
|
deq.add_back(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_add_front(b: &mut test::BenchHarness) {
|
||||||
|
let mut deq = Deque::new();
|
||||||
|
do b.iter {
|
||||||
|
deq.add_front(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_grow(b: &mut test::BenchHarness) {
|
||||||
|
let mut deq = Deque::new();
|
||||||
|
do b.iter {
|
||||||
|
for 65.times {
|
||||||
|
deq.add_front(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
enum Taggy { One(int), Two(int, int), Three(int, int, int), }
|
enum Taggy { One(int), Two(int, int), Three(int, int, int), }
|
||||||
|
|
||||||
|
@ -417,22 +516,13 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_eachi() {
|
fn test_with_capacity() {
|
||||||
let mut deq = Deque::new();
|
let mut d = Deque::with_capacity(0);
|
||||||
deq.add_back(1);
|
d.add_back(1);
|
||||||
deq.add_back(2);
|
assert_eq!(d.len(), 1);
|
||||||
deq.add_back(3);
|
let mut d = Deque::with_capacity(50);
|
||||||
|
d.add_back(1);
|
||||||
for deq.eachi |i, e| {
|
assert_eq!(d.len(), 1);
|
||||||
assert_eq!(*e, i + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
deq.pop_front();
|
|
||||||
|
|
||||||
for deq.eachi |i, e| {
|
|
||||||
assert_eq!(*e, i + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -462,6 +552,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iter() {
|
fn test_iter() {
|
||||||
let mut d = Deque::new();
|
let mut d = Deque::new();
|
||||||
|
assert_eq!(d.iter().next(), None);
|
||||||
|
|
||||||
for int::range(0,5) |i| {
|
for int::range(0,5) |i| {
|
||||||
d.add_back(i);
|
d.add_back(i);
|
||||||
}
|
}
|
||||||
|
@ -476,6 +568,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rev_iter() {
|
fn test_rev_iter() {
|
||||||
let mut d = Deque::new();
|
let mut d = Deque::new();
|
||||||
|
assert_eq!(d.rev_iter().next(), None);
|
||||||
|
|
||||||
for int::range(0,5) |i| {
|
for int::range(0,5) |i| {
|
||||||
d.add_back(i);
|
d.add_back(i);
|
||||||
}
|
}
|
||||||
|
@ -486,4 +580,104 @@ mod tests {
|
||||||
}
|
}
|
||||||
assert_eq!(d.rev_iter().collect::<~[&int]>(), ~[&4,&3,&2,&1,&0,&6,&7,&8]);
|
assert_eq!(d.rev_iter().collect::<~[&int]>(), ~[&4,&3,&2,&1,&0,&6,&7,&8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mut_iter() {
|
||||||
|
let mut d = Deque::new();
|
||||||
|
assert!(d.mut_iter().next().is_none());
|
||||||
|
|
||||||
|
for uint::range(0,3) |i| {
|
||||||
|
d.add_front(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for d.mut_iter().enumerate().advance |(i, elt)| {
|
||||||
|
assert_eq!(*elt, 2 - i);
|
||||||
|
*elt = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut it = d.mut_iter();
|
||||||
|
assert_eq!(*it.next().unwrap(), 0);
|
||||||
|
assert_eq!(*it.next().unwrap(), 1);
|
||||||
|
assert_eq!(*it.next().unwrap(), 2);
|
||||||
|
assert!(it.next().is_none());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mut_rev_iter() {
|
||||||
|
let mut d = Deque::new();
|
||||||
|
assert!(d.mut_rev_iter().next().is_none());
|
||||||
|
|
||||||
|
for uint::range(0,3) |i| {
|
||||||
|
d.add_front(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for d.mut_rev_iter().enumerate().advance |(i, elt)| {
|
||||||
|
assert_eq!(*elt, i);
|
||||||
|
*elt = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut it = d.mut_rev_iter();
|
||||||
|
assert_eq!(*it.next().unwrap(), 0);
|
||||||
|
assert_eq!(*it.next().unwrap(), 1);
|
||||||
|
assert_eq!(*it.next().unwrap(), 2);
|
||||||
|
assert!(it.next().is_none());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_iterator() {
|
||||||
|
use std::iterator;
|
||||||
|
let v = ~[1,2,3,4,5,6,7];
|
||||||
|
let deq: Deque<int> = v.iter().transform(|&x| x).collect();
|
||||||
|
let u: ~[int] = deq.iter().transform(|&x| x).collect();
|
||||||
|
assert_eq!(u, v);
|
||||||
|
|
||||||
|
let mut seq = iterator::Counter::new(0u, 2).take_(256);
|
||||||
|
let deq: Deque<uint> = seq.collect();
|
||||||
|
for deq.iter().enumerate().advance |(i, &x)| {
|
||||||
|
assert_eq!(2*i, x);
|
||||||
|
}
|
||||||
|
assert_eq!(deq.len(), 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_clone() {
|
||||||
|
let mut d = Deque::new();
|
||||||
|
d.add_front(17);
|
||||||
|
d.add_front(42);
|
||||||
|
d.add_back(137);
|
||||||
|
d.add_back(137);
|
||||||
|
assert_eq!(d.len(), 4u);
|
||||||
|
let mut e = d.clone();
|
||||||
|
assert_eq!(e.len(), 4u);
|
||||||
|
while !d.is_empty() {
|
||||||
|
assert_eq!(d.pop_back(), e.pop_back());
|
||||||
|
}
|
||||||
|
assert_eq!(d.len(), 0u);
|
||||||
|
assert_eq!(e.len(), 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_eq() {
|
||||||
|
let mut d = Deque::new();
|
||||||
|
assert_eq!(&d, &Deque::with_capacity(0));
|
||||||
|
d.add_front(137);
|
||||||
|
d.add_front(17);
|
||||||
|
d.add_front(42);
|
||||||
|
d.add_back(137);
|
||||||
|
let mut e = Deque::with_capacity(0);
|
||||||
|
e.add_back(42);
|
||||||
|
e.add_back(17);
|
||||||
|
e.add_back(137);
|
||||||
|
e.add_back(137);
|
||||||
|
assert_eq!(&e, &d);
|
||||||
|
e.pop_back();
|
||||||
|
e.add_back(0);
|
||||||
|
assert!(e != d);
|
||||||
|
e.clear();
|
||||||
|
assert_eq!(e, Deque::new());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -748,7 +748,7 @@ pub mod writer {
|
||||||
|
|
||||||
// Set to true to generate more debugging in EBML code.
|
// Set to true to generate more debugging in EBML code.
|
||||||
// Totally lame approach.
|
// Totally lame approach.
|
||||||
static debug: bool = true;
|
static DEBUG: bool = true;
|
||||||
|
|
||||||
impl Encoder {
|
impl Encoder {
|
||||||
// used internally to emit things like the vector length and so on
|
// used internally to emit things like the vector length and so on
|
||||||
|
@ -764,7 +764,7 @@ pub mod writer {
|
||||||
// efficiency. When debugging, though, we can emit such
|
// efficiency. When debugging, though, we can emit such
|
||||||
// labels and then they will be checked by decoder to
|
// labels and then they will be checked by decoder to
|
||||||
// try and check failures more quickly.
|
// try and check failures more quickly.
|
||||||
if debug { self.wr_tagged_str(EsLabel as uint, label) }
|
if DEBUG { self.wr_tagged_str(EsLabel as uint, label) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ Rust extras are part of the standard Rust distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[link(name = "extra",
|
#[link(name = "extra",
|
||||||
vers = "0.7",
|
vers = "0.8-pre",
|
||||||
uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297",
|
uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297",
|
||||||
url = "https://github.com/mozilla/rust/tree/master/src/libextra")];
|
url = "https://github.com/mozilla/rust/tree/master/src/libextra")];
|
||||||
|
|
||||||
|
@ -40,10 +40,8 @@ pub mod uv_ll;
|
||||||
|
|
||||||
// General io and system-services modules
|
// General io and system-services modules
|
||||||
|
|
||||||
|
#[path = "net/mod.rs"]
|
||||||
pub mod net;
|
pub mod net;
|
||||||
pub mod net_ip;
|
|
||||||
pub mod net_tcp;
|
|
||||||
pub mod net_url;
|
|
||||||
|
|
||||||
// libuv modules
|
// libuv modules
|
||||||
pub mod uv;
|
pub mod uv;
|
||||||
|
@ -74,7 +72,6 @@ pub mod deque;
|
||||||
pub mod fun_treemap;
|
pub mod fun_treemap;
|
||||||
pub mod list;
|
pub mod list;
|
||||||
pub mod priority_queue;
|
pub mod priority_queue;
|
||||||
pub mod rope;
|
|
||||||
pub mod smallintmap;
|
pub mod smallintmap;
|
||||||
|
|
||||||
pub mod sort;
|
pub mod sort;
|
||||||
|
|
|
@ -39,20 +39,20 @@ pub mod rustrt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static lz_none : c_int = 0x0; // Huffman-coding only.
|
static LZ_NONE : c_int = 0x0; // Huffman-coding only.
|
||||||
static lz_fast : c_int = 0x1; // LZ with only one probe
|
static LZ_FAST : c_int = 0x1; // LZ with only one probe
|
||||||
static lz_norm : c_int = 0x80; // LZ with 128 probes, "normal"
|
static LZ_NORM : c_int = 0x80; // LZ with 128 probes, "normal"
|
||||||
static lz_best : c_int = 0xfff; // LZ with 4095 probes, "best"
|
static LZ_BEST : c_int = 0xfff; // LZ with 4095 probes, "best"
|
||||||
|
|
||||||
pub fn deflate_bytes(bytes: &[u8]) -> ~[u8] {
|
pub fn deflate_bytes(bytes: &[u8]) -> ~[u8] {
|
||||||
do vec::as_imm_buf(bytes) |b, len| {
|
do bytes.as_imm_buf |b, len| {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut outsz : size_t = 0;
|
let mut outsz : size_t = 0;
|
||||||
let res =
|
let res =
|
||||||
rustrt::tdefl_compress_mem_to_heap(b as *c_void,
|
rustrt::tdefl_compress_mem_to_heap(b as *c_void,
|
||||||
len as size_t,
|
len as size_t,
|
||||||
&mut outsz,
|
&mut outsz,
|
||||||
lz_norm);
|
LZ_NORM);
|
||||||
assert!(res as int != 0);
|
assert!(res as int != 0);
|
||||||
let out = vec::raw::from_buf_raw(res as *u8,
|
let out = vec::raw::from_buf_raw(res as *u8,
|
||||||
outsz as uint);
|
outsz as uint);
|
||||||
|
@ -63,7 +63,7 @@ pub fn deflate_bytes(bytes: &[u8]) -> ~[u8] {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inflate_bytes(bytes: &[u8]) -> ~[u8] {
|
pub fn inflate_bytes(bytes: &[u8]) -> ~[u8] {
|
||||||
do vec::as_imm_buf(bytes) |b, len| {
|
do bytes.as_imm_buf |b, len| {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut outsz : size_t = 0;
|
let mut outsz : size_t = 0;
|
||||||
let res =
|
let res =
|
||||||
|
|
|
@ -55,7 +55,6 @@ use std::io;
|
||||||
use std::comm::GenericChan;
|
use std::comm::GenericChan;
|
||||||
use std::comm::GenericPort;
|
use std::comm::GenericPort;
|
||||||
use std::sys::size_of;
|
use std::sys::size_of;
|
||||||
use std::vec;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A FlatPort, consisting of a `BytePort` that receives byte vectors,
|
A FlatPort, consisting of a `BytePort` that receives byte vectors,
|
||||||
|
@ -274,7 +273,7 @@ impl<T,U:Unflattener<T>,P:BytePort> GenericPort<T> for FlatPort<T, U, P> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if vec::eq(command, CONTINUE) {
|
if CONTINUE.as_slice() == command {
|
||||||
let msg_len = match self.byte_port.try_recv(size_of::<u64>()) {
|
let msg_len = match self.byte_port.try_recv(size_of::<u64>()) {
|
||||||
Some(bytes) => {
|
Some(bytes) => {
|
||||||
io::u64_from_be_bytes(bytes, 0, size_of::<u64>())
|
io::u64_from_be_bytes(bytes, 0, size_of::<u64>())
|
||||||
|
@ -931,7 +930,7 @@ mod test {
|
||||||
fn test_try_recv_none3<P:BytePort>(loader: PortLoader<P>) {
|
fn test_try_recv_none3<P:BytePort>(loader: PortLoader<P>) {
|
||||||
static CONTINUE: [u8, ..4] = [0xAA, 0xBB, 0xCC, 0xDD];
|
static CONTINUE: [u8, ..4] = [0xAA, 0xBB, 0xCC, 0xDD];
|
||||||
// The control word is followed by garbage
|
// The control word is followed by garbage
|
||||||
let bytes = CONTINUE.to_owned() + [0];
|
let bytes = CONTINUE.to_owned() + &[0u8];
|
||||||
let port = loader(bytes);
|
let port = loader(bytes);
|
||||||
let res: Option<int> = port.try_recv();
|
let res: Option<int> = port.try_recv();
|
||||||
assert!(res.is_none());
|
assert!(res.is_none());
|
||||||
|
@ -955,7 +954,7 @@ mod test {
|
||||||
1, sys::size_of::<u64>()) |len_bytes| {
|
1, sys::size_of::<u64>()) |len_bytes| {
|
||||||
len_bytes.to_owned()
|
len_bytes.to_owned()
|
||||||
};
|
};
|
||||||
let bytes = CONTINUE.to_owned() + len_bytes + [0, 0, 0, 0];
|
let bytes = CONTINUE.to_owned() + len_bytes + &[0u8, 0, 0, 0];
|
||||||
|
|
||||||
let port = loader(bytes);
|
let port = loader(bytes);
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ fn name_str(nm: &Name) -> ~str {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_opt(opts: &[Opt], nm: Name) -> Option<uint> {
|
fn find_opt(opts: &[Opt], nm: Name) -> Option<uint> {
|
||||||
opts.iter().position_(|opt| opt.name == nm)
|
opts.iter().position(|opt| opt.name == nm)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
328
src/libextra/iter.rs
Normal file
328
src/libextra/iter.rs
Normal file
|
@ -0,0 +1,328 @@
|
||||||
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
/*! Composable internal iterators
|
||||||
|
|
||||||
|
Internal iterators are functions implementing the protocol used by the `for` loop.
|
||||||
|
|
||||||
|
An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal
|
||||||
|
breaking out of iteration. The adaptors in the module work with any such iterator, not just ones
|
||||||
|
tied to specific traits. For example:
|
||||||
|
|
||||||
|
~~~ {.rust}
|
||||||
|
println(iter::to_vec(|f| uint::range(0, 20, f)).to_str());
|
||||||
|
~~~
|
||||||
|
|
||||||
|
An external iterator object implementing the interface in the `iterator` module can be used as an
|
||||||
|
internal iterator by calling the `advance` method. For example:
|
||||||
|
|
||||||
|
~~~ {.rust}
|
||||||
|
let xs = [0u, 1, 2, 3, 4, 5];
|
||||||
|
let ys = [30, 40, 50, 60];
|
||||||
|
let mut it = xs.iter().chain(ys.iter());
|
||||||
|
for it.advance |&x: &uint| {
|
||||||
|
println(x.to_str());
|
||||||
|
}
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Internal iterators provide a subset of the functionality of an external iterator. It's not possible
|
||||||
|
to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often
|
||||||
|
much easier to implement.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::vec;
|
||||||
|
use std::cmp::Ord;
|
||||||
|
use std::option::{Option, Some, None};
|
||||||
|
use std::num::{One, Zero};
|
||||||
|
use std::ops::{Add, Mul};
|
||||||
|
|
||||||
|
#[allow(missing_doc)]
|
||||||
|
pub trait FromIter<T> {
|
||||||
|
/// Build a container with elements from an internal iterator.
|
||||||
|
///
|
||||||
|
/// # Example:
|
||||||
|
///
|
||||||
|
/// ~~~ {.rust}
|
||||||
|
/// let xs = ~[1, 2, 3];
|
||||||
|
/// let ys: ~[int] = do FromIter::from_iter |f| { xs.iter().advance(|x| f(*x)) };
|
||||||
|
/// assert_eq!(xs, ys);
|
||||||
|
/// ~~~
|
||||||
|
pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if `predicate` is true for any values yielded by an internal iterator.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ~~~ {.rust}
|
||||||
|
* let xs = ~[1u, 2, 3, 4, 5];
|
||||||
|
* assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f)));
|
||||||
|
* assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f)));
|
||||||
|
* ~~~
|
||||||
|
*/
|
||||||
|
#[inline]
|
||||||
|
pub fn any<T>(predicate: &fn(T) -> bool,
|
||||||
|
iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
|
||||||
|
for iter |x| {
|
||||||
|
if predicate(x) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if `predicate` is true for all values yielded by an internal iterator.
|
||||||
|
*
|
||||||
|
* # Example:
|
||||||
|
*
|
||||||
|
* ~~~ {.rust}
|
||||||
|
* assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f)));
|
||||||
|
* assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f)));
|
||||||
|
* ~~~
|
||||||
|
*/
|
||||||
|
#[inline]
|
||||||
|
pub fn all<T>(predicate: &fn(T) -> bool,
|
||||||
|
iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
|
||||||
|
// If we ever break, iter will return false, so this will only return true
|
||||||
|
// if predicate returns true for everything.
|
||||||
|
iter(|x| predicate(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the first element where `predicate` returns `true`. Return `None` if no element is found.
|
||||||
|
*
|
||||||
|
* # Example:
|
||||||
|
*
|
||||||
|
* ~~~ {.rust}
|
||||||
|
* let xs = ~[1u, 2, 3, 4, 5, 6];
|
||||||
|
* assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4);
|
||||||
|
* ~~~
|
||||||
|
*/
|
||||||
|
#[inline]
|
||||||
|
pub fn find<T>(predicate: &fn(&T) -> bool,
|
||||||
|
iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
|
||||||
|
for iter |x| {
|
||||||
|
if predicate(&x) {
|
||||||
|
return Some(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the largest item yielded by an iterator. Return `None` if the iterator is empty.
|
||||||
|
*
|
||||||
|
* # Example:
|
||||||
|
*
|
||||||
|
* ~~~ {.rust}
|
||||||
|
* let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
|
||||||
|
* assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15);
|
||||||
|
* ~~~
|
||||||
|
*/
|
||||||
|
#[inline]
|
||||||
|
pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
|
||||||
|
let mut result = None;
|
||||||
|
for iter |x| {
|
||||||
|
match result {
|
||||||
|
Some(ref mut y) => {
|
||||||
|
if x > *y {
|
||||||
|
*y = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => result = Some(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the smallest item yielded by an iterator. Return `None` if the iterator is empty.
|
||||||
|
*
|
||||||
|
* # Example:
|
||||||
|
*
|
||||||
|
* ~~~ {.rust}
|
||||||
|
* let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
|
||||||
|
* assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &-5);
|
||||||
|
* ~~~
|
||||||
|
*/
|
||||||
|
#[inline]
|
||||||
|
pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
|
||||||
|
let mut result = None;
|
||||||
|
for iter |x| {
|
||||||
|
match result {
|
||||||
|
Some(ref mut y) => {
|
||||||
|
if x < *y {
|
||||||
|
*y = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => result = Some(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduce an iterator to an accumulated value.
|
||||||
|
*
|
||||||
|
* # Example:
|
||||||
|
*
|
||||||
|
* ~~~ {.rust}
|
||||||
|
* assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
|
||||||
|
* ~~~
|
||||||
|
*/
|
||||||
|
#[inline]
|
||||||
|
pub fn fold<T, U>(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, U)) -> T {
|
||||||
|
let mut result = start;
|
||||||
|
for iter |x| {
|
||||||
|
f(&mut result, x);
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduce an iterator to an accumulated value.
|
||||||
|
*
|
||||||
|
* `fold_ref` is usable in some generic functions where `fold` is too lenient to type-check, but it
|
||||||
|
* forces the iterator to yield borrowed pointers.
|
||||||
|
*
|
||||||
|
* # Example:
|
||||||
|
*
|
||||||
|
* ~~~ {.rust}
|
||||||
|
* fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
|
||||||
|
* fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
|
||||||
|
* }
|
||||||
|
* ~~~
|
||||||
|
*/
|
||||||
|
#[inline]
|
||||||
|
pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&mut T, &U)) -> T {
|
||||||
|
let mut result = start;
|
||||||
|
for iter |x| {
|
||||||
|
f(&mut result, x);
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the sum of the items yielding by an iterator.
|
||||||
|
*
|
||||||
|
* # Example:
|
||||||
|
*
|
||||||
|
* ~~~ {.rust}
|
||||||
|
* let xs: ~[int] = ~[1, 2, 3, 4];
|
||||||
|
* assert_eq!(do sum |f| { xs.iter().advance(f) }, 10);
|
||||||
|
* ~~~
|
||||||
|
*/
|
||||||
|
#[inline]
|
||||||
|
pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
|
||||||
|
fold_ref(Zero::zero::<T>(), iter, |a, x| *a = a.add(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the product of the items yielded by an iterator.
|
||||||
|
*
|
||||||
|
* # Example:
|
||||||
|
*
|
||||||
|
* ~~~ {.rust}
|
||||||
|
* let xs: ~[int] = ~[1, 2, 3, 4];
|
||||||
|
* assert_eq!(do product |f| { xs.iter().advance(f) }, 24);
|
||||||
|
* ~~~
|
||||||
|
*/
|
||||||
|
#[inline]
|
||||||
|
pub fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
|
||||||
|
fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> FromIter<T> for ~[T]{
|
||||||
|
#[inline]
|
||||||
|
pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] {
|
||||||
|
let mut v = ~[];
|
||||||
|
for iter |x| { v.push(x) }
|
||||||
|
v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use prelude::*;
|
||||||
|
|
||||||
|
use int;
|
||||||
|
use uint;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_iter() {
|
||||||
|
let xs = ~[1, 2, 3];
|
||||||
|
let ys: ~[int] = do FromIter::from_iter |f| { xs.iter().advance(|x| f(*x)) };
|
||||||
|
assert_eq!(xs, ys);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_any() {
|
||||||
|
let xs = ~[1u, 2, 3, 4, 5];
|
||||||
|
assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f)));
|
||||||
|
assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_all() {
|
||||||
|
assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f)));
|
||||||
|
assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_find() {
|
||||||
|
let xs = ~[1u, 2, 3, 4, 5, 6];
|
||||||
|
assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_max() {
|
||||||
|
let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
|
||||||
|
assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_min() {
|
||||||
|
let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
|
||||||
|
assert_eq!(min(|f| xs.iter().advance(f)).unwrap(), &-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fold() {
|
||||||
|
assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sum() {
|
||||||
|
let xs: ~[int] = ~[1, 2, 3, 4];
|
||||||
|
assert_eq!(do sum |f| { xs.iter().advance(f) }, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty_sum() {
|
||||||
|
let xs: ~[int] = ~[];
|
||||||
|
assert_eq!(do sum |f| { xs.iter().advance(f) }, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_product() {
|
||||||
|
let xs: ~[int] = ~[1, 2, 3, 4];
|
||||||
|
assert_eq!(do product |f| { xs.iter().advance(f) }, 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty_product() {
|
||||||
|
let xs: ~[int] = ~[];
|
||||||
|
assert_eq!(do product |f| { xs.iter().advance(f) }, 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,7 +24,6 @@ use std::io::{WriterUtil, ReaderUtil};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::to_str;
|
use std::to_str;
|
||||||
use std::vec;
|
|
||||||
|
|
||||||
use serialize::Encodable;
|
use serialize::Encodable;
|
||||||
use serialize;
|
use serialize;
|
||||||
|
@ -482,9 +481,13 @@ pub fn to_pretty_str(json: &Json) -> ~str {
|
||||||
io::with_str_writer(|wr| to_pretty_writer(wr, json))
|
io::with_str_writer(|wr| to_pretty_writer(wr, json))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BUF_SIZE : uint = 64000;
|
||||||
|
|
||||||
#[allow(missing_doc)]
|
#[allow(missing_doc)]
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
priv rdr: @io::Reader,
|
priv rdr: @io::Reader,
|
||||||
|
priv buf: ~[char],
|
||||||
|
priv buf_idx: uint,
|
||||||
priv ch: char,
|
priv ch: char,
|
||||||
priv line: uint,
|
priv line: uint,
|
||||||
priv col: uint,
|
priv col: uint,
|
||||||
|
@ -492,12 +495,16 @@ pub struct Parser {
|
||||||
|
|
||||||
/// Decode a json value from an io::reader
|
/// Decode a json value from an io::reader
|
||||||
pub fn Parser(rdr: @io::Reader) -> Parser {
|
pub fn Parser(rdr: @io::Reader) -> Parser {
|
||||||
Parser {
|
let mut p = Parser {
|
||||||
rdr: rdr,
|
rdr: rdr,
|
||||||
ch: rdr.read_char(),
|
buf: rdr.read_chars(BUF_SIZE),
|
||||||
|
buf_idx: 0,
|
||||||
|
ch: 0 as char,
|
||||||
line: 1,
|
line: 1,
|
||||||
col: 1,
|
col: 0,
|
||||||
}
|
};
|
||||||
|
p.bump();
|
||||||
|
p
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parser {
|
impl Parser {
|
||||||
|
@ -522,13 +529,26 @@ impl Parser {
|
||||||
fn eof(&self) -> bool { self.ch == -1 as char }
|
fn eof(&self) -> bool { self.ch == -1 as char }
|
||||||
|
|
||||||
fn bump(&mut self) {
|
fn bump(&mut self) {
|
||||||
self.ch = self.rdr.read_char();
|
if self.eof() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.col += 1u;
|
||||||
|
|
||||||
|
if self.buf_idx >= self.buf.len() {
|
||||||
|
self.buf = self.rdr.read_chars(BUF_SIZE);
|
||||||
|
if self.buf.len() == 0 {
|
||||||
|
self.ch = -1 as char;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.buf_idx = 0;
|
||||||
|
}
|
||||||
|
self.ch = self.buf[self.buf_idx];
|
||||||
|
self.buf_idx += 1;
|
||||||
|
|
||||||
if self.ch == '\n' {
|
if self.ch == '\n' {
|
||||||
self.line += 1u;
|
self.line += 1u;
|
||||||
self.col = 1u;
|
self.col = 1u;
|
||||||
} else {
|
|
||||||
self.col += 1u;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -941,7 +961,7 @@ impl serialize::Decoder for Decoder {
|
||||||
let name = match self.stack.pop() {
|
let name = match self.stack.pop() {
|
||||||
String(s) => s,
|
String(s) => s,
|
||||||
List(list) => {
|
List(list) => {
|
||||||
do vec::consume_reverse(list) |_i, v| {
|
for list.consume_rev_iter().advance |v| {
|
||||||
self.stack.push(v);
|
self.stack.push(v);
|
||||||
}
|
}
|
||||||
match self.stack.pop() {
|
match self.stack.pop() {
|
||||||
|
@ -951,7 +971,7 @@ impl serialize::Decoder for Decoder {
|
||||||
}
|
}
|
||||||
ref json => fail!("invalid variant: %?", *json),
|
ref json => fail!("invalid variant: %?", *json),
|
||||||
};
|
};
|
||||||
let idx = match names.iter().position_(|n| str::eq_slice(*n, name)) {
|
let idx = match names.iter().position(|n| str::eq_slice(*n, name)) {
|
||||||
Some(idx) => idx,
|
Some(idx) => idx,
|
||||||
None => fail!("Unknown variant name: %?", name),
|
None => fail!("Unknown variant name: %?", name),
|
||||||
};
|
};
|
||||||
|
@ -1059,7 +1079,7 @@ impl serialize::Decoder for Decoder {
|
||||||
let len = match self.stack.pop() {
|
let len = match self.stack.pop() {
|
||||||
List(list) => {
|
List(list) => {
|
||||||
let len = list.len();
|
let len = list.len();
|
||||||
do vec::consume_reverse(list) |_i, v| {
|
for list.consume_rev_iter().advance |v| {
|
||||||
self.stack.push(v);
|
self.stack.push(v);
|
||||||
}
|
}
|
||||||
len
|
len
|
||||||
|
|
|
@ -22,20 +22,20 @@ use std::str;
|
||||||
use iotask = uv::iotask::IoTask;
|
use iotask = uv::iotask::IoTask;
|
||||||
use interact = uv::iotask::interact;
|
use interact = uv::iotask::interact;
|
||||||
|
|
||||||
use sockaddr_in = super::uv_ll::sockaddr_in;
|
use sockaddr_in = uv_ll::sockaddr_in;
|
||||||
use sockaddr_in6 = super::uv_ll::sockaddr_in6;
|
use sockaddr_in6 = uv_ll::sockaddr_in6;
|
||||||
use addrinfo = super::uv_ll::addrinfo;
|
use addrinfo = uv_ll::addrinfo;
|
||||||
use uv_getaddrinfo_t = super::uv_ll::uv_getaddrinfo_t;
|
use uv_getaddrinfo_t = uv_ll::uv_getaddrinfo_t;
|
||||||
use uv_ip4_name = super::uv_ll::ip4_name;
|
use uv_ip4_name = uv_ll::ip4_name;
|
||||||
use uv_ip4_port = super::uv_ll::ip4_port;
|
use uv_ip4_port = uv_ll::ip4_port;
|
||||||
use uv_ip6_name = super::uv_ll::ip6_name;
|
use uv_ip6_name = uv_ll::ip6_name;
|
||||||
use uv_ip6_port = super::uv_ll::ip6_port;
|
use uv_ip6_port = uv_ll::ip6_port;
|
||||||
use uv_getaddrinfo = super::uv_ll::getaddrinfo;
|
use uv_getaddrinfo = uv_ll::getaddrinfo;
|
||||||
use uv_freeaddrinfo = super::uv_ll::freeaddrinfo;
|
use uv_freeaddrinfo = uv_ll::freeaddrinfo;
|
||||||
use create_uv_getaddrinfo_t = super::uv_ll::getaddrinfo_t;
|
use create_uv_getaddrinfo_t = uv_ll::getaddrinfo_t;
|
||||||
use set_data_for_req = super::uv_ll::set_data_for_req;
|
use set_data_for_req = uv_ll::set_data_for_req;
|
||||||
use get_data_for_req = super::uv_ll::get_data_for_req;
|
use get_data_for_req = uv_ll::get_data_for_req;
|
||||||
use ll = super::uv_ll;
|
use ll = uv_ll;
|
||||||
|
|
||||||
/// An IP address
|
/// An IP address
|
||||||
pub enum IpAddr {
|
pub enum IpAddr {
|
||||||
|
@ -203,7 +203,7 @@ pub mod v4 {
|
||||||
}).collect();
|
}).collect();
|
||||||
if parts.len() != 4 {
|
if parts.len() != 4 {
|
||||||
Err(fmt!("'%s' doesn't have 4 parts", ip))
|
Err(fmt!("'%s' doesn't have 4 parts", ip))
|
||||||
} else if parts.iter().any_(|x| *x == 256u) {
|
} else if parts.iter().any(|x| *x == 256u) {
|
||||||
Err(fmt!("invalid octal in addr '%s'", ip))
|
Err(fmt!("invalid octal in addr '%s'", ip))
|
||||||
} else {
|
} else {
|
||||||
Ok(Ipv4Rep {
|
Ok(Ipv4Rep {
|
||||||
|
@ -363,9 +363,9 @@ extern fn get_addr_cb(handle: *uv_getaddrinfo_t,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
use net_ip::*;
|
use net::ip::*;
|
||||||
use net_ip::v4;
|
use net::ip::v4;
|
||||||
use net_ip::v6;
|
use net::ip::v6;
|
||||||
use uv;
|
use uv;
|
||||||
|
|
||||||
use std::result;
|
use std::result;
|
|
@ -13,13 +13,13 @@ Top-level module for network-related functionality.
|
||||||
|
|
||||||
Basically, including this module gives you:
|
Basically, including this module gives you:
|
||||||
|
|
||||||
* `net_tcp`
|
* `tcp`
|
||||||
* `net_ip`
|
* `ip`
|
||||||
* `net_url`
|
* `url`
|
||||||
|
|
||||||
See each of those three modules for documentation on what they do.
|
See each of those three modules for documentation on what they do.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub use tcp = net_tcp;
|
pub mod tcp;
|
||||||
pub use ip = net_ip;
|
pub mod ip;
|
||||||
pub use url = net_url;
|
pub mod url;
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
use future;
|
use future;
|
||||||
use future_spawn = future::spawn;
|
use future_spawn = future::spawn;
|
||||||
use ip = net_ip;
|
use ip = net::ip;
|
||||||
use uv;
|
use uv;
|
||||||
use uv::iotask;
|
use uv::iotask;
|
||||||
use uv::iotask::IoTask;
|
use uv::iotask::IoTask;
|
|
@ -522,7 +522,7 @@ fn get_authority(rawurl: &str) ->
|
||||||
let host_is_end_plus_one: &fn() -> bool = || {
|
let host_is_end_plus_one: &fn() -> bool = || {
|
||||||
let xs = ['?', '#', '/'];
|
let xs = ['?', '#', '/'];
|
||||||
end+1 == len
|
end+1 == len
|
||||||
&& !xs.iter().any_(|x| *x == (rawurl[end] as char))
|
&& !xs.iter().any(|x| *x == (rawurl[end] as char))
|
||||||
};
|
};
|
||||||
|
|
||||||
// finish up
|
// finish up
|
||||||
|
@ -800,7 +800,7 @@ fn test_get_path() {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use net_url::*;
|
use net::url::*;
|
||||||
|
|
||||||
use std::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
|
|
|
@ -17,6 +17,7 @@ A BigInt is a combination of BigUint and Sign.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[allow(missing_doc)];
|
#[allow(missing_doc)];
|
||||||
|
#[allow(non_uppercase_statics)];
|
||||||
|
|
||||||
use std::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
|
use std::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
|
||||||
use std::int;
|
use std::int;
|
||||||
|
@ -206,7 +207,7 @@ impl Add<BigUint, BigUint> for BigUint {
|
||||||
let new_len = uint::max(self.data.len(), other.data.len());
|
let new_len = uint::max(self.data.len(), other.data.len());
|
||||||
|
|
||||||
let mut carry = 0;
|
let mut carry = 0;
|
||||||
let sum = do vec::from_fn(new_len) |i| {
|
let mut sum = do vec::from_fn(new_len) |i| {
|
||||||
let ai = if i < self.data.len() { self.data[i] } else { 0 };
|
let ai = if i < self.data.len() { self.data[i] } else { 0 };
|
||||||
let bi = if i < other.data.len() { other.data[i] } else { 0 };
|
let bi = if i < other.data.len() { other.data[i] } else { 0 };
|
||||||
let (hi, lo) = BigDigit::from_uint(
|
let (hi, lo) = BigDigit::from_uint(
|
||||||
|
@ -215,8 +216,8 @@ impl Add<BigUint, BigUint> for BigUint {
|
||||||
carry = hi;
|
carry = hi;
|
||||||
lo
|
lo
|
||||||
};
|
};
|
||||||
if carry == 0 { return BigUint::new(sum) };
|
if carry != 0 { sum.push(carry); }
|
||||||
return BigUint::new(sum + [carry]);
|
return BigUint::new(sum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,15 +284,15 @@ impl Mul<BigUint, BigUint> for BigUint {
|
||||||
if n == 1 { return copy *a; }
|
if n == 1 { return copy *a; }
|
||||||
|
|
||||||
let mut carry = 0;
|
let mut carry = 0;
|
||||||
let prod = do a.data.iter().transform |ai| {
|
let mut prod = do a.data.iter().transform |ai| {
|
||||||
let (hi, lo) = BigDigit::from_uint(
|
let (hi, lo) = BigDigit::from_uint(
|
||||||
(*ai as uint) * (n as uint) + (carry as uint)
|
(*ai as uint) * (n as uint) + (carry as uint)
|
||||||
);
|
);
|
||||||
carry = hi;
|
carry = hi;
|
||||||
lo
|
lo
|
||||||
}.collect::<~[BigDigit]>();
|
}.collect::<~[BigDigit]>();
|
||||||
if carry == 0 { return BigUint::new(prod) };
|
if carry != 0 { prod.push(carry); }
|
||||||
return BigUint::new(prod + [carry]);
|
return BigUint::new(prod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -519,10 +520,12 @@ impl ToStrRadix for BigUint {
|
||||||
|
|
||||||
fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str {
|
fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str {
|
||||||
if v.is_empty() { return ~"0" }
|
if v.is_empty() { return ~"0" }
|
||||||
let s = vec::reversed(v).map(|n| {
|
let mut s = str::with_capacity(v.len() * l);
|
||||||
let s = uint::to_str_radix(*n as uint, radix);
|
for v.rev_iter().advance |n| {
|
||||||
str::from_chars(vec::from_elem(l - s.len(), '0')) + s
|
let ss = uint::to_str_radix(*n as uint, radix);
|
||||||
}).concat();
|
s.push_str("0".repeat(l - ss.len()));
|
||||||
|
s.push_str(ss);
|
||||||
|
}
|
||||||
s.trim_left_chars(&'0').to_owned()
|
s.trim_left_chars(&'0').to_owned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -618,15 +621,15 @@ impl BigUint {
|
||||||
if n_bits == 0 || self.is_zero() { return copy *self; }
|
if n_bits == 0 || self.is_zero() { return copy *self; }
|
||||||
|
|
||||||
let mut carry = 0;
|
let mut carry = 0;
|
||||||
let shifted = do self.data.iter().transform |elem| {
|
let mut shifted = do self.data.iter().transform |elem| {
|
||||||
let (hi, lo) = BigDigit::from_uint(
|
let (hi, lo) = BigDigit::from_uint(
|
||||||
(*elem as uint) << n_bits | (carry as uint)
|
(*elem as uint) << n_bits | (carry as uint)
|
||||||
);
|
);
|
||||||
carry = hi;
|
carry = hi;
|
||||||
lo
|
lo
|
||||||
}.collect::<~[BigDigit]>();
|
}.collect::<~[BigDigit]>();
|
||||||
if carry == 0 { return BigUint::new(shifted); }
|
if carry != 0 { shifted.push(carry); }
|
||||||
return BigUint::new(shifted + [carry]);
|
return BigUint::new(shifted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1628,7 +1631,6 @@ mod bigint_tests {
|
||||||
use std::int;
|
use std::int;
|
||||||
use std::num::{IntConvertible, Zero, One, FromStrRadix};
|
use std::num::{IntConvertible, Zero, One, FromStrRadix};
|
||||||
use std::uint;
|
use std::uint;
|
||||||
use std::vec;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_biguint() {
|
fn test_from_biguint() {
|
||||||
|
@ -1645,9 +1647,11 @@ mod bigint_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cmp() {
|
fn test_cmp() {
|
||||||
let vs = [ &[2], &[1, 1], &[2, 1], &[1, 1, 1] ];
|
let vs = [ &[2 as BigDigit], &[1, 1], &[2, 1], &[1, 1, 1] ];
|
||||||
let mut nums = vec::reversed(vs)
|
let mut nums = ~[];
|
||||||
.map(|s| BigInt::from_slice(Minus, *s));
|
for vs.rev_iter().advance |s| {
|
||||||
|
nums.push(BigInt::from_slice(Minus, *s));
|
||||||
|
}
|
||||||
nums.push(Zero::zero());
|
nums.push(Zero::zero());
|
||||||
nums.push_all_move(vs.map(|s| BigInt::from_slice(Plus, *s)));
|
nums.push_all_move(vs.map(|s| BigInt::from_slice(Plus, *s)));
|
||||||
|
|
||||||
|
|
|
@ -191,6 +191,8 @@ impl<T: ToStrRadix + Num + Ord> ToStrRadix for Cmplx<T> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
#[allow(non_uppercase_statics)];
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::num::{Zero,One,Real};
|
use std::num::{Zero,One,Real};
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,10 @@ use future_spawn = future::spawn;
|
||||||
* The maximum number of tasks this module will spawn for a single
|
* The maximum number of tasks this module will spawn for a single
|
||||||
* operation.
|
* operation.
|
||||||
*/
|
*/
|
||||||
static max_tasks : uint = 32u;
|
static MAX_TASKS : uint = 32u;
|
||||||
|
|
||||||
/// The minimum number of elements each task will process.
|
/// The minimum number of elements each task will process.
|
||||||
static min_granularity : uint = 1024u;
|
static MIN_GRANULARITY : uint = 1024u;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An internal helper to map a function over a large vector and
|
* An internal helper to map a function over a large vector and
|
||||||
|
@ -38,13 +38,13 @@ fn map_slices<A:Copy + Send,B:Copy + Send>(
|
||||||
-> ~[B] {
|
-> ~[B] {
|
||||||
|
|
||||||
let len = xs.len();
|
let len = xs.len();
|
||||||
if len < min_granularity {
|
if len < MIN_GRANULARITY {
|
||||||
info!("small slice");
|
info!("small slice");
|
||||||
// This is a small vector, fall back on the normal map.
|
// This is a small vector, fall back on the normal map.
|
||||||
~[f()(0u, xs)]
|
~[f()(0u, xs)]
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let num_tasks = uint::min(max_tasks, len / min_granularity);
|
let num_tasks = uint::min(MAX_TASKS, len / MIN_GRANULARITY);
|
||||||
|
|
||||||
let items_per_task = len / num_tasks;
|
let items_per_task = len / num_tasks;
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ fn map_slices<A:Copy + Send,B:Copy + Send>(
|
||||||
info!("spawning tasks");
|
info!("spawning tasks");
|
||||||
while base < len {
|
while base < len {
|
||||||
let end = uint::min(len, base + items_per_task);
|
let end = uint::min(len, base + items_per_task);
|
||||||
do vec::as_imm_buf(xs) |p, _len| {
|
do xs.as_imm_buf |p, _len| {
|
||||||
let f = f();
|
let f = f();
|
||||||
let base = base;
|
let base = base;
|
||||||
let f = do future_spawn() || {
|
let f = do future_spawn() || {
|
||||||
|
@ -78,11 +78,10 @@ fn map_slices<A:Copy + Send,B:Copy + Send>(
|
||||||
info!("num_tasks: %?", (num_tasks, futures.len()));
|
info!("num_tasks: %?", (num_tasks, futures.len()));
|
||||||
assert_eq!(num_tasks, futures.len());
|
assert_eq!(num_tasks, futures.len());
|
||||||
|
|
||||||
let r = do vec::map_consume(futures) |ys| {
|
do futures.consume_iter().transform |ys| {
|
||||||
let mut ys = ys;
|
let mut ys = ys;
|
||||||
ys.get()
|
ys.get()
|
||||||
};
|
}.collect()
|
||||||
r
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,8 +136,8 @@ pub fn any<A:Copy + Send>(
|
||||||
fn_factory: &fn() -> ~fn(&A) -> bool) -> bool {
|
fn_factory: &fn() -> ~fn(&A) -> bool) -> bool {
|
||||||
let mapped = map_slices(xs, || {
|
let mapped = map_slices(xs, || {
|
||||||
let f = fn_factory();
|
let f = fn_factory();
|
||||||
let result: ~fn(uint, &[A]) -> bool = |_, slice| slice.iter().any_(f);
|
let result: ~fn(uint, &[A]) -> bool = |_, slice| slice.iter().any(f);
|
||||||
result
|
result
|
||||||
});
|
});
|
||||||
mapped.iter().any_(|&x| x)
|
mapped.iter().any(|&x| x)
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,6 +186,9 @@ pub struct PriorityQueueIterator <'self, T> {
|
||||||
impl<'self, T> Iterator<&'self T> for PriorityQueueIterator<'self, T> {
|
impl<'self, T> Iterator<&'self T> for PriorityQueueIterator<'self, T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<(&'self T)> { self.iter.next() }
|
fn next(&mut self) -> Option<(&'self T)> { self.iter.next() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
1442
src/libextra/rope.rs
1442
src/libextra/rope.rs
File diff suppressed because it is too large
Load diff
|
@ -682,7 +682,7 @@ impl<
|
||||||
> Encodable<S> for Deque<T> {
|
> Encodable<S> for Deque<T> {
|
||||||
fn encode(&self, s: &mut S) {
|
fn encode(&self, s: &mut S) {
|
||||||
do s.emit_seq(self.len()) |s| {
|
do s.emit_seq(self.len()) |s| {
|
||||||
for self.eachi |i, e| {
|
for self.iter().enumerate().advance |(i, e)| {
|
||||||
s.emit_seq_elt(i, |s| e.encode(s));
|
s.emit_seq_elt(i, |s| e.encode(s));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,32 +8,135 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#[allow(missing_doc)];
|
|
||||||
|
|
||||||
|
|
||||||
use std::f64;
|
|
||||||
use std::cmp;
|
|
||||||
use std::num;
|
|
||||||
use std::vec;
|
|
||||||
use sort;
|
use sort;
|
||||||
|
use std::cmp;
|
||||||
|
use std::io;
|
||||||
|
use std::num;
|
||||||
|
use std::f64;
|
||||||
|
use std::vec;
|
||||||
|
|
||||||
// NB: this can probably be rewritten in terms of num::Num
|
// NB: this can probably be rewritten in terms of num::Num
|
||||||
// to be less f64-specific.
|
// to be less f64-specific.
|
||||||
|
|
||||||
|
/// Trait that provides simple descriptive statistics on a univariate set of numeric samples.
|
||||||
pub trait Stats {
|
pub trait Stats {
|
||||||
|
|
||||||
|
/// Sum of the samples.
|
||||||
fn sum(self) -> f64;
|
fn sum(self) -> f64;
|
||||||
|
|
||||||
|
/// Minimum value of the samples.
|
||||||
fn min(self) -> f64;
|
fn min(self) -> f64;
|
||||||
|
|
||||||
|
/// Maximum value of the samples.
|
||||||
fn max(self) -> f64;
|
fn max(self) -> f64;
|
||||||
|
|
||||||
|
/// Arithmetic mean (average) of the samples: sum divided by sample-count.
|
||||||
|
///
|
||||||
|
/// See: https://en.wikipedia.org/wiki/Arithmetic_mean
|
||||||
fn mean(self) -> f64;
|
fn mean(self) -> f64;
|
||||||
|
|
||||||
|
/// Median of the samples: value separating the lower half of the samples from the higher half.
|
||||||
|
/// Equal to `self.percentile(50.0)`.
|
||||||
|
///
|
||||||
|
/// See: https://en.wikipedia.org/wiki/Median
|
||||||
fn median(self) -> f64;
|
fn median(self) -> f64;
|
||||||
|
|
||||||
|
/// Variance of the samples: bias-corrected mean of the squares of the differences of each
|
||||||
|
/// sample from the sample mean. Note that this calculates the _sample variance_ rather than the
|
||||||
|
/// population variance, which is assumed to be unknown. It therefore corrects the `(n-1)/n`
|
||||||
|
/// bias that would appear if we calculated a population variance, by dividing by `(n-1)` rather
|
||||||
|
/// than `n`.
|
||||||
|
///
|
||||||
|
/// See: https://en.wikipedia.org/wiki/Variance
|
||||||
fn var(self) -> f64;
|
fn var(self) -> f64;
|
||||||
|
|
||||||
|
/// Standard deviation: the square root of the sample variance.
|
||||||
|
///
|
||||||
|
/// Note: this is not a robust statistic for non-normal distributions. Prefer the
|
||||||
|
/// `median_abs_dev` for unknown distributions.
|
||||||
|
///
|
||||||
|
/// See: https://en.wikipedia.org/wiki/Standard_deviation
|
||||||
fn std_dev(self) -> f64;
|
fn std_dev(self) -> f64;
|
||||||
|
|
||||||
|
/// Standard deviation as a percent of the mean value. See `std_dev` and `mean`.
|
||||||
|
///
|
||||||
|
/// Note: this is not a robust statistic for non-normal distributions. Prefer the
|
||||||
|
/// `median_abs_dev_pct` for unknown distributions.
|
||||||
fn std_dev_pct(self) -> f64;
|
fn std_dev_pct(self) -> f64;
|
||||||
|
|
||||||
|
/// Scaled median of the absolute deviations of each sample from the sample median. This is a
|
||||||
|
/// robust (distribution-agnostic) estimator of sample variability. Use this in preference to
|
||||||
|
/// `std_dev` if you cannot assume your sample is normally distributed. Note that this is scaled
|
||||||
|
/// by the constant `1.4826` to allow its use as a consistent estimator for the standard
|
||||||
|
/// deviation.
|
||||||
|
///
|
||||||
|
/// See: http://en.wikipedia.org/wiki/Median_absolute_deviation
|
||||||
fn median_abs_dev(self) -> f64;
|
fn median_abs_dev(self) -> f64;
|
||||||
|
|
||||||
|
/// Median absolute deviation as a percent of the median. See `median_abs_dev` and `median`.
|
||||||
fn median_abs_dev_pct(self) -> f64;
|
fn median_abs_dev_pct(self) -> f64;
|
||||||
|
|
||||||
|
/// Percentile: the value below which `pct` percent of the values in `self` fall. For example,
|
||||||
|
/// percentile(95.0) will return the value `v` such that that 95% of the samples `s` in `self`
|
||||||
|
/// satisfy `s <= v`.
|
||||||
|
///
|
||||||
|
/// Calculated by linear interpolation between closest ranks.
|
||||||
|
///
|
||||||
|
/// See: http://en.wikipedia.org/wiki/Percentile
|
||||||
|
fn percentile(self, pct: f64) -> f64;
|
||||||
|
|
||||||
|
/// Quartiles of the sample: three values that divide the sample into four equal groups, each
|
||||||
|
/// with 1/4 of the data. The middle value is the median. See `median` and `percentile`. This
|
||||||
|
/// function may calculate the 3 quartiles more efficiently than 3 calls to `percentile`, but
|
||||||
|
/// is otherwise equivalent.
|
||||||
|
///
|
||||||
|
/// See also: https://en.wikipedia.org/wiki/Quartile
|
||||||
|
fn quartiles(self) -> (f64,f64,f64);
|
||||||
|
|
||||||
|
/// Inter-quartile range: the difference between the 25th percentile (1st quartile) and the 75th
|
||||||
|
/// percentile (3rd quartile). See `quartiles`.
|
||||||
|
///
|
||||||
|
/// See also: https://en.wikipedia.org/wiki/Interquartile_range
|
||||||
|
fn iqr(self) -> f64;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extracted collection of all the summary statistics of a sample set.
|
||||||
|
struct Summary {
|
||||||
|
sum: f64,
|
||||||
|
min: f64,
|
||||||
|
max: f64,
|
||||||
|
mean: f64,
|
||||||
|
median: f64,
|
||||||
|
var: f64,
|
||||||
|
std_dev: f64,
|
||||||
|
std_dev_pct: f64,
|
||||||
|
median_abs_dev: f64,
|
||||||
|
median_abs_dev_pct: f64,
|
||||||
|
quartiles: (f64,f64,f64),
|
||||||
|
iqr: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Summary {
|
||||||
|
fn new(samples: &[f64]) -> Summary {
|
||||||
|
Summary {
|
||||||
|
sum: samples.sum(),
|
||||||
|
min: samples.min(),
|
||||||
|
max: samples.max(),
|
||||||
|
mean: samples.mean(),
|
||||||
|
median: samples.median(),
|
||||||
|
var: samples.var(),
|
||||||
|
std_dev: samples.std_dev(),
|
||||||
|
std_dev_pct: samples.std_dev_pct(),
|
||||||
|
median_abs_dev: samples.median_abs_dev(),
|
||||||
|
median_abs_dev_pct: samples.median_abs_dev_pct(),
|
||||||
|
quartiles: samples.quartiles(),
|
||||||
|
iqr: samples.iqr()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'self> Stats for &'self [f64] {
|
impl<'self> Stats for &'self [f64] {
|
||||||
|
|
||||||
fn sum(self) -> f64 {
|
fn sum(self) -> f64 {
|
||||||
self.iter().fold(0.0, |p,q| p + *q)
|
self.iter().fold(0.0, |p,q| p + *q)
|
||||||
}
|
}
|
||||||
|
@ -54,19 +157,11 @@ impl<'self> Stats for &'self [f64] {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn median(self) -> f64 {
|
fn median(self) -> f64 {
|
||||||
assert!(self.len() != 0);
|
self.percentile(50.0)
|
||||||
let mut tmp = vec::to_owned(self);
|
|
||||||
sort::tim_sort(tmp);
|
|
||||||
if tmp.len() & 1 == 0 {
|
|
||||||
let m = tmp.len() / 2;
|
|
||||||
(tmp[m] + tmp[m-1]) / 2.0
|
|
||||||
} else {
|
|
||||||
tmp[tmp.len() / 2]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn var(self) -> f64 {
|
fn var(self) -> f64 {
|
||||||
if self.len() == 0 {
|
if self.len() < 2 {
|
||||||
0.0
|
0.0
|
||||||
} else {
|
} else {
|
||||||
let mean = self.mean();
|
let mean = self.mean();
|
||||||
|
@ -75,7 +170,10 @@ impl<'self> Stats for &'self [f64] {
|
||||||
let x = *s - mean;
|
let x = *s - mean;
|
||||||
v += x*x;
|
v += x*x;
|
||||||
}
|
}
|
||||||
v/(self.len() as f64)
|
// NB: this is _supposed to be_ len-1, not len. If you
|
||||||
|
// change it back to len, you will be calculating a
|
||||||
|
// population variance, not a sample variance.
|
||||||
|
v/((self.len()-1) as f64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,11 +187,725 @@ impl<'self> Stats for &'self [f64] {
|
||||||
|
|
||||||
fn median_abs_dev(self) -> f64 {
|
fn median_abs_dev(self) -> f64 {
|
||||||
let med = self.median();
|
let med = self.median();
|
||||||
let abs_devs = self.map(|v| num::abs(med - *v));
|
let abs_devs = self.map(|&v| num::abs(med - v));
|
||||||
abs_devs.median()
|
// This constant is derived by smarter statistics brains than me, but it is
|
||||||
|
// consistent with how R and other packages treat the MAD.
|
||||||
|
abs_devs.median() * 1.4826
|
||||||
}
|
}
|
||||||
|
|
||||||
fn median_abs_dev_pct(self) -> f64 {
|
fn median_abs_dev_pct(self) -> f64 {
|
||||||
(self.median_abs_dev() / self.median()) * 100.0
|
(self.median_abs_dev() / self.median()) * 100.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn percentile(self, pct: f64) -> f64 {
|
||||||
|
let mut tmp = vec::to_owned(self);
|
||||||
|
sort::tim_sort(tmp);
|
||||||
|
percentile_of_sorted(tmp, pct)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quartiles(self) -> (f64,f64,f64) {
|
||||||
|
let mut tmp = vec::to_owned(self);
|
||||||
|
sort::tim_sort(tmp);
|
||||||
|
let a = percentile_of_sorted(tmp, 25.0);
|
||||||
|
let b = percentile_of_sorted(tmp, 50.0);
|
||||||
|
let c = percentile_of_sorted(tmp, 75.0);
|
||||||
|
(a,b,c)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iqr(self) -> f64 {
|
||||||
|
let (a,_,c) = self.quartiles();
|
||||||
|
c - a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function: extract a value representing the `pct` percentile of a sorted sample-set, using
|
||||||
|
// linear interpolation. If samples are not sorted, return nonsensical value.
|
||||||
|
priv fn percentile_of_sorted(sorted_samples: &[f64],
|
||||||
|
pct: f64) -> f64 {
|
||||||
|
assert!(sorted_samples.len() != 0);
|
||||||
|
if sorted_samples.len() == 1 {
|
||||||
|
return sorted_samples[0];
|
||||||
|
}
|
||||||
|
assert!(0.0 <= pct);
|
||||||
|
assert!(pct <= 100.0);
|
||||||
|
if pct == 100.0 {
|
||||||
|
return sorted_samples[sorted_samples.len() - 1];
|
||||||
|
}
|
||||||
|
let rank = (pct / 100.0) * ((sorted_samples.len() - 1) as f64);
|
||||||
|
let lrank = rank.floor();
|
||||||
|
let d = rank - lrank;
|
||||||
|
let n = lrank as uint;
|
||||||
|
let lo = sorted_samples[n];
|
||||||
|
let hi = sorted_samples[n+1];
|
||||||
|
lo + (hi - lo) * d
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Winsorize a set of samples, replacing values above the `100-pct` percentile and below the `pct`
|
||||||
|
/// percentile with those percentiles themselves. This is a way of minimizing the effect of
|
||||||
|
/// outliers, at the cost of biasing the sample. It differs from trimming in that it does not
|
||||||
|
/// change the number of samples, just changes the values of those that are outliers.
|
||||||
|
///
|
||||||
|
/// See: http://en.wikipedia.org/wiki/Winsorising
|
||||||
|
pub fn winsorize(samples: &mut [f64], pct: f64) {
|
||||||
|
let mut tmp = vec::to_owned(samples);
|
||||||
|
sort::tim_sort(tmp);
|
||||||
|
let lo = percentile_of_sorted(tmp, pct);
|
||||||
|
let hi = percentile_of_sorted(tmp, 100.0-pct);
|
||||||
|
for samples.mut_iter().advance |samp| {
|
||||||
|
if *samp > hi {
|
||||||
|
*samp = hi
|
||||||
|
} else if *samp < lo {
|
||||||
|
*samp = lo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render writes the min, max and quartiles of the provided `Summary` to the provided `Writer`.
|
||||||
|
pub fn write_5_number_summary(w: @io::Writer, s: &Summary) {
|
||||||
|
let (q1,q2,q3) = s.quartiles;
|
||||||
|
w.write_str(fmt!("(min=%f, q1=%f, med=%f, q3=%f, max=%f)",
|
||||||
|
s.min as float,
|
||||||
|
q1 as float,
|
||||||
|
q2 as float,
|
||||||
|
q3 as float,
|
||||||
|
s.max as float));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render a boxplot to the provided writer. The boxplot shows the min, max and quartiles of the
|
||||||
|
/// provided `Summary` (thus includes the mean) and is scaled to display within the range of the
|
||||||
|
/// nearest multiple-of-a-power-of-ten above and below the min and max of possible values, and
|
||||||
|
/// target `width_hint` characters of display (though it will be wider if necessary).
|
||||||
|
///
|
||||||
|
/// As an example, the summary with 5-number-summary `(min=15, q1=17, med=20, q3=24, max=31)` might
|
||||||
|
/// display as:
|
||||||
|
///
|
||||||
|
/// ~~~~
|
||||||
|
/// 10 | [--****#******----------] | 40
|
||||||
|
/// ~~~~
|
||||||
|
|
||||||
|
pub fn write_boxplot(w: @io::Writer, s: &Summary, width_hint: uint) {
|
||||||
|
|
||||||
|
let (q1,q2,q3) = s.quartiles;
|
||||||
|
|
||||||
|
let lomag = (10.0_f64).pow(&s.min.log10().floor());
|
||||||
|
let himag = (10.0_f64).pow(&(s.max.log10().floor()));
|
||||||
|
let lo = (s.min / lomag).floor() * lomag;
|
||||||
|
let hi = (s.max / himag).ceil() * himag;
|
||||||
|
|
||||||
|
let range = hi - lo;
|
||||||
|
|
||||||
|
let lostr = lo.to_str();
|
||||||
|
let histr = hi.to_str();
|
||||||
|
|
||||||
|
let overhead_width = lostr.len() + histr.len() + 4;
|
||||||
|
let range_width = width_hint - overhead_width;;
|
||||||
|
let char_step = range / (range_width as f64);
|
||||||
|
|
||||||
|
w.write_str(lostr);
|
||||||
|
w.write_char(' ');
|
||||||
|
w.write_char('|');
|
||||||
|
|
||||||
|
let mut c = 0;
|
||||||
|
let mut v = lo;
|
||||||
|
|
||||||
|
while c < range_width && v < s.min {
|
||||||
|
w.write_char(' ');
|
||||||
|
v += char_step;
|
||||||
|
c += 1;
|
||||||
|
}
|
||||||
|
w.write_char('[');
|
||||||
|
c += 1;
|
||||||
|
while c < range_width && v < q1 {
|
||||||
|
w.write_char('-');
|
||||||
|
v += char_step;
|
||||||
|
c += 1;
|
||||||
|
}
|
||||||
|
while c < range_width && v < q2 {
|
||||||
|
w.write_char('*');
|
||||||
|
v += char_step;
|
||||||
|
c += 1;
|
||||||
|
}
|
||||||
|
w.write_char('#');
|
||||||
|
c += 1;
|
||||||
|
while c < range_width && v < q3 {
|
||||||
|
w.write_char('*');
|
||||||
|
v += char_step;
|
||||||
|
c += 1;
|
||||||
|
}
|
||||||
|
while c < range_width && v < s.max {
|
||||||
|
w.write_char('-');
|
||||||
|
v += char_step;
|
||||||
|
c += 1;
|
||||||
|
}
|
||||||
|
w.write_char(']');
|
||||||
|
while c < range_width {
|
||||||
|
w.write_char(' ');
|
||||||
|
v += char_step;
|
||||||
|
c += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
w.write_char('|');
|
||||||
|
w.write_char(' ');
|
||||||
|
w.write_str(histr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test vectors generated from R, using the script src/etc/stat-test-vectors.r.
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use stats::Stats;
|
||||||
|
use stats::Summary;
|
||||||
|
use stats::write_5_number_summary;
|
||||||
|
use stats::write_boxplot;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
fn check(samples: &[f64], summ: &Summary) {
|
||||||
|
|
||||||
|
let summ2 = Summary::new(samples);
|
||||||
|
|
||||||
|
let w = io::stdout();
|
||||||
|
w.write_char('\n');
|
||||||
|
write_5_number_summary(w, &summ2);
|
||||||
|
w.write_char('\n');
|
||||||
|
write_boxplot(w, &summ2, 50);
|
||||||
|
w.write_char('\n');
|
||||||
|
|
||||||
|
assert_eq!(summ.sum, summ2.sum);
|
||||||
|
assert_eq!(summ.min, summ2.min);
|
||||||
|
assert_eq!(summ.max, summ2.max);
|
||||||
|
assert_eq!(summ.mean, summ2.mean);
|
||||||
|
assert_eq!(summ.median, summ2.median);
|
||||||
|
|
||||||
|
// We needed a few more digits to get exact equality on these
|
||||||
|
// but they're within float epsilon, which is 1.0e-6.
|
||||||
|
assert_approx_eq!(summ.var, summ2.var);
|
||||||
|
assert_approx_eq!(summ.std_dev, summ2.std_dev);
|
||||||
|
assert_approx_eq!(summ.std_dev_pct, summ2.std_dev_pct);
|
||||||
|
assert_approx_eq!(summ.median_abs_dev, summ2.median_abs_dev);
|
||||||
|
assert_approx_eq!(summ.median_abs_dev_pct, summ2.median_abs_dev_pct);
|
||||||
|
|
||||||
|
assert_eq!(summ.quartiles, summ2.quartiles);
|
||||||
|
assert_eq!(summ.iqr, summ2.iqr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_norm2() {
|
||||||
|
let val = &[
|
||||||
|
958.0000000000,
|
||||||
|
924.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 1882.0000000000,
|
||||||
|
min: 924.0000000000,
|
||||||
|
max: 958.0000000000,
|
||||||
|
mean: 941.0000000000,
|
||||||
|
median: 941.0000000000,
|
||||||
|
var: 578.0000000000,
|
||||||
|
std_dev: 24.0416305603,
|
||||||
|
std_dev_pct: 2.5549022912,
|
||||||
|
median_abs_dev: 25.2042000000,
|
||||||
|
median_abs_dev_pct: 2.6784484591,
|
||||||
|
quartiles: (932.5000000000,941.0000000000,949.5000000000),
|
||||||
|
iqr: 17.0000000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_norm10narrow() {
|
||||||
|
let val = &[
|
||||||
|
966.0000000000,
|
||||||
|
985.0000000000,
|
||||||
|
1110.0000000000,
|
||||||
|
848.0000000000,
|
||||||
|
821.0000000000,
|
||||||
|
975.0000000000,
|
||||||
|
962.0000000000,
|
||||||
|
1157.0000000000,
|
||||||
|
1217.0000000000,
|
||||||
|
955.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 9996.0000000000,
|
||||||
|
min: 821.0000000000,
|
||||||
|
max: 1217.0000000000,
|
||||||
|
mean: 999.6000000000,
|
||||||
|
median: 970.5000000000,
|
||||||
|
var: 16050.7111111111,
|
||||||
|
std_dev: 126.6914010938,
|
||||||
|
std_dev_pct: 12.6742097933,
|
||||||
|
median_abs_dev: 102.2994000000,
|
||||||
|
median_abs_dev_pct: 10.5408964451,
|
||||||
|
quartiles: (956.7500000000,970.5000000000,1078.7500000000),
|
||||||
|
iqr: 122.0000000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_norm10medium() {
|
||||||
|
let val = &[
|
||||||
|
954.0000000000,
|
||||||
|
1064.0000000000,
|
||||||
|
855.0000000000,
|
||||||
|
1000.0000000000,
|
||||||
|
743.0000000000,
|
||||||
|
1084.0000000000,
|
||||||
|
704.0000000000,
|
||||||
|
1023.0000000000,
|
||||||
|
357.0000000000,
|
||||||
|
869.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 8653.0000000000,
|
||||||
|
min: 357.0000000000,
|
||||||
|
max: 1084.0000000000,
|
||||||
|
mean: 865.3000000000,
|
||||||
|
median: 911.5000000000,
|
||||||
|
var: 48628.4555555556,
|
||||||
|
std_dev: 220.5186059170,
|
||||||
|
std_dev_pct: 25.4846418487,
|
||||||
|
median_abs_dev: 195.7032000000,
|
||||||
|
median_abs_dev_pct: 21.4704552935,
|
||||||
|
quartiles: (771.0000000000,911.5000000000,1017.2500000000),
|
||||||
|
iqr: 246.2500000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_norm10wide() {
|
||||||
|
let val = &[
|
||||||
|
505.0000000000,
|
||||||
|
497.0000000000,
|
||||||
|
1591.0000000000,
|
||||||
|
887.0000000000,
|
||||||
|
1026.0000000000,
|
||||||
|
136.0000000000,
|
||||||
|
1580.0000000000,
|
||||||
|
940.0000000000,
|
||||||
|
754.0000000000,
|
||||||
|
1433.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 9349.0000000000,
|
||||||
|
min: 136.0000000000,
|
||||||
|
max: 1591.0000000000,
|
||||||
|
mean: 934.9000000000,
|
||||||
|
median: 913.5000000000,
|
||||||
|
var: 239208.9888888889,
|
||||||
|
std_dev: 489.0899599142,
|
||||||
|
std_dev_pct: 52.3146817750,
|
||||||
|
median_abs_dev: 611.5725000000,
|
||||||
|
median_abs_dev_pct: 66.9482758621,
|
||||||
|
quartiles: (567.2500000000,913.5000000000,1331.2500000000),
|
||||||
|
iqr: 764.0000000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_norm25verynarrow() {
|
||||||
|
let val = &[
|
||||||
|
991.0000000000,
|
||||||
|
1018.0000000000,
|
||||||
|
998.0000000000,
|
||||||
|
1013.0000000000,
|
||||||
|
974.0000000000,
|
||||||
|
1007.0000000000,
|
||||||
|
1014.0000000000,
|
||||||
|
999.0000000000,
|
||||||
|
1011.0000000000,
|
||||||
|
978.0000000000,
|
||||||
|
985.0000000000,
|
||||||
|
999.0000000000,
|
||||||
|
983.0000000000,
|
||||||
|
982.0000000000,
|
||||||
|
1015.0000000000,
|
||||||
|
1002.0000000000,
|
||||||
|
977.0000000000,
|
||||||
|
948.0000000000,
|
||||||
|
1040.0000000000,
|
||||||
|
974.0000000000,
|
||||||
|
996.0000000000,
|
||||||
|
989.0000000000,
|
||||||
|
1015.0000000000,
|
||||||
|
994.0000000000,
|
||||||
|
1024.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 24926.0000000000,
|
||||||
|
min: 948.0000000000,
|
||||||
|
max: 1040.0000000000,
|
||||||
|
mean: 997.0400000000,
|
||||||
|
median: 998.0000000000,
|
||||||
|
var: 393.2066666667,
|
||||||
|
std_dev: 19.8294393937,
|
||||||
|
std_dev_pct: 1.9888308788,
|
||||||
|
median_abs_dev: 22.2390000000,
|
||||||
|
median_abs_dev_pct: 2.2283567134,
|
||||||
|
quartiles: (983.0000000000,998.0000000000,1013.0000000000),
|
||||||
|
iqr: 30.0000000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_exp10a() {
|
||||||
|
let val = &[
|
||||||
|
23.0000000000,
|
||||||
|
11.0000000000,
|
||||||
|
2.0000000000,
|
||||||
|
57.0000000000,
|
||||||
|
4.0000000000,
|
||||||
|
12.0000000000,
|
||||||
|
5.0000000000,
|
||||||
|
29.0000000000,
|
||||||
|
3.0000000000,
|
||||||
|
21.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 167.0000000000,
|
||||||
|
min: 2.0000000000,
|
||||||
|
max: 57.0000000000,
|
||||||
|
mean: 16.7000000000,
|
||||||
|
median: 11.5000000000,
|
||||||
|
var: 287.7888888889,
|
||||||
|
std_dev: 16.9643416875,
|
||||||
|
std_dev_pct: 101.5828843560,
|
||||||
|
median_abs_dev: 13.3434000000,
|
||||||
|
median_abs_dev_pct: 116.0295652174,
|
||||||
|
quartiles: (4.2500000000,11.5000000000,22.5000000000),
|
||||||
|
iqr: 18.2500000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_exp10b() {
|
||||||
|
let val = &[
|
||||||
|
24.0000000000,
|
||||||
|
17.0000000000,
|
||||||
|
6.0000000000,
|
||||||
|
38.0000000000,
|
||||||
|
25.0000000000,
|
||||||
|
7.0000000000,
|
||||||
|
51.0000000000,
|
||||||
|
2.0000000000,
|
||||||
|
61.0000000000,
|
||||||
|
32.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 263.0000000000,
|
||||||
|
min: 2.0000000000,
|
||||||
|
max: 61.0000000000,
|
||||||
|
mean: 26.3000000000,
|
||||||
|
median: 24.5000000000,
|
||||||
|
var: 383.5666666667,
|
||||||
|
std_dev: 19.5848580967,
|
||||||
|
std_dev_pct: 74.4671410520,
|
||||||
|
median_abs_dev: 22.9803000000,
|
||||||
|
median_abs_dev_pct: 93.7971428571,
|
||||||
|
quartiles: (9.5000000000,24.5000000000,36.5000000000),
|
||||||
|
iqr: 27.0000000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_exp10c() {
|
||||||
|
let val = &[
|
||||||
|
71.0000000000,
|
||||||
|
2.0000000000,
|
||||||
|
32.0000000000,
|
||||||
|
1.0000000000,
|
||||||
|
6.0000000000,
|
||||||
|
28.0000000000,
|
||||||
|
13.0000000000,
|
||||||
|
37.0000000000,
|
||||||
|
16.0000000000,
|
||||||
|
36.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 242.0000000000,
|
||||||
|
min: 1.0000000000,
|
||||||
|
max: 71.0000000000,
|
||||||
|
mean: 24.2000000000,
|
||||||
|
median: 22.0000000000,
|
||||||
|
var: 458.1777777778,
|
||||||
|
std_dev: 21.4050876611,
|
||||||
|
std_dev_pct: 88.4507754589,
|
||||||
|
median_abs_dev: 21.4977000000,
|
||||||
|
median_abs_dev_pct: 97.7168181818,
|
||||||
|
quartiles: (7.7500000000,22.0000000000,35.0000000000),
|
||||||
|
iqr: 27.2500000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_exp25() {
|
||||||
|
let val = &[
|
||||||
|
3.0000000000,
|
||||||
|
24.0000000000,
|
||||||
|
1.0000000000,
|
||||||
|
19.0000000000,
|
||||||
|
7.0000000000,
|
||||||
|
5.0000000000,
|
||||||
|
30.0000000000,
|
||||||
|
39.0000000000,
|
||||||
|
31.0000000000,
|
||||||
|
13.0000000000,
|
||||||
|
25.0000000000,
|
||||||
|
48.0000000000,
|
||||||
|
1.0000000000,
|
||||||
|
6.0000000000,
|
||||||
|
42.0000000000,
|
||||||
|
63.0000000000,
|
||||||
|
2.0000000000,
|
||||||
|
12.0000000000,
|
||||||
|
108.0000000000,
|
||||||
|
26.0000000000,
|
||||||
|
1.0000000000,
|
||||||
|
7.0000000000,
|
||||||
|
44.0000000000,
|
||||||
|
25.0000000000,
|
||||||
|
11.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 593.0000000000,
|
||||||
|
min: 1.0000000000,
|
||||||
|
max: 108.0000000000,
|
||||||
|
mean: 23.7200000000,
|
||||||
|
median: 19.0000000000,
|
||||||
|
var: 601.0433333333,
|
||||||
|
std_dev: 24.5161851301,
|
||||||
|
std_dev_pct: 103.3565983562,
|
||||||
|
median_abs_dev: 19.2738000000,
|
||||||
|
median_abs_dev_pct: 101.4410526316,
|
||||||
|
quartiles: (6.0000000000,19.0000000000,31.0000000000),
|
||||||
|
iqr: 25.0000000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_binom25() {
|
||||||
|
let val = &[
|
||||||
|
18.0000000000,
|
||||||
|
17.0000000000,
|
||||||
|
27.0000000000,
|
||||||
|
15.0000000000,
|
||||||
|
21.0000000000,
|
||||||
|
25.0000000000,
|
||||||
|
17.0000000000,
|
||||||
|
24.0000000000,
|
||||||
|
25.0000000000,
|
||||||
|
24.0000000000,
|
||||||
|
26.0000000000,
|
||||||
|
26.0000000000,
|
||||||
|
23.0000000000,
|
||||||
|
15.0000000000,
|
||||||
|
23.0000000000,
|
||||||
|
17.0000000000,
|
||||||
|
18.0000000000,
|
||||||
|
18.0000000000,
|
||||||
|
21.0000000000,
|
||||||
|
16.0000000000,
|
||||||
|
15.0000000000,
|
||||||
|
31.0000000000,
|
||||||
|
20.0000000000,
|
||||||
|
17.0000000000,
|
||||||
|
15.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 514.0000000000,
|
||||||
|
min: 15.0000000000,
|
||||||
|
max: 31.0000000000,
|
||||||
|
mean: 20.5600000000,
|
||||||
|
median: 20.0000000000,
|
||||||
|
var: 20.8400000000,
|
||||||
|
std_dev: 4.5650848842,
|
||||||
|
std_dev_pct: 22.2037202539,
|
||||||
|
median_abs_dev: 5.9304000000,
|
||||||
|
median_abs_dev_pct: 29.6520000000,
|
||||||
|
quartiles: (17.0000000000,20.0000000000,24.0000000000),
|
||||||
|
iqr: 7.0000000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_pois25lambda30() {
|
||||||
|
let val = &[
|
||||||
|
27.0000000000,
|
||||||
|
33.0000000000,
|
||||||
|
34.0000000000,
|
||||||
|
34.0000000000,
|
||||||
|
24.0000000000,
|
||||||
|
39.0000000000,
|
||||||
|
28.0000000000,
|
||||||
|
27.0000000000,
|
||||||
|
31.0000000000,
|
||||||
|
28.0000000000,
|
||||||
|
38.0000000000,
|
||||||
|
21.0000000000,
|
||||||
|
33.0000000000,
|
||||||
|
36.0000000000,
|
||||||
|
29.0000000000,
|
||||||
|
37.0000000000,
|
||||||
|
32.0000000000,
|
||||||
|
34.0000000000,
|
||||||
|
31.0000000000,
|
||||||
|
39.0000000000,
|
||||||
|
25.0000000000,
|
||||||
|
31.0000000000,
|
||||||
|
32.0000000000,
|
||||||
|
40.0000000000,
|
||||||
|
24.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 787.0000000000,
|
||||||
|
min: 21.0000000000,
|
||||||
|
max: 40.0000000000,
|
||||||
|
mean: 31.4800000000,
|
||||||
|
median: 32.0000000000,
|
||||||
|
var: 26.5933333333,
|
||||||
|
std_dev: 5.1568724372,
|
||||||
|
std_dev_pct: 16.3814245145,
|
||||||
|
median_abs_dev: 5.9304000000,
|
||||||
|
median_abs_dev_pct: 18.5325000000,
|
||||||
|
quartiles: (28.0000000000,32.0000000000,34.0000000000),
|
||||||
|
iqr: 6.0000000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_pois25lambda40() {
|
||||||
|
let val = &[
|
||||||
|
42.0000000000,
|
||||||
|
50.0000000000,
|
||||||
|
42.0000000000,
|
||||||
|
46.0000000000,
|
||||||
|
34.0000000000,
|
||||||
|
45.0000000000,
|
||||||
|
34.0000000000,
|
||||||
|
49.0000000000,
|
||||||
|
39.0000000000,
|
||||||
|
28.0000000000,
|
||||||
|
40.0000000000,
|
||||||
|
35.0000000000,
|
||||||
|
37.0000000000,
|
||||||
|
39.0000000000,
|
||||||
|
46.0000000000,
|
||||||
|
44.0000000000,
|
||||||
|
32.0000000000,
|
||||||
|
45.0000000000,
|
||||||
|
42.0000000000,
|
||||||
|
37.0000000000,
|
||||||
|
48.0000000000,
|
||||||
|
42.0000000000,
|
||||||
|
33.0000000000,
|
||||||
|
42.0000000000,
|
||||||
|
48.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 1019.0000000000,
|
||||||
|
min: 28.0000000000,
|
||||||
|
max: 50.0000000000,
|
||||||
|
mean: 40.7600000000,
|
||||||
|
median: 42.0000000000,
|
||||||
|
var: 34.4400000000,
|
||||||
|
std_dev: 5.8685603004,
|
||||||
|
std_dev_pct: 14.3978417577,
|
||||||
|
median_abs_dev: 5.9304000000,
|
||||||
|
median_abs_dev_pct: 14.1200000000,
|
||||||
|
quartiles: (37.0000000000,42.0000000000,45.0000000000),
|
||||||
|
iqr: 8.0000000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_pois25lambda50() {
|
||||||
|
let val = &[
|
||||||
|
45.0000000000,
|
||||||
|
43.0000000000,
|
||||||
|
44.0000000000,
|
||||||
|
61.0000000000,
|
||||||
|
51.0000000000,
|
||||||
|
53.0000000000,
|
||||||
|
59.0000000000,
|
||||||
|
52.0000000000,
|
||||||
|
49.0000000000,
|
||||||
|
51.0000000000,
|
||||||
|
51.0000000000,
|
||||||
|
50.0000000000,
|
||||||
|
49.0000000000,
|
||||||
|
56.0000000000,
|
||||||
|
42.0000000000,
|
||||||
|
52.0000000000,
|
||||||
|
51.0000000000,
|
||||||
|
43.0000000000,
|
||||||
|
48.0000000000,
|
||||||
|
48.0000000000,
|
||||||
|
50.0000000000,
|
||||||
|
42.0000000000,
|
||||||
|
43.0000000000,
|
||||||
|
42.0000000000,
|
||||||
|
60.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 1235.0000000000,
|
||||||
|
min: 42.0000000000,
|
||||||
|
max: 61.0000000000,
|
||||||
|
mean: 49.4000000000,
|
||||||
|
median: 50.0000000000,
|
||||||
|
var: 31.6666666667,
|
||||||
|
std_dev: 5.6273143387,
|
||||||
|
std_dev_pct: 11.3913245723,
|
||||||
|
median_abs_dev: 4.4478000000,
|
||||||
|
median_abs_dev_pct: 8.8956000000,
|
||||||
|
quartiles: (44.0000000000,50.0000000000,52.0000000000),
|
||||||
|
iqr: 8.0000000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_unif25() {
|
||||||
|
let val = &[
|
||||||
|
99.0000000000,
|
||||||
|
55.0000000000,
|
||||||
|
92.0000000000,
|
||||||
|
79.0000000000,
|
||||||
|
14.0000000000,
|
||||||
|
2.0000000000,
|
||||||
|
33.0000000000,
|
||||||
|
49.0000000000,
|
||||||
|
3.0000000000,
|
||||||
|
32.0000000000,
|
||||||
|
84.0000000000,
|
||||||
|
59.0000000000,
|
||||||
|
22.0000000000,
|
||||||
|
86.0000000000,
|
||||||
|
76.0000000000,
|
||||||
|
31.0000000000,
|
||||||
|
29.0000000000,
|
||||||
|
11.0000000000,
|
||||||
|
41.0000000000,
|
||||||
|
53.0000000000,
|
||||||
|
45.0000000000,
|
||||||
|
44.0000000000,
|
||||||
|
98.0000000000,
|
||||||
|
98.0000000000,
|
||||||
|
7.0000000000,
|
||||||
|
];
|
||||||
|
let summ = &Summary {
|
||||||
|
sum: 1242.0000000000,
|
||||||
|
min: 2.0000000000,
|
||||||
|
max: 99.0000000000,
|
||||||
|
mean: 49.6800000000,
|
||||||
|
median: 45.0000000000,
|
||||||
|
var: 1015.6433333333,
|
||||||
|
std_dev: 31.8691595957,
|
||||||
|
std_dev_pct: 64.1488719719,
|
||||||
|
median_abs_dev: 45.9606000000,
|
||||||
|
median_abs_dev_pct: 102.1346666667,
|
||||||
|
quartiles: (29.0000000000,45.0000000000,79.0000000000),
|
||||||
|
iqr: 50.0000000000,
|
||||||
|
};
|
||||||
|
check(val, summ);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,23 +26,23 @@ use std::io;
|
||||||
pub mod color {
|
pub mod color {
|
||||||
pub type Color = u16;
|
pub type Color = u16;
|
||||||
|
|
||||||
pub static black: Color = 0u16;
|
pub static BLACK: Color = 0u16;
|
||||||
pub static red: Color = 1u16;
|
pub static RED: Color = 1u16;
|
||||||
pub static green: Color = 2u16;
|
pub static GREEN: Color = 2u16;
|
||||||
pub static yellow: Color = 3u16;
|
pub static YELLOW: Color = 3u16;
|
||||||
pub static blue: Color = 4u16;
|
pub static BLUE: Color = 4u16;
|
||||||
pub static magenta: Color = 5u16;
|
pub static MAGENTA: Color = 5u16;
|
||||||
pub static cyan: Color = 6u16;
|
pub static CYAN: Color = 6u16;
|
||||||
pub static white: Color = 7u16;
|
pub static WHITE: Color = 7u16;
|
||||||
|
|
||||||
pub static bright_black: Color = 8u16;
|
pub static BRIGHT_BLACK: Color = 8u16;
|
||||||
pub static bright_red: Color = 9u16;
|
pub static BRIGHT_RED: Color = 9u16;
|
||||||
pub static bright_green: Color = 10u16;
|
pub static BRIGHT_GREEN: Color = 10u16;
|
||||||
pub static bright_yellow: Color = 11u16;
|
pub static BRIGHT_YELLOW: Color = 11u16;
|
||||||
pub static bright_blue: Color = 12u16;
|
pub static BRIGHT_BLUE: Color = 12u16;
|
||||||
pub static bright_magenta: Color = 13u16;
|
pub static BRIGHT_MAGENTA: Color = 13u16;
|
||||||
pub static bright_cyan: Color = 14u16;
|
pub static BRIGHT_CYAN: Color = 14u16;
|
||||||
pub static bright_white: Color = 15u16;
|
pub static BRIGHT_WHITE: Color = 15u16;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "win32"))]
|
#[cfg(not(target_os = "win32"))]
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[allow(non_uppercase_statics)];
|
||||||
|
|
||||||
/// ncurses-compatible compiled terminfo format parsing (term(5))
|
/// ncurses-compatible compiled terminfo format parsing (term(5))
|
||||||
|
|
||||||
|
|
||||||
|
@ -292,7 +294,7 @@ pub fn parse(file: @Reader, longnames: bool) -> Result<~TermInfo, ~str> {
|
||||||
|
|
||||||
// Find the offset of the NUL we want to go to
|
// Find the offset of the NUL we want to go to
|
||||||
let nulpos = string_table.slice(offset as uint, string_table_bytes as uint)
|
let nulpos = string_table.slice(offset as uint, string_table_bytes as uint)
|
||||||
.iter().position_(|&b| b == 0);
|
.iter().position(|&b| b == 0);
|
||||||
match nulpos {
|
match nulpos {
|
||||||
Some(len) => {
|
Some(len) => {
|
||||||
string_map.insert(name.to_owned(),
|
string_map.insert(name.to_owned(),
|
||||||
|
|
|
@ -323,19 +323,19 @@ pub fn run_tests_console(opts: &TestOpts,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_ok(out: @io::Writer, use_color: bool) {
|
fn write_ok(out: @io::Writer, use_color: bool) {
|
||||||
write_pretty(out, "ok", term::color::green, use_color);
|
write_pretty(out, "ok", term::color::GREEN, use_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_failed(out: @io::Writer, use_color: bool) {
|
fn write_failed(out: @io::Writer, use_color: bool) {
|
||||||
write_pretty(out, "FAILED", term::color::red, use_color);
|
write_pretty(out, "FAILED", term::color::RED, use_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_ignored(out: @io::Writer, use_color: bool) {
|
fn write_ignored(out: @io::Writer, use_color: bool) {
|
||||||
write_pretty(out, "ignored", term::color::yellow, use_color);
|
write_pretty(out, "ignored", term::color::YELLOW, use_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_bench(out: @io::Writer, use_color: bool) {
|
fn write_bench(out: @io::Writer, use_color: bool) {
|
||||||
write_pretty(out, "bench", term::color::cyan, use_color);
|
write_pretty(out, "bench", term::color::CYAN, use_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_pretty(out: @io::Writer,
|
fn write_pretty(out: @io::Writer,
|
||||||
|
@ -469,7 +469,7 @@ fn run_tests(opts: &TestOpts,
|
||||||
}
|
}
|
||||||
|
|
||||||
// All benchmarks run at the end, in serial.
|
// All benchmarks run at the end, in serial.
|
||||||
do vec::consume(filtered_benchs) |_, b| {
|
for filtered_benchs.consume_iter().advance |b| {
|
||||||
callback(TeWait(copy b.desc));
|
callback(TeWait(copy b.desc));
|
||||||
run_test(!opts.run_benchmarks, b, ch.clone());
|
run_test(!opts.run_benchmarks, b, ch.clone());
|
||||||
let (test, result) = p.recv();
|
let (test, result) = p.recv();
|
||||||
|
@ -479,16 +479,16 @@ fn run_tests(opts: &TestOpts,
|
||||||
|
|
||||||
// Windows tends to dislike being overloaded with threads.
|
// Windows tends to dislike being overloaded with threads.
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
static sched_overcommit : uint = 1;
|
static SCHED_OVERCOMMIT : uint = 1;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
static sched_overcommit : uint = 4u;
|
static SCHED_OVERCOMMIT : uint = 4u;
|
||||||
|
|
||||||
fn get_concurrency() -> uint {
|
fn get_concurrency() -> uint {
|
||||||
use std::rt;
|
use std::rt;
|
||||||
let threads = rt::util::default_sched_threads();
|
let threads = rt::util::default_sched_threads();
|
||||||
if threads == 1 { 1 }
|
if threads == 1 { 1 }
|
||||||
else { threads * sched_overcommit }
|
else { threads * SCHED_OVERCOMMIT }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
|
@ -514,7 +514,7 @@ pub fn filter_tests(
|
||||||
} else { return option::None; }
|
} else { return option::None; }
|
||||||
}
|
}
|
||||||
|
|
||||||
vec::filter_map(filtered, |x| filter_fn(x, filter_str))
|
filtered.consume_iter().filter_map(|x| filter_fn(x, filter_str)).collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Maybe pull out the ignored test and unignore them
|
// Maybe pull out the ignored test and unignore them
|
||||||
|
@ -532,7 +532,7 @@ pub fn filter_tests(
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
vec::filter_map(filtered, |x| filter(x))
|
filtered.consume_iter().filter_map(|x| filter(x)).collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sort the tests alphabetically
|
// Sort the tests alphabetically
|
||||||
|
@ -711,9 +711,9 @@ impl BenchHarness {
|
||||||
// Eliminate outliers
|
// Eliminate outliers
|
||||||
let med = samples.median();
|
let med = samples.median();
|
||||||
let mad = samples.median_abs_dev();
|
let mad = samples.median_abs_dev();
|
||||||
let samples = do vec::filter(samples) |f| {
|
let samples = do samples.consume_iter().filter |f| {
|
||||||
num::abs(*f - med) <= 3.0 * mad
|
num::abs(*f - med) <= 3.0 * mad
|
||||||
};
|
}.collect::<~[f64]>();
|
||||||
|
|
||||||
debug!("%u samples, median %f, MAD=%f, %u survived filter",
|
debug!("%u samples, median %f, MAD=%f, %u survived filter",
|
||||||
n_samples, med as float, mad as float,
|
n_samples, med as float, mad as float,
|
||||||
|
|
|
@ -868,20 +868,20 @@ mod tests {
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
fn test_get_time() {
|
fn test_get_time() {
|
||||||
static some_recent_date: i64 = 1325376000i64; // 2012-01-01T00:00:00Z
|
static SOME_RECENT_DATE: i64 = 1325376000i64; // 2012-01-01T00:00:00Z
|
||||||
static some_future_date: i64 = 1577836800i64; // 2020-01-01T00:00:00Z
|
static SOME_FUTURE_DATE: i64 = 1577836800i64; // 2020-01-01T00:00:00Z
|
||||||
|
|
||||||
let tv1 = get_time();
|
let tv1 = get_time();
|
||||||
debug!("tv1=%? sec + %? nsec", tv1.sec as uint, tv1.nsec as uint);
|
debug!("tv1=%? sec + %? nsec", tv1.sec as uint, tv1.nsec as uint);
|
||||||
|
|
||||||
assert!(tv1.sec > some_recent_date);
|
assert!(tv1.sec > SOME_RECENT_DATE);
|
||||||
assert!(tv1.nsec < 1000000000i32);
|
assert!(tv1.nsec < 1000000000i32);
|
||||||
|
|
||||||
let tv2 = get_time();
|
let tv2 = get_time();
|
||||||
debug!("tv2=%? sec + %? nsec", tv2.sec as uint, tv2.nsec as uint);
|
debug!("tv2=%? sec + %? nsec", tv2.sec as uint, tv2.nsec as uint);
|
||||||
|
|
||||||
assert!(tv2.sec >= tv1.sec);
|
assert!(tv2.sec >= tv1.sec);
|
||||||
assert!(tv2.sec < some_future_date);
|
assert!(tv2.sec < SOME_FUTURE_DATE);
|
||||||
assert!(tv2.nsec < 1000000000i32);
|
assert!(tv2.nsec < 1000000000i32);
|
||||||
if tv2.sec == tv1.sec {
|
if tv2.sec == tv1.sec {
|
||||||
assert!(tv2.nsec >= tv1.nsec);
|
assert!(tv2.nsec >= tv1.nsec);
|
||||||
|
|
|
@ -57,23 +57,25 @@ impl<K: Eq + TotalOrd, V: Eq> Eq for TreeMap<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lexicographical comparison
|
// Lexicographical comparison
|
||||||
fn lt<K: Ord + TotalOrd, V>(a: &TreeMap<K, V>,
|
fn lt<K: Ord + TotalOrd, V: Ord>(a: &TreeMap<K, V>,
|
||||||
b: &TreeMap<K, V>) -> bool {
|
b: &TreeMap<K, V>) -> bool {
|
||||||
let mut x = a.iter();
|
let mut x = a.iter();
|
||||||
let mut y = b.iter();
|
let mut y = b.iter();
|
||||||
|
|
||||||
let (a_len, b_len) = (a.len(), b.len());
|
let (a_len, b_len) = (a.len(), b.len());
|
||||||
for uint::min(a_len, b_len).times {
|
for uint::min(a_len, b_len).times {
|
||||||
let (key_a,_) = x.next().unwrap();
|
let (key_a, value_a) = x.next().unwrap();
|
||||||
let (key_b,_) = y.next().unwrap();
|
let (key_b, value_b) = y.next().unwrap();
|
||||||
if *key_a < *key_b { return true; }
|
if *key_a < *key_b { return true; }
|
||||||
if *key_a > *key_b { return false; }
|
if *key_a > *key_b { return false; }
|
||||||
};
|
if *value_a < *value_b { return true; }
|
||||||
|
if *value_a > *value_b { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
a_len < b_len
|
a_len < b_len
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Ord + TotalOrd, V> Ord for TreeMap<K, V> {
|
impl<K: Ord + TotalOrd, V: Ord> Ord for TreeMap<K, V> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn lt(&self, other: &TreeMap<K, V>) -> bool { lt(self, other) }
|
fn lt(&self, other: &TreeMap<K, V>) -> bool { lt(self, other) }
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -196,14 +198,15 @@ impl<K: TotalOrd, V> TreeMap<K, V> {
|
||||||
/// Get a lazy iterator over the key-value pairs in the map.
|
/// Get a lazy iterator over the key-value pairs in the map.
|
||||||
/// Requires that it be frozen (immutable).
|
/// Requires that it be frozen (immutable).
|
||||||
pub fn iter<'a>(&'a self) -> TreeMapIterator<'a, K, V> {
|
pub fn iter<'a>(&'a self) -> TreeMapIterator<'a, K, V> {
|
||||||
TreeMapIterator{stack: ~[], node: &self.root}
|
TreeMapIterator{stack: ~[], node: &self.root, remaining: self.length}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lazy forward iterator over a map
|
/// Lazy forward iterator over a map
|
||||||
pub struct TreeMapIterator<'self, K, V> {
|
pub struct TreeMapIterator<'self, K, V> {
|
||||||
priv stack: ~[&'self ~TreeNode<K, V>],
|
priv stack: ~[&'self ~TreeNode<K, V>],
|
||||||
priv node: &'self Option<~TreeNode<K, V>>
|
priv node: &'self Option<~TreeNode<K, V>>,
|
||||||
|
priv remaining: uint
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapIterator<'self, K, V> {
|
impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapIterator<'self, K, V> {
|
||||||
|
@ -220,12 +223,18 @@ impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapIterator<'self, K, V
|
||||||
None => {
|
None => {
|
||||||
let res = self.stack.pop();
|
let res = self.stack.pop();
|
||||||
self.node = &res.right;
|
self.node = &res.right;
|
||||||
|
self.remaining -= 1;
|
||||||
return Some((&res.key, &res.value));
|
return Some((&res.key, &res.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||||
|
(self.remaining, Some(self.remaining))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'self, T> Iterator<&'self T> for TreeSetIterator<'self, T> {
|
impl<'self, T> Iterator<&'self T> for TreeSetIterator<'self, T> {
|
||||||
|
@ -835,7 +844,7 @@ mod test_treemap {
|
||||||
for 90.times {
|
for 90.times {
|
||||||
let k = rng.gen();
|
let k = rng.gen();
|
||||||
let v = rng.gen();
|
let v = rng.gen();
|
||||||
if !ctrl.iter().any_(|x| x == &(k, v)) {
|
if !ctrl.iter().any(|x| x == &(k, v)) {
|
||||||
assert!(map.insert(k, v));
|
assert!(map.insert(k, v));
|
||||||
ctrl.push((k, v));
|
ctrl.push((k, v));
|
||||||
check_structure(&map);
|
check_structure(&map);
|
||||||
|
@ -935,7 +944,7 @@ mod test_treemap {
|
||||||
assert!(b.insert(0, 5));
|
assert!(b.insert(0, 5));
|
||||||
assert!(a < b);
|
assert!(a < b);
|
||||||
assert!(a.insert(0, 7));
|
assert!(a.insert(0, 7));
|
||||||
assert!(!(a < b) && !(b < a));
|
assert!(!(a < b) && b < a);
|
||||||
assert!(b.insert(-2, 0));
|
assert!(b.insert(-2, 0));
|
||||||
assert!(b < a);
|
assert!(b < a);
|
||||||
assert!(a.insert(-5, 2));
|
assert!(a.insert(-5, 2));
|
||||||
|
|
|
@ -1046,7 +1046,7 @@ pub unsafe fn ip4_name(src: &sockaddr_in) -> ~str {
|
||||||
// ipv4 addr max size: 15 + 1 trailing null byte
|
// ipv4 addr max size: 15 + 1 trailing null byte
|
||||||
let dst: ~[u8] = ~[0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
|
let dst: ~[u8] = ~[0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
|
||||||
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8];
|
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8];
|
||||||
do vec::as_imm_buf(dst) |dst_buf, size| {
|
do dst.as_imm_buf |dst_buf, size| {
|
||||||
rust_uv_ip4_name(to_unsafe_ptr(src),
|
rust_uv_ip4_name(to_unsafe_ptr(src),
|
||||||
dst_buf, size as libc::size_t);
|
dst_buf, size as libc::size_t);
|
||||||
// seems that checking the result of uv_ip4_name
|
// seems that checking the result of uv_ip4_name
|
||||||
|
@ -1066,7 +1066,7 @@ pub unsafe fn ip6_name(src: &sockaddr_in6) -> ~str {
|
||||||
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
|
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
|
||||||
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
|
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
|
||||||
0u8,0u8,0u8,0u8,0u8,0u8];
|
0u8,0u8,0u8,0u8,0u8,0u8];
|
||||||
do vec::as_imm_buf(dst) |dst_buf, size| {
|
do dst.as_imm_buf |dst_buf, size| {
|
||||||
let src_unsafe_ptr = to_unsafe_ptr(src);
|
let src_unsafe_ptr = to_unsafe_ptr(src);
|
||||||
let result = rust_uv_ip6_name(src_unsafe_ptr,
|
let result = rust_uv_ip6_name(src_unsafe_ptr,
|
||||||
dst_buf, size as libc::size_t);
|
dst_buf, size as libc::size_t);
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// FIXME #2238 Make run only accept source that emits an executable
|
// FIXME #2238 Make run only accept source that emits an executable
|
||||||
|
|
||||||
#[link(name = "rust",
|
#[link(name = "rust",
|
||||||
vers = "0.7",
|
vers = "0.8-pre",
|
||||||
uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c",
|
uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c",
|
||||||
url = "https://github.com/mozilla/rust/tree/master/src/rust")];
|
url = "https://github.com/mozilla/rust/tree/master/src/rust")];
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ struct Command<'self> {
|
||||||
usage_full: UsageSource<'self>,
|
usage_full: UsageSource<'self>,
|
||||||
}
|
}
|
||||||
|
|
||||||
static commands: &'static [Command<'static>] = &[
|
static COMMANDS: &'static [Command<'static>] = &[
|
||||||
Command{
|
Command{
|
||||||
cmd: "build",
|
cmd: "build",
|
||||||
action: CallMain("rustc", rustc::main),
|
action: CallMain("rustc", rustc::main),
|
||||||
|
@ -122,7 +122,7 @@ fn rustc_help() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_cmd(command_string: &str) -> Option<Command> {
|
fn find_cmd(command_string: &str) -> Option<Command> {
|
||||||
do commands.iter().find_ |command| {
|
do COMMANDS.iter().find_ |command| {
|
||||||
command.cmd == command_string
|
command.cmd == command_string
|
||||||
}.map_consume(|x| copy *x)
|
}.map_consume(|x| copy *x)
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage() {
|
fn usage() {
|
||||||
static indent: uint = 8;
|
static INDENT: uint = 8;
|
||||||
|
|
||||||
io::print(
|
io::print(
|
||||||
"The rust tool is a convenience for managing rust source code.\n\
|
"The rust tool is a convenience for managing rust source code.\n\
|
||||||
|
@ -209,8 +209,8 @@ fn usage() {
|
||||||
\n"
|
\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
for commands.iter().advance |command| {
|
for COMMANDS.iter().advance |command| {
|
||||||
let padding = " ".repeat(indent - command.cmd.len());
|
let padding = " ".repeat(INDENT - command.cmd.len());
|
||||||
io::println(fmt!(" %s%s%s",
|
io::println(fmt!(" %s%s%s",
|
||||||
command.cmd, padding, command.usage_line));
|
command.cmd, padding, command.usage_line));
|
||||||
}
|
}
|
||||||
|
|
|
@ -893,7 +893,7 @@ pub fn link_args(sess: Session,
|
||||||
// Add all the link args for external crates.
|
// Add all the link args for external crates.
|
||||||
do cstore::iter_crate_data(cstore) |crate_num, _| {
|
do cstore::iter_crate_data(cstore) |crate_num, _| {
|
||||||
let link_args = csearch::get_link_args_for_crate(cstore, crate_num);
|
let link_args = csearch::get_link_args_for_crate(cstore, crate_num);
|
||||||
do vec::consume(link_args) |_, link_arg| {
|
for link_args.consume_iter().advance |link_arg| {
|
||||||
args.push(link_arg);
|
args.push(link_arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,10 +123,10 @@ pub fn build_configuration(sess: Session, argv0: @str, input: &input) ->
|
||||||
// Convert strings provided as --cfg [cfgspec] into a crate_cfg
|
// Convert strings provided as --cfg [cfgspec] into a crate_cfg
|
||||||
fn parse_cfgspecs(cfgspecs: ~[~str],
|
fn parse_cfgspecs(cfgspecs: ~[~str],
|
||||||
demitter: diagnostic::Emitter) -> ast::crate_cfg {
|
demitter: diagnostic::Emitter) -> ast::crate_cfg {
|
||||||
do vec::map_consume(cfgspecs) |s| {
|
do cfgspecs.consume_iter().transform |s| {
|
||||||
let sess = parse::new_parse_sess(Some(demitter));
|
let sess = parse::new_parse_sess(Some(demitter));
|
||||||
parse::parse_meta_from_source_str(@"cfgspec", s.to_managed(), ~[], sess)
|
parse::parse_meta_from_source_str(@"cfgspec", s.to_managed(), ~[], sess)
|
||||||
}
|
}.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum input {
|
pub enum input {
|
||||||
|
|
|
@ -10,10 +10,9 @@
|
||||||
|
|
||||||
|
|
||||||
use std::option;
|
use std::option;
|
||||||
use std::vec;
|
|
||||||
use syntax::{ast, fold, attr};
|
use syntax::{ast, fold, attr};
|
||||||
|
|
||||||
type in_cfg_pred = @fn(attrs: ~[ast::attribute]) -> bool;
|
type in_cfg_pred = @fn(attrs: &[ast::attribute]) -> bool;
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
in_cfg: in_cfg_pred
|
in_cfg: in_cfg_pred
|
||||||
|
@ -51,8 +50,7 @@ fn filter_item(cx: @Context, item: @ast::item) ->
|
||||||
if item_in_cfg(cx, item) { option::Some(item) } else { option::None }
|
if item_in_cfg(cx, item) { option::Some(item) } else { option::None }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_view_item(cx: @Context, view_item: @ast::view_item
|
fn filter_view_item<'r>(cx: @Context, view_item: &'r ast::view_item)-> Option<&'r ast::view_item> {
|
||||||
)-> Option<@ast::view_item> {
|
|
||||||
if view_item_in_cfg(cx, view_item) {
|
if view_item_in_cfg(cx, view_item) {
|
||||||
option::Some(view_item)
|
option::Some(view_item)
|
||||||
} else {
|
} else {
|
||||||
|
@ -61,13 +59,15 @@ fn filter_view_item(cx: @Context, view_item: @ast::view_item
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_mod(cx: @Context, m: &ast::_mod, fld: @fold::ast_fold) -> ast::_mod {
|
fn fold_mod(cx: @Context, m: &ast::_mod, fld: @fold::ast_fold) -> ast::_mod {
|
||||||
let filtered_items =
|
let filtered_items = do m.items.iter().filter_map |a| {
|
||||||
m.items.filter_mapped(|a| filter_item(cx, *a));
|
filter_item(cx, *a).chain(|x| fld.fold_item(x))
|
||||||
let filtered_view_items =
|
}.collect();
|
||||||
m.view_items.filter_mapped(|a| filter_view_item(cx, *a));
|
let filtered_view_items = do m.view_items.iter().filter_map |a| {
|
||||||
|
filter_view_item(cx, a).map(|&x| fld.fold_view_item(x))
|
||||||
|
}.collect();
|
||||||
ast::_mod {
|
ast::_mod {
|
||||||
view_items: filtered_view_items.map(|x| fld.fold_view_item(*x)),
|
view_items: filtered_view_items,
|
||||||
items: vec::filter_map(filtered_items, |x| fld.fold_item(x))
|
items: filtered_items
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,14 +83,14 @@ fn fold_foreign_mod(
|
||||||
nm: &ast::foreign_mod,
|
nm: &ast::foreign_mod,
|
||||||
fld: @fold::ast_fold
|
fld: @fold::ast_fold
|
||||||
) -> ast::foreign_mod {
|
) -> ast::foreign_mod {
|
||||||
let filtered_items =
|
let filtered_items = nm.items.iter().filter_map(|a| filter_foreign_item(cx, *a)).collect();
|
||||||
nm.items.filter_mapped(|a| filter_foreign_item(cx, *a));
|
let filtered_view_items = do nm.view_items.iter().filter_map |a| {
|
||||||
let filtered_view_items =
|
filter_view_item(cx, a).map(|&x| fld.fold_view_item(x))
|
||||||
nm.view_items.filter_mapped(|a| filter_view_item(cx, *a));
|
}.collect();
|
||||||
ast::foreign_mod {
|
ast::foreign_mod {
|
||||||
sort: nm.sort,
|
sort: nm.sort,
|
||||||
abis: nm.abis,
|
abis: nm.abis,
|
||||||
view_items: filtered_view_items.iter().transform(|x| fld.fold_view_item(*x)).collect(),
|
view_items: filtered_view_items,
|
||||||
items: filtered_items
|
items: filtered_items
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,12 +98,14 @@ fn fold_foreign_mod(
|
||||||
fn fold_item_underscore(cx: @Context, item: &ast::item_,
|
fn fold_item_underscore(cx: @Context, item: &ast::item_,
|
||||||
fld: @fold::ast_fold) -> ast::item_ {
|
fld: @fold::ast_fold) -> ast::item_ {
|
||||||
let item = match *item {
|
let item = match *item {
|
||||||
ast::item_impl(ref a, b, c, ref methods) => {
|
ast::item_impl(ref a, ref b, ref c, ref methods) => {
|
||||||
let methods = methods.filtered(|m| method_in_cfg(cx, *m) );
|
let methods = methods.iter().filter(|m| method_in_cfg(cx, **m))
|
||||||
ast::item_impl(/*bad*/ copy *a, b, c, methods)
|
.transform(|x| *x).collect();
|
||||||
|
ast::item_impl(/*bad*/ copy *a, /*bad*/ copy *b, /*bad*/ copy *c, methods)
|
||||||
}
|
}
|
||||||
ast::item_trait(ref a, ref b, ref methods) => {
|
ast::item_trait(ref a, ref b, ref methods) => {
|
||||||
let methods = methods.filtered(|m| trait_method_in_cfg(cx, m) );
|
let methods = methods.iter().filter(|m| trait_method_in_cfg(cx, *m) )
|
||||||
|
.transform(|x| /* bad */copy *x).collect();
|
||||||
ast::item_trait(/*bad*/copy *a, /*bad*/copy *b, methods)
|
ast::item_trait(/*bad*/copy *a, /*bad*/copy *b, methods)
|
||||||
}
|
}
|
||||||
ref item => /*bad*/ copy *item
|
ref item => /*bad*/ copy *item
|
||||||
|
@ -134,19 +136,12 @@ fn fold_block(
|
||||||
b: &ast::blk_,
|
b: &ast::blk_,
|
||||||
fld: @fold::ast_fold
|
fld: @fold::ast_fold
|
||||||
) -> ast::blk_ {
|
) -> ast::blk_ {
|
||||||
let filtered_stmts =
|
let resulting_stmts = do b.stmts.iter().filter_map |a| {
|
||||||
b.stmts.filter_mapped(|a| filter_stmt(cx, *a));
|
filter_stmt(cx, *a).chain(|stmt| fld.fold_stmt(stmt))
|
||||||
let filtered_view_items =
|
}.collect();
|
||||||
b.view_items.filter_mapped(|a| filter_view_item(cx, *a));
|
let filtered_view_items = do b.view_items.iter().filter_map |a| {
|
||||||
let filtered_view_items =
|
filter_view_item(cx, a).map(|&x| fld.fold_view_item(x))
|
||||||
filtered_view_items.map(|x| fld.fold_view_item(*x));
|
}.collect();
|
||||||
let mut resulting_stmts = ~[];
|
|
||||||
for filtered_stmts.iter().advance |stmt| {
|
|
||||||
match fld.fold_stmt(*stmt) {
|
|
||||||
None => {}
|
|
||||||
Some(stmt) => resulting_stmts.push(stmt),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ast::blk_ {
|
ast::blk_ {
|
||||||
view_items: filtered_view_items,
|
view_items: filtered_view_items,
|
||||||
stmts: resulting_stmts,
|
stmts: resulting_stmts,
|
||||||
|
@ -164,8 +159,8 @@ fn foreign_item_in_cfg(cx: @Context, item: @ast::foreign_item) -> bool {
|
||||||
return (cx.in_cfg)(/*bad*/copy item.attrs);
|
return (cx.in_cfg)(/*bad*/copy item.attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_item_in_cfg(cx: @Context, item: @ast::view_item) -> bool {
|
fn view_item_in_cfg(cx: @Context, item: &ast::view_item) -> bool {
|
||||||
return (cx.in_cfg)(/*bad*/copy item.attrs);
|
return (cx.in_cfg)(item.attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn method_in_cfg(cx: @Context, meth: @ast::method) -> bool {
|
fn method_in_cfg(cx: @Context, meth: @ast::method) -> bool {
|
||||||
|
@ -193,11 +188,13 @@ pub fn metas_in_cfg(cfg: &[@ast::meta_item],
|
||||||
// Pull the inner meta_items from the #[cfg(meta_item, ...)] attributes,
|
// Pull the inner meta_items from the #[cfg(meta_item, ...)] attributes,
|
||||||
// so we can match against them. This is the list of configurations for
|
// so we can match against them. This is the list of configurations for
|
||||||
// which the item is valid
|
// which the item is valid
|
||||||
let cfg_metas = vec::filter_map(cfg_metas, |i| attr::get_meta_item_list(i));
|
let cfg_metas = cfg_metas.consume_iter()
|
||||||
|
.filter_map(|i| attr::get_meta_item_list(i))
|
||||||
|
.collect::<~[~[@ast::meta_item]]>();
|
||||||
|
|
||||||
if cfg_metas.iter().all(|c| c.is_empty()) { return true; }
|
if cfg_metas.iter().all(|c| c.is_empty()) { return true; }
|
||||||
|
|
||||||
cfg_metas.iter().any_(|cfg_meta| {
|
cfg_metas.iter().any(|cfg_meta| {
|
||||||
cfg_meta.iter().all(|cfg_mi| {
|
cfg_meta.iter().all(|cfg_mi| {
|
||||||
match cfg_mi.node {
|
match cfg_mi.node {
|
||||||
ast::meta_list(s, ref it) if "not" == s
|
ast::meta_list(s, ref it) if "not" == s
|
||||||
|
|
|
@ -18,7 +18,7 @@ use syntax::codemap::dummy_sp;
|
||||||
use syntax::codemap;
|
use syntax::codemap;
|
||||||
use syntax::fold;
|
use syntax::fold;
|
||||||
|
|
||||||
static STD_VERSION: &'static str = "0.7";
|
static STD_VERSION: &'static str = "0.8-pre";
|
||||||
|
|
||||||
pub fn maybe_inject_libstd_ref(sess: Session, crate: @ast::crate)
|
pub fn maybe_inject_libstd_ref(sess: Session, crate: @ast::crate)
|
||||||
-> @ast::crate {
|
-> @ast::crate {
|
||||||
|
@ -41,7 +41,7 @@ fn inject_libstd_ref(sess: Session, crate: &ast::crate) -> @ast::crate {
|
||||||
let precursor = @fold::AstFoldFns {
|
let precursor = @fold::AstFoldFns {
|
||||||
fold_crate: |crate, span, fld| {
|
fold_crate: |crate, span, fld| {
|
||||||
let n1 = sess.next_node_id();
|
let n1 = sess.next_node_id();
|
||||||
let vi1 = @ast::view_item {
|
let vi1 = ast::view_item {
|
||||||
node: ast::view_item_extern_mod(
|
node: ast::view_item_extern_mod(
|
||||||
sess.ident_of("std"), ~[], n1),
|
sess.ident_of("std"), ~[], n1),
|
||||||
attrs: ~[
|
attrs: ~[
|
||||||
|
@ -75,7 +75,7 @@ fn inject_libstd_ref(sess: Session, crate: &ast::crate) -> @ast::crate {
|
||||||
fold_mod: |module, fld| {
|
fold_mod: |module, fld| {
|
||||||
let n2 = sess.next_node_id();
|
let n2 = sess.next_node_id();
|
||||||
|
|
||||||
let prelude_path = @ast::Path {
|
let prelude_path = ast::Path {
|
||||||
span: dummy_sp(),
|
span: dummy_sp(),
|
||||||
global: false,
|
global: false,
|
||||||
idents: ~[
|
idents: ~[
|
||||||
|
@ -87,7 +87,7 @@ fn inject_libstd_ref(sess: Session, crate: &ast::crate) -> @ast::crate {
|
||||||
};
|
};
|
||||||
|
|
||||||
let vp = @spanned(ast::view_path_glob(prelude_path, n2));
|
let vp = @spanned(ast::view_path_glob(prelude_path, n2));
|
||||||
let vi2 = @ast::view_item { node: ast::view_item_use(~[vp]),
|
let vi2 = ast::view_item { node: ast::view_item_use(~[vp]),
|
||||||
attrs: ~[],
|
attrs: ~[],
|
||||||
vis: ast::private,
|
vis: ast::private,
|
||||||
span: dummy_sp() };
|
span: dummy_sp() };
|
||||||
|
|
|
@ -17,7 +17,7 @@ use front::config;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use syntax::ast_util::*;
|
use syntax::ast_util::*;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::codemap::{dummy_sp, span, ExpandedFrom, CallInfo, NameAndSpan};
|
use syntax::codemap::{dummy_sp, span, ExpnInfo, NameAndSpan};
|
||||||
use syntax::codemap;
|
use syntax::codemap;
|
||||||
use syntax::ext::base::ExtCtxt;
|
use syntax::ext::base::ExtCtxt;
|
||||||
use syntax::fold;
|
use syntax::fold;
|
||||||
|
@ -72,13 +72,13 @@ fn generate_test_harness(sess: session::Session,
|
||||||
};
|
};
|
||||||
|
|
||||||
let ext_cx = cx.ext_cx;
|
let ext_cx = cx.ext_cx;
|
||||||
ext_cx.bt_push(ExpandedFrom(CallInfo {
|
ext_cx.bt_push(ExpnInfo {
|
||||||
call_site: dummy_sp(),
|
call_site: dummy_sp(),
|
||||||
callee: NameAndSpan {
|
callee: NameAndSpan {
|
||||||
name: @"test",
|
name: @"test",
|
||||||
span: None
|
span: None
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
|
||||||
let precursor = @fold::AstFoldFns {
|
let precursor = @fold::AstFoldFns {
|
||||||
fold_crate: fold::wrap(|a,b| fold_crate(cx, a, b) ),
|
fold_crate: fold::wrap(|a,b| fold_crate(cx, a, b) ),
|
||||||
|
@ -109,9 +109,11 @@ fn fold_mod(cx: @mut TestCtxt,
|
||||||
|
|
||||||
fn nomain(cx: @mut TestCtxt, item: @ast::item) -> @ast::item {
|
fn nomain(cx: @mut TestCtxt, item: @ast::item) -> @ast::item {
|
||||||
if !*cx.sess.building_library {
|
if !*cx.sess.building_library {
|
||||||
@ast::item{attrs: item.attrs.filtered(|attr| {
|
@ast::item{
|
||||||
"main" != attr::get_attr_name(attr)
|
attrs: do item.attrs.iter().filter_map |attr| {
|
||||||
}),.. copy *item}
|
if "main" != attr::get_attr_name(attr) {Some(*attr)} else {None}
|
||||||
|
}.collect(),
|
||||||
|
.. copy *item}
|
||||||
} else { item }
|
} else { item }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,10 +231,10 @@ fn is_ignored(cx: @mut TestCtxt, i: @ast::item) -> bool {
|
||||||
let ignoreattrs = attr::find_attrs_by_name(i.attrs, "ignore");
|
let ignoreattrs = attr::find_attrs_by_name(i.attrs, "ignore");
|
||||||
let ignoreitems = attr::attr_metas(ignoreattrs);
|
let ignoreitems = attr::attr_metas(ignoreattrs);
|
||||||
return if !ignoreitems.is_empty() {
|
return if !ignoreitems.is_empty() {
|
||||||
let cfg_metas =
|
let cfg_metas = ignoreitems.consume_iter()
|
||||||
vec::concat(
|
.filter_map(|i| attr::get_meta_item_list(i))
|
||||||
vec::filter_map(ignoreitems,
|
.collect::<~[~[@ast::meta_item]]>()
|
||||||
|i| attr::get_meta_item_list(i)));
|
.concat_vec();
|
||||||
config::metas_in_cfg(/*bad*/copy cx.crate.node.config, cfg_metas)
|
config::metas_in_cfg(/*bad*/copy cx.crate.node.config, cfg_metas)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -270,8 +272,8 @@ mod __test {
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fn mk_std(cx: &TestCtxt) -> @ast::view_item {
|
fn mk_std(cx: &TestCtxt) -> ast::view_item {
|
||||||
let vers = ast::lit_str(@"0.7");
|
let vers = ast::lit_str(@"0.8-pre");
|
||||||
let vers = nospan(vers);
|
let vers = nospan(vers);
|
||||||
let mi = ast::meta_name_value(@"vers", vers);
|
let mi = ast::meta_name_value(@"vers", vers);
|
||||||
let mi = nospan(mi);
|
let mi = nospan(mi);
|
||||||
|
@ -285,13 +287,12 @@ fn mk_std(cx: &TestCtxt) -> @ast::view_item {
|
||||||
ast::view_item_extern_mod(id_std, ~[@mi],
|
ast::view_item_extern_mod(id_std, ~[@mi],
|
||||||
cx.sess.next_node_id())
|
cx.sess.next_node_id())
|
||||||
};
|
};
|
||||||
let vi = ast::view_item {
|
ast::view_item {
|
||||||
node: vi,
|
node: vi,
|
||||||
attrs: ~[],
|
attrs: ~[],
|
||||||
vis: ast::public,
|
vis: ast::public,
|
||||||
span: dummy_sp()
|
span: dummy_sp()
|
||||||
};
|
}
|
||||||
return @vi;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk_test_module(cx: &TestCtxt) -> @ast::item {
|
fn mk_test_module(cx: &TestCtxt) -> @ast::item {
|
||||||
|
@ -308,7 +309,7 @@ fn mk_test_module(cx: &TestCtxt) -> @ast::item {
|
||||||
let mainfn = (quote_item!(
|
let mainfn = (quote_item!(
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
#[main];
|
#[main];
|
||||||
extra::test::test_main_static(::std::os::args(), tests);
|
extra::test::test_main_static(::std::os::args(), TESTS);
|
||||||
}
|
}
|
||||||
)).get();
|
)).get();
|
||||||
|
|
||||||
|
@ -341,16 +342,16 @@ fn nospan<T:Copy>(t: T) -> codemap::spanned<T> {
|
||||||
codemap::spanned { node: t, span: dummy_sp() }
|
codemap::spanned { node: t, span: dummy_sp() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_node(ids: ~[ast::ident]) -> @ast::Path {
|
fn path_node(ids: ~[ast::ident]) -> ast::Path {
|
||||||
@ast::Path { span: dummy_sp(),
|
ast::Path { span: dummy_sp(),
|
||||||
global: false,
|
global: false,
|
||||||
idents: ids,
|
idents: ids,
|
||||||
rp: None,
|
rp: None,
|
||||||
types: ~[] }
|
types: ~[] }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_node_global(ids: ~[ast::ident]) -> @ast::Path {
|
fn path_node_global(ids: ~[ast::ident]) -> ast::Path {
|
||||||
@ast::Path { span: dummy_sp(),
|
ast::Path { span: dummy_sp(),
|
||||||
global: true,
|
global: true,
|
||||||
idents: ids,
|
idents: ids,
|
||||||
rp: None,
|
rp: None,
|
||||||
|
@ -365,7 +366,7 @@ fn mk_tests(cx: &TestCtxt) -> @ast::item {
|
||||||
let test_descs = mk_test_descs(cx);
|
let test_descs = mk_test_descs(cx);
|
||||||
|
|
||||||
(quote_item!(
|
(quote_item!(
|
||||||
pub static tests : &'static [self::extra::test::TestDescAndFn] =
|
pub static TESTS : &'static [self::extra::test::TestDescAndFn] =
|
||||||
$test_descs
|
$test_descs
|
||||||
;
|
;
|
||||||
)).get()
|
)).get()
|
||||||
|
|
|
@ -136,7 +136,7 @@ fn visit_crate(e: &Env, c: &ast::crate) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_view_item(e: @mut Env, i: @ast::view_item) {
|
fn visit_view_item(e: @mut Env, i: &ast::view_item) {
|
||||||
match i.node {
|
match i.node {
|
||||||
ast::view_item_extern_mod(ident, ref meta_items, id) => {
|
ast::view_item_extern_mod(ident, ref meta_items, id) => {
|
||||||
debug!("resolving extern mod stmt. ident: %?, meta: %?",
|
debug!("resolving extern mod stmt. ident: %?, meta: %?",
|
||||||
|
|
|
@ -102,7 +102,7 @@ pub fn get_used_crate_files(cstore: &CStore) -> ~[Path] {
|
||||||
pub fn add_used_library(cstore: &mut CStore, lib: @str) -> bool {
|
pub fn add_used_library(cstore: &mut CStore, lib: @str) -> bool {
|
||||||
assert!(!lib.is_empty());
|
assert!(!lib.is_empty());
|
||||||
|
|
||||||
if cstore.used_libraries.iter().any_(|x| x == &lib) { return false; }
|
if cstore.used_libraries.iter().any(|x| x == &lib) { return false; }
|
||||||
cstore.used_libraries.push(lib);
|
cstore.used_libraries.push(lib);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1141,7 +1141,7 @@ fn list_crate_attributes(intr: @ident_interner, md: ebml::Doc, hash: &str,
|
||||||
|
|
||||||
let r = get_attributes(md);
|
let r = get_attributes(md);
|
||||||
for r.iter().advance |attr| {
|
for r.iter().advance |attr| {
|
||||||
out.write_str(fmt!("%s\n", pprust::attribute_to_str(*attr, intr)));
|
out.write_str(fmt!("%s\n", pprust::attribute_to_str(attr, intr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
out.write_str("\n\n");
|
out.write_str("\n\n");
|
||||||
|
|
|
@ -1003,7 +1003,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||||
index);
|
index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item_impl(ref generics, opt_trait, ty, ref methods) => {
|
item_impl(ref generics, ref opt_trait, ref ty, ref methods) => {
|
||||||
add_to_index();
|
add_to_index();
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
encode_def_id(ebml_w, local_def(item.id));
|
encode_def_id(ebml_w, local_def(item.id));
|
||||||
|
@ -1014,7 +1014,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||||
encode_name(ecx, ebml_w, item.ident);
|
encode_name(ecx, ebml_w, item.ident);
|
||||||
encode_attributes(ebml_w, item.attrs);
|
encode_attributes(ebml_w, item.attrs);
|
||||||
match ty.node {
|
match ty.node {
|
||||||
ast::ty_path(path, bounds, _) if path.idents.len() == 1 => {
|
ast::ty_path(ref path, ref bounds, _) if path.idents.len() == 1 => {
|
||||||
assert!(bounds.is_none());
|
assert!(bounds.is_none());
|
||||||
encode_impl_type_basename(ecx, ebml_w,
|
encode_impl_type_basename(ecx, ebml_w,
|
||||||
ast_util::path_to_ident(path));
|
ast_util::path_to_ident(path));
|
||||||
|
|
|
@ -291,16 +291,16 @@ fn encode_ast(ebml_w: &mut writer::Encoder, item: ast::inlined_item) {
|
||||||
// inlined items.
|
// inlined items.
|
||||||
fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item {
|
fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item {
|
||||||
fn drop_nested_items(blk: &ast::blk_, fld: @fold::ast_fold) -> ast::blk_ {
|
fn drop_nested_items(blk: &ast::blk_, fld: @fold::ast_fold) -> ast::blk_ {
|
||||||
let stmts_sans_items = do blk.stmts.filtered |stmt| {
|
let stmts_sans_items = do blk.stmts.iter().filter_map |stmt| {
|
||||||
match stmt.node {
|
match stmt.node {
|
||||||
ast::stmt_expr(_, _) | ast::stmt_semi(_, _) |
|
ast::stmt_expr(_, _) | ast::stmt_semi(_, _) |
|
||||||
ast::stmt_decl(@codemap::spanned { node: ast::decl_local(_),
|
ast::stmt_decl(@codemap::spanned { node: ast::decl_local(_), span: _}, _)
|
||||||
span: _}, _) => true,
|
=> Some(*stmt),
|
||||||
ast::stmt_decl(@codemap::spanned { node: ast::decl_item(_),
|
ast::stmt_decl(@codemap::spanned { node: ast::decl_item(_), span: _}, _)
|
||||||
span: _}, _) => false,
|
=> None,
|
||||||
ast::stmt_mac(*) => fail!("unexpanded macro in astencode")
|
ast::stmt_mac(*) => fail!("unexpanded macro in astencode")
|
||||||
}
|
}
|
||||||
};
|
}.collect();
|
||||||
let blk_sans_items = ast::blk_ {
|
let blk_sans_items = ast::blk_ {
|
||||||
view_items: ~[], // I don't know if we need the view_items here,
|
view_items: ~[], // I don't know if we need the view_items here,
|
||||||
// but it doesn't break tests!
|
// but it doesn't break tests!
|
||||||
|
|
|
@ -538,12 +538,13 @@ impl BorrowckCtxt {
|
||||||
|
|
||||||
move_data::MoveExpr(expr) => {
|
move_data::MoveExpr(expr) => {
|
||||||
let expr_ty = ty::expr_ty_adjusted(self.tcx, expr);
|
let expr_ty = ty::expr_ty_adjusted(self.tcx, expr);
|
||||||
|
let suggestion = move_suggestion(self.tcx, expr_ty,
|
||||||
|
"moved by default (use `copy` to override)");
|
||||||
self.tcx.sess.span_note(
|
self.tcx.sess.span_note(
|
||||||
expr.span,
|
expr.span,
|
||||||
fmt!("`%s` moved here because it has type `%s`, \
|
fmt!("`%s` moved here because it has type `%s`, which is %s",
|
||||||
which is moved by default (use `copy` to override)",
|
|
||||||
self.loan_path_to_str(moved_lp),
|
self.loan_path_to_str(moved_lp),
|
||||||
expr_ty.user_string(self.tcx)));
|
expr_ty.user_string(self.tcx), suggestion));
|
||||||
}
|
}
|
||||||
|
|
||||||
move_data::MovePat(pat) => {
|
move_data::MovePat(pat) => {
|
||||||
|
@ -557,12 +558,28 @@ impl BorrowckCtxt {
|
||||||
}
|
}
|
||||||
|
|
||||||
move_data::Captured(expr) => {
|
move_data::Captured(expr) => {
|
||||||
|
let expr_ty = ty::expr_ty_adjusted(self.tcx, expr);
|
||||||
|
let suggestion = move_suggestion(self.tcx, expr_ty,
|
||||||
|
"moved by default (make a copy and \
|
||||||
|
capture that instead to override)");
|
||||||
self.tcx.sess.span_note(
|
self.tcx.sess.span_note(
|
||||||
expr.span,
|
expr.span,
|
||||||
fmt!("`%s` moved into closure environment here \
|
fmt!("`%s` moved into closure environment here because it \
|
||||||
because its type is moved by default \
|
has type `%s`, which is %s",
|
||||||
(make a copy and capture that instead to override)",
|
self.loan_path_to_str(moved_lp),
|
||||||
self.loan_path_to_str(moved_lp)));
|
expr_ty.user_string(self.tcx), suggestion));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_suggestion(tcx: ty::ctxt, ty: ty::t, default_msg: &'static str)
|
||||||
|
-> &'static str {
|
||||||
|
match ty::get(ty).sty {
|
||||||
|
ty::ty_closure(ref cty) if cty.sigil == ast::BorrowedSigil =>
|
||||||
|
"a non-copyable stack closure (capture it in a new closure, \
|
||||||
|
e.g. `|x| f(x)`, to override)",
|
||||||
|
_ if !ty::type_is_copyable(tcx, ty) =>
|
||||||
|
"non-copyable (perhaps you meant to use clone()?)",
|
||||||
|
_ => default_msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -506,7 +506,7 @@ impl FlowedMoveData {
|
||||||
for self.dfcx_moves.each_bit_on_entry_frozen(id) |index| {
|
for self.dfcx_moves.each_bit_on_entry_frozen(id) |index| {
|
||||||
let move = &self.move_data.moves[index];
|
let move = &self.move_data.moves[index];
|
||||||
let moved_path = move.path;
|
let moved_path = move.path;
|
||||||
if base_indices.iter().any_(|x| x == &moved_path) {
|
if base_indices.iter().any(|x| x == &moved_path) {
|
||||||
// Scenario 1 or 2: `loan_path` or some base path of
|
// Scenario 1 or 2: `loan_path` or some base path of
|
||||||
// `loan_path` was moved.
|
// `loan_path` was moved.
|
||||||
if !f(move, self.move_data.path(moved_path).loan_path) {
|
if !f(move, self.move_data.path(moved_path).loan_path) {
|
||||||
|
@ -535,7 +535,7 @@ impl FlowedMoveData {
|
||||||
-> bool {
|
-> bool {
|
||||||
//! True if `id` is the id of the LHS of an assignment
|
//! True if `id` is the id of the LHS of an assignment
|
||||||
|
|
||||||
self.move_data.assignee_ids.iter().any_(|x| x == &id)
|
self.move_data.assignee_ids.iter().any(|x| x == &id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn each_assignment_of(&self,
|
pub fn each_assignment_of(&self,
|
||||||
|
|
|
@ -112,7 +112,7 @@ pub fn check_expr(sess: Session,
|
||||||
"` in a constant expression");
|
"` in a constant expression");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr_path(pth) => {
|
expr_path(ref pth) => {
|
||||||
// NB: In the future you might wish to relax this slightly
|
// NB: In the future you might wish to relax this slightly
|
||||||
// to handle on-demand instantiation of functions via
|
// to handle on-demand instantiation of functions via
|
||||||
// foo::<bar> in a const. Currently that is only done on
|
// foo::<bar> in a const. Currently that is only done on
|
||||||
|
@ -224,7 +224,7 @@ pub fn check_item_recursion(sess: Session,
|
||||||
(visitor.visit_item)(it, (env, visitor));
|
(visitor.visit_item)(it, (env, visitor));
|
||||||
|
|
||||||
fn visit_item(it: @item, (env, v): (env, visit::vt<env>)) {
|
fn visit_item(it: @item, (env, v): (env, visit::vt<env>)) {
|
||||||
if env.idstack.iter().any_(|x| x == &(it.id)) {
|
if env.idstack.iter().any(|x| x == &(it.id)) {
|
||||||
env.sess.span_fatal(env.root_it.span, "recursive constant");
|
env.sess.span_fatal(env.root_it.span, "recursive constant");
|
||||||
}
|
}
|
||||||
env.idstack.push(it.id);
|
env.idstack.push(it.id);
|
||||||
|
|
|
@ -95,7 +95,7 @@ pub fn check_expr(cx: @MatchCheckCtxt, ex: @expr, (s, v): ((), visit::vt<()>)) {
|
||||||
}
|
}
|
||||||
_ => { /* We assume only enum types can be uninhabited */ }
|
_ => { /* We assume only enum types can be uninhabited */ }
|
||||||
}
|
}
|
||||||
let arms = vec::concat(arms.filter_mapped(unguarded_pat));
|
let arms = arms.iter().filter_map(unguarded_pat).collect::<~[~[@pat]]>().concat_vec();
|
||||||
if arms.is_empty() {
|
if arms.is_empty() {
|
||||||
cx.tcx.sess.span_err(ex.span, "non-exhaustive patterns");
|
cx.tcx.sess.span_err(ex.span, "non-exhaustive patterns");
|
||||||
} else {
|
} else {
|
||||||
|
@ -265,7 +265,7 @@ pub fn is_useful(cx: &MatchCheckCtxt, m: &matrix, v: &[@pat]) -> useful {
|
||||||
}
|
}
|
||||||
Some(ref ctor) => {
|
Some(ref ctor) => {
|
||||||
match is_useful(cx,
|
match is_useful(cx,
|
||||||
&m.filter_mapped(|r| default(cx, *r)),
|
&m.iter().filter_map(|r| default(cx, *r)).collect::<matrix>(),
|
||||||
v.tail()) {
|
v.tail()) {
|
||||||
useful_ => useful(left_ty, /*bad*/copy *ctor),
|
useful_ => useful(left_ty, /*bad*/copy *ctor),
|
||||||
ref u => (/*bad*/copy *u)
|
ref u => (/*bad*/copy *u)
|
||||||
|
@ -287,7 +287,7 @@ pub fn is_useful_specialized(cx: &MatchCheckCtxt,
|
||||||
arity: uint,
|
arity: uint,
|
||||||
lty: ty::t)
|
lty: ty::t)
|
||||||
-> useful {
|
-> useful {
|
||||||
let ms = m.filter_mapped(|r| specialize(cx, *r, &ctor, arity, lty));
|
let ms = m.iter().filter_map(|r| specialize(cx, *r, &ctor, arity, lty)).collect::<matrix>();
|
||||||
let could_be_useful = is_useful(
|
let could_be_useful = is_useful(
|
||||||
cx, &ms, specialize(cx, v, &ctor, arity, lty).get());
|
cx, &ms, specialize(cx, v, &ctor, arity, lty).get());
|
||||||
match could_be_useful {
|
match could_be_useful {
|
||||||
|
@ -371,7 +371,7 @@ pub fn missing_ctor(cx: &MatchCheckCtxt,
|
||||||
let variants = ty::enum_variants(cx.tcx, eid);
|
let variants = ty::enum_variants(cx.tcx, eid);
|
||||||
if found.len() != (*variants).len() {
|
if found.len() != (*variants).len() {
|
||||||
for (*variants).iter().advance |v| {
|
for (*variants).iter().advance |v| {
|
||||||
if !found.iter().any_(|x| x == &(variant(v.id))) {
|
if !found.iter().any(|x| x == &(variant(v.id))) {
|
||||||
return Some(variant(v.id));
|
return Some(variant(v.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,14 +397,14 @@ pub fn missing_ctor(cx: &MatchCheckCtxt,
|
||||||
ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
|
ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
|
||||||
|
|
||||||
// Find the lengths and slices of all vector patterns.
|
// Find the lengths and slices of all vector patterns.
|
||||||
let vec_pat_lens = do m.filter_mapped |r| {
|
let vec_pat_lens = do m.iter().filter_map |r| {
|
||||||
match r[0].node {
|
match r[0].node {
|
||||||
pat_vec(ref before, ref slice, ref after) => {
|
pat_vec(ref before, ref slice, ref after) => {
|
||||||
Some((before.len() + after.len(), slice.is_some()))
|
Some((before.len() + after.len(), slice.is_some()))
|
||||||
}
|
}
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
};
|
}.collect::<~[(uint, bool)]>();
|
||||||
|
|
||||||
// Sort them by length such that for patterns of the same length,
|
// Sort them by length such that for patterns of the same length,
|
||||||
// those with a destructured slice come first.
|
// those with a destructured slice come first.
|
||||||
|
@ -805,13 +805,13 @@ pub fn is_refutable(cx: &MatchCheckCtxt, pat: &pat) -> bool {
|
||||||
}
|
}
|
||||||
pat_lit(_) | pat_range(_, _) => { true }
|
pat_lit(_) | pat_range(_, _) => { true }
|
||||||
pat_struct(_, ref fields, _) => {
|
pat_struct(_, ref fields, _) => {
|
||||||
fields.iter().any_(|f| is_refutable(cx, f.pat))
|
fields.iter().any(|f| is_refutable(cx, f.pat))
|
||||||
}
|
}
|
||||||
pat_tup(ref elts) => {
|
pat_tup(ref elts) => {
|
||||||
elts.iter().any_(|elt| is_refutable(cx, *elt))
|
elts.iter().any(|elt| is_refutable(cx, *elt))
|
||||||
}
|
}
|
||||||
pat_enum(_, Some(ref args)) => {
|
pat_enum(_, Some(ref args)) => {
|
||||||
args.iter().any_(|a| is_refutable(cx, *a))
|
args.iter().any(|a| is_refutable(cx, *a))
|
||||||
}
|
}
|
||||||
pat_enum(_,_) => { false }
|
pat_enum(_,_) => { false }
|
||||||
pat_vec(*) => { true }
|
pat_vec(*) => { true }
|
||||||
|
|
|
@ -341,14 +341,14 @@ impl<O:DataFlowOperator+Copy+'static> DataFlowContext<O> {
|
||||||
let entry_str = bits_to_str(on_entry);
|
let entry_str = bits_to_str(on_entry);
|
||||||
|
|
||||||
let gens = self.gens.slice(start, end);
|
let gens = self.gens.slice(start, end);
|
||||||
let gens_str = if gens.iter().any_(|&u| u != 0) {
|
let gens_str = if gens.iter().any(|&u| u != 0) {
|
||||||
fmt!(" gen: %s", bits_to_str(gens))
|
fmt!(" gen: %s", bits_to_str(gens))
|
||||||
} else {
|
} else {
|
||||||
~""
|
~""
|
||||||
};
|
};
|
||||||
|
|
||||||
let kills = self.kills.slice(start, end);
|
let kills = self.kills.slice(start, end);
|
||||||
let kills_str = if kills.iter().any_(|&u| u != 0) {
|
let kills_str = if kills.iter().any(|&u| u != 0) {
|
||||||
fmt!(" kill: %s", bits_to_str(kills))
|
fmt!(" kill: %s", bits_to_str(kills))
|
||||||
} else {
|
} else {
|
||||||
~""
|
~""
|
||||||
|
@ -643,7 +643,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
|
||||||
self.walk_opt_expr(o_e, in_out, loop_scopes);
|
self.walk_opt_expr(o_e, in_out, loop_scopes);
|
||||||
|
|
||||||
// is this a return from a `for`-loop closure?
|
// is this a return from a `for`-loop closure?
|
||||||
match loop_scopes.iter().position_(|s| s.loop_kind == ForLoop) {
|
match loop_scopes.iter().position(|s| s.loop_kind == ForLoop) {
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
// if so, add the in_out bits to the state
|
// if so, add the in_out bits to the state
|
||||||
// upon exit. Remember that we cannot count
|
// upon exit. Remember that we cannot count
|
||||||
|
@ -916,7 +916,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
match self.tcx().def_map.find(&expr.id) {
|
match self.tcx().def_map.find(&expr.id) {
|
||||||
Some(&ast::def_label(loop_id)) => {
|
Some(&ast::def_label(loop_id)) => {
|
||||||
match loop_scopes.iter().position_(|l| l.loop_id == loop_id) {
|
match loop_scopes.iter().position(|l| l.loop_id == loop_id) {
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
None => {
|
None => {
|
||||||
self.tcx().sess.span_bug(
|
self.tcx().sess.span_bug(
|
||||||
|
|
|
@ -117,7 +117,7 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt<Context>)) {
|
||||||
// If this is a destructor, check kinds.
|
// If this is a destructor, check kinds.
|
||||||
if !attrs_contains_name(item.attrs, "unsafe_destructor") {
|
if !attrs_contains_name(item.attrs, "unsafe_destructor") {
|
||||||
match item.node {
|
match item.node {
|
||||||
item_impl(_, Some(trait_ref), self_type, _) => {
|
item_impl(_, Some(ref trait_ref), ref self_type, _) => {
|
||||||
match cx.tcx.def_map.find(&trait_ref.ref_id) {
|
match cx.tcx.def_map.find(&trait_ref.ref_id) {
|
||||||
None => cx.tcx.sess.bug("trait ref not in def map!"),
|
None => cx.tcx.sess.bug("trait ref not in def map!"),
|
||||||
Some(&trait_def) => {
|
Some(&trait_def) => {
|
||||||
|
@ -125,7 +125,7 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt<Context>)) {
|
||||||
if cx.tcx.lang_items.drop_trait() == trait_def_id {
|
if cx.tcx.lang_items.drop_trait() == trait_def_id {
|
||||||
// Yes, it's a destructor.
|
// Yes, it's a destructor.
|
||||||
match self_type.node {
|
match self_type.node {
|
||||||
ty_path(_, bounds, path_node_id) => {
|
ty_path(_, ref bounds, path_node_id) => {
|
||||||
assert!(bounds.is_none());
|
assert!(bounds.is_none());
|
||||||
let struct_def = cx.tcx.def_map.get_copy(
|
let struct_def = cx.tcx.def_map.get_copy(
|
||||||
&path_node_id);
|
&path_node_id);
|
||||||
|
@ -198,8 +198,9 @@ fn with_appropriate_checker(cx: Context, id: node_id,
|
||||||
fn check_for_bare(cx: Context, fv: @freevar_entry) {
|
fn check_for_bare(cx: Context, fv: @freevar_entry) {
|
||||||
cx.tcx.sess.span_err(
|
cx.tcx.sess.span_err(
|
||||||
fv.span,
|
fv.span,
|
||||||
"attempted dynamic environment capture");
|
"can't capture dynamic environment in a fn item; \
|
||||||
}
|
use the || { ... } closure form instead");
|
||||||
|
} // same check is done in resolve.rs, but shouldn't be done
|
||||||
|
|
||||||
let fty = ty::node_id_to_type(cx.tcx, id);
|
let fty = ty::node_id_to_type(cx.tcx, id);
|
||||||
match ty::get(fty).sty {
|
match ty::get(fty).sty {
|
||||||
|
@ -320,7 +321,7 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
|
||||||
visit::visit_expr(e, (cx, v));
|
visit::visit_expr(e, (cx, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_ty(aty: @Ty, (cx, v): (Context, visit::vt<Context>)) {
|
fn check_ty(aty: &Ty, (cx, v): (Context, visit::vt<Context>)) {
|
||||||
match aty.node {
|
match aty.node {
|
||||||
ty_path(_, _, id) => {
|
ty_path(_, _, id) => {
|
||||||
let r = cx.tcx.node_type_substs.find(&id);
|
let r = cx.tcx.node_type_substs.find(&id);
|
||||||
|
@ -535,7 +536,7 @@ pub fn check_cast_for_escaping_regions(
|
||||||
// Check, based on the region associated with the trait, whether it can
|
// Check, based on the region associated with the trait, whether it can
|
||||||
// possibly escape the enclosing fn item (note that all type parameters
|
// possibly escape the enclosing fn item (note that all type parameters
|
||||||
// must have been declared on the enclosing fn item).
|
// must have been declared on the enclosing fn item).
|
||||||
if target_regions.iter().any_(|r| is_re_scope(*r)) {
|
if target_regions.iter().any(|r| is_re_scope(*r)) {
|
||||||
return; /* case (1) */
|
return; /* case (1) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,7 +551,7 @@ pub fn check_cast_for_escaping_regions(
|
||||||
|_r| {
|
|_r| {
|
||||||
// FIXME(#5723) --- turn this check on once &Objects are usable
|
// FIXME(#5723) --- turn this check on once &Objects are usable
|
||||||
//
|
//
|
||||||
// if !target_regions.iter().any_(|t_r| is_subregion_of(cx, *t_r, r)) {
|
// if !target_regions.iter().any(|t_r| is_subregion_of(cx, *t_r, r)) {
|
||||||
// cx.tcx.sess.span_err(
|
// cx.tcx.sess.span_err(
|
||||||
// source.span,
|
// source.span,
|
||||||
// fmt!("source contains borrowed pointer with lifetime \
|
// fmt!("source contains borrowed pointer with lifetime \
|
||||||
|
@ -564,7 +565,7 @@ pub fn check_cast_for_escaping_regions(
|
||||||
|ty| {
|
|ty| {
|
||||||
match ty::get(ty).sty {
|
match ty::get(ty).sty {
|
||||||
ty::ty_param(source_param) => {
|
ty::ty_param(source_param) => {
|
||||||
if target_params.iter().any_(|x| x == &source_param) {
|
if target_params.iter().any(|x| x == &source_param) {
|
||||||
/* case (2) */
|
/* case (2) */
|
||||||
} else {
|
} else {
|
||||||
check_durable(cx.tcx, ty, source.span); /* case (3) */
|
check_durable(cx.tcx, ty, source.span); /* case (3) */
|
||||||
|
|
|
@ -63,33 +63,34 @@ pub enum LangItem {
|
||||||
FailFnLangItem, // 24
|
FailFnLangItem, // 24
|
||||||
FailBoundsCheckFnLangItem, // 25
|
FailBoundsCheckFnLangItem, // 25
|
||||||
ExchangeMallocFnLangItem, // 26
|
ExchangeMallocFnLangItem, // 26
|
||||||
ClosureExchangeMallocFnLangItem, // 27
|
VectorExchangeMallocFnLangItem, // 27
|
||||||
ExchangeFreeFnLangItem, // 28
|
ClosureExchangeMallocFnLangItem, // 28
|
||||||
MallocFnLangItem, // 29
|
ExchangeFreeFnLangItem, // 29
|
||||||
FreeFnLangItem, // 30
|
MallocFnLangItem, // 30
|
||||||
BorrowAsImmFnLangItem, // 31
|
FreeFnLangItem, // 31
|
||||||
BorrowAsMutFnLangItem, // 32
|
BorrowAsImmFnLangItem, // 32
|
||||||
ReturnToMutFnLangItem, // 33
|
BorrowAsMutFnLangItem, // 33
|
||||||
CheckNotBorrowedFnLangItem, // 34
|
ReturnToMutFnLangItem, // 34
|
||||||
StrDupUniqFnLangItem, // 35
|
CheckNotBorrowedFnLangItem, // 35
|
||||||
RecordBorrowFnLangItem, // 36
|
StrDupUniqFnLangItem, // 36
|
||||||
UnrecordBorrowFnLangItem, // 37
|
RecordBorrowFnLangItem, // 37
|
||||||
|
UnrecordBorrowFnLangItem, // 38
|
||||||
|
|
||||||
StartFnLangItem, // 38
|
StartFnLangItem, // 39
|
||||||
|
|
||||||
TyDescStructLangItem, // 39
|
TyDescStructLangItem, // 40
|
||||||
TyVisitorTraitLangItem, // 40
|
TyVisitorTraitLangItem, // 41
|
||||||
OpaqueStructLangItem, // 41
|
OpaqueStructLangItem, // 42
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LanguageItems {
|
pub struct LanguageItems {
|
||||||
items: [Option<def_id>, ..42]
|
items: [Option<def_id>, ..43]
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LanguageItems {
|
impl LanguageItems {
|
||||||
pub fn new() -> LanguageItems {
|
pub fn new() -> LanguageItems {
|
||||||
LanguageItems {
|
LanguageItems {
|
||||||
items: [ None, ..42 ]
|
items: [ None, ..43 ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,23 +130,24 @@ impl LanguageItems {
|
||||||
24 => "fail_",
|
24 => "fail_",
|
||||||
25 => "fail_bounds_check",
|
25 => "fail_bounds_check",
|
||||||
26 => "exchange_malloc",
|
26 => "exchange_malloc",
|
||||||
27 => "closure_exchange_malloc",
|
27 => "vector_exchange_malloc",
|
||||||
28 => "exchange_free",
|
28 => "closure_exchange_malloc",
|
||||||
29 => "malloc",
|
29 => "exchange_free",
|
||||||
30 => "free",
|
30 => "malloc",
|
||||||
31 => "borrow_as_imm",
|
31 => "free",
|
||||||
32 => "borrow_as_mut",
|
32 => "borrow_as_imm",
|
||||||
33 => "return_to_mut",
|
33 => "borrow_as_mut",
|
||||||
34 => "check_not_borrowed",
|
34 => "return_to_mut",
|
||||||
35 => "strdup_uniq",
|
35 => "check_not_borrowed",
|
||||||
36 => "record_borrow",
|
36 => "strdup_uniq",
|
||||||
37 => "unrecord_borrow",
|
37 => "record_borrow",
|
||||||
|
38 => "unrecord_borrow",
|
||||||
|
|
||||||
38 => "start",
|
39 => "start",
|
||||||
|
|
||||||
39 => "ty_desc",
|
40 => "ty_desc",
|
||||||
40 => "ty_visitor",
|
41 => "ty_visitor",
|
||||||
41 => "opaque",
|
42 => "opaque",
|
||||||
|
|
||||||
_ => "???"
|
_ => "???"
|
||||||
}
|
}
|
||||||
|
@ -238,6 +240,9 @@ impl LanguageItems {
|
||||||
pub fn exchange_malloc_fn(&self) -> def_id {
|
pub fn exchange_malloc_fn(&self) -> def_id {
|
||||||
self.items[ExchangeMallocFnLangItem as uint].get()
|
self.items[ExchangeMallocFnLangItem as uint].get()
|
||||||
}
|
}
|
||||||
|
pub fn vector_exchange_malloc_fn(&self) -> def_id {
|
||||||
|
self.items[VectorExchangeMallocFnLangItem as uint].get()
|
||||||
|
}
|
||||||
pub fn closure_exchange_malloc_fn(&self) -> def_id {
|
pub fn closure_exchange_malloc_fn(&self) -> def_id {
|
||||||
self.items[ClosureExchangeMallocFnLangItem as uint].get()
|
self.items[ClosureExchangeMallocFnLangItem as uint].get()
|
||||||
}
|
}
|
||||||
|
@ -331,6 +336,7 @@ impl<'self> LanguageItemCollector<'self> {
|
||||||
item_refs.insert(@"fail_bounds_check",
|
item_refs.insert(@"fail_bounds_check",
|
||||||
FailBoundsCheckFnLangItem as uint);
|
FailBoundsCheckFnLangItem as uint);
|
||||||
item_refs.insert(@"exchange_malloc", ExchangeMallocFnLangItem as uint);
|
item_refs.insert(@"exchange_malloc", ExchangeMallocFnLangItem as uint);
|
||||||
|
item_refs.insert(@"vector_exchange_malloc", VectorExchangeMallocFnLangItem as uint);
|
||||||
item_refs.insert(@"closure_exchange_malloc", ClosureExchangeMallocFnLangItem as uint);
|
item_refs.insert(@"closure_exchange_malloc", ClosureExchangeMallocFnLangItem as uint);
|
||||||
item_refs.insert(@"exchange_free", ExchangeFreeFnLangItem as uint);
|
item_refs.insert(@"exchange_free", ExchangeFreeFnLangItem as uint);
|
||||||
item_refs.insert(@"malloc", MallocFnLangItem as uint);
|
item_refs.insert(@"malloc", MallocFnLangItem as uint);
|
||||||
|
|
|
@ -14,7 +14,6 @@ use middle::ty;
|
||||||
use middle::pat_util;
|
use middle::pat_util;
|
||||||
use util::ppaux::{ty_to_str};
|
use util::ppaux::{ty_to_str};
|
||||||
|
|
||||||
use std::char;
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
use std::i16;
|
use std::i16;
|
||||||
|
@ -25,7 +24,6 @@ use std::u16;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
use std::u64;
|
use std::u64;
|
||||||
use std::u8;
|
use std::u8;
|
||||||
use std::vec;
|
|
||||||
use extra::smallintmap::SmallIntMap;
|
use extra::smallintmap::SmallIntMap;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::codemap::span;
|
use syntax::codemap::span;
|
||||||
|
@ -80,6 +78,7 @@ pub enum lint {
|
||||||
non_implicitly_copyable_typarams,
|
non_implicitly_copyable_typarams,
|
||||||
deprecated_pattern,
|
deprecated_pattern,
|
||||||
non_camel_case_types,
|
non_camel_case_types,
|
||||||
|
non_uppercase_statics,
|
||||||
type_limits,
|
type_limits,
|
||||||
default_methods,
|
default_methods,
|
||||||
unused_unsafe,
|
unused_unsafe,
|
||||||
|
@ -198,6 +197,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
|
||||||
default: allow
|
default: allow
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
("non_uppercase_statics",
|
||||||
|
LintSpec {
|
||||||
|
lint: non_uppercase_statics,
|
||||||
|
desc: "static constants should have uppercase identifiers",
|
||||||
|
default: warn
|
||||||
|
}),
|
||||||
|
|
||||||
("managed_heap_memory",
|
("managed_heap_memory",
|
||||||
LintSpec {
|
LintSpec {
|
||||||
lint: managed_heap_memory,
|
lint: managed_heap_memory,
|
||||||
|
@ -741,9 +747,9 @@ fn check_item_ctypes(cx: &Context, it: &ast::item) {
|
||||||
|
|
||||||
fn check_foreign_fn(cx: &Context, decl: &ast::fn_decl) {
|
fn check_foreign_fn(cx: &Context, decl: &ast::fn_decl) {
|
||||||
for decl.inputs.iter().advance |in| {
|
for decl.inputs.iter().advance |in| {
|
||||||
check_ty(cx, in.ty);
|
check_ty(cx, &in.ty);
|
||||||
}
|
}
|
||||||
check_ty(cx, decl.output)
|
check_ty(cx, &decl.output)
|
||||||
}
|
}
|
||||||
|
|
||||||
match it.node {
|
match it.node {
|
||||||
|
@ -753,7 +759,7 @@ fn check_item_ctypes(cx: &Context, it: &ast::item) {
|
||||||
ast::foreign_item_fn(ref decl, _, _) => {
|
ast::foreign_item_fn(ref decl, _, _) => {
|
||||||
check_foreign_fn(cx, decl);
|
check_foreign_fn(cx, decl);
|
||||||
}
|
}
|
||||||
ast::foreign_item_static(t, _) => { check_ty(cx, t); }
|
ast::foreign_item_static(ref t, _) => { check_ty(cx, t); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -854,7 +860,10 @@ fn check_item_non_camel_case_types(cx: &Context, it: &ast::item) {
|
||||||
let ident = cx.sess.str_of(ident);
|
let ident = cx.sess.str_of(ident);
|
||||||
assert!(!ident.is_empty());
|
assert!(!ident.is_empty());
|
||||||
let ident = ident.trim_chars(&'_');
|
let ident = ident.trim_chars(&'_');
|
||||||
char::is_uppercase(ident.char_at(0)) &&
|
|
||||||
|
// start with a non-lowercase letter rather than non-uppercase
|
||||||
|
// ones (some scripts don't have a concept of upper/lowercase)
|
||||||
|
!ident.char_at(0).is_lowercase() &&
|
||||||
!ident.contains_char('_')
|
!ident.contains_char('_')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -881,6 +890,23 @@ fn check_item_non_camel_case_types(cx: &Context, it: &ast::item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_item_non_uppercase_statics(cx: &Context, it: &ast::item) {
|
||||||
|
match it.node {
|
||||||
|
// only check static constants
|
||||||
|
ast::item_static(_, ast::m_imm, _) => {
|
||||||
|
let s = cx.tcx.sess.str_of(it.ident);
|
||||||
|
// check for lowercase letters rather than non-uppercase
|
||||||
|
// ones (some scripts don't have a concept of
|
||||||
|
// upper/lowercase)
|
||||||
|
if s.iter().any(|c| c.is_lowercase()) {
|
||||||
|
cx.span_lint(non_uppercase_statics, it.span,
|
||||||
|
"static constant should have an uppercase identifier");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn lint_unused_unsafe() -> visit::vt<@mut Context> {
|
fn lint_unused_unsafe() -> visit::vt<@mut Context> {
|
||||||
visit::mk_vt(@visit::Visitor {
|
visit::mk_vt(@visit::Visitor {
|
||||||
visit_expr: |e, (cx, vt): (@mut Context, visit::vt<@mut Context>)| {
|
visit_expr: |e, (cx, vt): (@mut Context, visit::vt<@mut Context>)| {
|
||||||
|
@ -940,10 +966,6 @@ fn lint_unused_mut() -> visit::vt<@mut Context> {
|
||||||
visit_fn_decl(cx, &tm.decl);
|
visit_fn_decl(cx, &tm.decl);
|
||||||
visit::visit_ty_method(tm, (cx, vt));
|
visit::visit_ty_method(tm, (cx, vt));
|
||||||
},
|
},
|
||||||
visit_struct_method: |sm, (cx, vt)| {
|
|
||||||
visit_fn_decl(cx, &sm.decl);
|
|
||||||
visit::visit_struct_method(sm, (cx, vt));
|
|
||||||
},
|
|
||||||
visit_trait_method: |tm, (cx, vt)| {
|
visit_trait_method: |tm, (cx, vt)| {
|
||||||
match *tm {
|
match *tm {
|
||||||
ast::required(ref tm) => visit_fn_decl(cx, &tm.decl),
|
ast::required(ref tm) => visit_fn_decl(cx, &tm.decl),
|
||||||
|
@ -960,7 +982,7 @@ fn lint_session() -> visit::vt<@mut Context> {
|
||||||
match cx.tcx.sess.lints.pop(&id) {
|
match cx.tcx.sess.lints.pop(&id) {
|
||||||
None => {},
|
None => {},
|
||||||
Some(l) => {
|
Some(l) => {
|
||||||
do vec::consume(l) |_, (lint, span, msg)| {
|
for l.consume_iter().advance |(lint, span, msg)| {
|
||||||
cx.span_lint(lint, span, msg)
|
cx.span_lint(lint, span, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1016,21 +1038,13 @@ fn lint_missing_doc() -> visit::vt<@mut Context> {
|
||||||
// If we have doc(hidden), nothing to do
|
// If we have doc(hidden), nothing to do
|
||||||
if cx.doc_hidden { return }
|
if cx.doc_hidden { return }
|
||||||
// If we're documented, nothing to do
|
// If we're documented, nothing to do
|
||||||
if attrs.iter().any_(|a| a.node.is_sugared_doc) { return }
|
if attrs.iter().any(|a| a.node.is_sugared_doc) { return }
|
||||||
|
|
||||||
// otherwise, warn!
|
// otherwise, warn!
|
||||||
cx.span_lint(missing_doc, sp, msg);
|
cx.span_lint(missing_doc, sp, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
visit::mk_vt(@visit::Visitor {
|
visit::mk_vt(@visit::Visitor {
|
||||||
visit_struct_method: |m, (cx, vt)| {
|
|
||||||
if m.vis == ast::public {
|
|
||||||
check_attrs(cx, m.attrs, m.span,
|
|
||||||
"missing documentation for a method");
|
|
||||||
}
|
|
||||||
visit::visit_struct_method(m, (cx, vt));
|
|
||||||
},
|
|
||||||
|
|
||||||
visit_ty_method: |m, (cx, vt)| {
|
visit_ty_method: |m, (cx, vt)| {
|
||||||
// All ty_method objects are linted about because they're part of a
|
// All ty_method objects are linted about because they're part of a
|
||||||
// trait (no visibility)
|
// trait (no visibility)
|
||||||
|
@ -1143,6 +1157,7 @@ pub fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
|
||||||
}
|
}
|
||||||
check_item_ctypes(cx, it);
|
check_item_ctypes(cx, it);
|
||||||
check_item_non_camel_case_types(cx, it);
|
check_item_non_camel_case_types(cx, it);
|
||||||
|
check_item_non_uppercase_statics(cx, it);
|
||||||
check_item_default_methods(cx, it);
|
check_item_default_methods(cx, it);
|
||||||
check_item_heap(cx, it);
|
check_item_heap(cx, it);
|
||||||
|
|
||||||
|
|
|
@ -390,8 +390,8 @@ impl VisitContext {
|
||||||
// any fields which (1) were not explicitly
|
// any fields which (1) were not explicitly
|
||||||
// specified and (2) have a type that
|
// specified and (2) have a type that
|
||||||
// moves-by-default:
|
// moves-by-default:
|
||||||
let consume_with = with_fields.iter().any_(|tf| {
|
let consume_with = with_fields.iter().any(|tf| {
|
||||||
!fields.iter().any_(|f| f.node.ident == tf.ident) &&
|
!fields.iter().any(|f| f.node.ident == tf.ident) &&
|
||||||
ty::type_moves_by_default(self.tcx, tf.mt.ty)
|
ty::type_moves_by_default(self.tcx, tf.mt.ty)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -71,10 +71,10 @@ pub fn pat_is_binding_or_wild(dm: resolve::DefMap, pat: @pat) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pat_bindings(dm: resolve::DefMap, pat: @pat,
|
pub fn pat_bindings(dm: resolve::DefMap, pat: @pat,
|
||||||
it: &fn(binding_mode, node_id, span, @Path)) {
|
it: &fn(binding_mode, node_id, span, &Path)) {
|
||||||
for walk_pat(pat) |p| {
|
for walk_pat(pat) |p| {
|
||||||
match p.node {
|
match p.node {
|
||||||
pat_ident(binding_mode, pth, _) if pat_is_binding(dm, p) => {
|
pat_ident(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
|
||||||
it(binding_mode, p.id, p.span, pth);
|
it(binding_mode, p.id, p.span, pth);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -245,13 +245,21 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||||
method_id: def_id,
|
method_id: def_id,
|
||||||
name: &ident) =
|
name: &ident) =
|
||||||
|span, method_id, name| {
|
|span, method_id, name| {
|
||||||
|
// If the method is a default method, we need to use the def_id of
|
||||||
|
// the default implementation.
|
||||||
|
// Having to do this this is really unfortunate.
|
||||||
|
let method_id = match tcx.provided_method_sources.find(&method_id) {
|
||||||
|
None => method_id,
|
||||||
|
Some(source) => source.method_id
|
||||||
|
};
|
||||||
|
|
||||||
if method_id.crate == local_crate {
|
if method_id.crate == local_crate {
|
||||||
let is_private = method_is_private(span, method_id.node);
|
let is_private = method_is_private(span, method_id.node);
|
||||||
let container_id = local_method_container_id(span,
|
let container_id = local_method_container_id(span,
|
||||||
method_id.node);
|
method_id.node);
|
||||||
if is_private &&
|
if is_private &&
|
||||||
(container_id.crate != local_crate ||
|
(container_id.crate != local_crate ||
|
||||||
!privileged_items.iter().any_(|x| x == &(container_id.node))) {
|
!privileged_items.iter().any(|x| x == &(container_id.node))) {
|
||||||
tcx.sess.span_err(span,
|
tcx.sess.span_err(span,
|
||||||
fmt!("method `%s` is private",
|
fmt!("method `%s` is private",
|
||||||
token::ident_to_str(name)));
|
token::ident_to_str(name)));
|
||||||
|
@ -268,7 +276,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Checks that a private path is in scope.
|
// Checks that a private path is in scope.
|
||||||
let check_path: @fn(span: span, def: def, path: @Path) =
|
let check_path: @fn(span: span, def: def, path: &Path) =
|
||||||
|span, def, path| {
|
|span, def, path| {
|
||||||
debug!("checking path");
|
debug!("checking path");
|
||||||
match def {
|
match def {
|
||||||
|
@ -279,7 +287,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||||
def_fn(def_id, _) => {
|
def_fn(def_id, _) => {
|
||||||
if def_id.crate == local_crate {
|
if def_id.crate == local_crate {
|
||||||
if local_item_is_private(span, def_id.node) &&
|
if local_item_is_private(span, def_id.node) &&
|
||||||
!privileged_items.iter().any_(|x| x == &def_id.node) {
|
!privileged_items.iter().any(|x| x == &def_id.node) {
|
||||||
tcx.sess.span_err(span,
|
tcx.sess.span_err(span,
|
||||||
fmt!("function `%s` is private",
|
fmt!("function `%s` is private",
|
||||||
token::ident_to_str(path.idents.last())));
|
token::ident_to_str(path.idents.last())));
|
||||||
|
@ -324,7 +332,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||||
provided(method)
|
provided(method)
|
||||||
if method.vis == private &&
|
if method.vis == private &&
|
||||||
!privileged_items.iter()
|
!privileged_items.iter()
|
||||||
.any_(|x| x == &(trait_id.node)) => {
|
.any(|x| x == &(trait_id.node)) => {
|
||||||
tcx.sess.span_err(span,
|
tcx.sess.span_err(span,
|
||||||
fmt!("method `%s` is private",
|
fmt!("method `%s` is private",
|
||||||
token::ident_to_str(&method
|
token::ident_to_str(&method
|
||||||
|
@ -409,7 +417,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||||
base))).sty {
|
base))).sty {
|
||||||
ty_struct(id, _)
|
ty_struct(id, _)
|
||||||
if id.crate != local_crate || !privileged_items.iter()
|
if id.crate != local_crate || !privileged_items.iter()
|
||||||
.any_(|x| x == &(id.node)) => {
|
.any(|x| x == &(id.node)) => {
|
||||||
debug!("(privacy checking) checking field access");
|
debug!("(privacy checking) checking field access");
|
||||||
check_field(expr.span, id, ident);
|
check_field(expr.span, id, ident);
|
||||||
}
|
}
|
||||||
|
@ -422,7 +430,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||||
base))).sty {
|
base))).sty {
|
||||||
ty_struct(id, _)
|
ty_struct(id, _)
|
||||||
if id.crate != local_crate ||
|
if id.crate != local_crate ||
|
||||||
!privileged_items.iter().any_(|x| x == &(id.node)) => {
|
!privileged_items.iter().any(|x| x == &(id.node)) => {
|
||||||
match method_map.find(&expr.id) {
|
match method_map.find(&expr.id) {
|
||||||
None => {
|
None => {
|
||||||
tcx.sess.span_bug(expr.span,
|
tcx.sess.span_bug(expr.span,
|
||||||
|
@ -441,14 +449,14 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr_path(path) => {
|
expr_path(ref path) => {
|
||||||
check_path(expr.span, tcx.def_map.get_copy(&expr.id), path);
|
check_path(expr.span, tcx.def_map.get_copy(&expr.id), path);
|
||||||
}
|
}
|
||||||
expr_struct(_, ref fields, _) => {
|
expr_struct(_, ref fields, _) => {
|
||||||
match ty::get(ty::expr_ty(tcx, expr)).sty {
|
match ty::get(ty::expr_ty(tcx, expr)).sty {
|
||||||
ty_struct(id, _) => {
|
ty_struct(id, _) => {
|
||||||
if id.crate != local_crate ||
|
if id.crate != local_crate ||
|
||||||
!privileged_items.iter().any_(|x| x == &(id.node)) {
|
!privileged_items.iter().any(|x| x == &(id.node)) {
|
||||||
for (*fields).iter().advance |field| {
|
for (*fields).iter().advance |field| {
|
||||||
debug!("(privacy checking) checking \
|
debug!("(privacy checking) checking \
|
||||||
field in struct literal");
|
field in struct literal");
|
||||||
|
@ -459,7 +467,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||||
}
|
}
|
||||||
ty_enum(id, _) => {
|
ty_enum(id, _) => {
|
||||||
if id.crate != local_crate ||
|
if id.crate != local_crate ||
|
||||||
!privileged_items.iter().any_(|x| x == &(id.node)) {
|
!privileged_items.iter().any(|x| x == &(id.node)) {
|
||||||
match tcx.def_map.get_copy(&expr.id) {
|
match tcx.def_map.get_copy(&expr.id) {
|
||||||
def_variant(_, variant_id) => {
|
def_variant(_, variant_id) => {
|
||||||
for (*fields).iter().advance |field| {
|
for (*fields).iter().advance |field| {
|
||||||
|
@ -496,7 +504,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||||
match ty::get(ty::expr_ty(tcx, operand)).sty {
|
match ty::get(ty::expr_ty(tcx, operand)).sty {
|
||||||
ty_enum(id, _) => {
|
ty_enum(id, _) => {
|
||||||
if id.crate != local_crate ||
|
if id.crate != local_crate ||
|
||||||
!privileged_items.iter().any_(|x| x == &(id.node)) {
|
!privileged_items.iter().any(|x| x == &(id.node)) {
|
||||||
check_variant(expr.span, id);
|
check_variant(expr.span, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,7 +522,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||||
match ty::get(ty::pat_ty(tcx, pattern)).sty {
|
match ty::get(ty::pat_ty(tcx, pattern)).sty {
|
||||||
ty_struct(id, _) => {
|
ty_struct(id, _) => {
|
||||||
if id.crate != local_crate ||
|
if id.crate != local_crate ||
|
||||||
!privileged_items.iter().any_(|x| x == &(id.node)) {
|
!privileged_items.iter().any(|x| x == &(id.node)) {
|
||||||
for fields.iter().advance |field| {
|
for fields.iter().advance |field| {
|
||||||
debug!("(privacy checking) checking \
|
debug!("(privacy checking) checking \
|
||||||
struct pattern");
|
struct pattern");
|
||||||
|
@ -525,7 +533,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||||
}
|
}
|
||||||
ty_enum(enum_id, _) => {
|
ty_enum(enum_id, _) => {
|
||||||
if enum_id.crate != local_crate ||
|
if enum_id.crate != local_crate ||
|
||||||
!privileged_items.iter().any_(|x| x == &enum_id.node) {
|
!privileged_items.iter().any(|x| x == &enum_id.node) {
|
||||||
match tcx.def_map.find(&pattern.id) {
|
match tcx.def_map.find(&pattern.id) {
|
||||||
Some(&def_variant(_, variant_id)) => {
|
Some(&def_variant(_, variant_id)) => {
|
||||||
for fields.iter().advance |field| {
|
for fields.iter().advance |field| {
|
||||||
|
|
|
@ -141,7 +141,7 @@ impl ReachableContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item_impl(ref generics, trait_ref, _, ref methods) => {
|
item_impl(ref generics, ref trait_ref, _, ref methods) => {
|
||||||
// XXX(pcwalton): We conservatively assume any methods
|
// XXX(pcwalton): We conservatively assume any methods
|
||||||
// on a trait implementation are reachable, when this
|
// on a trait implementation are reachable, when this
|
||||||
// is not the case. We could be more precise by only
|
// is not the case. We could be more precise by only
|
||||||
|
|
|
@ -78,7 +78,7 @@ impl RegionMaps {
|
||||||
pub fn relate_free_regions(&mut self, sub: FreeRegion, sup: FreeRegion) {
|
pub fn relate_free_regions(&mut self, sub: FreeRegion, sup: FreeRegion) {
|
||||||
match self.free_region_map.find_mut(&sub) {
|
match self.free_region_map.find_mut(&sub) {
|
||||||
Some(sups) => {
|
Some(sups) => {
|
||||||
if !sups.iter().any_(|x| x == &sup) {
|
if !sups.iter().any(|x| x == &sup) {
|
||||||
sups.push(sup);
|
sups.push(sup);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -202,7 +202,7 @@ impl RegionMaps {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !queue.iter().any_(|x| x == parent) {
|
if !queue.iter().any(|x| x == parent) {
|
||||||
queue.push(*parent);
|
queue.push(*parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -612,7 +612,7 @@ impl DetermineRpCtxt {
|
||||||
ambient_variance: self.ambient_variance,
|
ambient_variance: self.ambient_variance,
|
||||||
id: self.item_id
|
id: self.item_id
|
||||||
};
|
};
|
||||||
if !vec.iter().any_(|x| x == &dep) { vec.push(dep); }
|
if !vec.iter().any(|x| x == &dep) { vec.push(dep); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determines whether a reference to a region that appears in the
|
// Determines whether a reference to a region that appears in the
|
||||||
|
@ -651,18 +651,18 @@ impl DetermineRpCtxt {
|
||||||
// with &self type, &self is also bound. We detect those last two
|
// with &self type, &self is also bound. We detect those last two
|
||||||
// cases via flags (anon_implies_rp and self_implies_rp) that are
|
// cases via flags (anon_implies_rp and self_implies_rp) that are
|
||||||
// true when the anon or self region implies RP.
|
// true when the anon or self region implies RP.
|
||||||
pub fn region_is_relevant(&self, r: Option<@ast::Lifetime>) -> bool {
|
pub fn region_is_relevant(&self, r: &Option<ast::Lifetime>) -> bool {
|
||||||
match r {
|
match r {
|
||||||
None => {
|
&None => {
|
||||||
self.anon_implies_rp
|
self.anon_implies_rp
|
||||||
}
|
}
|
||||||
Some(ref l) if l.ident == special_idents::statik => {
|
&Some(ref l) if l.ident == special_idents::statik => {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
Some(ref l) if l.ident == special_idents::self_ => {
|
&Some(ref l) if l.ident == special_idents::self_ => {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Some(_) => {
|
&Some(_) => {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -713,10 +713,10 @@ fn determine_rp_in_fn(fk: &visit::fn_kind,
|
||||||
do cx.with(cx.item_id, false) {
|
do cx.with(cx.item_id, false) {
|
||||||
do cx.with_ambient_variance(rv_contravariant) {
|
do cx.with_ambient_variance(rv_contravariant) {
|
||||||
for decl.inputs.iter().advance |a| {
|
for decl.inputs.iter().advance |a| {
|
||||||
(visitor.visit_ty)(a.ty, (cx, visitor));
|
(visitor.visit_ty)(&a.ty, (cx, visitor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(visitor.visit_ty)(decl.output, (cx, visitor));
|
(visitor.visit_ty)(&decl.output, (cx, visitor));
|
||||||
let generics = visit::generics_of_fn(fk);
|
let generics = visit::generics_of_fn(fk);
|
||||||
(visitor.visit_generics)(&generics, (cx, visitor));
|
(visitor.visit_generics)(&generics, (cx, visitor));
|
||||||
(visitor.visit_block)(body, (cx, visitor));
|
(visitor.visit_block)(body, (cx, visitor));
|
||||||
|
@ -731,7 +731,7 @@ fn determine_rp_in_ty_method(ty_m: &ast::ty_method,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn determine_rp_in_ty(ty: @ast::Ty,
|
fn determine_rp_in_ty(ty: &ast::Ty,
|
||||||
(cx, visitor): (@mut DetermineRpCtxt,
|
(cx, visitor): (@mut DetermineRpCtxt,
|
||||||
visit::vt<@mut DetermineRpCtxt>)) {
|
visit::vt<@mut DetermineRpCtxt>)) {
|
||||||
// we are only interested in types that will require an item to
|
// we are only interested in types that will require an item to
|
||||||
|
@ -747,7 +747,7 @@ fn determine_rp_in_ty(ty: @ast::Ty,
|
||||||
// locations)
|
// locations)
|
||||||
let sess = cx.sess;
|
let sess = cx.sess;
|
||||||
match ty.node {
|
match ty.node {
|
||||||
ast::ty_rptr(r, _) => {
|
ast::ty_rptr(ref r, _) => {
|
||||||
debug!("referenced rptr type %s",
|
debug!("referenced rptr type %s",
|
||||||
pprust::ty_to_str(ty, sess.intr()));
|
pprust::ty_to_str(ty, sess.intr()));
|
||||||
|
|
||||||
|
@ -762,7 +762,7 @@ fn determine_rp_in_ty(ty: @ast::Ty,
|
||||||
pprust::ty_to_str(ty, sess.intr()));
|
pprust::ty_to_str(ty, sess.intr()));
|
||||||
match f.region {
|
match f.region {
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
if cx.region_is_relevant(f.region) {
|
if cx.region_is_relevant(&f.region) {
|
||||||
let rv = cx.add_variance(rv_contravariant);
|
let rv = cx.add_variance(rv_contravariant);
|
||||||
cx.add_rp(cx.item_id, rv)
|
cx.add_rp(cx.item_id, rv)
|
||||||
}
|
}
|
||||||
|
@ -784,13 +784,13 @@ fn determine_rp_in_ty(ty: @ast::Ty,
|
||||||
// then check whether it is region-parameterized and consider
|
// then check whether it is region-parameterized and consider
|
||||||
// that as a direct dependency.
|
// that as a direct dependency.
|
||||||
match ty.node {
|
match ty.node {
|
||||||
ast::ty_path(path, _bounds, id) => {
|
ast::ty_path(ref path, _, id) => {
|
||||||
match cx.def_map.find(&id) {
|
match cx.def_map.find(&id) {
|
||||||
Some(&ast::def_ty(did)) |
|
Some(&ast::def_ty(did)) |
|
||||||
Some(&ast::def_trait(did)) |
|
Some(&ast::def_trait(did)) |
|
||||||
Some(&ast::def_struct(did)) => {
|
Some(&ast::def_struct(did)) => {
|
||||||
if did.crate == ast::local_crate {
|
if did.crate == ast::local_crate {
|
||||||
if cx.region_is_relevant(path.rp) {
|
if cx.region_is_relevant(&path.rp) {
|
||||||
cx.add_dep(did.node);
|
cx.add_dep(did.node);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -800,7 +800,7 @@ fn determine_rp_in_ty(ty: @ast::Ty,
|
||||||
Some(variance) => {
|
Some(variance) => {
|
||||||
debug!("reference to external, rp'd type %s",
|
debug!("reference to external, rp'd type %s",
|
||||||
pprust::ty_to_str(ty, sess.intr()));
|
pprust::ty_to_str(ty, sess.intr()));
|
||||||
if cx.region_is_relevant(path.rp) {
|
if cx.region_is_relevant(&path.rp) {
|
||||||
let rv = cx.add_variance(variance);
|
let rv = cx.add_variance(variance);
|
||||||
cx.add_rp(cx.item_id, rv)
|
cx.add_rp(cx.item_id, rv)
|
||||||
}
|
}
|
||||||
|
@ -815,16 +815,16 @@ fn determine_rp_in_ty(ty: @ast::Ty,
|
||||||
}
|
}
|
||||||
|
|
||||||
match ty.node {
|
match ty.node {
|
||||||
ast::ty_box(mt) | ast::ty_uniq(mt) | ast::ty_vec(mt) |
|
ast::ty_box(ref mt) | ast::ty_uniq(ref mt) | ast::ty_vec(ref mt) |
|
||||||
ast::ty_rptr(_, mt) | ast::ty_ptr(mt) => {
|
ast::ty_rptr(_, ref mt) | ast::ty_ptr(ref mt) => {
|
||||||
visit_mt(mt, (cx, visitor));
|
visit_mt(mt, (cx, visitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ty_path(path, _bounds, _) => {
|
ast::ty_path(ref path, _, _) => {
|
||||||
// type parameters are---for now, anyway---always invariant
|
// type parameters are---for now, anyway---always invariant
|
||||||
do cx.with_ambient_variance(rv_invariant) {
|
do cx.with_ambient_variance(rv_invariant) {
|
||||||
for path.types.iter().advance |tp| {
|
for path.types.iter().advance |tp| {
|
||||||
(visitor.visit_ty)(*tp, (cx, visitor));
|
(visitor.visit_ty)(tp, (cx, visitor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -837,10 +837,10 @@ fn determine_rp_in_ty(ty: @ast::Ty,
|
||||||
// parameters are contravariant
|
// parameters are contravariant
|
||||||
do cx.with_ambient_variance(rv_contravariant) {
|
do cx.with_ambient_variance(rv_contravariant) {
|
||||||
for decl.inputs.iter().advance |a| {
|
for decl.inputs.iter().advance |a| {
|
||||||
(visitor.visit_ty)(a.ty, (cx, visitor));
|
(visitor.visit_ty)(&a.ty, (cx, visitor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(visitor.visit_ty)(decl.output, (cx, visitor));
|
(visitor.visit_ty)(&decl.output, (cx, visitor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,7 +849,7 @@ fn determine_rp_in_ty(ty: @ast::Ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_mt(mt: ast::mt,
|
fn visit_mt(mt: &ast::mt,
|
||||||
(cx, visitor): (@mut DetermineRpCtxt,
|
(cx, visitor): (@mut DetermineRpCtxt,
|
||||||
visit::vt<@mut DetermineRpCtxt>)) {
|
visit::vt<@mut DetermineRpCtxt>)) {
|
||||||
// mutability is invariant
|
// mutability is invariant
|
||||||
|
|
|
@ -41,7 +41,6 @@ use syntax::opt_vec::OptVec;
|
||||||
|
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::uint;
|
use std::uint;
|
||||||
use std::vec;
|
|
||||||
use std::hashmap::{HashMap, HashSet};
|
use std::hashmap::{HashMap, HashSet};
|
||||||
use std::util;
|
use std::util;
|
||||||
|
|
||||||
|
@ -511,6 +510,13 @@ pub struct NameBindings {
|
||||||
value_def: Option<ValueNsDef>, //< Meaning in value namespace.
|
value_def: Option<ValueNsDef>, //< Meaning in value namespace.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ways in which a trait can be referenced
|
||||||
|
enum TraitReferenceType {
|
||||||
|
TraitImplementation, // impl SomeTrait for T { ... }
|
||||||
|
TraitDerivation, // trait T : SomeTrait { ... }
|
||||||
|
TraitBoundingTypeParameter, // fn f<T:SomeTrait>() { ... }
|
||||||
|
}
|
||||||
|
|
||||||
impl NameBindings {
|
impl NameBindings {
|
||||||
/// Creates a new module in this set of name bindings.
|
/// Creates a new module in this set of name bindings.
|
||||||
pub fn define_module(@mut self,
|
pub fn define_module(@mut self,
|
||||||
|
@ -1227,7 +1233,7 @@ impl Resolver {
|
||||||
visit_item(item, (new_parent, visitor));
|
visit_item(item, (new_parent, visitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
item_impl(_, None, ty, ref methods) => {
|
item_impl(_, None, ref ty, ref methods) => {
|
||||||
// If this implements an anonymous trait, then add all the
|
// If this implements an anonymous trait, then add all the
|
||||||
// methods within to a new module, if the type was defined
|
// methods within to a new module, if the type was defined
|
||||||
// within this module.
|
// within this module.
|
||||||
|
@ -1237,9 +1243,9 @@ impl Resolver {
|
||||||
// the same module that declared the type.
|
// the same module that declared the type.
|
||||||
|
|
||||||
// Create the module and add all methods.
|
// Create the module and add all methods.
|
||||||
match *ty {
|
match ty {
|
||||||
Ty {
|
&Ty {
|
||||||
node: ty_path(path, _, _),
|
node: ty_path(ref path, _, _),
|
||||||
_
|
_
|
||||||
} if path.idents.len() == 1 => {
|
} if path.idents.len() == 1 => {
|
||||||
let name = path_to_ident(path);
|
let name = path_to_ident(path);
|
||||||
|
@ -1307,7 +1313,7 @@ impl Resolver {
|
||||||
visit_item(item, (parent, visitor));
|
visit_item(item, (parent, visitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
item_impl(_, Some(_), _ty, ref _methods) => {
|
item_impl(_, Some(_), _, _) => {
|
||||||
visit_item(item, (parent, visitor));
|
visit_item(item, (parent, visitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1426,7 +1432,7 @@ impl Resolver {
|
||||||
/// Constructs the reduced graph for one 'view item'. View items consist
|
/// Constructs the reduced graph for one 'view item'. View items consist
|
||||||
/// of imports and use directives.
|
/// of imports and use directives.
|
||||||
pub fn build_reduced_graph_for_view_item(@mut self,
|
pub fn build_reduced_graph_for_view_item(@mut self,
|
||||||
view_item: @view_item,
|
view_item: &view_item,
|
||||||
(parent, _):
|
(parent, _):
|
||||||
(ReducedGraphParent,
|
(ReducedGraphParent,
|
||||||
vt<ReducedGraphParent>)) {
|
vt<ReducedGraphParent>)) {
|
||||||
|
@ -1440,7 +1446,7 @@ impl Resolver {
|
||||||
|
|
||||||
let mut module_path = ~[];
|
let mut module_path = ~[];
|
||||||
match view_path.node {
|
match view_path.node {
|
||||||
view_path_simple(_, full_path, _) => {
|
view_path_simple(_, ref full_path, _) => {
|
||||||
let path_len = full_path.idents.len();
|
let path_len = full_path.idents.len();
|
||||||
assert!(path_len != 0);
|
assert!(path_len != 0);
|
||||||
|
|
||||||
|
@ -1451,8 +1457,8 @@ impl Resolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
view_path_glob(module_ident_path, _) |
|
view_path_glob(ref module_ident_path, _) |
|
||||||
view_path_list(module_ident_path, _, _) => {
|
view_path_list(ref module_ident_path, _, _) => {
|
||||||
for module_ident_path.idents.iter().advance |ident| {
|
for module_ident_path.idents.iter().advance |ident| {
|
||||||
module_path.push(*ident);
|
module_path.push(*ident);
|
||||||
}
|
}
|
||||||
|
@ -1462,7 +1468,7 @@ impl Resolver {
|
||||||
// Build up the import directives.
|
// Build up the import directives.
|
||||||
let module_ = self.get_module_from_parent(parent);
|
let module_ = self.get_module_from_parent(parent);
|
||||||
match view_path.node {
|
match view_path.node {
|
||||||
view_path_simple(binding, full_path, id) => {
|
view_path_simple(binding, ref full_path, id) => {
|
||||||
let source_ident = *full_path.idents.last();
|
let source_ident = *full_path.idents.last();
|
||||||
let subclass = @SingleImport(binding,
|
let subclass = @SingleImport(binding,
|
||||||
source_ident);
|
source_ident);
|
||||||
|
@ -3382,7 +3388,8 @@ impl Resolver {
|
||||||
|
|
||||||
self.session.span_err(
|
self.session.span_err(
|
||||||
span,
|
span,
|
||||||
"attempted dynamic environment-capture");
|
"can't capture dynamic environment in a fn item; \
|
||||||
|
use the || { ... } closure form instead");
|
||||||
} else {
|
} else {
|
||||||
// This was an attempt to use a type parameter outside
|
// This was an attempt to use a type parameter outside
|
||||||
// its scope.
|
// its scope.
|
||||||
|
@ -3404,7 +3411,8 @@ impl Resolver {
|
||||||
|
|
||||||
self.session.span_err(
|
self.session.span_err(
|
||||||
span,
|
span,
|
||||||
"attempted dynamic environment-capture");
|
"can't capture dynamic environment in a fn item; \
|
||||||
|
use the || { ... } closure form instead");
|
||||||
} else {
|
} else {
|
||||||
// This was an attempt to use a type parameter outside
|
// This was an attempt to use a type parameter outside
|
||||||
// its scope.
|
// its scope.
|
||||||
|
@ -3525,8 +3533,8 @@ impl Resolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
item_impl(ref generics,
|
item_impl(ref generics,
|
||||||
implemented_traits,
|
ref implemented_traits,
|
||||||
self_type,
|
ref self_type,
|
||||||
ref methods) => {
|
ref methods) => {
|
||||||
self.resolve_implementation(item.id,
|
self.resolve_implementation(item.id,
|
||||||
generics,
|
generics,
|
||||||
|
@ -3553,23 +3561,7 @@ impl Resolver {
|
||||||
|
|
||||||
// Resolve derived traits.
|
// Resolve derived traits.
|
||||||
for traits.iter().advance |trt| {
|
for traits.iter().advance |trt| {
|
||||||
match self.resolve_path(trt.path, TypeNS, true,
|
self.resolve_trait_reference(trt, visitor, TraitDerivation);
|
||||||
visitor) {
|
|
||||||
None =>
|
|
||||||
self.session.span_err(trt.path.span,
|
|
||||||
"attempt to derive a \
|
|
||||||
nonexistent trait"),
|
|
||||||
Some(def) => {
|
|
||||||
// Write a mapping from the trait ID to the
|
|
||||||
// definition of the trait into the definition
|
|
||||||
// map.
|
|
||||||
|
|
||||||
debug!("(resolving trait) found trait def: \
|
|
||||||
%?", def);
|
|
||||||
|
|
||||||
self.record_def(trt.ref_id, def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (*methods).iter().advance |method| {
|
for (*methods).iter().advance |method| {
|
||||||
|
@ -3593,10 +3585,10 @@ impl Resolver {
|
||||||
visitor);
|
visitor);
|
||||||
|
|
||||||
for ty_m.decl.inputs.iter().advance |argument| {
|
for ty_m.decl.inputs.iter().advance |argument| {
|
||||||
self.resolve_type(argument.ty, visitor);
|
self.resolve_type(&argument.ty, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.resolve_type(ty_m.decl.output, visitor);
|
self.resolve_type(&ty_m.decl.output, visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
provided(m) => {
|
provided(m) => {
|
||||||
|
@ -3786,12 +3778,12 @@ impl Resolver {
|
||||||
None,
|
None,
|
||||||
visitor);
|
visitor);
|
||||||
|
|
||||||
self.resolve_type(argument.ty, visitor);
|
self.resolve_type(&argument.ty, visitor);
|
||||||
|
|
||||||
debug!("(resolving function) recorded argument");
|
debug!("(resolving function) recorded argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.resolve_type(declaration.output, visitor);
|
self.resolve_type(&declaration.output, visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3819,8 +3811,8 @@ impl Resolver {
|
||||||
type_parameter_bound: &TyParamBound,
|
type_parameter_bound: &TyParamBound,
|
||||||
visitor: ResolveVisitor) {
|
visitor: ResolveVisitor) {
|
||||||
match *type_parameter_bound {
|
match *type_parameter_bound {
|
||||||
TraitTyParamBound(tref) => {
|
TraitTyParamBound(ref tref) => {
|
||||||
self.resolve_trait_reference(tref, visitor)
|
self.resolve_trait_reference(tref, visitor, TraitBoundingTypeParameter)
|
||||||
}
|
}
|
||||||
RegionTyParamBound => {}
|
RegionTyParamBound => {}
|
||||||
}
|
}
|
||||||
|
@ -3828,14 +3820,23 @@ impl Resolver {
|
||||||
|
|
||||||
pub fn resolve_trait_reference(@mut self,
|
pub fn resolve_trait_reference(@mut self,
|
||||||
trait_reference: &trait_ref,
|
trait_reference: &trait_ref,
|
||||||
visitor: ResolveVisitor) {
|
visitor: ResolveVisitor,
|
||||||
match self.resolve_path(trait_reference.path, TypeNS, true, visitor) {
|
reference_type: TraitReferenceType) {
|
||||||
|
match self.resolve_path(&trait_reference.path, TypeNS, true, visitor) {
|
||||||
None => {
|
None => {
|
||||||
self.session.span_err(trait_reference.path.span,
|
let path_str = self.idents_to_str(trait_reference.path.idents);
|
||||||
"attempt to implement an \
|
|
||||||
unknown trait");
|
let usage_str = match reference_type {
|
||||||
|
TraitBoundingTypeParameter => "bound type parameter with",
|
||||||
|
TraitImplementation => "implement",
|
||||||
|
TraitDerivation => "derive"
|
||||||
|
};
|
||||||
|
|
||||||
|
let msg = fmt!("attempt to %s a nonexistent trait `%s`", usage_str, path_str);
|
||||||
|
self.session.span_err(trait_reference.path.span, msg);
|
||||||
}
|
}
|
||||||
Some(def) => {
|
Some(def) => {
|
||||||
|
debug!("(resolving trait) found trait def: %?", def);
|
||||||
self.record_def(trait_reference.ref_id, def);
|
self.record_def(trait_reference.ref_id, def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3877,7 +3878,7 @@ impl Resolver {
|
||||||
|
|
||||||
// Resolve fields.
|
// Resolve fields.
|
||||||
for fields.iter().advance |field| {
|
for fields.iter().advance |field| {
|
||||||
self.resolve_type(field.node.ty, visitor);
|
self.resolve_type(&field.node.ty, visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3912,8 +3913,8 @@ impl Resolver {
|
||||||
pub fn resolve_implementation(@mut self,
|
pub fn resolve_implementation(@mut self,
|
||||||
id: node_id,
|
id: node_id,
|
||||||
generics: &Generics,
|
generics: &Generics,
|
||||||
opt_trait_reference: Option<@trait_ref>,
|
opt_trait_reference: &Option<trait_ref>,
|
||||||
self_type: @Ty,
|
self_type: &Ty,
|
||||||
methods: &[@method],
|
methods: &[@method],
|
||||||
visitor: ResolveVisitor) {
|
visitor: ResolveVisitor) {
|
||||||
// If applicable, create a rib for the type parameters.
|
// If applicable, create a rib for the type parameters.
|
||||||
|
@ -3928,8 +3929,8 @@ impl Resolver {
|
||||||
// Resolve the trait reference, if necessary.
|
// Resolve the trait reference, if necessary.
|
||||||
let original_trait_refs;
|
let original_trait_refs;
|
||||||
match opt_trait_reference {
|
match opt_trait_reference {
|
||||||
Some(trait_reference) => {
|
&Some(ref trait_reference) => {
|
||||||
self.resolve_trait_reference(trait_reference, visitor);
|
self.resolve_trait_reference(trait_reference, visitor, TraitImplementation);
|
||||||
|
|
||||||
// Record the current set of trait references.
|
// Record the current set of trait references.
|
||||||
let mut new_trait_refs = ~[];
|
let mut new_trait_refs = ~[];
|
||||||
|
@ -3943,7 +3944,7 @@ impl Resolver {
|
||||||
&mut self.current_trait_refs,
|
&mut self.current_trait_refs,
|
||||||
Some(new_trait_refs)));
|
Some(new_trait_refs)));
|
||||||
}
|
}
|
||||||
None => {
|
&None => {
|
||||||
original_trait_refs = None;
|
original_trait_refs = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4000,7 +4001,7 @@ impl Resolver {
|
||||||
let mutability = if local.node.is_mutbl {Mutable} else {Immutable};
|
let mutability = if local.node.is_mutbl {Mutable} else {Immutable};
|
||||||
|
|
||||||
// Resolve the type.
|
// Resolve the type.
|
||||||
self.resolve_type(local.node.ty, visitor);
|
self.resolve_type(&local.node.ty, visitor);
|
||||||
|
|
||||||
// Resolve the initializer, if necessary.
|
// Resolve the initializer, if necessary.
|
||||||
match local.node.init {
|
match local.node.init {
|
||||||
|
@ -4111,12 +4112,12 @@ impl Resolver {
|
||||||
debug!("(resolving block) leaving block");
|
debug!("(resolving block) leaving block");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_type(@mut self, ty: @Ty, visitor: ResolveVisitor) {
|
pub fn resolve_type(@mut self, ty: &Ty, visitor: ResolveVisitor) {
|
||||||
match ty.node {
|
match ty.node {
|
||||||
// Like path expressions, the interpretation of path types depends
|
// Like path expressions, the interpretation of path types depends
|
||||||
// on whether the path has multiple elements in it or not.
|
// on whether the path has multiple elements in it or not.
|
||||||
|
|
||||||
ty_path(path, bounds, path_id) => {
|
ty_path(ref path, ref bounds, path_id) => {
|
||||||
// This is a path in the type namespace. Walk through scopes
|
// This is a path in the type namespace. Walk through scopes
|
||||||
// scopes looking for it.
|
// scopes looking for it.
|
||||||
let mut result_def = None;
|
let mut result_def = None;
|
||||||
|
@ -4210,7 +4211,7 @@ impl Resolver {
|
||||||
let pat_id = pattern.id;
|
let pat_id = pattern.id;
|
||||||
for walk_pat(pattern) |pattern| {
|
for walk_pat(pattern) |pattern| {
|
||||||
match pattern.node {
|
match pattern.node {
|
||||||
pat_ident(binding_mode, path, _)
|
pat_ident(binding_mode, ref path, _)
|
||||||
if !path.global && path.idents.len() == 1 => {
|
if !path.global && path.idents.len() == 1 => {
|
||||||
|
|
||||||
// The meaning of pat_ident with no type parameters
|
// The meaning of pat_ident with no type parameters
|
||||||
|
@ -4333,11 +4334,11 @@ impl Resolver {
|
||||||
|
|
||||||
// Check the types in the path pattern.
|
// Check the types in the path pattern.
|
||||||
for path.types.iter().advance |ty| {
|
for path.types.iter().advance |ty| {
|
||||||
self.resolve_type(*ty, visitor);
|
self.resolve_type(ty, visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pat_ident(binding_mode, path, _) => {
|
pat_ident(binding_mode, ref path, _) => {
|
||||||
// This must be an enum variant, struct, or constant.
|
// This must be an enum variant, struct, or constant.
|
||||||
match self.resolve_path(path, ValueNS, false, visitor) {
|
match self.resolve_path(path, ValueNS, false, visitor) {
|
||||||
Some(def @ def_variant(*)) |
|
Some(def @ def_variant(*)) |
|
||||||
|
@ -4366,11 +4367,11 @@ impl Resolver {
|
||||||
|
|
||||||
// Check the types in the path pattern.
|
// Check the types in the path pattern.
|
||||||
for path.types.iter().advance |ty| {
|
for path.types.iter().advance |ty| {
|
||||||
self.resolve_type(*ty, visitor);
|
self.resolve_type(ty, visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pat_enum(path, _) => {
|
pat_enum(ref path, _) => {
|
||||||
// This must be an enum variant, struct or const.
|
// This must be an enum variant, struct or const.
|
||||||
match self.resolve_path(path, ValueNS, false, visitor) {
|
match self.resolve_path(path, ValueNS, false, visitor) {
|
||||||
Some(def @ def_fn(*)) |
|
Some(def @ def_fn(*)) |
|
||||||
|
@ -4395,7 +4396,7 @@ impl Resolver {
|
||||||
|
|
||||||
// Check the types in the path pattern.
|
// Check the types in the path pattern.
|
||||||
for path.types.iter().advance |ty| {
|
for path.types.iter().advance |ty| {
|
||||||
self.resolve_type(*ty, visitor);
|
self.resolve_type(ty, visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4408,7 +4409,7 @@ impl Resolver {
|
||||||
self.resolve_expr(last_expr, visitor);
|
self.resolve_expr(last_expr, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
pat_struct(path, _, _) => {
|
pat_struct(ref path, _, _) => {
|
||||||
match self.resolve_path(path, TypeNS, false, visitor) {
|
match self.resolve_path(path, TypeNS, false, visitor) {
|
||||||
Some(def_ty(class_id))
|
Some(def_ty(class_id))
|
||||||
if self.structs.contains(&class_id) => {
|
if self.structs.contains(&class_id) => {
|
||||||
|
@ -4483,14 +4484,14 @@ impl Resolver {
|
||||||
/// If `check_ribs` is true, checks the local definitions first; i.e.
|
/// If `check_ribs` is true, checks the local definitions first; i.e.
|
||||||
/// doesn't skip straight to the containing module.
|
/// doesn't skip straight to the containing module.
|
||||||
pub fn resolve_path(@mut self,
|
pub fn resolve_path(@mut self,
|
||||||
path: @Path,
|
path: &Path,
|
||||||
namespace: Namespace,
|
namespace: Namespace,
|
||||||
check_ribs: bool,
|
check_ribs: bool,
|
||||||
visitor: ResolveVisitor)
|
visitor: ResolveVisitor)
|
||||||
-> Option<def> {
|
-> Option<def> {
|
||||||
// First, resolve the types.
|
// First, resolve the types.
|
||||||
for path.types.iter().advance |ty| {
|
for path.types.iter().advance |ty| {
|
||||||
self.resolve_type(*ty, visitor);
|
self.resolve_type(ty, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if path.global {
|
if path.global {
|
||||||
|
@ -4609,7 +4610,7 @@ impl Resolver {
|
||||||
return NoNameDefinition;
|
return NoNameDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intern_module_part_of_path(@mut self, path: @Path) -> ~[ident] {
|
pub fn intern_module_part_of_path(@mut self, path: &Path) -> ~[ident] {
|
||||||
let mut module_path_idents = ~[];
|
let mut module_path_idents = ~[];
|
||||||
for path.idents.iter().enumerate().advance |(index, ident)| {
|
for path.idents.iter().enumerate().advance |(index, ident)| {
|
||||||
if index == path.idents.len() - 1 {
|
if index == path.idents.len() - 1 {
|
||||||
|
@ -4623,7 +4624,7 @@ impl Resolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_module_relative_path(@mut self,
|
pub fn resolve_module_relative_path(@mut self,
|
||||||
path: @Path,
|
path: &Path,
|
||||||
xray: XrayFlag,
|
xray: XrayFlag,
|
||||||
namespace: Namespace)
|
namespace: Namespace)
|
||||||
-> Option<def> {
|
-> Option<def> {
|
||||||
|
@ -4689,7 +4690,7 @@ impl Resolver {
|
||||||
/// Invariant: This must be called only during main resolution, not during
|
/// Invariant: This must be called only during main resolution, not during
|
||||||
/// import resolution.
|
/// import resolution.
|
||||||
pub fn resolve_crate_relative_path(@mut self,
|
pub fn resolve_crate_relative_path(@mut self,
|
||||||
path: @Path,
|
path: &Path,
|
||||||
xray: XrayFlag,
|
xray: XrayFlag,
|
||||||
namespace: Namespace)
|
namespace: Namespace)
|
||||||
-> Option<def> {
|
-> Option<def> {
|
||||||
|
@ -4915,7 +4916,7 @@ impl Resolver {
|
||||||
// The interpretation of paths depends on whether the path has
|
// The interpretation of paths depends on whether the path has
|
||||||
// multiple elements in it or not.
|
// multiple elements in it or not.
|
||||||
|
|
||||||
expr_path(path) => {
|
expr_path(ref path) => {
|
||||||
// This is a local path in the value namespace. Walk through
|
// This is a local path in the value namespace. Walk through
|
||||||
// scopes looking for it.
|
// scopes looking for it.
|
||||||
|
|
||||||
|
@ -4984,7 +4985,7 @@ impl Resolver {
|
||||||
visitor);
|
visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_struct(path, _, _) => {
|
expr_struct(ref path, _, _) => {
|
||||||
// Resolve the path to the structure it goes to.
|
// Resolve the path to the structure it goes to.
|
||||||
match self.resolve_path(path, TypeNS, false, visitor) {
|
match self.resolve_path(path, TypeNS, false, visitor) {
|
||||||
Some(def_ty(class_id)) | Some(def_struct(class_id))
|
Some(def_ty(class_id)) | Some(def_struct(class_id))
|
||||||
|
@ -5294,7 +5295,7 @@ impl Resolver {
|
||||||
visit_crate(self.crate, ((), vt));
|
visit_crate(self.crate, ((), vt));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_for_item_unused_imports(&mut self, vi: @view_item) {
|
pub fn check_for_item_unused_imports(&mut self, vi: &view_item) {
|
||||||
// Ignore public import statements because there's no way to be sure
|
// Ignore public import statements because there's no way to be sure
|
||||||
// whether they're used or not. Also ignore imports with a dummy span
|
// whether they're used or not. Also ignore imports with a dummy span
|
||||||
// because this means that they were generated in some fashion by the
|
// because this means that they were generated in some fashion by the
|
||||||
|
@ -5360,7 +5361,7 @@ impl Resolver {
|
||||||
if idents.len() == 0 {
|
if idents.len() == 0 {
|
||||||
return ~"???";
|
return ~"???";
|
||||||
}
|
}
|
||||||
return self.idents_to_str(vec::reversed(idents));
|
return self.idents_to_str(idents.consume_rev_iter().collect::<~[ast::ident]>());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump_module(@mut self, module_: @mut Module) {
|
pub fn dump_module(@mut self, module_: @mut Module) {
|
||||||
|
|
|
@ -385,7 +385,7 @@ pub fn expand_nested_bindings<'r>(bcx: block,
|
||||||
|
|
||||||
do m.map |br| {
|
do m.map |br| {
|
||||||
match br.pats[col].node {
|
match br.pats[col].node {
|
||||||
ast::pat_ident(_, path, Some(inner)) => {
|
ast::pat_ident(_, ref path, Some(inner)) => {
|
||||||
let pats = vec::append(
|
let pats = vec::append(
|
||||||
br.pats.slice(0u, col).to_owned(),
|
br.pats.slice(0u, col).to_owned(),
|
||||||
vec::append(~[inner],
|
vec::append(~[inner],
|
||||||
|
@ -441,7 +441,7 @@ pub fn enter_match<'r>(bcx: block,
|
||||||
|
|
||||||
let this = br.pats[col];
|
let this = br.pats[col];
|
||||||
match this.node {
|
match this.node {
|
||||||
ast::pat_ident(_, path, None) => {
|
ast::pat_ident(_, ref path, None) => {
|
||||||
if pat_is_binding(dm, this) {
|
if pat_is_binding(dm, this) {
|
||||||
let binding_info =
|
let binding_info =
|
||||||
br.data.bindings_map.get(
|
br.data.bindings_map.get(
|
||||||
|
@ -796,7 +796,7 @@ pub fn enter_region<'r>(bcx: block,
|
||||||
pub fn get_options(bcx: block, m: &[@Match], col: uint) -> ~[Opt] {
|
pub fn get_options(bcx: block, m: &[@Match], col: uint) -> ~[Opt] {
|
||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) {
|
fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) {
|
||||||
if set.iter().any_(|l| opt_eq(tcx, l, &val)) {return;}
|
if set.iter().any(|l| opt_eq(tcx, l, &val)) {return;}
|
||||||
set.push(val);
|
set.push(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,7 +963,7 @@ pub fn collect_record_or_struct_fields(bcx: block,
|
||||||
fn extend(idents: &mut ~[ast::ident], field_pats: &[ast::field_pat]) {
|
fn extend(idents: &mut ~[ast::ident], field_pats: &[ast::field_pat]) {
|
||||||
for field_pats.iter().advance |field_pat| {
|
for field_pats.iter().advance |field_pat| {
|
||||||
let field_ident = field_pat.ident;
|
let field_ident = field_pat.ident;
|
||||||
if !idents.iter().any_(|x| *x == field_ident) {
|
if !idents.iter().any(|x| *x == field_ident) {
|
||||||
idents.push(field_ident);
|
idents.push(field_ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -974,7 +974,7 @@ pub fn pats_require_rooting(bcx: block,
|
||||||
m: &[@Match],
|
m: &[@Match],
|
||||||
col: uint)
|
col: uint)
|
||||||
-> bool {
|
-> bool {
|
||||||
do m.iter().any_ |br| {
|
do m.iter().any |br| {
|
||||||
let pat_id = br.pats[col].id;
|
let pat_id = br.pats[col].id;
|
||||||
let key = root_map_key {id: pat_id, derefs: 0u };
|
let key = root_map_key {id: pat_id, derefs: 0u };
|
||||||
bcx.ccx().maps.root_map.contains_key(&key)
|
bcx.ccx().maps.root_map.contains_key(&key)
|
||||||
|
@ -1003,7 +1003,7 @@ pub fn root_pats_as_necessary(mut bcx: block,
|
||||||
// matches may be wildcards like _ or identifiers).
|
// matches may be wildcards like _ or identifiers).
|
||||||
macro_rules! any_pat (
|
macro_rules! any_pat (
|
||||||
($m:expr, $pattern:pat) => (
|
($m:expr, $pattern:pat) => (
|
||||||
do ($m).iter().any_ |br| {
|
do ($m).iter().any |br| {
|
||||||
match br.pats[col].node {
|
match br.pats[col].node {
|
||||||
$pattern => true,
|
$pattern => true,
|
||||||
_ => false
|
_ => false
|
||||||
|
@ -1029,7 +1029,7 @@ pub fn any_tup_pat(m: &[@Match], col: uint) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn any_tuple_struct_pat(bcx: block, m: &[@Match], col: uint) -> bool {
|
pub fn any_tuple_struct_pat(bcx: block, m: &[@Match], col: uint) -> bool {
|
||||||
do m.iter().any_ |br| {
|
do m.iter().any |br| {
|
||||||
let pat = br.pats[col];
|
let pat = br.pats[col];
|
||||||
match pat.node {
|
match pat.node {
|
||||||
ast::pat_enum(_, Some(_)) => {
|
ast::pat_enum(_, Some(_)) => {
|
||||||
|
@ -1095,26 +1095,20 @@ pub fn compare_values(cx: block,
|
||||||
|
|
||||||
match ty::get(rhs_t).sty {
|
match ty::get(rhs_t).sty {
|
||||||
ty::ty_estr(ty::vstore_uniq) => {
|
ty::ty_estr(ty::vstore_uniq) => {
|
||||||
let scratch_result = scratch_datum(cx, ty::mk_bool(), false);
|
|
||||||
let scratch_lhs = alloca(cx, val_ty(lhs));
|
let scratch_lhs = alloca(cx, val_ty(lhs));
|
||||||
Store(cx, lhs, scratch_lhs);
|
Store(cx, lhs, scratch_lhs);
|
||||||
let scratch_rhs = alloca(cx, val_ty(rhs));
|
let scratch_rhs = alloca(cx, val_ty(rhs));
|
||||||
Store(cx, rhs, scratch_rhs);
|
Store(cx, rhs, scratch_rhs);
|
||||||
let did = cx.tcx().lang_items.uniq_str_eq_fn();
|
let did = cx.tcx().lang_items.uniq_str_eq_fn();
|
||||||
let bcx = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs],
|
let result = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], None);
|
||||||
expr::SaveIn(scratch_result.val));
|
|
||||||
let result = scratch_result.to_result(bcx);
|
|
||||||
Result {
|
Result {
|
||||||
bcx: result.bcx,
|
bcx: result.bcx,
|
||||||
val: bool_to_i1(result.bcx, result.val)
|
val: bool_to_i1(result.bcx, result.val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::ty_estr(_) => {
|
ty::ty_estr(_) => {
|
||||||
let scratch_result = scratch_datum(cx, ty::mk_bool(), false);
|
|
||||||
let did = cx.tcx().lang_items.str_eq_fn();
|
let did = cx.tcx().lang_items.str_eq_fn();
|
||||||
let bcx = callee::trans_lang_call(cx, did, [lhs, rhs],
|
let result = callee::trans_lang_call(cx, did, [lhs, rhs], None);
|
||||||
expr::SaveIn(scratch_result.val));
|
|
||||||
let result = scratch_result.to_result(bcx);
|
|
||||||
Result {
|
Result {
|
||||||
bcx: result.bcx,
|
bcx: result.bcx,
|
||||||
val: bool_to_i1(result.bcx, result.val)
|
val: bool_to_i1(result.bcx, result.val)
|
||||||
|
@ -1395,8 +1389,12 @@ pub fn compile_submatch(bcx: block,
|
||||||
}
|
}
|
||||||
|
|
||||||
if any_uniq_pat(m, col) {
|
if any_uniq_pat(m, col) {
|
||||||
|
let pat_ty = node_id_type(bcx, pat_id);
|
||||||
let llbox = Load(bcx, val);
|
let llbox = Load(bcx, val);
|
||||||
let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
|
let unboxed = match ty::get(pat_ty).sty {
|
||||||
|
ty::ty_uniq(*) if !ty::type_contents(bcx.tcx(), pat_ty).contains_managed() => llbox,
|
||||||
|
_ => GEPi(bcx, llbox, [0u, abi::box_field_body])
|
||||||
|
};
|
||||||
compile_submatch(bcx, enter_uniq(bcx, dm, m, col, val),
|
compile_submatch(bcx, enter_uniq(bcx, dm, m, col, val),
|
||||||
vec::append(~[unboxed], vals_left), chk);
|
vec::append(~[unboxed], vals_left), chk);
|
||||||
return;
|
return;
|
||||||
|
@ -1868,8 +1866,12 @@ pub fn bind_irrefutable_pat(bcx: block,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::pat_box(inner) | ast::pat_uniq(inner) => {
|
ast::pat_box(inner) | ast::pat_uniq(inner) => {
|
||||||
|
let pat_ty = node_id_type(bcx, pat.id);
|
||||||
let llbox = Load(bcx, val);
|
let llbox = Load(bcx, val);
|
||||||
let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
|
let unboxed = match ty::get(pat_ty).sty {
|
||||||
|
ty::ty_uniq(*) if !ty::type_contents(bcx.tcx(), pat_ty).contains_managed() => llbox,
|
||||||
|
_ => GEPi(bcx, llbox, [0u, abi::box_field_body])
|
||||||
|
};
|
||||||
bcx = bind_irrefutable_pat(bcx,
|
bcx = bind_irrefutable_pat(bcx,
|
||||||
inner,
|
inner,
|
||||||
unboxed,
|
unboxed,
|
||||||
|
|
|
@ -131,13 +131,13 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
|
||||||
}
|
}
|
||||||
ty::ty_struct(def_id, ref substs) => {
|
ty::ty_struct(def_id, ref substs) => {
|
||||||
let fields = ty::lookup_struct_fields(cx.tcx, def_id);
|
let fields = ty::lookup_struct_fields(cx.tcx, def_id);
|
||||||
let ftys = do fields.map |field| {
|
let mut ftys = do fields.map |field| {
|
||||||
ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
|
ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
|
||||||
};
|
};
|
||||||
let packed = ty::lookup_packed(cx.tcx, def_id);
|
let packed = ty::lookup_packed(cx.tcx, def_id);
|
||||||
let dtor = ty::ty_dtor(cx.tcx, def_id).has_drop_flag();
|
let dtor = ty::ty_dtor(cx.tcx, def_id).has_drop_flag();
|
||||||
let ftys =
|
if dtor { ftys.push(ty::mk_bool()); }
|
||||||
if dtor { ftys + [ty::mk_bool()] } else { ftys };
|
|
||||||
return Univariant(mk_struct(cx, ftys, packed), dtor)
|
return Univariant(mk_struct(cx, ftys, packed), dtor)
|
||||||
}
|
}
|
||||||
ty::ty_enum(def_id, ref substs) => {
|
ty::ty_enum(def_id, ref substs) => {
|
||||||
|
@ -147,7 +147,7 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
|
||||||
mk_struct(cx, self.tys, false).size == 0
|
mk_struct(cx, self.tys, false).size == 0
|
||||||
}
|
}
|
||||||
fn find_ptr(&self) -> Option<uint> {
|
fn find_ptr(&self) -> Option<uint> {
|
||||||
self.tys.iter().position_(|&ty| mono_data_classify(ty) == MonoNonNull)
|
self.tys.iter().position(|&ty| mono_data_classify(ty) == MonoNonNull)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ fn generic_fields_of(cx: &mut CrateContext, r: &Repr, sizing: bool) -> ~[Type] {
|
||||||
let padding = largest_size - most_aligned.size;
|
let padding = largest_size - most_aligned.size;
|
||||||
|
|
||||||
struct_llfields(cx, most_aligned, sizing)
|
struct_llfields(cx, most_aligned, sizing)
|
||||||
+ [Type::array(&Type::i8(), padding)]
|
+ &[Type::array(&Type::i8(), padding)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -512,7 +512,7 @@ pub fn trans_const(ccx: &mut CrateContext, r: &Repr, discr: int,
|
||||||
let discr_ty = C_int(ccx, discr);
|
let discr_ty = C_int(ccx, discr);
|
||||||
let contents = build_const_struct(ccx, case,
|
let contents = build_const_struct(ccx, case,
|
||||||
~[discr_ty] + vals);
|
~[discr_ty] + vals);
|
||||||
C_struct(contents + [padding(max_sz - case.size)])
|
C_struct(contents + &[padding(max_sz - case.size)])
|
||||||
}
|
}
|
||||||
NullablePointer{ nonnull: ref nonnull, nndiscr, ptrfield, _ } => {
|
NullablePointer{ nonnull: ref nonnull, nndiscr, ptrfield, _ } => {
|
||||||
if discr == nndiscr {
|
if discr == nndiscr {
|
||||||
|
|
|
@ -72,6 +72,7 @@ use std::uint;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use std::local_data;
|
use std::local_data;
|
||||||
use extra::time;
|
use extra::time;
|
||||||
|
use extra::sort;
|
||||||
use syntax::ast::ident;
|
use syntax::ast::ident;
|
||||||
use syntax::ast_map::{path, path_elt_to_str, path_name};
|
use syntax::ast_map::{path, path_elt_to_str, path_name};
|
||||||
use syntax::ast_util::{local_def, path_to_ident};
|
use syntax::ast_util::{local_def, path_to_ident};
|
||||||
|
@ -141,6 +142,48 @@ fn fcx_has_nonzero_span(fcx: fn_ctxt) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StatRecorder<'self> {
|
||||||
|
ccx: @mut CrateContext,
|
||||||
|
name: &'self str,
|
||||||
|
start: u64,
|
||||||
|
istart: uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'self> StatRecorder<'self> {
|
||||||
|
pub fn new(ccx: @mut CrateContext,
|
||||||
|
name: &'self str) -> StatRecorder<'self> {
|
||||||
|
let start = if ccx.sess.trans_stats() {
|
||||||
|
time::precise_time_ns()
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
let istart = ccx.stats.n_llvm_insns;
|
||||||
|
StatRecorder {
|
||||||
|
ccx: ccx,
|
||||||
|
name: name,
|
||||||
|
start: start,
|
||||||
|
istart: istart,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe_destructor]
|
||||||
|
impl<'self> Drop for StatRecorder<'self> {
|
||||||
|
pub fn drop(&self) {
|
||||||
|
if self.ccx.sess.trans_stats() {
|
||||||
|
let end = time::precise_time_ns();
|
||||||
|
let elapsed = ((end - self.start) / 1_000_000) as uint;
|
||||||
|
let iend = self.ccx.stats.n_llvm_insns;
|
||||||
|
self.ccx.stats.fn_stats.push((self.name.to_owned(),
|
||||||
|
elapsed,
|
||||||
|
iend - self.istart));
|
||||||
|
self.ccx.stats.n_fns += 1;
|
||||||
|
// Reset LLVM insn count to avoid compound costs.
|
||||||
|
self.ccx.stats.n_llvm_insns = self.istart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
|
pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
|
||||||
let llfn: ValueRef = do name.as_c_str |buf| {
|
let llfn: ValueRef = do name.as_c_str |buf| {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -246,35 +289,48 @@ pub fn malloc_raw_dyn(bcx: block,
|
||||||
let _icx = push_ctxt("malloc_raw");
|
let _icx = push_ctxt("malloc_raw");
|
||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
|
|
||||||
let (mk_fn, langcall) = match heap {
|
|
||||||
heap_managed | heap_managed_unique => {
|
|
||||||
(ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn())
|
|
||||||
}
|
|
||||||
heap_exchange => {
|
|
||||||
(ty::mk_imm_uniq, bcx.tcx().lang_items.exchange_malloc_fn())
|
|
||||||
}
|
|
||||||
heap_exchange_closure => {
|
|
||||||
(ty::mk_imm_uniq, bcx.tcx().lang_items.closure_exchange_malloc_fn())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if heap == heap_exchange {
|
if heap == heap_exchange {
|
||||||
|
let llty_value = type_of::type_of(ccx, t);
|
||||||
|
let llalign = llalign_of_min(ccx, llty_value);
|
||||||
|
|
||||||
|
// Allocate space:
|
||||||
|
let r = callee::trans_lang_call(
|
||||||
|
bcx,
|
||||||
|
bcx.tcx().lang_items.exchange_malloc_fn(),
|
||||||
|
[C_i32(llalign as i32), size],
|
||||||
|
None);
|
||||||
|
rslt(r.bcx, PointerCast(r.bcx, r.val, llty_value.ptr_to()))
|
||||||
|
} else if heap == heap_exchange_vector {
|
||||||
// Grab the TypeRef type of box_ptr_ty.
|
// Grab the TypeRef type of box_ptr_ty.
|
||||||
let box_ptr_ty = mk_fn(bcx.tcx(), t);
|
let element_type = match ty::get(t).sty {
|
||||||
|
ty::ty_unboxed_vec(e) => e,
|
||||||
|
_ => fail!("not a vector body")
|
||||||
|
};
|
||||||
|
let box_ptr_ty = ty::mk_evec(bcx.tcx(), element_type, ty::vstore_uniq);
|
||||||
let llty = type_of(ccx, box_ptr_ty);
|
let llty = type_of(ccx, box_ptr_ty);
|
||||||
|
|
||||||
let llty_value = type_of::type_of(ccx, t);
|
let llty_value = type_of::type_of(ccx, t);
|
||||||
let llalign = llalign_of_min(ccx, llty_value);
|
let llalign = llalign_of_min(ccx, llty_value);
|
||||||
|
|
||||||
// Allocate space:
|
// Allocate space:
|
||||||
let rval = alloca(bcx, Type::i8p());
|
let r = callee::trans_lang_call(
|
||||||
let bcx = callee::trans_lang_call(
|
|
||||||
bcx,
|
bcx,
|
||||||
langcall,
|
bcx.tcx().lang_items.vector_exchange_malloc_fn(),
|
||||||
[C_i32(llalign as i32), size],
|
[C_i32(llalign as i32), size],
|
||||||
expr::SaveIn(rval));
|
None);
|
||||||
rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty))
|
rslt(r.bcx, PointerCast(r.bcx, r.val, llty))
|
||||||
} else {
|
} else {
|
||||||
|
// we treat ~fn, @fn and @[] as @ here, which isn't ideal
|
||||||
|
let (mk_fn, langcall) = match heap {
|
||||||
|
heap_managed | heap_managed_unique => {
|
||||||
|
(ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn())
|
||||||
|
}
|
||||||
|
heap_exchange_closure => {
|
||||||
|
(ty::mk_imm_box, bcx.tcx().lang_items.closure_exchange_malloc_fn())
|
||||||
|
}
|
||||||
|
_ => fail!("heap_exchange/heap_exchange_vector already handled")
|
||||||
|
};
|
||||||
|
|
||||||
// Grab the TypeRef type of box_ptr_ty.
|
// Grab the TypeRef type of box_ptr_ty.
|
||||||
let box_ptr_ty = mk_fn(bcx.tcx(), t);
|
let box_ptr_ty = mk_fn(bcx.tcx(), t);
|
||||||
let llty = type_of(ccx, box_ptr_ty);
|
let llty = type_of(ccx, box_ptr_ty);
|
||||||
|
@ -285,13 +341,12 @@ pub fn malloc_raw_dyn(bcx: block,
|
||||||
|
|
||||||
// Allocate space:
|
// Allocate space:
|
||||||
let tydesc = PointerCast(bcx, static_ti.tydesc, Type::i8p());
|
let tydesc = PointerCast(bcx, static_ti.tydesc, Type::i8p());
|
||||||
let rval = alloca(bcx, Type::i8p());
|
let r = callee::trans_lang_call(
|
||||||
let bcx = callee::trans_lang_call(
|
|
||||||
bcx,
|
bcx,
|
||||||
langcall,
|
langcall,
|
||||||
[tydesc, size],
|
[tydesc, size],
|
||||||
expr::SaveIn(rval));
|
None);
|
||||||
let r = rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty));
|
let r = rslt(r.bcx, PointerCast(r.bcx, r.val, llty));
|
||||||
maybe_set_managed_unique_rc(r.bcx, r.val, heap);
|
maybe_set_managed_unique_rc(r.bcx, r.val, heap);
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
@ -316,6 +371,7 @@ pub struct MallocResult {
|
||||||
// and pulls out the body
|
// and pulls out the body
|
||||||
pub fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef)
|
pub fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef)
|
||||||
-> MallocResult {
|
-> MallocResult {
|
||||||
|
assert!(heap != heap_exchange);
|
||||||
let _icx = push_ctxt("malloc_general");
|
let _icx = push_ctxt("malloc_general");
|
||||||
let Result {bcx: bcx, val: llbox} = malloc_raw_dyn(bcx, t, heap, size);
|
let Result {bcx: bcx, val: llbox} = malloc_raw_dyn(bcx, t, heap, size);
|
||||||
let body = GEPi(bcx, llbox, [0u, abi::box_field_body]);
|
let body = GEPi(bcx, llbox, [0u, abi::box_field_body]);
|
||||||
|
@ -323,9 +379,9 @@ pub fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef)
|
||||||
MallocResult { bcx: bcx, box: llbox, body: body }
|
MallocResult { bcx: bcx, box: llbox, body: body }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn malloc_general(bcx: block, t: ty::t, heap: heap)
|
pub fn malloc_general(bcx: block, t: ty::t, heap: heap) -> MallocResult {
|
||||||
-> MallocResult {
|
let ty = type_of(bcx.ccx(), t);
|
||||||
let ty = type_of(bcx.ccx(), t);
|
assert!(heap != heap_exchange);
|
||||||
malloc_general_dyn(bcx, t, heap, llsize_of(bcx.ccx(), ty))
|
malloc_general_dyn(bcx, t, heap, llsize_of(bcx.ccx(), ty))
|
||||||
}
|
}
|
||||||
pub fn malloc_boxed(bcx: block, t: ty::t)
|
pub fn malloc_boxed(bcx: block, t: ty::t)
|
||||||
|
@ -342,6 +398,7 @@ pub fn heap_for_unique(bcx: block, t: ty::t) -> heap {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maybe_set_managed_unique_rc(bcx: block, bx: ValueRef, heap: heap) {
|
pub fn maybe_set_managed_unique_rc(bcx: block, bx: ValueRef, heap: heap) {
|
||||||
|
assert!(heap != heap_exchange);
|
||||||
if heap == heap_managed_unique {
|
if heap == heap_managed_unique {
|
||||||
// In cases where we are looking at a unique-typed allocation in the
|
// In cases where we are looking at a unique-typed allocation in the
|
||||||
// managed heap (thus have refcount 1 from the managed allocator),
|
// managed heap (thus have refcount 1 from the managed allocator),
|
||||||
|
@ -353,11 +410,6 @@ pub fn maybe_set_managed_unique_rc(bcx: block, bx: ValueRef, heap: heap) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn malloc_unique(bcx: block, t: ty::t)
|
|
||||||
-> MallocResult {
|
|
||||||
malloc_general(bcx, t, heap_for_unique(bcx, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type descriptor and type glue stuff
|
// Type descriptor and type glue stuff
|
||||||
|
|
||||||
pub fn get_tydesc_simple(ccx: &mut CrateContext, t: ty::t) -> ValueRef {
|
pub fn get_tydesc_simple(ccx: &mut CrateContext, t: ty::t) -> ValueRef {
|
||||||
|
@ -863,10 +915,10 @@ pub fn need_invoke(bcx: block) -> bool {
|
||||||
|
|
||||||
// Walk the scopes to look for cleanups
|
// Walk the scopes to look for cleanups
|
||||||
let mut cur = bcx;
|
let mut cur = bcx;
|
||||||
|
let mut cur_scope = cur.scope;
|
||||||
loop {
|
loop {
|
||||||
match cur.kind {
|
cur_scope = match cur_scope {
|
||||||
block_scope(inf) => {
|
Some(inf) => {
|
||||||
let inf = &mut *inf; // FIXME(#5074) workaround old borrowck
|
|
||||||
for inf.cleanups.iter().advance |cleanup| {
|
for inf.cleanups.iter().advance |cleanup| {
|
||||||
match *cleanup {
|
match *cleanup {
|
||||||
clean(_, cleanup_type) | clean_temp(_, _, cleanup_type) => {
|
clean(_, cleanup_type) | clean_temp(_, _, cleanup_type) => {
|
||||||
|
@ -876,12 +928,15 @@ pub fn need_invoke(bcx: block) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inf.parent
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
cur = match cur.parent {
|
||||||
|
Some(next) => next,
|
||||||
|
None => return false
|
||||||
|
};
|
||||||
|
cur.scope
|
||||||
}
|
}
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
cur = match cur.parent {
|
|
||||||
Some(next) => next,
|
|
||||||
None => return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -899,23 +954,21 @@ pub fn have_cached_lpad(bcx: block) -> bool {
|
||||||
|
|
||||||
pub fn in_lpad_scope_cx(bcx: block, f: &fn(si: &mut scope_info)) {
|
pub fn in_lpad_scope_cx(bcx: block, f: &fn(si: &mut scope_info)) {
|
||||||
let mut bcx = bcx;
|
let mut bcx = bcx;
|
||||||
|
let mut cur_scope = bcx.scope;
|
||||||
loop {
|
loop {
|
||||||
{
|
cur_scope = match cur_scope {
|
||||||
match bcx.kind {
|
Some(inf) => {
|
||||||
block_scope(inf) => {
|
if !inf.empty_cleanups() || (inf.parent.is_none() && bcx.parent.is_none()) {
|
||||||
let len = { // FIXME(#5074) workaround old borrowck
|
f(inf);
|
||||||
let inf = &mut *inf;
|
return;
|
||||||
inf.cleanups.len()
|
|
||||||
};
|
|
||||||
if len > 0u || bcx.parent.is_none() {
|
|
||||||
f(inf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => ()
|
inf.parent
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
bcx = block_parent(bcx);
|
||||||
|
bcx.scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bcx = block_parent(bcx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -972,27 +1025,31 @@ pub fn get_landing_pad(bcx: block) -> BasicBlockRef {
|
||||||
|
|
||||||
pub fn find_bcx_for_scope(bcx: block, scope_id: ast::node_id) -> block {
|
pub fn find_bcx_for_scope(bcx: block, scope_id: ast::node_id) -> block {
|
||||||
let mut bcx_sid = bcx;
|
let mut bcx_sid = bcx;
|
||||||
|
let mut cur_scope = bcx_sid.scope;
|
||||||
loop {
|
loop {
|
||||||
bcx_sid = match bcx_sid.node_info {
|
cur_scope = match cur_scope {
|
||||||
Some(NodeInfo { id, _ }) if id == scope_id => {
|
Some(inf) => {
|
||||||
return bcx_sid
|
match inf.node_info {
|
||||||
}
|
Some(NodeInfo { id, _ }) if id == scope_id => {
|
||||||
|
return bcx_sid
|
||||||
// FIXME(#6268, #6248) hacky cleanup for nested method calls
|
|
||||||
Some(NodeInfo { callee_id: Some(id), _ }) if id == scope_id => {
|
|
||||||
return bcx_sid
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
match bcx_sid.parent {
|
|
||||||
None => bcx.tcx().sess.bug(
|
|
||||||
fmt!("no enclosing scope with id %d", scope_id)),
|
|
||||||
Some(bcx_par) => bcx_par
|
|
||||||
}
|
}
|
||||||
|
// FIXME(#6268, #6248) hacky cleanup for nested method calls
|
||||||
|
Some(NodeInfo { callee_id: Some(id), _ }) if id == scope_id => {
|
||||||
|
return bcx_sid
|
||||||
|
}
|
||||||
|
_ => inf.parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
None => {
|
||||||
|
bcx_sid = match bcx_sid.parent {
|
||||||
|
None => bcx.tcx().sess.bug(fmt!("no enclosing scope with id %d", scope_id)),
|
||||||
|
Some(bcx_par) => bcx_par
|
||||||
|
};
|
||||||
|
bcx_sid.scope
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn do_spill(bcx: block, v: ValueRef, t: ty::t) -> ValueRef {
|
pub fn do_spill(bcx: block, v: ValueRef, t: ty::t) -> ValueRef {
|
||||||
|
@ -1014,13 +1071,13 @@ pub fn do_spill_noroot(cx: block, v: ValueRef) -> ValueRef {
|
||||||
|
|
||||||
pub fn spill_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
|
pub fn spill_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
|
||||||
let _icx = push_ctxt("spill_if_immediate");
|
let _icx = push_ctxt("spill_if_immediate");
|
||||||
if ty::type_is_immediate(t) { return do_spill(cx, v, t); }
|
if ty::type_is_immediate(cx.tcx(), t) { return do_spill(cx, v, t); }
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
|
pub fn load_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
|
||||||
let _icx = push_ctxt("load_if_immediate");
|
let _icx = push_ctxt("load_if_immediate");
|
||||||
if ty::type_is_immediate(t) { return Load(cx, v); }
|
if ty::type_is_immediate(cx.tcx(), t) { return Load(cx, v); }
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1145,7 +1202,7 @@ pub fn trans_stmt(cx: block, s: &ast::stmt) -> block {
|
||||||
|
|
||||||
// You probably don't want to use this one. See the
|
// You probably don't want to use this one. See the
|
||||||
// next three functions instead.
|
// next three functions instead.
|
||||||
pub fn new_block(cx: fn_ctxt, parent: Option<block>, kind: block_kind,
|
pub fn new_block(cx: fn_ctxt, parent: Option<block>, scope: Option<@mut scope_info>,
|
||||||
is_lpad: bool, name: &str, opt_node_info: Option<NodeInfo>)
|
is_lpad: bool, name: &str, opt_node_info: Option<NodeInfo>)
|
||||||
-> block {
|
-> block {
|
||||||
|
|
||||||
|
@ -1155,10 +1212,10 @@ pub fn new_block(cx: fn_ctxt, parent: Option<block>, kind: block_kind,
|
||||||
};
|
};
|
||||||
let bcx = mk_block(llbb,
|
let bcx = mk_block(llbb,
|
||||||
parent,
|
parent,
|
||||||
kind,
|
|
||||||
is_lpad,
|
is_lpad,
|
||||||
opt_node_info,
|
opt_node_info,
|
||||||
cx);
|
cx);
|
||||||
|
bcx.scope = scope;
|
||||||
for parent.iter().advance |cx| {
|
for parent.iter().advance |cx| {
|
||||||
if cx.unreachable {
|
if cx.unreachable {
|
||||||
Unreachable(bcx);
|
Unreachable(bcx);
|
||||||
|
@ -1169,27 +1226,30 @@ pub fn new_block(cx: fn_ctxt, parent: Option<block>, kind: block_kind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn simple_block_scope() -> block_kind {
|
pub fn simple_block_scope(parent: Option<@mut scope_info>,
|
||||||
block_scope(@mut scope_info {
|
node_info: Option<NodeInfo>) -> @mut scope_info {
|
||||||
|
@mut scope_info {
|
||||||
|
parent: parent,
|
||||||
loop_break: None,
|
loop_break: None,
|
||||||
loop_label: None,
|
loop_label: None,
|
||||||
cleanups: ~[],
|
cleanups: ~[],
|
||||||
cleanup_paths: ~[],
|
cleanup_paths: ~[],
|
||||||
landing_pad: None
|
landing_pad: None,
|
||||||
})
|
node_info: node_info,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use this when you're at the top block of a function or the like.
|
// Use this when you're at the top block of a function or the like.
|
||||||
pub fn top_scope_block(fcx: fn_ctxt, opt_node_info: Option<NodeInfo>)
|
pub fn top_scope_block(fcx: fn_ctxt, opt_node_info: Option<NodeInfo>)
|
||||||
-> block {
|
-> block {
|
||||||
return new_block(fcx, None, simple_block_scope(), false,
|
return new_block(fcx, None, Some(simple_block_scope(None, opt_node_info)), false,
|
||||||
"function top level", opt_node_info);
|
"function top level", opt_node_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scope_block(bcx: block,
|
pub fn scope_block(bcx: block,
|
||||||
opt_node_info: Option<NodeInfo>,
|
opt_node_info: Option<NodeInfo>,
|
||||||
n: &str) -> block {
|
n: &str) -> block {
|
||||||
return new_block(bcx.fcx, Some(bcx), simple_block_scope(), bcx.is_lpad,
|
return new_block(bcx.fcx, Some(bcx), Some(simple_block_scope(None, opt_node_info)), bcx.is_lpad,
|
||||||
n, opt_node_info);
|
n, opt_node_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1198,27 +1258,29 @@ pub fn loop_scope_block(bcx: block,
|
||||||
loop_label: Option<ident>,
|
loop_label: Option<ident>,
|
||||||
n: &str,
|
n: &str,
|
||||||
opt_node_info: Option<NodeInfo>) -> block {
|
opt_node_info: Option<NodeInfo>) -> block {
|
||||||
return new_block(bcx.fcx, Some(bcx), block_scope(@mut scope_info {
|
return new_block(bcx.fcx, Some(bcx), Some(@mut scope_info {
|
||||||
|
parent: None,
|
||||||
loop_break: Some(loop_break),
|
loop_break: Some(loop_break),
|
||||||
loop_label: loop_label,
|
loop_label: loop_label,
|
||||||
cleanups: ~[],
|
cleanups: ~[],
|
||||||
cleanup_paths: ~[],
|
cleanup_paths: ~[],
|
||||||
landing_pad: None
|
landing_pad: None,
|
||||||
|
node_info: opt_node_info,
|
||||||
}), bcx.is_lpad, n, opt_node_info);
|
}), bcx.is_lpad, n, opt_node_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use this when creating a block for the inside of a landing pad.
|
// Use this when creating a block for the inside of a landing pad.
|
||||||
pub fn lpad_block(bcx: block, n: &str) -> block {
|
pub fn lpad_block(bcx: block, n: &str) -> block {
|
||||||
new_block(bcx.fcx, Some(bcx), block_non_scope, true, n, None)
|
new_block(bcx.fcx, Some(bcx), None, true, n, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use this when you're making a general CFG BB within a scope.
|
// Use this when you're making a general CFG BB within a scope.
|
||||||
pub fn sub_block(bcx: block, n: &str) -> block {
|
pub fn sub_block(bcx: block, n: &str) -> block {
|
||||||
new_block(bcx.fcx, Some(bcx), block_non_scope, bcx.is_lpad, n, None)
|
new_block(bcx.fcx, Some(bcx), None, bcx.is_lpad, n, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raw_block(fcx: fn_ctxt, is_lpad: bool, llbb: BasicBlockRef) -> block {
|
pub fn raw_block(fcx: fn_ctxt, is_lpad: bool, llbb: BasicBlockRef) -> block {
|
||||||
mk_block(llbb, None, block_non_scope, is_lpad, None, fcx)
|
mk_block(llbb, None, is_lpad, None, fcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1277,42 +1339,47 @@ pub fn cleanup_and_leave(bcx: block,
|
||||||
(fmt!("cleanup_and_leave(%s)", cur.to_str())).to_managed());
|
(fmt!("cleanup_and_leave(%s)", cur.to_str())).to_managed());
|
||||||
}
|
}
|
||||||
|
|
||||||
match cur.kind {
|
let mut cur_scope = cur.scope;
|
||||||
block_scope(inf) if !inf.empty_cleanups() => {
|
loop {
|
||||||
let (sub_cx, dest, inf_cleanups) = {
|
cur_scope = match cur_scope {
|
||||||
let inf = &mut *inf;
|
Some (inf) if !inf.empty_cleanups() => {
|
||||||
let mut skip = 0;
|
let (sub_cx, dest, inf_cleanups) = {
|
||||||
let mut dest = None;
|
let inf = &mut *inf;
|
||||||
{
|
let mut skip = 0;
|
||||||
let r = (*inf).cleanup_paths.rev_iter().find_(|cp| cp.target == leave);
|
let mut dest = None;
|
||||||
for r.iter().advance |cp| {
|
{
|
||||||
if cp.size == inf.cleanups.len() {
|
let r = (*inf).cleanup_paths.rev_iter().find_(|cp| cp.target == leave);
|
||||||
Br(bcx, cp.dest);
|
for r.iter().advance |cp| {
|
||||||
return;
|
if cp.size == inf.cleanups.len() {
|
||||||
}
|
Br(bcx, cp.dest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
skip = cp.size;
|
skip = cp.size;
|
||||||
dest = Some(cp.dest);
|
dest = Some(cp.dest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
let sub_cx = sub_block(bcx, "cleanup");
|
||||||
|
Br(bcx, sub_cx.llbb);
|
||||||
|
inf.cleanup_paths.push(cleanup_path {
|
||||||
|
target: leave,
|
||||||
|
size: inf.cleanups.len(),
|
||||||
|
dest: sub_cx.llbb
|
||||||
|
});
|
||||||
|
(sub_cx, dest, inf.cleanups.tailn(skip).to_owned())
|
||||||
|
};
|
||||||
|
bcx = trans_block_cleanups_(sub_cx,
|
||||||
|
inf_cleanups,
|
||||||
|
is_lpad);
|
||||||
|
for dest.iter().advance |&dest| {
|
||||||
|
Br(bcx, dest);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
let sub_cx = sub_block(bcx, "cleanup");
|
inf.parent
|
||||||
Br(bcx, sub_cx.llbb);
|
|
||||||
inf.cleanup_paths.push(cleanup_path {
|
|
||||||
target: leave,
|
|
||||||
size: inf.cleanups.len(),
|
|
||||||
dest: sub_cx.llbb
|
|
||||||
});
|
|
||||||
(sub_cx, dest, inf.cleanups.tailn(skip).to_owned())
|
|
||||||
};
|
|
||||||
bcx = trans_block_cleanups_(sub_cx,
|
|
||||||
inf_cleanups,
|
|
||||||
is_lpad);
|
|
||||||
for dest.iter().advance |&dest| {
|
|
||||||
Br(bcx, dest);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
Some(inf) => inf.parent,
|
||||||
|
None => break
|
||||||
}
|
}
|
||||||
_ => ()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match upto {
|
match upto {
|
||||||
|
@ -1353,9 +1420,12 @@ pub fn with_scope(bcx: block,
|
||||||
bcx.to_str(), opt_node_info, name);
|
bcx.to_str(), opt_node_info, name);
|
||||||
let _indenter = indenter();
|
let _indenter = indenter();
|
||||||
|
|
||||||
let scope_cx = scope_block(bcx, opt_node_info, name);
|
let scope = simple_block_scope(bcx.scope, opt_node_info);
|
||||||
Br(bcx, scope_cx.llbb);
|
bcx.scope = Some(scope);
|
||||||
leave_block(f(scope_cx), scope_cx)
|
let ret = f(bcx);
|
||||||
|
let ret = trans_block_cleanups_(ret, /*bad*/copy scope.cleanups, false);
|
||||||
|
bcx.scope = scope.parent;
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_scope_result(bcx: block,
|
pub fn with_scope_result(bcx: block,
|
||||||
|
@ -1363,10 +1433,14 @@ pub fn with_scope_result(bcx: block,
|
||||||
name: &str,
|
name: &str,
|
||||||
f: &fn(block) -> Result) -> Result {
|
f: &fn(block) -> Result) -> Result {
|
||||||
let _icx = push_ctxt("with_scope_result");
|
let _icx = push_ctxt("with_scope_result");
|
||||||
let scope_cx = scope_block(bcx, opt_node_info, name);
|
|
||||||
Br(bcx, scope_cx.llbb);
|
let scope = simple_block_scope(bcx.scope, opt_node_info);
|
||||||
let Result {bcx, val} = f(scope_cx);
|
bcx.scope = Some(scope);
|
||||||
rslt(leave_block(bcx, scope_cx), val)
|
let Result { bcx: out_bcx, val } = f(bcx);
|
||||||
|
let out_bcx = trans_block_cleanups_(out_bcx, /*bad*/copy scope.cleanups, false);
|
||||||
|
bcx.scope = scope.parent;
|
||||||
|
|
||||||
|
rslt(out_bcx, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_scope_datumblock(bcx: block, opt_node_info: Option<NodeInfo>,
|
pub fn with_scope_datumblock(bcx: block, opt_node_info: Option<NodeInfo>,
|
||||||
|
@ -1399,7 +1473,7 @@ pub fn alloc_local(cx: block, local: &ast::local) -> block {
|
||||||
let _icx = push_ctxt("alloc_local");
|
let _icx = push_ctxt("alloc_local");
|
||||||
let t = node_id_type(cx, local.node.id);
|
let t = node_id_type(cx, local.node.id);
|
||||||
let simple_name = match local.node.pat.node {
|
let simple_name = match local.node.pat.node {
|
||||||
ast::pat_ident(_, pth, None) => Some(path_to_ident(pth)),
|
ast::pat_ident(_, ref pth, None) => Some(path_to_ident(pth)),
|
||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
let val = alloc_ty(cx, t);
|
let val = alloc_ty(cx, t);
|
||||||
|
@ -1545,7 +1619,7 @@ pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
|
||||||
// slot where the return value of the function must go.
|
// slot where the return value of the function must go.
|
||||||
pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
|
pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
if !ty::type_is_immediate(output_type) {
|
if !ty::type_is_immediate(fcx.ccx.tcx, output_type) {
|
||||||
llvm::LLVMGetParam(fcx.llfn, 0)
|
llvm::LLVMGetParam(fcx.llfn, 0)
|
||||||
} else {
|
} else {
|
||||||
let lloutputtype = type_of::type_of(fcx.ccx, output_type);
|
let lloutputtype = type_of::type_of(fcx.ccx, output_type);
|
||||||
|
@ -1584,7 +1658,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
|
||||||
ty::subst_tps(ccx.tcx, substs.tys, substs.self_ty, output_type)
|
ty::subst_tps(ccx.tcx, substs.tys, substs.self_ty, output_type)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let is_immediate = ty::type_is_immediate(substd_output_type);
|
let is_immediate = ty::type_is_immediate(ccx.tcx, substd_output_type);
|
||||||
let fcx = @mut fn_ctxt_ {
|
let fcx = @mut fn_ctxt_ {
|
||||||
llfn: llfndecl,
|
llfn: llfndecl,
|
||||||
llenv: unsafe {
|
llenv: unsafe {
|
||||||
|
@ -1690,7 +1764,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
|
||||||
match fcx.llself {
|
match fcx.llself {
|
||||||
Some(slf) => {
|
Some(slf) => {
|
||||||
let self_val = if slf.is_copy
|
let self_val = if slf.is_copy
|
||||||
&& datum::appropriate_mode(slf.t).is_by_value() {
|
&& datum::appropriate_mode(bcx.tcx(), slf.t).is_by_value() {
|
||||||
let tmp = BitCast(bcx, slf.v, type_of(bcx.ccx(), slf.t));
|
let tmp = BitCast(bcx, slf.v, type_of(bcx.ccx(), slf.t));
|
||||||
let alloc = alloc_ty(bcx, slf.t);
|
let alloc = alloc_ty(bcx, slf.t);
|
||||||
Store(bcx, tmp, alloc);
|
Store(bcx, tmp, alloc);
|
||||||
|
@ -1718,7 +1792,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
|
||||||
// This alloca should be optimized away by LLVM's mem-to-reg pass in
|
// This alloca should be optimized away by LLVM's mem-to-reg pass in
|
||||||
// the event it's not truly needed.
|
// the event it's not truly needed.
|
||||||
// only by value if immediate:
|
// only by value if immediate:
|
||||||
let llarg = if datum::appropriate_mode(arg_ty).is_by_value() {
|
let llarg = if datum::appropriate_mode(bcx.tcx(), arg_ty).is_by_value() {
|
||||||
let alloc = alloc_ty(bcx, arg_ty);
|
let alloc = alloc_ty(bcx, arg_ty);
|
||||||
Store(bcx, raw_llarg, alloc);
|
Store(bcx, raw_llarg, alloc);
|
||||||
alloc
|
alloc
|
||||||
|
@ -1737,7 +1811,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
|
||||||
fcx.llargs.insert(arg_id, llarg);
|
fcx.llargs.insert(arg_id, llarg);
|
||||||
|
|
||||||
if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) {
|
if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) {
|
||||||
debuginfo::create_arg(bcx, args[arg_n], args[arg_n].ty.span);
|
debuginfo::create_arg(bcx, &args[arg_n], args[arg_n].ty.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1866,18 +1940,16 @@ pub fn trans_fn(ccx: @mut CrateContext,
|
||||||
param_substs: Option<@param_substs>,
|
param_substs: Option<@param_substs>,
|
||||||
id: ast::node_id,
|
id: ast::node_id,
|
||||||
attrs: &[ast::attribute]) {
|
attrs: &[ast::attribute]) {
|
||||||
let do_time = ccx.sess.trans_stats();
|
|
||||||
let start = if do_time { time::get_time() }
|
let the_path_str = path_str(ccx.sess, path);
|
||||||
else { time::Timespec::new(0, 0) };
|
let _s = StatRecorder::new(ccx, the_path_str);
|
||||||
debug!("trans_fn(self_arg=%?, param_substs=%s)",
|
debug!("trans_fn(self_arg=%?, param_substs=%s)",
|
||||||
self_arg,
|
self_arg,
|
||||||
param_substs.repr(ccx.tcx));
|
param_substs.repr(ccx.tcx));
|
||||||
let _icx = push_ctxt("trans_fn");
|
let _icx = push_ctxt("trans_fn");
|
||||||
ccx.stats.n_fns += 1;
|
|
||||||
let the_path_str = path_str(ccx.sess, path);
|
|
||||||
let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id));
|
let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id));
|
||||||
trans_closure(ccx,
|
trans_closure(ccx,
|
||||||
path,
|
copy path,
|
||||||
decl,
|
decl,
|
||||||
body,
|
body,
|
||||||
llfndecl,
|
llfndecl,
|
||||||
|
@ -1893,10 +1965,6 @@ pub fn trans_fn(ccx: @mut CrateContext,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|_bcx| { });
|
|_bcx| { });
|
||||||
if do_time {
|
|
||||||
let end = time::get_time();
|
|
||||||
ccx.log_fn_time(the_path_str, start, end);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_enum_variant(ccx: @mut CrateContext,
|
pub fn trans_enum_variant(ccx: @mut CrateContext,
|
||||||
|
@ -1911,7 +1979,7 @@ pub fn trans_enum_variant(ccx: @mut CrateContext,
|
||||||
let fn_args = do args.map |varg| {
|
let fn_args = do args.map |varg| {
|
||||||
ast::arg {
|
ast::arg {
|
||||||
is_mutbl: false,
|
is_mutbl: false,
|
||||||
ty: varg.ty,
|
ty: copy varg.ty,
|
||||||
pat: ast_util::ident_to_pat(
|
pat: ast_util::ident_to_pat(
|
||||||
ccx.tcx.sess.next_node_id(),
|
ccx.tcx.sess.next_node_id(),
|
||||||
codemap::dummy_sp(),
|
codemap::dummy_sp(),
|
||||||
|
@ -1985,7 +2053,7 @@ pub fn trans_tuple_struct(ccx: @mut CrateContext,
|
||||||
let fn_args = do fields.map |field| {
|
let fn_args = do fields.map |field| {
|
||||||
ast::arg {
|
ast::arg {
|
||||||
is_mutbl: false,
|
is_mutbl: false,
|
||||||
ty: field.node.ty,
|
ty: copy field.node.ty,
|
||||||
pat: ast_util::ident_to_pat(ccx.tcx.sess.next_node_id(),
|
pat: ast_util::ident_to_pat(ccx.tcx.sess.next_node_id(),
|
||||||
codemap::dummy_sp(),
|
codemap::dummy_sp(),
|
||||||
special_idents::arg),
|
special_idents::arg),
|
||||||
|
@ -2961,8 +3029,14 @@ pub fn trans_crate(sess: session::Session,
|
||||||
io::println(fmt!("n_monos: %u", ccx.stats.n_monos));
|
io::println(fmt!("n_monos: %u", ccx.stats.n_monos));
|
||||||
io::println(fmt!("n_inlines: %u", ccx.stats.n_inlines));
|
io::println(fmt!("n_inlines: %u", ccx.stats.n_inlines));
|
||||||
io::println(fmt!("n_closures: %u", ccx.stats.n_closures));
|
io::println(fmt!("n_closures: %u", ccx.stats.n_closures));
|
||||||
|
io::println("fn stats:");
|
||||||
|
do sort::quick_sort(ccx.stats.fn_stats) |&(_, _, insns_a), &(_, _, insns_b)| {
|
||||||
|
insns_a > insns_b
|
||||||
|
}
|
||||||
|
for ccx.stats.fn_stats.iter().advance |&(name, ms, insns)| {
|
||||||
|
io::println(fmt!("%u insns, %u ms, %s", insns, ms, name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ccx.sess.count_llvm_insns() {
|
if ccx.sess.count_llvm_insns() {
|
||||||
for ccx.stats.llvm_insns.iter().advance |(&k, &v)| {
|
for ccx.stats.llvm_insns.iter().advance |(&k, &v)| {
|
||||||
io::println(fmt!("%-7u %s", v, k));
|
io::println(fmt!("%-7u %s", v, k));
|
||||||
|
|
|
@ -46,6 +46,9 @@ pub fn B(cx: block) -> BuilderRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn count_insn(cx: block, category: &str) {
|
pub fn count_insn(cx: block, category: &str) {
|
||||||
|
if cx.ccx().sess.trans_stats() {
|
||||||
|
cx.ccx().stats.n_llvm_insns += 1;
|
||||||
|
}
|
||||||
do base::with_insn_ctxt |v| {
|
do base::with_insn_ctxt |v| {
|
||||||
let h = &mut cx.ccx().stats.llvm_insns;
|
let h = &mut cx.ccx().stats.llvm_insns;
|
||||||
|
|
||||||
|
@ -565,7 +568,7 @@ pub fn LoadRangeAssert(cx: block, PointerVal: ValueRef, lo: c_ulonglong,
|
||||||
let min = llvm::LLVMConstInt(t, lo, signed);
|
let min = llvm::LLVMConstInt(t, lo, signed);
|
||||||
let max = llvm::LLVMConstInt(t, hi, signed);
|
let max = llvm::LLVMConstInt(t, hi, signed);
|
||||||
|
|
||||||
do vec::as_imm_buf([min, max]) |ptr, len| {
|
do [min, max].as_imm_buf |ptr, len| {
|
||||||
llvm::LLVMSetMetadata(value, lib::llvm::MD_range as c_uint,
|
llvm::LLVMSetMetadata(value, lib::llvm::MD_range as c_uint,
|
||||||
llvm::LLVMMDNodeInContext(cx.fcx.ccx.llcx,
|
llvm::LLVMMDNodeInContext(cx.fcx.ccx.llcx,
|
||||||
ptr, len as c_uint));
|
ptr, len as c_uint));
|
||||||
|
@ -942,7 +945,7 @@ pub fn Call(cx: block, Fn: ValueRef, Args: &[ValueRef]) -> ValueRef {
|
||||||
cx.val_to_str(Fn),
|
cx.val_to_str(Fn),
|
||||||
Args.map(|arg| cx.val_to_str(*arg)));
|
Args.map(|arg| cx.val_to_str(*arg)));
|
||||||
|
|
||||||
do vec::as_imm_buf(Args) |ptr, len| {
|
do Args.as_imm_buf |ptr, len| {
|
||||||
llvm::LLVMBuildCall(B(cx), Fn, ptr, len as c_uint, noname())
|
llvm::LLVMBuildCall(B(cx), Fn, ptr, len as c_uint, noname())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,8 +446,8 @@ pub fn trans_call(in_cx: block,
|
||||||
node_id_type(in_cx, id),
|
node_id_type(in_cx, id),
|
||||||
|cx| trans(cx, f),
|
|cx| trans(cx, f),
|
||||||
args,
|
args,
|
||||||
dest,
|
Some(dest),
|
||||||
DontAutorefArg)
|
DontAutorefArg).bcx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_method_call(in_cx: block,
|
pub fn trans_method_call(in_cx: block,
|
||||||
|
@ -484,15 +484,15 @@ pub fn trans_method_call(in_cx: block,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
args,
|
args,
|
||||||
dest,
|
Some(dest),
|
||||||
DontAutorefArg)
|
DontAutorefArg).bcx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_lang_call(bcx: block,
|
pub fn trans_lang_call(bcx: block,
|
||||||
did: ast::def_id,
|
did: ast::def_id,
|
||||||
args: &[ValueRef],
|
args: &[ValueRef],
|
||||||
dest: expr::Dest)
|
dest: Option<expr::Dest>)
|
||||||
-> block {
|
-> Result {
|
||||||
let fty = if did.crate == ast::local_crate {
|
let fty = if did.crate == ast::local_crate {
|
||||||
ty::node_id_to_type(bcx.ccx().tcx, did.node)
|
ty::node_id_to_type(bcx.ccx().tcx, did.node)
|
||||||
} else {
|
} else {
|
||||||
|
@ -552,7 +552,7 @@ pub fn trans_lang_call_with_type_params(bcx: block,
|
||||||
}
|
}
|
||||||
Callee { bcx: callee.bcx, data: Fn(FnData { llfn: new_llval }) }
|
Callee { bcx: callee.bcx, data: Fn(FnData { llfn: new_llval }) }
|
||||||
},
|
},
|
||||||
ArgVals(args), dest, DontAutorefArg);
|
ArgVals(args), Some(dest), DontAutorefArg).bcx;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn body_contains_ret(body: &ast::blk) -> bool {
|
pub fn body_contains_ret(body: &ast::blk) -> bool {
|
||||||
|
@ -579,10 +579,10 @@ pub fn trans_call_inner(in_cx: block,
|
||||||
ret_ty: ty::t,
|
ret_ty: ty::t,
|
||||||
get_callee: &fn(block) -> Callee,
|
get_callee: &fn(block) -> Callee,
|
||||||
args: CallArgs,
|
args: CallArgs,
|
||||||
dest: expr::Dest,
|
dest: Option<expr::Dest>,
|
||||||
autoref_arg: AutorefArg)
|
autoref_arg: AutorefArg)
|
||||||
-> block {
|
-> Result {
|
||||||
do base::with_scope(in_cx, call_info, "call") |cx| {
|
do base::with_scope_result(in_cx, call_info, "call") |cx| {
|
||||||
let ret_in_loop = match args {
|
let ret_in_loop = match args {
|
||||||
ArgExprs(args) => {
|
ArgExprs(args) => {
|
||||||
args.len() > 0u && match args.last().node {
|
args.len() > 0u && match args.last().node {
|
||||||
|
@ -633,7 +633,7 @@ pub fn trans_call_inner(in_cx: block,
|
||||||
|
|
||||||
let mut llargs = ~[];
|
let mut llargs = ~[];
|
||||||
|
|
||||||
if !ty::type_is_immediate(ret_ty) {
|
if !ty::type_is_immediate(bcx.tcx(), ret_ty) {
|
||||||
llargs.push(llretslot);
|
llargs.push(llretslot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,18 +669,12 @@ pub fn trans_call_inner(in_cx: block,
|
||||||
bcx = new_bcx;
|
bcx = new_bcx;
|
||||||
|
|
||||||
match dest {
|
match dest {
|
||||||
expr::Ignore => {
|
None => { assert!(ty::type_is_immediate(bcx.tcx(), ret_ty)) }
|
||||||
|
Some(expr::Ignore) => {
|
||||||
// drop the value if it is not being saved.
|
// drop the value if it is not being saved.
|
||||||
unsafe {
|
unsafe {
|
||||||
if llvm::LLVMIsUndef(llretslot) != lib::llvm::True {
|
if ty::type_needs_drop(bcx.tcx(), ret_ty) {
|
||||||
if ty::type_is_nil(ret_ty) {
|
if ty::type_is_immediate(bcx.tcx(), ret_ty) {
|
||||||
// When implementing the for-loop sugar syntax, the
|
|
||||||
// type of the for-loop is nil, but the function
|
|
||||||
// it's invoking returns a bool. This is a special
|
|
||||||
// case to ignore instead of invoking the Store
|
|
||||||
// below into a scratch pointer of a mismatched
|
|
||||||
// type.
|
|
||||||
} else if ty::type_is_immediate(ret_ty) {
|
|
||||||
let llscratchptr = alloc_ty(bcx, ret_ty);
|
let llscratchptr = alloc_ty(bcx, ret_ty);
|
||||||
Store(bcx, llresult, llscratchptr);
|
Store(bcx, llresult, llscratchptr);
|
||||||
bcx = glue::drop_ty(bcx, llscratchptr, ret_ty);
|
bcx = glue::drop_ty(bcx, llscratchptr, ret_ty);
|
||||||
|
@ -690,11 +684,11 @@ pub fn trans_call_inner(in_cx: block,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr::SaveIn(lldest) => {
|
Some(expr::SaveIn(lldest)) => {
|
||||||
// If this is an immediate, store into the result location.
|
// If this is an immediate, store into the result location.
|
||||||
// (If this was not an immediate, the result will already be
|
// (If this was not an immediate, the result will already be
|
||||||
// directly written into the output slot.)
|
// directly written into the output slot.)
|
||||||
if ty::type_is_immediate(ret_ty) {
|
if ty::type_is_immediate(bcx.tcx(), ret_ty) {
|
||||||
Store(bcx, llresult, lldest);
|
Store(bcx, llresult, lldest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -717,7 +711,7 @@ pub fn trans_call_inner(in_cx: block,
|
||||||
bcx
|
bcx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bcx
|
rslt(bcx, llresult)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,14 +721,14 @@ pub enum CallArgs<'self> {
|
||||||
ArgVals(&'self [ValueRef])
|
ArgVals(&'self [ValueRef])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_ret_slot(bcx: block, fn_ty: ty::t, dest: expr::Dest)
|
pub fn trans_ret_slot(bcx: block, fn_ty: ty::t, dest: Option<expr::Dest>)
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
let retty = ty::ty_fn_ret(fn_ty);
|
let retty = ty::ty_fn_ret(fn_ty);
|
||||||
|
|
||||||
match dest {
|
match dest {
|
||||||
expr::SaveIn(dst) => dst,
|
Some(expr::SaveIn(dst)) => dst,
|
||||||
expr::Ignore => {
|
_ => {
|
||||||
if ty::type_is_nil(retty) {
|
if ty::type_is_immediate(bcx.tcx(), retty) {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref())
|
llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref())
|
||||||
}
|
}
|
||||||
|
@ -898,7 +892,7 @@ pub fn trans_arg_expr(bcx: block,
|
||||||
}
|
}
|
||||||
ty::ByCopy => {
|
ty::ByCopy => {
|
||||||
if ty::type_needs_drop(bcx.tcx(), arg_datum.ty) ||
|
if ty::type_needs_drop(bcx.tcx(), arg_datum.ty) ||
|
||||||
arg_datum.appropriate_mode().is_by_ref() {
|
arg_datum.appropriate_mode(bcx.tcx()).is_by_ref() {
|
||||||
debug!("by copy arg with type %s, storing to scratch",
|
debug!("by copy arg with type %s, storing to scratch",
|
||||||
bcx.ty_to_str(arg_datum.ty));
|
bcx.ty_to_str(arg_datum.ty));
|
||||||
let scratch = scratch_datum(bcx, arg_datum.ty, false);
|
let scratch = scratch_datum(bcx, arg_datum.ty, false);
|
||||||
|
@ -914,7 +908,7 @@ pub fn trans_arg_expr(bcx: block,
|
||||||
scratch.add_clean(bcx);
|
scratch.add_clean(bcx);
|
||||||
temp_cleanups.push(scratch.val);
|
temp_cleanups.push(scratch.val);
|
||||||
|
|
||||||
match scratch.appropriate_mode() {
|
match scratch.appropriate_mode(bcx.tcx()) {
|
||||||
ByValue => val = Load(bcx, scratch.val),
|
ByValue => val = Load(bcx, scratch.val),
|
||||||
ByRef(_) => val = scratch.val,
|
ByRef(_) => val = scratch.val,
|
||||||
}
|
}
|
||||||
|
|
|
@ -531,13 +531,13 @@ pub fn make_opaque_cbox_take_glue(
|
||||||
|
|
||||||
// Allocate memory, update original ptr, and copy existing data
|
// Allocate memory, update original ptr, and copy existing data
|
||||||
let opaque_tydesc = PointerCast(bcx, tydesc, Type::i8p());
|
let opaque_tydesc = PointerCast(bcx, tydesc, Type::i8p());
|
||||||
let rval = alloca(bcx, Type::i8p());
|
let mut bcx = bcx;
|
||||||
let bcx = callee::trans_lang_call(
|
let llresult = unpack_result!(bcx, callee::trans_lang_call(
|
||||||
bcx,
|
bcx,
|
||||||
bcx.tcx().lang_items.closure_exchange_malloc_fn(),
|
bcx.tcx().lang_items.closure_exchange_malloc_fn(),
|
||||||
[opaque_tydesc, sz],
|
[opaque_tydesc, sz],
|
||||||
expr::SaveIn(rval));
|
None));
|
||||||
let cbox_out = PointerCast(bcx, Load(bcx, rval), llopaquecboxty);
|
let cbox_out = PointerCast(bcx, llresult, llopaquecboxty);
|
||||||
call_memcpy(bcx, cbox_out, cbox_in, sz, 1);
|
call_memcpy(bcx, cbox_out, cbox_in, sz, 1);
|
||||||
Store(bcx, cbox_out, cboxptr);
|
Store(bcx, cbox_out, cboxptr);
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,6 @@ use std::cast::transmute;
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::hashmap::{HashMap};
|
use std::hashmap::{HashMap};
|
||||||
use std::libc::{c_uint, c_longlong, c_ulonglong};
|
use std::libc::{c_uint, c_longlong, c_ulonglong};
|
||||||
use std::to_bytes;
|
|
||||||
use std::str;
|
|
||||||
use std::vec::raw::to_ptr;
|
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use syntax::ast::ident;
|
use syntax::ast::ident;
|
||||||
use syntax::ast_map::{path, path_elt};
|
use syntax::ast_map::{path, path_elt};
|
||||||
|
@ -96,8 +93,10 @@ pub struct Stats {
|
||||||
n_monos: uint,
|
n_monos: uint,
|
||||||
n_inlines: uint,
|
n_inlines: uint,
|
||||||
n_closures: uint,
|
n_closures: uint,
|
||||||
|
n_llvm_insns: uint,
|
||||||
|
llvm_insn_ctxt: ~[~str],
|
||||||
llvm_insns: HashMap<~str, uint>,
|
llvm_insns: HashMap<~str, uint>,
|
||||||
fn_times: ~[(~str, int)] // (ident, time)
|
fn_stats: ~[(~str, uint, uint)] // (ident, time-in-ms, llvm-instructions)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BuilderRef_res {
|
pub struct BuilderRef_res {
|
||||||
|
@ -275,6 +274,7 @@ pub enum heap {
|
||||||
heap_managed,
|
heap_managed,
|
||||||
heap_managed_unique,
|
heap_managed_unique,
|
||||||
heap_exchange,
|
heap_exchange,
|
||||||
|
heap_exchange_vector,
|
||||||
heap_exchange_closure
|
heap_exchange_closure
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +321,7 @@ pub fn add_clean(bcx: block, val: ValueRef, t: ty::t) {
|
||||||
debug!("add_clean(%s, %s, %s)", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx()));
|
debug!("add_clean(%s, %s, %s)", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx()));
|
||||||
|
|
||||||
let cleanup_type = cleanup_type(bcx.tcx(), t);
|
let cleanup_type = cleanup_type(bcx.tcx(), t);
|
||||||
do in_scope_cx(bcx) |scope_info| {
|
do in_scope_cx(bcx, None) |scope_info| {
|
||||||
scope_info.cleanups.push(clean(|a| glue::drop_ty(a, val, t), cleanup_type));
|
scope_info.cleanups.push(clean(|a| glue::drop_ty(a, val, t), cleanup_type));
|
||||||
grow_scope_clean(scope_info);
|
grow_scope_clean(scope_info);
|
||||||
}
|
}
|
||||||
|
@ -333,25 +333,36 @@ pub fn add_clean_temp_immediate(cx: block, val: ValueRef, ty: ty::t) {
|
||||||
cx.to_str(), cx.val_to_str(val),
|
cx.to_str(), cx.val_to_str(val),
|
||||||
ty.repr(cx.tcx()));
|
ty.repr(cx.tcx()));
|
||||||
let cleanup_type = cleanup_type(cx.tcx(), ty);
|
let cleanup_type = cleanup_type(cx.tcx(), ty);
|
||||||
do in_scope_cx(cx) |scope_info| {
|
do in_scope_cx(cx, None) |scope_info| {
|
||||||
scope_info.cleanups.push(
|
scope_info.cleanups.push(
|
||||||
clean_temp(val, |a| glue::drop_ty_immediate(a, val, ty),
|
clean_temp(val, |a| glue::drop_ty_immediate(a, val, ty),
|
||||||
cleanup_type));
|
cleanup_type));
|
||||||
grow_scope_clean(scope_info);
|
grow_scope_clean(scope_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) {
|
pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) {
|
||||||
|
add_clean_temp_mem_in_scope_(bcx, None, val, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_clean_temp_mem_in_scope(bcx: block, scope_id: ast::node_id, val: ValueRef, t: ty::t) {
|
||||||
|
add_clean_temp_mem_in_scope_(bcx, Some(scope_id), val, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_clean_temp_mem_in_scope_(bcx: block, scope_id: Option<ast::node_id>,
|
||||||
|
val: ValueRef, t: ty::t) {
|
||||||
if !ty::type_needs_drop(bcx.tcx(), t) { return; }
|
if !ty::type_needs_drop(bcx.tcx(), t) { return; }
|
||||||
debug!("add_clean_temp_mem(%s, %s, %s)",
|
debug!("add_clean_temp_mem(%s, %s, %s)",
|
||||||
bcx.to_str(), bcx.val_to_str(val),
|
bcx.to_str(), bcx.val_to_str(val),
|
||||||
t.repr(bcx.tcx()));
|
t.repr(bcx.tcx()));
|
||||||
let cleanup_type = cleanup_type(bcx.tcx(), t);
|
let cleanup_type = cleanup_type(bcx.tcx(), t);
|
||||||
do in_scope_cx(bcx) |scope_info| {
|
do in_scope_cx(bcx, scope_id) |scope_info| {
|
||||||
scope_info.cleanups.push(clean_temp(val, |a| glue::drop_ty(a, val, t), cleanup_type));
|
scope_info.cleanups.push(clean_temp(val, |a| glue::drop_ty(a, val, t), cleanup_type));
|
||||||
grow_scope_clean(scope_info);
|
grow_scope_clean(scope_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn add_clean_return_to_mut(bcx: block,
|
pub fn add_clean_return_to_mut(bcx: block,
|
||||||
|
scope_id: ast::node_id,
|
||||||
root_key: root_map_key,
|
root_key: root_map_key,
|
||||||
frozen_val_ref: ValueRef,
|
frozen_val_ref: ValueRef,
|
||||||
bits_val_ref: ValueRef,
|
bits_val_ref: ValueRef,
|
||||||
|
@ -369,7 +380,7 @@ pub fn add_clean_return_to_mut(bcx: block,
|
||||||
bcx.to_str(),
|
bcx.to_str(),
|
||||||
bcx.val_to_str(frozen_val_ref),
|
bcx.val_to_str(frozen_val_ref),
|
||||||
bcx.val_to_str(bits_val_ref));
|
bcx.val_to_str(bits_val_ref));
|
||||||
do in_scope_cx(bcx) |scope_info| {
|
do in_scope_cx(bcx, Some(scope_id)) |scope_info| {
|
||||||
scope_info.cleanups.push(
|
scope_info.cleanups.push(
|
||||||
clean_temp(
|
clean_temp(
|
||||||
frozen_val_ref,
|
frozen_val_ref,
|
||||||
|
@ -385,12 +396,12 @@ pub fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) {
|
||||||
let f: @fn(block) -> block = |a| glue::trans_free(a, ptr);
|
let f: @fn(block) -> block = |a| glue::trans_free(a, ptr);
|
||||||
f
|
f
|
||||||
}
|
}
|
||||||
heap_exchange | heap_exchange_closure => {
|
heap_exchange | heap_exchange_vector | heap_exchange_closure => {
|
||||||
let f: @fn(block) -> block = |a| glue::trans_exchange_free(a, ptr);
|
let f: @fn(block) -> block = |a| glue::trans_exchange_free(a, ptr);
|
||||||
f
|
f
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
do in_scope_cx(cx) |scope_info| {
|
do in_scope_cx(cx, None) |scope_info| {
|
||||||
scope_info.cleanups.push(clean_temp(ptr, free_fn,
|
scope_info.cleanups.push(clean_temp(ptr, free_fn,
|
||||||
normal_exit_and_unwind));
|
normal_exit_and_unwind));
|
||||||
grow_scope_clean(scope_info);
|
grow_scope_clean(scope_info);
|
||||||
|
@ -402,8 +413,8 @@ pub fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) {
|
||||||
// this will be more involved. For now, we simply zero out the local, and the
|
// this will be more involved. For now, we simply zero out the local, and the
|
||||||
// drop glue checks whether it is zero.
|
// drop glue checks whether it is zero.
|
||||||
pub fn revoke_clean(cx: block, val: ValueRef) {
|
pub fn revoke_clean(cx: block, val: ValueRef) {
|
||||||
do in_scope_cx(cx) |scope_info| {
|
do in_scope_cx(cx, None) |scope_info| {
|
||||||
let cleanup_pos = scope_info.cleanups.iter().position_(
|
let cleanup_pos = scope_info.cleanups.iter().position(
|
||||||
|cu| match *cu {
|
|cu| match *cu {
|
||||||
clean_temp(v, _, _) if v == val => true,
|
clean_temp(v, _, _) if v == val => true,
|
||||||
_ => false
|
_ => false
|
||||||
|
@ -419,27 +430,14 @@ pub fn revoke_clean(cx: block, val: ValueRef) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block_cleanups(bcx: block) -> ~[cleanup] {
|
pub fn block_cleanups(bcx: block) -> ~[cleanup] {
|
||||||
match bcx.kind {
|
match bcx.scope {
|
||||||
block_non_scope => ~[],
|
None => ~[],
|
||||||
block_scope(inf) => /*bad*/copy inf.cleanups
|
Some(inf) => /*bad*/copy inf.cleanups
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum block_kind {
|
|
||||||
// A scope at the end of which temporary values created inside of it are
|
|
||||||
// cleaned up. May correspond to an actual block in the language, but also
|
|
||||||
// to an implicit scope, for example, calls introduce an implicit scope in
|
|
||||||
// which the arguments are evaluated and cleaned up.
|
|
||||||
block_scope(@mut scope_info),
|
|
||||||
|
|
||||||
// A non-scope block is a basic block created as a translation artifact
|
|
||||||
// from translating code that expresses conditional logic rather than by
|
|
||||||
// explicit { ... } block structure in the source language. It's called a
|
|
||||||
// non-scope block because it doesn't introduce a new variable scope.
|
|
||||||
block_non_scope,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct scope_info {
|
pub struct scope_info {
|
||||||
|
parent: Option<@mut scope_info>,
|
||||||
loop_break: Option<block>,
|
loop_break: Option<block>,
|
||||||
loop_label: Option<ident>,
|
loop_label: Option<ident>,
|
||||||
// A list of functions that must be run at when leaving this
|
// A list of functions that must be run at when leaving this
|
||||||
|
@ -451,6 +449,8 @@ pub struct scope_info {
|
||||||
cleanup_paths: ~[cleanup_path],
|
cleanup_paths: ~[cleanup_path],
|
||||||
// Unwinding landing pad. Also cleared when cleanups change.
|
// Unwinding landing pad. Also cleared when cleanups change.
|
||||||
landing_pad: Option<BasicBlockRef>,
|
landing_pad: Option<BasicBlockRef>,
|
||||||
|
// info about the AST node this scope originated from, if any
|
||||||
|
node_info: Option<NodeInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl scope_info {
|
impl scope_info {
|
||||||
|
@ -506,8 +506,8 @@ pub struct block_ {
|
||||||
terminated: bool,
|
terminated: bool,
|
||||||
unreachable: bool,
|
unreachable: bool,
|
||||||
parent: Option<block>,
|
parent: Option<block>,
|
||||||
// The 'kind' of basic block this is.
|
// The current scope within this basic block
|
||||||
kind: block_kind,
|
scope: Option<@mut scope_info>,
|
||||||
// Is this block part of a landing pad?
|
// Is this block part of a landing pad?
|
||||||
is_lpad: bool,
|
is_lpad: bool,
|
||||||
// info about the AST node this block originated from, if any
|
// info about the AST node this block originated from, if any
|
||||||
|
@ -517,7 +517,7 @@ pub struct block_ {
|
||||||
fcx: fn_ctxt
|
fcx: fn_ctxt
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block_(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
|
pub fn block_(llbb: BasicBlockRef, parent: Option<block>,
|
||||||
is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
|
is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
|
||||||
-> block_ {
|
-> block_ {
|
||||||
|
|
||||||
|
@ -526,7 +526,7 @@ pub fn block_(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
|
||||||
terminated: false,
|
terminated: false,
|
||||||
unreachable: false,
|
unreachable: false,
|
||||||
parent: parent,
|
parent: parent,
|
||||||
kind: kind,
|
scope: None,
|
||||||
is_lpad: is_lpad,
|
is_lpad: is_lpad,
|
||||||
node_info: node_info,
|
node_info: node_info,
|
||||||
fcx: fcx
|
fcx: fcx
|
||||||
|
@ -535,10 +535,10 @@ pub fn block_(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
|
||||||
|
|
||||||
pub type block = @mut block_;
|
pub type block = @mut block_;
|
||||||
|
|
||||||
pub fn mk_block(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
|
pub fn mk_block(llbb: BasicBlockRef, parent: Option<block>,
|
||||||
is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
|
is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
|
||||||
-> block {
|
-> block {
|
||||||
@mut block_(llbb, parent, kind, is_lpad, node_info, fcx)
|
@mut block_(llbb, parent, is_lpad, node_info, fcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Result {
|
pub struct Result {
|
||||||
|
@ -563,19 +563,33 @@ pub fn val_ty(v: ValueRef) -> Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn in_scope_cx(cx: block, f: &fn(si: &mut scope_info)) {
|
pub fn in_scope_cx(cx: block, scope_id: Option<ast::node_id>, f: &fn(si: &mut scope_info)) {
|
||||||
let mut cur = cx;
|
let mut cur = cx;
|
||||||
|
let mut cur_scope = cur.scope;
|
||||||
loop {
|
loop {
|
||||||
match cur.kind {
|
cur_scope = match cur_scope {
|
||||||
block_scope(inf) => {
|
Some(inf) => match scope_id {
|
||||||
debug!("in_scope_cx: selected cur=%s (cx=%s)",
|
Some(wanted) => match inf.node_info {
|
||||||
cur.to_str(), cx.to_str());
|
Some(NodeInfo { id: actual, _ }) if wanted == actual => {
|
||||||
f(inf);
|
debug!("in_scope_cx: selected cur=%s (cx=%s)",
|
||||||
return;
|
cur.to_str(), cx.to_str());
|
||||||
|
f(inf);
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
_ => inf.parent,
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
debug!("in_scope_cx: selected cur=%s (cx=%s)",
|
||||||
|
cur.to_str(), cx.to_str());
|
||||||
|
f(inf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
cur = block_parent(cur);
|
||||||
|
cur.scope
|
||||||
}
|
}
|
||||||
_ => ()
|
|
||||||
}
|
}
|
||||||
cur = block_parent(cur);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,7 +788,7 @@ pub fn C_zero_byte_arr(size: uint) -> ValueRef {
|
||||||
|
|
||||||
pub fn C_struct(elts: &[ValueRef]) -> ValueRef {
|
pub fn C_struct(elts: &[ValueRef]) -> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
do vec::as_imm_buf(elts) |ptr, len| {
|
do elts.as_imm_buf |ptr, len| {
|
||||||
llvm::LLVMConstStructInContext(base::task_llcx(), ptr, len as c_uint, False)
|
llvm::LLVMConstStructInContext(base::task_llcx(), ptr, len as c_uint, False)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -782,7 +796,7 @@ pub fn C_struct(elts: &[ValueRef]) -> ValueRef {
|
||||||
|
|
||||||
pub fn C_packed_struct(elts: &[ValueRef]) -> ValueRef {
|
pub fn C_packed_struct(elts: &[ValueRef]) -> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
do vec::as_imm_buf(elts) |ptr, len| {
|
do elts.as_imm_buf |ptr, len| {
|
||||||
llvm::LLVMConstStructInContext(base::task_llcx(), ptr, len as c_uint, True)
|
llvm::LLVMConstStructInContext(base::task_llcx(), ptr, len as c_uint, True)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -790,7 +804,7 @@ pub fn C_packed_struct(elts: &[ValueRef]) -> ValueRef {
|
||||||
|
|
||||||
pub fn C_named_struct(T: Type, elts: &[ValueRef]) -> ValueRef {
|
pub fn C_named_struct(T: Type, elts: &[ValueRef]) -> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
do vec::as_imm_buf(elts) |ptr, len| {
|
do elts.as_imm_buf |ptr, len| {
|
||||||
llvm::LLVMConstNamedStruct(T.to_ref(), ptr, len as c_uint)
|
llvm::LLVMConstNamedStruct(T.to_ref(), ptr, len as c_uint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -826,7 +840,7 @@ pub fn get_param(fndecl: ValueRef, param: uint) -> ValueRef {
|
||||||
pub fn const_get_elt(cx: &CrateContext, v: ValueRef, us: &[c_uint])
|
pub fn const_get_elt(cx: &CrateContext, v: ValueRef, us: &[c_uint])
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
let r = do vec::as_imm_buf(us) |p, len| {
|
let r = do us.as_imm_buf |p, len| {
|
||||||
llvm::LLVMConstExtractValue(v, p, len as c_uint)
|
llvm::LLVMConstExtractValue(v, p, len as c_uint)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ pub fn const_vec(cx: @mut CrateContext, e: &ast::expr, es: &[@ast::expr])
|
||||||
let sz = llvm::LLVMConstMul(C_uint(cx, es.len()), unit_sz);
|
let sz = llvm::LLVMConstMul(C_uint(cx, es.len()), unit_sz);
|
||||||
let vs = es.map(|e| const_expr(cx, *e));
|
let vs = es.map(|e| const_expr(cx, *e));
|
||||||
// If the vector contains enums, an LLVM array won't work.
|
// If the vector contains enums, an LLVM array won't work.
|
||||||
let v = if vs.iter().any_(|vi| val_ty(*vi) != llunitty) {
|
let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
|
||||||
C_struct(vs)
|
C_struct(vs)
|
||||||
} else {
|
} else {
|
||||||
C_array(llunitty, vs)
|
C_array(llunitty, vs)
|
||||||
|
@ -525,7 +525,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::expr) -> ValueRef {
|
||||||
_ => cx.sess.span_bug(e.span, "bad const-slice expr")
|
_ => cx.sess.span_bug(e.span, "bad const-slice expr")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::expr_path(pth) => {
|
ast::expr_path(ref pth) => {
|
||||||
assert_eq!(pth.types.len(), 0);
|
assert_eq!(pth.types.len(), 0);
|
||||||
let tcx = cx.tcx;
|
let tcx = cx.tcx;
|
||||||
match tcx.def_map.find(&e.id) {
|
match tcx.def_map.find(&e.id) {
|
||||||
|
|
|
@ -210,8 +210,10 @@ impl CrateContext {
|
||||||
n_monos: 0u,
|
n_monos: 0u,
|
||||||
n_inlines: 0u,
|
n_inlines: 0u,
|
||||||
n_closures: 0u,
|
n_closures: 0u,
|
||||||
|
n_llvm_insns: 0u,
|
||||||
|
llvm_insn_ctxt: ~[],
|
||||||
llvm_insns: HashMap::new(),
|
llvm_insns: HashMap::new(),
|
||||||
fn_times: ~[]
|
fn_stats: ~[]
|
||||||
},
|
},
|
||||||
upcalls: upcall::declare_upcalls(targ_cfg, llmod),
|
upcalls: upcall::declare_upcalls(targ_cfg, llmod),
|
||||||
tydesc_type: tydesc_type,
|
tydesc_type: tydesc_type,
|
||||||
|
@ -226,12 +228,6 @@ impl CrateContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log_fn_time(&mut self, name: ~str, start: time::Timespec, end: time::Timespec) {
|
|
||||||
let elapsed = 1000 * ((end.sec - start.sec) as int) +
|
|
||||||
((end.nsec as int) - (start.nsec as int)) / 1000000;
|
|
||||||
self.stats.fn_times.push((name, elapsed));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
|
|
|
@ -26,7 +26,6 @@ use util::ppaux;
|
||||||
use middle::trans::type_::Type;
|
use middle::trans::type_::Type;
|
||||||
|
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::vec;
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ast::ident;
|
use syntax::ast::ident;
|
||||||
use syntax::ast_map::path_mod;
|
use syntax::ast_map::path_mod;
|
||||||
|
@ -190,9 +189,13 @@ pub fn trans_log(log_ex: &ast::expr,
|
||||||
|
|
||||||
let (modpath, modname) = {
|
let (modpath, modname) = {
|
||||||
let path = &mut bcx.fcx.path;
|
let path = &mut bcx.fcx.path;
|
||||||
let modpath = vec::append(
|
let mut modpath = ~[path_mod(ccx.sess.ident_of(ccx.link_meta.name))];
|
||||||
~[path_mod(ccx.sess.ident_of(ccx.link_meta.name))],
|
for path.iter().advance |e| {
|
||||||
path.filtered(|e| match *e { path_mod(_) => true, _ => false }));
|
match *e {
|
||||||
|
path_mod(_) => { modpath.push(*e) }
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
let modname = path_str(ccx.sess, modpath);
|
let modname = path_str(ccx.sess, modpath);
|
||||||
(modpath, modname)
|
(modpath, modname)
|
||||||
};
|
};
|
||||||
|
@ -246,42 +249,48 @@ pub fn trans_break_cont(bcx: block,
|
||||||
let _icx = push_ctxt("trans_break_cont");
|
let _icx = push_ctxt("trans_break_cont");
|
||||||
// Locate closest loop block, outputting cleanup as we go.
|
// Locate closest loop block, outputting cleanup as we go.
|
||||||
let mut unwind = bcx;
|
let mut unwind = bcx;
|
||||||
let mut target;
|
let mut cur_scope = unwind.scope;
|
||||||
|
let mut target = unwind;
|
||||||
|
let mut quit = false;
|
||||||
loop {
|
loop {
|
||||||
match unwind.kind {
|
cur_scope = match cur_scope {
|
||||||
block_scope(@scope_info {
|
Some(@scope_info {
|
||||||
loop_break: Some(brk),
|
loop_break: Some(brk),
|
||||||
loop_label: l,
|
loop_label: l,
|
||||||
_
|
parent,
|
||||||
}) => {
|
_
|
||||||
// If we're looking for a labeled loop, check the label...
|
}) => {
|
||||||
target = if to_end {
|
// If we're looking for a labeled loop, check the label...
|
||||||
brk
|
target = if to_end {
|
||||||
} else {
|
brk
|
||||||
unwind
|
} else {
|
||||||
};
|
unwind
|
||||||
match opt_label {
|
};
|
||||||
Some(desired) => match l {
|
match opt_label {
|
||||||
Some(actual) if actual == desired => break,
|
Some(desired) => match l {
|
||||||
// If it doesn't match the one we want,
|
Some(actual) if actual == desired => break,
|
||||||
// don't break
|
// If it doesn't match the one we want,
|
||||||
_ => ()
|
// don't break
|
||||||
},
|
_ => parent,
|
||||||
None => break
|
},
|
||||||
}
|
None => break,
|
||||||
}
|
}
|
||||||
_ => ()
|
}
|
||||||
|
Some(inf) => inf.parent,
|
||||||
|
None => {
|
||||||
|
unwind = match unwind.parent {
|
||||||
|
Some(bcx) => bcx,
|
||||||
|
// This is a return from a loop body block
|
||||||
|
None => {
|
||||||
|
Store(bcx, C_bool(!to_end), bcx.fcx.llretptr.get());
|
||||||
|
cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
|
||||||
|
Unreachable(bcx);
|
||||||
|
return bcx;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unwind.scope
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unwind = match unwind.parent {
|
|
||||||
Some(bcx) => bcx,
|
|
||||||
// This is a return from a loop body block
|
|
||||||
None => {
|
|
||||||
Store(bcx, C_bool(!to_end), bcx.fcx.llretptr.get());
|
|
||||||
cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
|
|
||||||
Unreachable(bcx);
|
|
||||||
return bcx;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
cleanup_and_Br(bcx, unwind, target.llbb);
|
cleanup_and_Br(bcx, unwind, target.llbb);
|
||||||
Unreachable(bcx);
|
Unreachable(bcx);
|
||||||
|
@ -386,7 +395,7 @@ fn trans_fail_value(bcx: block,
|
||||||
let V_filename = PointerCast(bcx, V_filename, Type::i8p());
|
let V_filename = PointerCast(bcx, V_filename, Type::i8p());
|
||||||
let args = ~[V_str, V_filename, C_int(ccx, V_line)];
|
let args = ~[V_str, V_filename, C_int(ccx, V_line)];
|
||||||
let bcx = callee::trans_lang_call(
|
let bcx = callee::trans_lang_call(
|
||||||
bcx, bcx.tcx().lang_items.fail_fn(), args, expr::Ignore);
|
bcx, bcx.tcx().lang_items.fail_fn(), args, Some(expr::Ignore)).bcx;
|
||||||
Unreachable(bcx);
|
Unreachable(bcx);
|
||||||
return bcx;
|
return bcx;
|
||||||
}
|
}
|
||||||
|
@ -397,7 +406,7 @@ pub fn trans_fail_bounds_check(bcx: block, sp: span,
|
||||||
let (filename, line) = filename_and_line_num_from_span(bcx, sp);
|
let (filename, line) = filename_and_line_num_from_span(bcx, sp);
|
||||||
let args = ~[filename, line, index, len];
|
let args = ~[filename, line, index, len];
|
||||||
let bcx = callee::trans_lang_call(
|
let bcx = callee::trans_lang_call(
|
||||||
bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, expr::Ignore);
|
bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, Some(expr::Ignore)).bcx;
|
||||||
Unreachable(bcx);
|
Unreachable(bcx);
|
||||||
return bcx;
|
return bcx;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,7 @@ use middle::trans::glue;
|
||||||
use middle::trans::tvec;
|
use middle::trans::tvec;
|
||||||
use middle::trans::type_of;
|
use middle::trans::type_of;
|
||||||
use middle::trans::write_guard;
|
use middle::trans::write_guard;
|
||||||
|
use middle::trans::type_::Type;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use util::common::indenter;
|
use util::common::indenter;
|
||||||
use util::ppaux::ty_to_str;
|
use util::ppaux::ty_to_str;
|
||||||
|
@ -188,7 +189,7 @@ pub fn scratch_datum(bcx: block, ty: ty::t, zero: bool) -> Datum {
|
||||||
Datum { val: scratch, ty: ty, mode: ByRef(RevokeClean) }
|
Datum { val: scratch, ty: ty, mode: ByRef(RevokeClean) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn appropriate_mode(ty: ty::t) -> DatumMode {
|
pub fn appropriate_mode(tcx: ty::ctxt, ty: ty::t) -> DatumMode {
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* Indicates the "appropriate" mode for this value,
|
* Indicates the "appropriate" mode for this value,
|
||||||
|
@ -197,7 +198,7 @@ pub fn appropriate_mode(ty: ty::t) -> DatumMode {
|
||||||
|
|
||||||
if ty::type_is_nil(ty) || ty::type_is_bot(ty) {
|
if ty::type_is_nil(ty) || ty::type_is_bot(ty) {
|
||||||
ByValue
|
ByValue
|
||||||
} else if ty::type_is_immediate(ty) {
|
} else if ty::type_is_immediate(tcx, ty) {
|
||||||
ByValue
|
ByValue
|
||||||
} else {
|
} else {
|
||||||
ByRef(RevokeClean)
|
ByRef(RevokeClean)
|
||||||
|
@ -508,10 +509,10 @@ impl Datum {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn appropriate_mode(&self) -> DatumMode {
|
pub fn appropriate_mode(&self, tcx: ty::ctxt) -> DatumMode {
|
||||||
/*! See the `appropriate_mode()` function */
|
/*! See the `appropriate_mode()` function */
|
||||||
|
|
||||||
appropriate_mode(self.ty)
|
appropriate_mode(tcx, self.ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_appropriate_llval(&self, bcx: block) -> ValueRef {
|
pub fn to_appropriate_llval(&self, bcx: block) -> ValueRef {
|
||||||
|
@ -519,7 +520,7 @@ impl Datum {
|
||||||
*
|
*
|
||||||
* Yields an llvalue with the `appropriate_mode()`. */
|
* Yields an llvalue with the `appropriate_mode()`. */
|
||||||
|
|
||||||
match self.appropriate_mode() {
|
match self.appropriate_mode(bcx.tcx()) {
|
||||||
ByValue => self.to_value_llval(bcx),
|
ByValue => self.to_value_llval(bcx),
|
||||||
ByRef(_) => self.to_ref_llval(bcx)
|
ByRef(_) => self.to_ref_llval(bcx)
|
||||||
}
|
}
|
||||||
|
@ -530,7 +531,7 @@ impl Datum {
|
||||||
*
|
*
|
||||||
* Yields a datum with the `appropriate_mode()`. */
|
* Yields a datum with the `appropriate_mode()`. */
|
||||||
|
|
||||||
match self.appropriate_mode() {
|
match self.appropriate_mode(bcx.tcx()) {
|
||||||
ByValue => self.to_value_datum(bcx),
|
ByValue => self.to_value_datum(bcx),
|
||||||
ByRef(_) => self.to_ref_datum(bcx)
|
ByRef(_) => self.to_ref_datum(bcx)
|
||||||
}
|
}
|
||||||
|
@ -567,8 +568,14 @@ impl Datum {
|
||||||
* This datum must represent an @T or ~T box. Returns a new
|
* This datum must represent an @T or ~T box. Returns a new
|
||||||
* by-ref datum of type T, pointing at the contents. */
|
* by-ref datum of type T, pointing at the contents. */
|
||||||
|
|
||||||
let content_ty = match ty::get(self.ty).sty {
|
let (content_ty, header) = match ty::get(self.ty).sty {
|
||||||
ty::ty_box(mt) | ty::ty_uniq(mt) => mt.ty,
|
ty::ty_box(mt) => (mt.ty, true),
|
||||||
|
ty::ty_uniq(mt) => (mt.ty, false),
|
||||||
|
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) => {
|
||||||
|
let unit_ty = ty::sequence_element_type(bcx.tcx(), self.ty);
|
||||||
|
let unboxed_vec_ty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty);
|
||||||
|
(unboxed_vec_ty, true)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
bcx.tcx().sess.bug(fmt!(
|
bcx.tcx().sess.bug(fmt!(
|
||||||
"box_body() invoked on non-box type %s",
|
"box_body() invoked on non-box type %s",
|
||||||
|
@ -576,9 +583,16 @@ impl Datum {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let ptr = self.to_value_llval(bcx);
|
if !header && !ty::type_contents(bcx.tcx(), content_ty).contains_managed() {
|
||||||
let body = opaque_box_body(bcx, content_ty, ptr);
|
let ptr = self.to_value_llval(bcx);
|
||||||
Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
|
let ty = type_of(bcx.ccx(), content_ty);
|
||||||
|
let body = PointerCast(bcx, ptr, ty.ptr_to());
|
||||||
|
Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
|
||||||
|
} else { // has a header
|
||||||
|
let ptr = self.to_value_llval(bcx);
|
||||||
|
let body = opaque_box_body(bcx, content_ty, ptr);
|
||||||
|
Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_rptr(&self, bcx: block) -> Datum {
|
pub fn to_rptr(&self, bcx: block) -> Datum {
|
||||||
|
@ -657,13 +671,7 @@ impl Datum {
|
||||||
ByValue => {
|
ByValue => {
|
||||||
// Actually, this case cannot happen right
|
// Actually, this case cannot happen right
|
||||||
// now, because enums are never immediate.
|
// now, because enums are never immediate.
|
||||||
// But in principle newtype'd immediate
|
assert!(ty::type_is_immediate(bcx.tcx(), ty));
|
||||||
// values should be immediate, and in that
|
|
||||||
// case the * would be a no-op except for
|
|
||||||
// changing the type, so I am putting this
|
|
||||||
// code in place here to do the right
|
|
||||||
// thing if this change ever goes through.
|
|
||||||
assert!(ty::type_is_immediate(ty));
|
|
||||||
(Some(Datum {ty: ty, ..*self}), bcx)
|
(Some(Datum {ty: ty, ..*self}), bcx)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -695,15 +703,15 @@ impl Datum {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ByValue => {
|
ByValue => {
|
||||||
// Actually, this case cannot happen right now,
|
assert!(ty::type_is_immediate(bcx.tcx(), ty));
|
||||||
// because structs are never immediate. But in
|
(
|
||||||
// principle, newtype'd immediate values should be
|
Some(Datum {
|
||||||
// immediate, and in that case the * would be a no-op
|
val: ExtractValue(bcx, self.val, 0),
|
||||||
// except for changing the type, so I am putting this
|
ty: ty,
|
||||||
// code in place here to do the right thing if this
|
mode: ByValue
|
||||||
// change ever goes through.
|
}),
|
||||||
assert!(ty::type_is_immediate(ty));
|
bcx
|
||||||
(Some(Datum {ty: ty, ..*self}), bcx)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,7 @@ pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable {
|
||||||
let cx = bcx.ccx();
|
let cx = bcx.ccx();
|
||||||
|
|
||||||
let ident = match local.node.pat.node {
|
let ident = match local.node.pat.node {
|
||||||
ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth),
|
ast::pat_ident(_, ref pth, _) => ast_util::path_to_ident(pth),
|
||||||
// FIXME this should be handled (#2533)
|
// FIXME this should be handled (#2533)
|
||||||
_ => {
|
_ => {
|
||||||
bcx.sess().span_note(local.span, "debuginfo for pattern bindings NYI");
|
bcx.sess().span_note(local.span, "debuginfo for pattern bindings NYI");
|
||||||
|
@ -182,7 +182,7 @@ pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable {
|
||||||
///
|
///
|
||||||
/// Adds the created metadata nodes directly to the crate's IR.
|
/// Adds the created metadata nodes directly to the crate's IR.
|
||||||
/// The return value should be ignored if called from outside of the debuginfo module.
|
/// The return value should be ignored if called from outside of the debuginfo module.
|
||||||
pub fn create_arg(bcx: block, arg: ast::arg, span: span) -> Option<DIVariable> {
|
pub fn create_arg(bcx: block, arg: &ast::arg, span: span) -> Option<DIVariable> {
|
||||||
debug!("create_arg");
|
debug!("create_arg");
|
||||||
if true {
|
if true {
|
||||||
// XXX create_arg disabled for now because "node_id_type(bcx, arg.id)" below blows
|
// XXX create_arg disabled for now because "node_id_type(bcx, arg.id)" below blows
|
||||||
|
@ -204,7 +204,7 @@ pub fn create_arg(bcx: block, arg: ast::arg, span: span) -> Option<DIVariable> {
|
||||||
let context = create_function(fcx);
|
let context = create_function(fcx);
|
||||||
|
|
||||||
match arg.pat.node {
|
match arg.pat.node {
|
||||||
ast::pat_ident(_, path, _) => {
|
ast::pat_ident(_, ref path, _) => {
|
||||||
// XXX: This is wrong; it should work for multiple bindings.
|
// XXX: This is wrong; it should work for multiple bindings.
|
||||||
let ident = path.idents.last();
|
let ident = path.idents.last();
|
||||||
let name: &str = cx.sess.str_of(*ident);
|
let name: &str = cx.sess.str_of(*ident);
|
||||||
|
@ -259,23 +259,25 @@ pub fn create_function(fcx: fn_ctxt) -> DISubprogram {
|
||||||
let fcx = &mut *fcx;
|
let fcx = &mut *fcx;
|
||||||
let span = fcx.span.get();
|
let span = fcx.span.get();
|
||||||
|
|
||||||
let (ident, ret_ty, id) = match cx.tcx.items.get_copy(&fcx.id) {
|
let fnitem = cx.tcx.items.get_copy(&fcx.id);
|
||||||
ast_map::node_item(item, _) => {
|
let (ident, ret_ty, id) = match fnitem {
|
||||||
|
ast_map::node_item(ref item, _) => {
|
||||||
match item.node {
|
match item.node {
|
||||||
ast::item_fn(ref decl, _, _, _, _) => {
|
ast::item_fn(ast::fn_decl { output: ref ty, _}, _, _, _, _) => {
|
||||||
(item.ident, decl.output, item.id)
|
(item.ident, ty, item.id)
|
||||||
}
|
}
|
||||||
_ => fcx.ccx.sess.span_bug(item.span, "create_function: item bound to non-function")
|
_ => fcx.ccx.sess.span_bug(item.span, "create_function: item bound to non-function")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast_map::node_method(method, _, _) => {
|
ast_map::node_method(@ast::method { decl: ast::fn_decl { output: ref ty, _ },
|
||||||
(method.ident, method.decl.output, method.id)
|
id: id, ident: ident, _}, _, _) => {
|
||||||
|
(ident, ty, id)
|
||||||
}
|
}
|
||||||
ast_map::node_expr(expr) => {
|
ast_map::node_expr(ref expr) => {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ast::expr_fn_block(ref decl, _) => {
|
ast::expr_fn_block(ref decl, _) => {
|
||||||
let name = gensym_name("fn");
|
let name = gensym_name("fn");
|
||||||
(name, decl.output, expr.id)
|
(name, &decl.output, expr.id)
|
||||||
}
|
}
|
||||||
_ => fcx.ccx.sess.span_bug(expr.span,
|
_ => fcx.ccx.sess.span_bug(expr.span,
|
||||||
"create_function: expected an expr_fn_block here")
|
"create_function: expected an expr_fn_block here")
|
||||||
|
|
|
@ -150,6 +150,7 @@ use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn,
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use util::common::indenter;
|
use util::common::indenter;
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
|
use middle::trans::machine::llsize_of;
|
||||||
|
|
||||||
use middle::trans::type_::Type;
|
use middle::trans::type_::Type;
|
||||||
|
|
||||||
|
@ -291,7 +292,7 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||||
debug!("add_env(closure_ty=%s)", closure_ty.repr(tcx));
|
debug!("add_env(closure_ty=%s)", closure_ty.repr(tcx));
|
||||||
let scratch = scratch_datum(bcx, closure_ty, false);
|
let scratch = scratch_datum(bcx, closure_ty, false);
|
||||||
let llfn = GEPi(bcx, scratch.val, [0u, abi::fn_field_code]);
|
let llfn = GEPi(bcx, scratch.val, [0u, abi::fn_field_code]);
|
||||||
assert_eq!(datum.appropriate_mode(), ByValue);
|
assert_eq!(datum.appropriate_mode(tcx), ByValue);
|
||||||
Store(bcx, datum.to_appropriate_llval(bcx), llfn);
|
Store(bcx, datum.to_appropriate_llval(bcx), llfn);
|
||||||
let llenv = GEPi(bcx, scratch.val, [0u, abi::fn_field_box]);
|
let llenv = GEPi(bcx, scratch.val, [0u, abi::fn_field_box]);
|
||||||
Store(bcx, base::null_env_ptr(bcx), llenv);
|
Store(bcx, base::null_env_ptr(bcx), llenv);
|
||||||
|
@ -464,7 +465,7 @@ fn trans_rvalue_datum_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||||
expr, contents);
|
expr, contents);
|
||||||
}
|
}
|
||||||
ast::expr_vstore(contents, ast::expr_vstore_uniq) => {
|
ast::expr_vstore(contents, ast::expr_vstore_uniq) => {
|
||||||
let heap = heap_for_unique(bcx, expr_ty(bcx, contents));
|
let heap = tvec::heap_for_unique_vector(bcx, expr_ty(bcx, contents));
|
||||||
return tvec::trans_uniq_or_managed_vstore(bcx, heap,
|
return tvec::trans_uniq_or_managed_vstore(bcx, heap,
|
||||||
expr, contents);
|
expr, contents);
|
||||||
}
|
}
|
||||||
|
@ -1147,7 +1148,7 @@ fn trans_rec_or_struct(bcx: block,
|
||||||
let mut need_base = vec::from_elem(field_tys.len(), true);
|
let mut need_base = vec::from_elem(field_tys.len(), true);
|
||||||
|
|
||||||
let numbered_fields = do fields.map |field| {
|
let numbered_fields = do fields.map |field| {
|
||||||
let opt_pos = field_tys.iter().position_(|field_ty| field_ty.ident == field.node.ident);
|
let opt_pos = field_tys.iter().position(|field_ty| field_ty.ident == field.node.ident);
|
||||||
match opt_pos {
|
match opt_pos {
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
need_base[i] = false;
|
need_base[i] = false;
|
||||||
|
@ -1171,7 +1172,7 @@ fn trans_rec_or_struct(bcx: block,
|
||||||
fields: leftovers })
|
fields: leftovers })
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if need_base.iter().any_(|b| *b) {
|
if need_base.iter().any(|b| *b) {
|
||||||
tcx.sess.span_bug(expr_span, "missing fields and no base expr")
|
tcx.sess.span_bug(expr_span, "missing fields and no base expr")
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
@ -1329,12 +1330,23 @@ fn trans_unary_datum(bcx: block,
|
||||||
contents_ty: ty::t,
|
contents_ty: ty::t,
|
||||||
heap: heap) -> DatumBlock {
|
heap: heap) -> DatumBlock {
|
||||||
let _icx = push_ctxt("trans_boxed_expr");
|
let _icx = push_ctxt("trans_boxed_expr");
|
||||||
let base::MallocResult { bcx, box: bx, body } =
|
if heap == heap_exchange {
|
||||||
base::malloc_general(bcx, contents_ty, heap);
|
let llty = type_of(bcx.ccx(), contents_ty);
|
||||||
add_clean_free(bcx, bx, heap);
|
let size = llsize_of(bcx.ccx(), llty);
|
||||||
let bcx = trans_into(bcx, contents, SaveIn(body));
|
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, contents_ty,
|
||||||
revoke_clean(bcx, bx);
|
heap_exchange, size);
|
||||||
return immediate_rvalue_bcx(bcx, bx, box_ty);
|
add_clean_free(bcx, val, heap_exchange);
|
||||||
|
let bcx = trans_into(bcx, contents, SaveIn(val));
|
||||||
|
revoke_clean(bcx, val);
|
||||||
|
return immediate_rvalue_bcx(bcx, val, box_ty);
|
||||||
|
} else {
|
||||||
|
let base::MallocResult { bcx, box: bx, body } =
|
||||||
|
base::malloc_general(bcx, contents_ty, heap);
|
||||||
|
add_clean_free(bcx, bx, heap);
|
||||||
|
let bcx = trans_into(bcx, contents, SaveIn(body));
|
||||||
|
revoke_clean(bcx, bx);
|
||||||
|
return immediate_rvalue_bcx(bcx, bx, box_ty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1539,8 +1551,8 @@ fn trans_overloaded_op(bcx: block,
|
||||||
origin)
|
origin)
|
||||||
},
|
},
|
||||||
callee::ArgExprs(args),
|
callee::ArgExprs(args),
|
||||||
dest,
|
Some(dest),
|
||||||
DoAutorefArg)
|
DoAutorefArg).bcx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn int_cast(bcx: block, lldsttype: Type, llsrctype: Type,
|
fn int_cast(bcx: block, lldsttype: Type, llsrctype: Type,
|
||||||
|
|
|
@ -103,7 +103,7 @@ fn foreign_signature(ccx: &mut CrateContext, fn_sig: &ty::FnSig)
|
||||||
LlvmSignature {
|
LlvmSignature {
|
||||||
llarg_tys: llarg_tys,
|
llarg_tys: llarg_tys,
|
||||||
llret_ty: llret_ty,
|
llret_ty: llret_ty,
|
||||||
sret: !ty::type_is_immediate(fn_sig.output),
|
sret: !ty::type_is_immediate(ccx.tcx, fn_sig.output),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ fn shim_types(ccx: @mut CrateContext, id: ast::node_id) -> ShimTypes {
|
||||||
_ => ccx.sess.bug("c_arg_and_ret_lltys called on non-function type")
|
_ => ccx.sess.bug("c_arg_and_ret_lltys called on non-function type")
|
||||||
};
|
};
|
||||||
let llsig = foreign_signature(ccx, &fn_sig);
|
let llsig = foreign_signature(ccx, &fn_sig);
|
||||||
let bundle_ty = Type::struct_(llsig.llarg_tys + [llsig.llret_ty.ptr_to()], false);
|
let bundle_ty = Type::struct_(llsig.llarg_tys + &[llsig.llret_ty.ptr_to()], false);
|
||||||
let ret_def = !ty::type_is_bot(fn_sig.output) &&
|
let ret_def = !ty::type_is_bot(fn_sig.output) &&
|
||||||
!ty::type_is_nil(fn_sig.output);
|
!ty::type_is_nil(fn_sig.output);
|
||||||
let fn_ty = abi_info(ccx).compute_info(llsig.llarg_tys, llsig.llret_ty, ret_def);
|
let fn_ty = abi_info(ccx).compute_info(llsig.llarg_tys, llsig.llret_ty, ret_def);
|
||||||
|
@ -192,7 +192,7 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
||||||
|
|
||||||
// Patch up the return type if it's not immediate and we're returning via
|
// Patch up the return type if it's not immediate and we're returning via
|
||||||
// the C ABI.
|
// the C ABI.
|
||||||
if needs_c_return && !ty::type_is_immediate(tys.fn_sig.output) {
|
if needs_c_return && !ty::type_is_immediate(ccx.tcx, tys.fn_sig.output) {
|
||||||
let lloutputtype = type_of::type_of(fcx.ccx, tys.fn_sig.output);
|
let lloutputtype = type_of::type_of(fcx.ccx, tys.fn_sig.output);
|
||||||
fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.llstaticallocas),
|
fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.llstaticallocas),
|
||||||
lloutputtype));
|
lloutputtype));
|
||||||
|
@ -648,7 +648,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||||
// intrinsics, there are no argument cleanups to
|
// intrinsics, there are no argument cleanups to
|
||||||
// concern ourselves with.
|
// concern ourselves with.
|
||||||
let tp_ty = substs.tys[0];
|
let tp_ty = substs.tys[0];
|
||||||
let mode = appropriate_mode(tp_ty);
|
let mode = appropriate_mode(ccx.tcx, tp_ty);
|
||||||
let src = Datum {val: get_param(decl, first_real_arg + 1u),
|
let src = Datum {val: get_param(decl, first_real_arg + 1u),
|
||||||
ty: tp_ty, mode: mode};
|
ty: tp_ty, mode: mode};
|
||||||
bcx = src.move_to(bcx, DROP_EXISTING,
|
bcx = src.move_to(bcx, DROP_EXISTING,
|
||||||
|
@ -657,7 +657,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||||
"move_val_init" => {
|
"move_val_init" => {
|
||||||
// See comments for `"move_val"`.
|
// See comments for `"move_val"`.
|
||||||
let tp_ty = substs.tys[0];
|
let tp_ty = substs.tys[0];
|
||||||
let mode = appropriate_mode(tp_ty);
|
let mode = appropriate_mode(ccx.tcx, tp_ty);
|
||||||
let src = Datum {val: get_param(decl, first_real_arg + 1u),
|
let src = Datum {val: get_param(decl, first_real_arg + 1u),
|
||||||
ty: tp_ty, mode: mode};
|
ty: tp_ty, mode: mode};
|
||||||
bcx = src.move_to(bcx, INIT, get_param(decl, first_real_arg));
|
bcx = src.move_to(bcx, INIT, get_param(decl, first_real_arg));
|
||||||
|
@ -731,7 +731,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||||
let lldestptr = PointerCast(bcx, lldestptr, Type::i8p());
|
let lldestptr = PointerCast(bcx, lldestptr, Type::i8p());
|
||||||
|
|
||||||
let llsrcval = get_param(decl, first_real_arg);
|
let llsrcval = get_param(decl, first_real_arg);
|
||||||
let llsrcptr = if ty::type_is_immediate(in_type) {
|
let llsrcptr = if ty::type_is_immediate(ccx.tcx, in_type) {
|
||||||
let llsrcptr = alloca(bcx, llintype);
|
let llsrcptr = alloca(bcx, llintype);
|
||||||
Store(bcx, llsrcval, llsrcptr);
|
Store(bcx, llsrcval, llsrcptr);
|
||||||
llsrcptr
|
llsrcptr
|
||||||
|
@ -789,7 +789,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||||
bcx = trans_call_inner(
|
bcx = trans_call_inner(
|
||||||
bcx, None, fty, ty::mk_nil(),
|
bcx, None, fty, ty::mk_nil(),
|
||||||
|bcx| Callee {bcx: bcx, data: Closure(datum)},
|
|bcx| Callee {bcx: bcx, data: Closure(datum)},
|
||||||
ArgVals(arg_vals), Ignore, DontAutorefArg);
|
ArgVals(arg_vals), Some(Ignore), DontAutorefArg).bcx;
|
||||||
}
|
}
|
||||||
"morestack_addr" => {
|
"morestack_addr" => {
|
||||||
// XXX This is a hack to grab the address of this particular
|
// XXX This is a hack to grab the address of this particular
|
||||||
|
@ -1221,7 +1221,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
||||||
let mut i = 0u;
|
let mut i = 0u;
|
||||||
let n = tys.fn_sig.inputs.len();
|
let n = tys.fn_sig.inputs.len();
|
||||||
|
|
||||||
if !ty::type_is_immediate(tys.fn_sig.output) {
|
if !ty::type_is_immediate(bcx.tcx(), tys.fn_sig.output) {
|
||||||
let llretptr = load_inbounds(bcx, llargbundle, [0u, n]);
|
let llretptr = load_inbounds(bcx, llargbundle, [0u, n]);
|
||||||
llargvals.push(llretptr);
|
llargvals.push(llretptr);
|
||||||
}
|
}
|
||||||
|
@ -1247,7 +1247,8 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
||||||
shim_types: &ShimTypes,
|
shim_types: &ShimTypes,
|
||||||
llargbundle: ValueRef,
|
llargbundle: ValueRef,
|
||||||
llretval: ValueRef) {
|
llretval: ValueRef) {
|
||||||
if bcx.fcx.llretptr.is_some() && ty::type_is_immediate(shim_types.fn_sig.output) {
|
if bcx.fcx.llretptr.is_some() &&
|
||||||
|
ty::type_is_immediate(bcx.tcx(), shim_types.fn_sig.output) {
|
||||||
// Write the value into the argument bundle.
|
// Write the value into the argument bundle.
|
||||||
let arg_count = shim_types.fn_sig.inputs.len();
|
let arg_count = shim_types.fn_sig.inputs.len();
|
||||||
let llretptr = load_inbounds(bcx,
|
let llretptr = load_inbounds(bcx,
|
||||||
|
|
|
@ -47,7 +47,7 @@ pub fn trans_free(cx: block, v: ValueRef) -> block {
|
||||||
callee::trans_lang_call(cx,
|
callee::trans_lang_call(cx,
|
||||||
cx.tcx().lang_items.free_fn(),
|
cx.tcx().lang_items.free_fn(),
|
||||||
[PointerCast(cx, v, Type::i8p())],
|
[PointerCast(cx, v, Type::i8p())],
|
||||||
expr::Ignore)
|
Some(expr::Ignore)).bcx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_exchange_free(cx: block, v: ValueRef) -> block {
|
pub fn trans_exchange_free(cx: block, v: ValueRef) -> block {
|
||||||
|
@ -55,7 +55,7 @@ pub fn trans_exchange_free(cx: block, v: ValueRef) -> block {
|
||||||
callee::trans_lang_call(cx,
|
callee::trans_lang_call(cx,
|
||||||
cx.tcx().lang_items.exchange_free_fn(),
|
cx.tcx().lang_items.exchange_free_fn(),
|
||||||
[PointerCast(cx, v, Type::i8p())],
|
[PointerCast(cx, v, Type::i8p())],
|
||||||
expr::Ignore)
|
Some(expr::Ignore)).bcx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take_ty(cx: block, v: ValueRef, t: ty::t) -> block {
|
pub fn take_ty(cx: block, v: ValueRef, t: ty::t) -> block {
|
||||||
|
@ -386,7 +386,9 @@ pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||||
ty::ty_uniq(*) => {
|
ty::ty_uniq(*) => {
|
||||||
uniq::make_free_glue(bcx, v, t)
|
uniq::make_free_glue(bcx, v, t)
|
||||||
}
|
}
|
||||||
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) |
|
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) => {
|
||||||
|
tvec::make_uniq_free_glue(bcx, v, t)
|
||||||
|
}
|
||||||
ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => {
|
ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => {
|
||||||
make_free_glue(bcx, v,
|
make_free_glue(bcx, v,
|
||||||
tvec::expand_boxed_vec_ty(bcx.tcx(), t));
|
tvec::expand_boxed_vec_ty(bcx.tcx(), t));
|
||||||
|
@ -738,15 +740,9 @@ pub fn make_generic_glue(ccx: @mut CrateContext,
|
||||||
name: &str)
|
name: &str)
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
let _icx = push_ctxt("make_generic_glue");
|
let _icx = push_ctxt("make_generic_glue");
|
||||||
if !ccx.sess.trans_stats() {
|
let glue_name = fmt!("glue %s %s", name, ty_to_short_str(ccx.tcx, t));
|
||||||
return make_generic_glue_inner(ccx, t, llfn, helper);
|
let _s = StatRecorder::new(ccx, glue_name);
|
||||||
}
|
make_generic_glue_inner(ccx, t, llfn, helper)
|
||||||
|
|
||||||
let start = time::get_time();
|
|
||||||
let llval = make_generic_glue_inner(ccx, t, llfn, helper);
|
|
||||||
let end = time::get_time();
|
|
||||||
ccx.log_fn_time(fmt!("glue %s %s", name, ty_to_short_str(ccx.tcx, t)), start, end);
|
|
||||||
return llval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_tydescs(ccx: &mut CrateContext) {
|
pub fn emit_tydescs(ccx: &mut CrateContext) {
|
||||||
|
|
|
@ -14,9 +14,6 @@ use lib::llvm::{ValueRef};
|
||||||
use lib::llvm::False;
|
use lib::llvm::False;
|
||||||
use lib::llvm::llvm;
|
use lib::llvm::llvm;
|
||||||
use middle::trans::common::*;
|
use middle::trans::common::*;
|
||||||
use middle::trans::type_of;
|
|
||||||
use middle::ty;
|
|
||||||
use util::ppaux::ty_to_str;
|
|
||||||
|
|
||||||
use middle::trans::type_::Type;
|
use middle::trans::type_::Type;
|
||||||
|
|
||||||
|
@ -116,42 +113,3 @@ pub fn llalign_of(cx: &CrateContext, ty: Type) -> ValueRef {
|
||||||
llvm::LLVMAlignOf(ty.to_ref()), cx.int_type.to_ref(), False);
|
llvm::LLVMAlignOf(ty.to_ref()), cx.int_type.to_ref(), False);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computes the size of the data part of an enum.
|
|
||||||
pub fn static_size_of_enum(cx: &mut CrateContext, t: ty::t) -> uint {
|
|
||||||
if cx.enum_sizes.contains_key(&t) {
|
|
||||||
return cx.enum_sizes.get_copy(&t);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("static_size_of_enum %s", ty_to_str(cx.tcx, t));
|
|
||||||
|
|
||||||
match ty::get(t).sty {
|
|
||||||
ty::ty_enum(tid, ref substs) => {
|
|
||||||
// Compute max(variant sizes).
|
|
||||||
let mut max_size = 0;
|
|
||||||
let variants = ty::enum_variants(cx.tcx, tid);
|
|
||||||
for variants.iter().advance |variant| {
|
|
||||||
if variant.args.len() == 0 {
|
|
||||||
loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
let lltypes = variant.args.map(|&variant_arg| {
|
|
||||||
let substituted = ty::subst(cx.tcx, substs, variant_arg);
|
|
||||||
type_of::sizing_type_of(cx, substituted)
|
|
||||||
});
|
|
||||||
|
|
||||||
debug!("static_size_of_enum: variant %s type %s",
|
|
||||||
cx.tcx.sess.str_of(variant.name),
|
|
||||||
cx.tn.type_to_str(Type::struct_(lltypes, false)));
|
|
||||||
|
|
||||||
let this_size = llsize_of_real(cx, Type::struct_(lltypes, false));
|
|
||||||
if max_size < this_size {
|
|
||||||
max_size = this_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cx.enum_sizes.insert(t, max_size);
|
|
||||||
return max_size;
|
|
||||||
}
|
|
||||||
_ => cx.sess.bug("static_size_of_enum called on non-enum")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -577,6 +577,10 @@ pub fn trans_trait_callee_from_llval(bcx: block,
|
||||||
}
|
}
|
||||||
ast::sty_region(*) => {
|
ast::sty_region(*) => {
|
||||||
match store {
|
match store {
|
||||||
|
ty::UniqTraitStore
|
||||||
|
if !ty::type_contents(bcx.tcx(), callee_ty).contains_managed() => {
|
||||||
|
llself = llbox;
|
||||||
|
}
|
||||||
ty::BoxTraitStore |
|
ty::BoxTraitStore |
|
||||||
ty::UniqTraitStore => {
|
ty::UniqTraitStore => {
|
||||||
llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
|
llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
|
||||||
|
@ -641,16 +645,18 @@ pub fn vtable_id(ccx: @mut CrateContext,
|
||||||
-> mono_id {
|
-> mono_id {
|
||||||
match origin {
|
match origin {
|
||||||
&typeck::vtable_static(impl_id, ref substs, sub_vtables) => {
|
&typeck::vtable_static(impl_id, ref substs, sub_vtables) => {
|
||||||
|
let psubsts = param_substs {
|
||||||
|
tys: copy *substs,
|
||||||
|
vtables: Some(sub_vtables),
|
||||||
|
self_ty: None,
|
||||||
|
self_vtable: None
|
||||||
|
};
|
||||||
|
|
||||||
monomorphize::make_mono_id(
|
monomorphize::make_mono_id(
|
||||||
ccx,
|
ccx,
|
||||||
impl_id,
|
impl_id,
|
||||||
*substs,
|
|
||||||
if sub_vtables.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(sub_vtables)
|
|
||||||
},
|
|
||||||
None,
|
None,
|
||||||
|
&psubsts,
|
||||||
None)
|
None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,11 +50,13 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
|
||||||
fn_id=%s, \
|
fn_id=%s, \
|
||||||
real_substs=%s, \
|
real_substs=%s, \
|
||||||
vtables=%s, \
|
vtables=%s, \
|
||||||
|
self_vtable=%s, \
|
||||||
impl_did_opt=%s, \
|
impl_did_opt=%s, \
|
||||||
ref_id=%?)",
|
ref_id=%?)",
|
||||||
fn_id.repr(ccx.tcx),
|
fn_id.repr(ccx.tcx),
|
||||||
real_substs.repr(ccx.tcx),
|
real_substs.repr(ccx.tcx),
|
||||||
vtables.repr(ccx.tcx),
|
vtables.repr(ccx.tcx),
|
||||||
|
self_vtable.repr(ccx.tcx),
|
||||||
impl_did_opt.repr(ccx.tcx),
|
impl_did_opt.repr(ccx.tcx),
|
||||||
ref_id);
|
ref_id);
|
||||||
|
|
||||||
|
@ -71,21 +73,28 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
|
||||||
for real_substs.tps.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
|
for real_substs.tps.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
|
||||||
for substs.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
|
for substs.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
|
||||||
let param_uses = type_use::type_uses_for(ccx, fn_id, substs.len());
|
let param_uses = type_use::type_uses_for(ccx, fn_id, substs.len());
|
||||||
let hash_id = make_mono_id(ccx, fn_id, substs, vtables, impl_did_opt,
|
|
||||||
|
let psubsts = @param_substs {
|
||||||
|
tys: substs,
|
||||||
|
vtables: vtables,
|
||||||
|
self_ty: real_substs.self_ty,
|
||||||
|
self_vtable: self_vtable
|
||||||
|
};
|
||||||
|
|
||||||
|
let hash_id = make_mono_id(ccx, fn_id, impl_did_opt,
|
||||||
|
&*psubsts,
|
||||||
Some(param_uses));
|
Some(param_uses));
|
||||||
if hash_id.params.iter().any_(
|
if hash_id.params.iter().any(
|
||||||
|p| match *p { mono_precise(_, _) => false, _ => true }) {
|
|p| match *p { mono_precise(_, _) => false, _ => true }) {
|
||||||
must_cast = true;
|
must_cast = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("monomorphic_fn(\
|
debug!("monomorphic_fn(\
|
||||||
fn_id=%s, \
|
fn_id=%s, \
|
||||||
vtables=%s, \
|
psubsts=%s, \
|
||||||
substs=%s, \
|
|
||||||
hash_id=%?)",
|
hash_id=%?)",
|
||||||
fn_id.repr(ccx.tcx),
|
fn_id.repr(ccx.tcx),
|
||||||
vtables.repr(ccx.tcx),
|
psubsts.repr(ccx.tcx),
|
||||||
substs.repr(ccx.tcx),
|
|
||||||
hash_id);
|
hash_id);
|
||||||
|
|
||||||
match ccx.monomorphized.find(&hash_id) {
|
match ccx.monomorphized.find(&hash_id) {
|
||||||
|
@ -142,8 +151,8 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
|
||||||
ast_map::node_struct_ctor(_, i, pt) => (pt, i.ident, i.span)
|
ast_map::node_struct_ctor(_, i, pt) => (pt, i.ident, i.span)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mono_ty = ty::subst_tps(ccx.tcx, substs,
|
let mono_ty = ty::subst_tps(ccx.tcx, psubsts.tys,
|
||||||
real_substs.self_ty, llitem_ty);
|
psubsts.self_ty, llitem_ty);
|
||||||
let llfty = type_of_fn_from_ty(ccx, mono_ty);
|
let llfty = type_of_fn_from_ty(ccx, mono_ty);
|
||||||
|
|
||||||
ccx.stats.n_monos += 1;
|
ccx.stats.n_monos += 1;
|
||||||
|
@ -172,13 +181,6 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
|
||||||
lldecl
|
lldecl
|
||||||
};
|
};
|
||||||
|
|
||||||
let psubsts = Some(@param_substs {
|
|
||||||
tys: substs,
|
|
||||||
vtables: vtables,
|
|
||||||
self_ty: real_substs.self_ty,
|
|
||||||
self_vtable: self_vtable
|
|
||||||
});
|
|
||||||
|
|
||||||
let lldecl = match map_node {
|
let lldecl = match map_node {
|
||||||
ast_map::node_item(i@@ast::item {
|
ast_map::node_item(i@@ast::item {
|
||||||
node: ast::item_fn(ref decl, _, _, _, ref body),
|
node: ast::item_fn(ref decl, _, _, _, ref body),
|
||||||
|
@ -192,7 +194,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
|
||||||
body,
|
body,
|
||||||
d,
|
d,
|
||||||
no_self,
|
no_self,
|
||||||
psubsts,
|
Some(psubsts),
|
||||||
fn_id.node,
|
fn_id.node,
|
||||||
[]);
|
[]);
|
||||||
d
|
d
|
||||||
|
@ -202,7 +204,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
|
||||||
}
|
}
|
||||||
ast_map::node_foreign_item(i, _, _, _) => {
|
ast_map::node_foreign_item(i, _, _, _) => {
|
||||||
let d = mk_lldecl();
|
let d = mk_lldecl();
|
||||||
foreign::trans_intrinsic(ccx, d, i, pt, psubsts.get(), i.attrs,
|
foreign::trans_intrinsic(ccx, d, i, pt, psubsts, i.attrs,
|
||||||
ref_id);
|
ref_id);
|
||||||
d
|
d
|
||||||
}
|
}
|
||||||
|
@ -214,7 +216,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
|
||||||
match v.node.kind {
|
match v.node.kind {
|
||||||
ast::tuple_variant_kind(ref args) => {
|
ast::tuple_variant_kind(ref args) => {
|
||||||
trans_enum_variant(ccx, enum_item.id, v, /*bad*/copy *args,
|
trans_enum_variant(ccx, enum_item.id, v, /*bad*/copy *args,
|
||||||
this_tv.disr_val, psubsts, d);
|
this_tv.disr_val, Some(psubsts), d);
|
||||||
}
|
}
|
||||||
ast::struct_variant_kind(_) =>
|
ast::struct_variant_kind(_) =>
|
||||||
ccx.tcx.sess.bug("can't monomorphize struct variants"),
|
ccx.tcx.sess.bug("can't monomorphize struct variants"),
|
||||||
|
@ -225,13 +227,13 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
|
||||||
// XXX: What should the self type be here?
|
// XXX: What should the self type be here?
|
||||||
let d = mk_lldecl();
|
let d = mk_lldecl();
|
||||||
set_inline_hint_if_appr(/*bad*/copy mth.attrs, d);
|
set_inline_hint_if_appr(/*bad*/copy mth.attrs, d);
|
||||||
meth::trans_method(ccx, pt, mth, psubsts, d);
|
meth::trans_method(ccx, pt, mth, Some(psubsts), d);
|
||||||
d
|
d
|
||||||
}
|
}
|
||||||
ast_map::node_trait_method(@ast::provided(mth), _, pt) => {
|
ast_map::node_trait_method(@ast::provided(mth), _, pt) => {
|
||||||
let d = mk_lldecl();
|
let d = mk_lldecl();
|
||||||
set_inline_hint_if_appr(/*bad*/copy mth.attrs, d);
|
set_inline_hint_if_appr(/*bad*/copy mth.attrs, d);
|
||||||
meth::trans_method(ccx, /*bad*/copy *pt, mth, psubsts, d);
|
meth::trans_method(ccx, /*bad*/copy *pt, mth, Some(psubsts), d);
|
||||||
d
|
d
|
||||||
}
|
}
|
||||||
ast_map::node_struct_ctor(struct_def, _, _) => {
|
ast_map::node_struct_ctor(struct_def, _, _) => {
|
||||||
|
@ -241,7 +243,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
|
||||||
/*bad*/copy struct_def.fields,
|
/*bad*/copy struct_def.fields,
|
||||||
struct_def.ctor_id.expect("ast-mapped tuple struct \
|
struct_def.ctor_id.expect("ast-mapped tuple struct \
|
||||||
didn't have a ctor id"),
|
didn't have a ctor id"),
|
||||||
psubsts,
|
Some(psubsts),
|
||||||
d);
|
d);
|
||||||
d
|
d
|
||||||
}
|
}
|
||||||
|
@ -320,26 +322,36 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
|
||||||
|
|
||||||
pub fn make_mono_id(ccx: @mut CrateContext,
|
pub fn make_mono_id(ccx: @mut CrateContext,
|
||||||
item: ast::def_id,
|
item: ast::def_id,
|
||||||
substs: &[ty::t],
|
|
||||||
vtables: Option<typeck::vtable_res>,
|
|
||||||
impl_did_opt: Option<ast::def_id>,
|
impl_did_opt: Option<ast::def_id>,
|
||||||
|
substs: ¶m_substs,
|
||||||
param_uses: Option<@~[type_use::type_uses]>) -> mono_id {
|
param_uses: Option<@~[type_use::type_uses]>) -> mono_id {
|
||||||
// FIXME (possibly #5801): Need a lot of type hints to get
|
// FIXME (possibly #5801): Need a lot of type hints to get
|
||||||
// .collect() to work.
|
// .collect() to work.
|
||||||
let precise_param_ids: ~[(ty::t, Option<@~[mono_id]>)] = match vtables {
|
let substs_iter = substs.self_ty.iter().chain_(substs.tys.iter());
|
||||||
|
let precise_param_ids: ~[(ty::t, Option<@~[mono_id]>)] = match substs.vtables {
|
||||||
Some(vts) => {
|
Some(vts) => {
|
||||||
debug!("make_mono_id vtables=%s substs=%s",
|
debug!("make_mono_id vtables=%s substs=%s",
|
||||||
vts.repr(ccx.tcx), substs.repr(ccx.tcx));
|
vts.repr(ccx.tcx), substs.tys.repr(ccx.tcx));
|
||||||
vts.iter().zip(substs.iter()).transform(|(vtable, subst)| {
|
let self_vtables = substs.self_vtable.map(|vtbl| @~[copy *vtbl]);
|
||||||
|
let vts_iter = self_vtables.iter().chain_(vts.iter());
|
||||||
|
vts_iter.zip(substs_iter).transform(|(vtable, subst)| {
|
||||||
let v = vtable.map(|vt| meth::vtable_id(ccx, vt));
|
let v = vtable.map(|vt| meth::vtable_id(ccx, vt));
|
||||||
(*subst, if !v.is_empty() { Some(@v) } else { None })
|
(*subst, if !v.is_empty() { Some(@v) } else { None })
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
None => substs.iter().transform(|subst| (*subst, None::<@~[mono_id]>)).collect()
|
None => substs_iter.transform(|subst| (*subst, None::<@~[mono_id]>)).collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
let param_ids = match param_uses {
|
let param_ids = match param_uses {
|
||||||
Some(ref uses) => {
|
Some(ref uses) => {
|
||||||
precise_param_ids.iter().zip(uses.iter()).transform(|(id, uses)| {
|
// param_uses doesn't include a use for the self type.
|
||||||
|
// We just say it is fully used.
|
||||||
|
let self_use =
|
||||||
|
substs.self_ty.map(|_| type_use::use_repr|type_use::use_tydesc);
|
||||||
|
let uses_iter = self_use.iter().chain_(uses.iter());
|
||||||
|
|
||||||
|
precise_param_ids.iter().zip(uses_iter).transform(|(id, uses)| {
|
||||||
if ccx.sess.no_monomorphic_collapse() {
|
if ccx.sess.no_monomorphic_collapse() {
|
||||||
match copy *id {
|
match copy *id {
|
||||||
(a, b) => mono_precise(a, b)
|
(a, b) => mono_precise(a, b)
|
||||||
|
@ -356,7 +368,7 @@ pub fn make_mono_id(ccx: @mut CrateContext,
|
||||||
let llty = type_of::type_of(ccx, subst);
|
let llty = type_of::type_of(ccx, subst);
|
||||||
let size = machine::llbitsize_of_real(ccx, llty);
|
let size = machine::llbitsize_of_real(ccx, llty);
|
||||||
let align = machine::llalign_of_min(ccx, llty);
|
let align = machine::llalign_of_min(ccx, llty);
|
||||||
let mode = datum::appropriate_mode(subst);
|
let mode = datum::appropriate_mode(ccx.tcx, subst);
|
||||||
let data_class = mono_data_classify(subst);
|
let data_class = mono_data_classify(subst);
|
||||||
|
|
||||||
debug!("make_mono_id: type %s -> size %u align %u mode %? class %?",
|
debug!("make_mono_id: type %s -> size %u align %u mode %? class %?",
|
||||||
|
|
|
@ -17,7 +17,6 @@ use middle::trans::callee::{ArgVals, DontAutorefArg};
|
||||||
use middle::trans::callee;
|
use middle::trans::callee;
|
||||||
use middle::trans::common::*;
|
use middle::trans::common::*;
|
||||||
use middle::trans::datum::*;
|
use middle::trans::datum::*;
|
||||||
use middle::trans::expr::SaveIn;
|
|
||||||
use middle::trans::glue;
|
use middle::trans::glue;
|
||||||
use middle::trans::machine;
|
use middle::trans::machine;
|
||||||
use middle::trans::meth;
|
use middle::trans::meth;
|
||||||
|
@ -96,14 +95,13 @@ impl Reflector {
|
||||||
ty::mk_bare_fn(tcx, copy self.visitor_methods[mth_idx].fty);
|
ty::mk_bare_fn(tcx, copy self.visitor_methods[mth_idx].fty);
|
||||||
let v = self.visitor_val;
|
let v = self.visitor_val;
|
||||||
debug!("passing %u args:", args.len());
|
debug!("passing %u args:", args.len());
|
||||||
let bcx = self.bcx;
|
let mut bcx = self.bcx;
|
||||||
for args.iter().enumerate().advance |(i, a)| {
|
for args.iter().enumerate().advance |(i, a)| {
|
||||||
debug!("arg %u: %s", i, bcx.val_to_str(*a));
|
debug!("arg %u: %s", i, bcx.val_to_str(*a));
|
||||||
}
|
}
|
||||||
let bool_ty = ty::mk_bool();
|
let bool_ty = ty::mk_bool();
|
||||||
let scratch = scratch_datum(bcx, bool_ty, false);
|
|
||||||
// XXX: Should not be BoxTraitStore!
|
// XXX: Should not be BoxTraitStore!
|
||||||
let bcx = callee::trans_call_inner(
|
let result = unpack_result!(bcx, callee::trans_call_inner(
|
||||||
self.bcx, None, mth_ty, bool_ty,
|
self.bcx, None, mth_ty, bool_ty,
|
||||||
|bcx| meth::trans_trait_callee_from_llval(bcx,
|
|bcx| meth::trans_trait_callee_from_llval(bcx,
|
||||||
mth_ty,
|
mth_ty,
|
||||||
|
@ -113,8 +111,7 @@ impl Reflector {
|
||||||
ast::sty_region(
|
ast::sty_region(
|
||||||
None,
|
None,
|
||||||
ast::m_imm)),
|
ast::m_imm)),
|
||||||
ArgVals(args), SaveIn(scratch.val), DontAutorefArg);
|
ArgVals(args), None, DontAutorefArg));
|
||||||
let result = scratch.to_value_llval(bcx);
|
|
||||||
let result = bool_to_i1(bcx, result);
|
let result = bool_to_i1(bcx, result);
|
||||||
let next_bcx = sub_block(bcx, "next");
|
let next_bcx = sub_block(bcx, "next");
|
||||||
CondBr(bcx, result, next_bcx.llbb, self.final_bcx.llbb);
|
CondBr(bcx, result, next_bcx.llbb, self.final_bcx.llbb);
|
||||||
|
@ -194,7 +191,11 @@ impl Reflector {
|
||||||
}
|
}
|
||||||
ty::ty_uniq(ref mt) => {
|
ty::ty_uniq(ref mt) => {
|
||||||
let extra = self.c_mt(mt);
|
let extra = self.c_mt(mt);
|
||||||
self.visit("uniq", extra)
|
if ty::type_contents(bcx.tcx(), t).contains_managed() {
|
||||||
|
self.visit("uniq_managed", extra)
|
||||||
|
} else {
|
||||||
|
self.visit("uniq", extra)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ty::ty_ptr(ref mt) => {
|
ty::ty_ptr(ref mt) => {
|
||||||
let extra = self.c_mt(mt);
|
let extra = self.c_mt(mt);
|
||||||
|
@ -278,7 +279,7 @@ impl Reflector {
|
||||||
let opaqueptrty = ty::mk_ptr(ccx.tcx, ty::mt { ty: opaquety, mutbl: ast::m_imm });
|
let opaqueptrty = ty::mk_ptr(ccx.tcx, ty::mt { ty: opaquety, mutbl: ast::m_imm });
|
||||||
|
|
||||||
let make_get_disr = || {
|
let make_get_disr = || {
|
||||||
let sub_path = bcx.fcx.path + [path_name(special_idents::anon)];
|
let sub_path = bcx.fcx.path + &[path_name(special_idents::anon)];
|
||||||
let sym = mangle_internal_name_by_path_and_seq(ccx,
|
let sym = mangle_internal_name_by_path_and_seq(ccx,
|
||||||
sub_path,
|
sub_path,
|
||||||
"get_disr");
|
"get_disr");
|
||||||
|
|
|
@ -33,6 +33,23 @@ use std::option::None;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::codemap;
|
use syntax::codemap;
|
||||||
|
|
||||||
|
pub fn make_uniq_free_glue(bcx: block, vptrptr: ValueRef, box_ty: ty::t)
|
||||||
|
-> block {
|
||||||
|
let box_datum = immediate_rvalue(Load(bcx, vptrptr), box_ty);
|
||||||
|
|
||||||
|
let not_null = IsNotNull(bcx, box_datum.val);
|
||||||
|
do with_cond(bcx, not_null) |bcx| {
|
||||||
|
let body_datum = box_datum.box_body(bcx);
|
||||||
|
let bcx = glue::drop_ty(bcx, body_datum.to_ref_llval(bcx),
|
||||||
|
body_datum.ty);
|
||||||
|
if ty::type_contents(bcx.tcx(), box_ty).contains_managed() {
|
||||||
|
glue::trans_free(bcx, box_datum.val)
|
||||||
|
} else {
|
||||||
|
glue::trans_exchange_free(bcx, box_datum.val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Boxed vector types are in some sense currently a "shorthand" for a box
|
// Boxed vector types are in some sense currently a "shorthand" for a box
|
||||||
// containing an unboxed vector. This expands a boxed vector type into such an
|
// containing an unboxed vector. This expands a boxed vector type into such an
|
||||||
// expanded type. It doesn't respect mutability, but that doesn't matter at
|
// expanded type. It doesn't respect mutability, but that doesn't matter at
|
||||||
|
@ -42,7 +59,7 @@ pub fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
|
||||||
let unboxed_vec_ty = ty::mk_mut_unboxed_vec(tcx, unit_ty);
|
let unboxed_vec_ty = ty::mk_mut_unboxed_vec(tcx, unit_ty);
|
||||||
match ty::get(t).sty {
|
match ty::get(t).sty {
|
||||||
ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) => {
|
ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) => {
|
||||||
ty::mk_imm_uniq(tcx, unboxed_vec_ty)
|
fail!("cannot treat vectors/strings as exchange allocations yet");
|
||||||
}
|
}
|
||||||
ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) => {
|
ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) => {
|
||||||
ty::mk_imm_box(tcx, unboxed_vec_ty)
|
ty::mk_imm_box(tcx, unboxed_vec_ty)
|
||||||
|
@ -95,9 +112,17 @@ pub fn alloc_raw(bcx: block, unit_ty: ty::t,
|
||||||
return rslt(bcx, bx);
|
return rslt(bcx, bx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn heap_for_unique_vector(bcx: block, t: ty::t) -> heap {
|
||||||
|
if ty::type_contents(bcx.tcx(), t).contains_managed() {
|
||||||
|
heap_managed_unique
|
||||||
|
} else {
|
||||||
|
heap_exchange_vector
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn alloc_uniq_raw(bcx: block, unit_ty: ty::t,
|
pub fn alloc_uniq_raw(bcx: block, unit_ty: ty::t,
|
||||||
fill: ValueRef, alloc: ValueRef) -> Result {
|
fill: ValueRef, alloc: ValueRef) -> Result {
|
||||||
alloc_raw(bcx, unit_ty, fill, alloc, base::heap_for_unique(bcx, unit_ty))
|
alloc_raw(bcx, unit_ty, fill, alloc, heap_for_unique_vector(bcx, unit_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc_vec(bcx: block,
|
pub fn alloc_vec(bcx: block,
|
||||||
|
@ -298,7 +323,7 @@ pub fn trans_uniq_or_managed_vstore(bcx: block, heap: heap, vstore_expr: @ast::e
|
||||||
|
|
||||||
// Handle ~"".
|
// Handle ~"".
|
||||||
match heap {
|
match heap {
|
||||||
heap_exchange => {
|
heap_exchange_vector => {
|
||||||
match content_expr.node {
|
match content_expr.node {
|
||||||
ast::expr_lit(@codemap::spanned {
|
ast::expr_lit(@codemap::spanned {
|
||||||
node: ast::lit_str(s), _
|
node: ast::lit_str(s), _
|
||||||
|
@ -312,7 +337,7 @@ pub fn trans_uniq_or_managed_vstore(bcx: block, heap: heap, vstore_expr: @ast::e
|
||||||
bcx,
|
bcx,
|
||||||
bcx.tcx().lang_items.strdup_uniq_fn(),
|
bcx.tcx().lang_items.strdup_uniq_fn(),
|
||||||
[ llptrval, llsizeval ],
|
[ llptrval, llsizeval ],
|
||||||
expr::SaveIn(lldestval.to_ref_llval(bcx)));
|
Some(expr::SaveIn(lldestval.to_ref_llval(bcx)))).bcx;
|
||||||
return DatumBlock {
|
return DatumBlock {
|
||||||
bcx: bcx,
|
bcx: bcx,
|
||||||
datum: lldestval
|
datum: lldestval
|
||||||
|
@ -321,7 +346,7 @@ pub fn trans_uniq_or_managed_vstore(bcx: block, heap: heap, vstore_expr: @ast::e
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
heap_exchange_closure => fail!("vectors are not allocated with closure_exchange_alloc"),
|
heap_exchange | heap_exchange_closure => fail!("vectors use vector_exchange_alloc"),
|
||||||
heap_managed | heap_managed_unique => {}
|
heap_managed | heap_managed_unique => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -245,7 +245,7 @@ impl Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn box(ctx: &CrateContext, ty: &Type) -> Type {
|
pub fn box(ctx: &CrateContext, ty: &Type) -> Type {
|
||||||
Type::struct_(Type::box_header_fields(ctx) + [*ty], false)
|
Type::struct_(Type::box_header_fields(ctx) + &[*ty], false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn opaque_box(ctx: &CrateContext) -> Type {
|
pub fn opaque_box(ctx: &CrateContext) -> Type {
|
||||||
|
|
|
@ -18,8 +18,8 @@ use middle::trans::type_::Type;
|
||||||
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
pub fn arg_is_indirect(_: &CrateContext, arg_ty: &ty::t) -> bool {
|
pub fn arg_is_indirect(ccx: &CrateContext, arg_ty: &ty::t) -> bool {
|
||||||
!ty::type_is_immediate(*arg_ty)
|
!ty::type_is_immediate(ccx.tcx, *arg_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_of_explicit_arg(ccx: &mut CrateContext, arg_ty: &ty::t) -> Type {
|
pub fn type_of_explicit_arg(ccx: &mut CrateContext, arg_ty: &ty::t) -> Type {
|
||||||
|
@ -41,7 +41,7 @@ pub fn type_of_fn(cx: &mut CrateContext, inputs: &[ty::t], output: ty::t) -> Typ
|
||||||
|
|
||||||
// Arg 0: Output pointer.
|
// Arg 0: Output pointer.
|
||||||
// (if the output type is non-immediate)
|
// (if the output type is non-immediate)
|
||||||
let output_is_immediate = ty::type_is_immediate(output);
|
let output_is_immediate = ty::type_is_immediate(cx.tcx, output);
|
||||||
let lloutputtype = type_of(cx, output);
|
let lloutputtype = type_of(cx, output);
|
||||||
if !output_is_immediate {
|
if !output_is_immediate {
|
||||||
atys.push(lloutputtype.ptr_to());
|
atys.push(lloutputtype.ptr_to());
|
||||||
|
@ -72,29 +72,6 @@ pub fn type_of_fn_from_ty(cx: &mut CrateContext, fty: ty::t) -> Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> Type {
|
|
||||||
assert!(!ty::type_needs_infer(t));
|
|
||||||
|
|
||||||
let t_norm = ty::normalize_ty(cx.tcx, t);
|
|
||||||
if t != t_norm {
|
|
||||||
type_of_non_gc_box(cx, t_norm)
|
|
||||||
} else {
|
|
||||||
match ty::get(t).sty {
|
|
||||||
ty::ty_box(mt) => {
|
|
||||||
let ty = type_of(cx, mt.ty);
|
|
||||||
Type::box(cx, &ty).ptr_to()
|
|
||||||
}
|
|
||||||
ty::ty_uniq(mt) => {
|
|
||||||
let ty = type_of(cx, mt.ty);
|
|
||||||
Type::unique(cx, &ty).ptr_to()
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
cx.sess.bug("non-box in type_of_non_gc_box");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A "sizing type" is an LLVM type, the size and alignment of which are
|
// A "sizing type" is an LLVM type, the size and alignment of which are
|
||||||
// guaranteed to be equivalent to what you would get out of `type_of()`. It's
|
// guaranteed to be equivalent to what you would get out of `type_of()`. It's
|
||||||
// useful because:
|
// useful because:
|
||||||
|
@ -104,8 +81,7 @@ pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> Type {
|
||||||
//
|
//
|
||||||
// (2) It won't make any recursive calls to determine the structure of the
|
// (2) It won't make any recursive calls to determine the structure of the
|
||||||
// type behind pointers. This can help prevent infinite loops for
|
// type behind pointers. This can help prevent infinite loops for
|
||||||
// recursive types. For example, `static_size_of_enum()` relies on this
|
// recursive types. For example, enum types rely on this behavior.
|
||||||
// behavior.
|
|
||||||
|
|
||||||
pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> Type {
|
pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> Type {
|
||||||
match cx.llsizingtypes.find_copy(&t) {
|
match cx.llsizingtypes.find_copy(&t) {
|
||||||
|
@ -232,7 +208,11 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type {
|
||||||
ty::ty_opaque_box => Type::opaque_box(cx).ptr_to(),
|
ty::ty_opaque_box => Type::opaque_box(cx).ptr_to(),
|
||||||
ty::ty_uniq(ref mt) => {
|
ty::ty_uniq(ref mt) => {
|
||||||
let ty = type_of(cx, mt.ty);
|
let ty = type_of(cx, mt.ty);
|
||||||
Type::unique(cx, &ty).ptr_to()
|
if ty::type_contents(cx.tcx, mt.ty).contains_managed() {
|
||||||
|
Type::unique(cx, &ty).ptr_to()
|
||||||
|
} else {
|
||||||
|
ty.ptr_to()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ty::ty_evec(ref mt, ty::vstore_uniq) => {
|
ty::ty_evec(ref mt, ty::vstore_uniq) => {
|
||||||
let ty = type_of(cx, mt.ty);
|
let ty = type_of(cx, mt.ty);
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
|
||||||
use back;
|
|
||||||
use lib::llvm::ValueRef;
|
use lib::llvm::ValueRef;
|
||||||
use middle::trans::base::*;
|
use middle::trans::base::*;
|
||||||
use middle::trans::build::*;
|
use middle::trans::build::*;
|
||||||
|
@ -18,6 +17,9 @@ use middle::trans::datum::immediate_rvalue;
|
||||||
use middle::trans::datum;
|
use middle::trans::datum;
|
||||||
use middle::trans::glue;
|
use middle::trans::glue;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
|
use middle::trans::machine::llsize_of;
|
||||||
|
use middle::trans::type_of;
|
||||||
|
use middle::trans::type_of::*;
|
||||||
|
|
||||||
pub fn make_free_glue(bcx: block, vptrptr: ValueRef, box_ty: ty::t)
|
pub fn make_free_glue(bcx: block, vptrptr: ValueRef, box_ty: ty::t)
|
||||||
-> block {
|
-> block {
|
||||||
|
@ -45,12 +47,21 @@ pub fn duplicate(bcx: block, src_box: ValueRef, src_ty: ty::t) -> Result {
|
||||||
let body_datum = src_datum.box_body(bcx);
|
let body_datum = src_datum.box_body(bcx);
|
||||||
|
|
||||||
// Malloc space in exchange heap and copy src into it
|
// Malloc space in exchange heap and copy src into it
|
||||||
let MallocResult {
|
if ty::type_contents(bcx.tcx(), src_ty).contains_managed() {
|
||||||
bcx: bcx,
|
let MallocResult {
|
||||||
box: dst_box,
|
bcx: bcx,
|
||||||
body: dst_body
|
box: dst_box,
|
||||||
} = malloc_unique(bcx, body_datum.ty);
|
body: dst_body
|
||||||
body_datum.copy_to(bcx, datum::INIT, dst_body);
|
} = malloc_general(bcx, body_datum.ty, heap_managed_unique);
|
||||||
|
body_datum.copy_to(bcx, datum::INIT, dst_body);
|
||||||
|
|
||||||
rslt(bcx, dst_box)
|
rslt(bcx, dst_box)
|
||||||
|
} else {
|
||||||
|
let body_datum = body_datum.to_value_datum(bcx);
|
||||||
|
let llty = type_of(bcx.ccx(), body_datum.ty);
|
||||||
|
let size = llsize_of(bcx.ccx(), llty);
|
||||||
|
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, body_datum.ty, heap_exchange, size);
|
||||||
|
body_datum.copy_to(bcx, datum::INIT, val);
|
||||||
|
Result { bcx: bcx, val: val }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ pub fn return_to_mut(mut bcx: block,
|
||||||
filename_val,
|
filename_val,
|
||||||
line_val
|
line_val
|
||||||
],
|
],
|
||||||
expr::Ignore);
|
Some(expr::Ignore)).bcx;
|
||||||
}
|
}
|
||||||
|
|
||||||
callee::trans_lang_call(
|
callee::trans_lang_call(
|
||||||
|
@ -93,8 +93,8 @@ pub fn return_to_mut(mut bcx: block,
|
||||||
filename_val,
|
filename_val,
|
||||||
line_val
|
line_val
|
||||||
],
|
],
|
||||||
expr::Ignore
|
Some(expr::Ignore)
|
||||||
)
|
).bcx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn root(datum: &Datum,
|
fn root(datum: &Datum,
|
||||||
|
@ -123,7 +123,7 @@ fn root(datum: &Datum,
|
||||||
let scratch = scratch_datum(bcx, datum.ty, true);
|
let scratch = scratch_datum(bcx, datum.ty, true);
|
||||||
datum.copy_to_datum(bcx, INIT, scratch);
|
datum.copy_to_datum(bcx, INIT, scratch);
|
||||||
let cleanup_bcx = find_bcx_for_scope(bcx, root_info.scope);
|
let cleanup_bcx = find_bcx_for_scope(bcx, root_info.scope);
|
||||||
add_clean_temp_mem(cleanup_bcx, scratch.val, scratch.ty);
|
add_clean_temp_mem_in_scope(cleanup_bcx, root_info.scope, scratch.val, scratch.ty);
|
||||||
|
|
||||||
// Now, consider also freezing it.
|
// Now, consider also freezing it.
|
||||||
match root_info.freeze {
|
match root_info.freeze {
|
||||||
|
@ -144,7 +144,7 @@ fn root(datum: &Datum,
|
||||||
|
|
||||||
let box_ptr = Load(bcx, PointerCast(bcx, scratch.val, Type::i8p().ptr_to()));
|
let box_ptr = Load(bcx, PointerCast(bcx, scratch.val, Type::i8p().ptr_to()));
|
||||||
|
|
||||||
bcx = callee::trans_lang_call(
|
let llresult = unpack_result!(bcx, callee::trans_lang_call(
|
||||||
bcx,
|
bcx,
|
||||||
freeze_did,
|
freeze_did,
|
||||||
[
|
[
|
||||||
|
@ -152,7 +152,7 @@ fn root(datum: &Datum,
|
||||||
filename,
|
filename,
|
||||||
line
|
line
|
||||||
],
|
],
|
||||||
expr::SaveIn(scratch_bits.val));
|
Some(expr::SaveIn(scratch_bits.val))));
|
||||||
|
|
||||||
if bcx.tcx().sess.debug_borrows() {
|
if bcx.tcx().sess.debug_borrows() {
|
||||||
bcx = callee::trans_lang_call(
|
bcx = callee::trans_lang_call(
|
||||||
|
@ -160,15 +160,15 @@ fn root(datum: &Datum,
|
||||||
bcx.tcx().lang_items.record_borrow_fn(),
|
bcx.tcx().lang_items.record_borrow_fn(),
|
||||||
[
|
[
|
||||||
box_ptr,
|
box_ptr,
|
||||||
Load(bcx, scratch_bits.val),
|
llresult,
|
||||||
filename,
|
filename,
|
||||||
line
|
line
|
||||||
],
|
],
|
||||||
expr::Ignore);
|
Some(expr::Ignore)).bcx;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_clean_return_to_mut(
|
add_clean_return_to_mut(
|
||||||
cleanup_bcx, root_key, scratch.val, scratch_bits.val,
|
cleanup_bcx, root_info.scope, root_key, scratch.val, scratch_bits.val,
|
||||||
filename, line);
|
filename, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,5 +188,5 @@ fn perform_write_guard(datum: &Datum,
|
||||||
bcx,
|
bcx,
|
||||||
bcx.tcx().lang_items.check_not_borrowed_fn(),
|
bcx.tcx().lang_items.check_not_borrowed_fn(),
|
||||||
[PointerCast(bcx, llval, Type::i8p()), filename, line],
|
[PointerCast(bcx, llval, Type::i8p()), filename, line],
|
||||||
expr::Ignore)
|
Some(expr::Ignore)).bcx
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ use util::enum_set::{EnumSet, CLike};
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::hashmap::{HashMap, HashSet};
|
use std::hashmap::{HashMap, HashSet};
|
||||||
use std::iter;
|
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use std::ptr::to_unsafe_ptr;
|
use std::ptr::to_unsafe_ptr;
|
||||||
use std::to_bytes;
|
use std::to_bytes;
|
||||||
|
@ -1486,8 +1485,8 @@ pub fn type_needs_subst(ty: t) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
|
pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
|
||||||
tref.substs.self_ty.iter().any_(|&t| type_is_error(t)) ||
|
tref.substs.self_ty.iter().any(|&t| type_is_error(t)) ||
|
||||||
tref.substs.tps.iter().any_(|&t| type_is_error(t))
|
tref.substs.tps.iter().any(|&t| type_is_error(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_is_ty_var(ty: t) -> bool {
|
pub fn type_is_ty_var(ty: t) -> bool {
|
||||||
|
@ -1647,9 +1646,22 @@ pub fn type_is_scalar(ty: t) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_is_immediate(ty: t) -> bool {
|
fn type_is_newtype_immediate(cx: ctxt, ty: t) -> bool {
|
||||||
|
match get(ty).sty {
|
||||||
|
ty_struct(def_id, ref substs) => {
|
||||||
|
let fields = struct_fields(cx, def_id, substs);
|
||||||
|
fields.len() == 1 &&
|
||||||
|
fields[0].ident == token::special_idents::unnamed_field &&
|
||||||
|
type_is_immediate(cx, fields[0].mt.ty)
|
||||||
|
}
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_is_immediate(cx: ctxt, ty: t) -> bool {
|
||||||
return type_is_scalar(ty) || type_is_boxed(ty) ||
|
return type_is_scalar(ty) || type_is_boxed(ty) ||
|
||||||
type_is_unique(ty) || type_is_region_ptr(ty);
|
type_is_unique(ty) || type_is_region_ptr(ty) ||
|
||||||
|
type_is_newtype_immediate(cx, ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
|
pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
|
||||||
|
@ -1752,7 +1764,7 @@ pub struct TypeContents {
|
||||||
|
|
||||||
impl TypeContents {
|
impl TypeContents {
|
||||||
pub fn meets_bounds(&self, cx: ctxt, bbs: BuiltinBounds) -> bool {
|
pub fn meets_bounds(&self, cx: ctxt, bbs: BuiltinBounds) -> bool {
|
||||||
iter::all(|bb| self.meets_bound(cx, bb), |f| bbs.each(f))
|
bbs.iter().all(|bb| self.meets_bound(cx, bb))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn meets_bound(&self, cx: ctxt, bb: BuiltinBound) -> bool {
|
pub fn meets_bound(&self, cx: ctxt, bb: BuiltinBound) -> bool {
|
||||||
|
@ -2330,13 +2342,13 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
|
||||||
ty_struct(did, ref substs) => {
|
ty_struct(did, ref substs) => {
|
||||||
seen.push(did);
|
seen.push(did);
|
||||||
let fields = struct_fields(cx, did, substs);
|
let fields = struct_fields(cx, did, substs);
|
||||||
let r = fields.iter().any_(|f| type_requires(cx, seen, r_ty, f.mt.ty));
|
let r = fields.iter().any(|f| type_requires(cx, seen, r_ty, f.mt.ty));
|
||||||
seen.pop();
|
seen.pop();
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
ty_tup(ref ts) => {
|
ty_tup(ref ts) => {
|
||||||
ts.iter().any_(|t| type_requires(cx, seen, r_ty, *t))
|
ts.iter().any(|t| type_requires(cx, seen, r_ty, *t))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty_enum(ref did, _) if seen.contains(did) => {
|
ty_enum(ref did, _) if seen.contains(did) => {
|
||||||
|
@ -2347,7 +2359,7 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
|
||||||
seen.push(did);
|
seen.push(did);
|
||||||
let vs = enum_variants(cx, did);
|
let vs = enum_variants(cx, did);
|
||||||
let r = !vs.is_empty() && do vs.iter().all |variant| {
|
let r = !vs.is_empty() && do vs.iter().all |variant| {
|
||||||
do variant.args.iter().any_ |aty| {
|
do variant.args.iter().any |aty| {
|
||||||
let sty = subst(cx, substs, *aty);
|
let sty = subst(cx, substs, *aty);
|
||||||
type_requires(cx, seen, r_ty, sty)
|
type_requires(cx, seen, r_ty, sty)
|
||||||
}
|
}
|
||||||
|
@ -3148,7 +3160,7 @@ pub fn expr_kind(tcx: ctxt,
|
||||||
ast::expr_cast(*) => {
|
ast::expr_cast(*) => {
|
||||||
match tcx.node_types.find(&(expr.id as uint)) {
|
match tcx.node_types.find(&(expr.id as uint)) {
|
||||||
Some(&t) => {
|
Some(&t) => {
|
||||||
if ty::type_is_immediate(t) {
|
if ty::type_is_immediate(tcx, t) {
|
||||||
RvalueDatumExpr
|
RvalueDatumExpr
|
||||||
} else {
|
} else {
|
||||||
RvalueDpsExpr
|
RvalueDpsExpr
|
||||||
|
@ -3229,7 +3241,7 @@ pub fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn method_idx(id: ast::ident, meths: &[@Method]) -> Option<uint> {
|
pub fn method_idx(id: ast::ident, meths: &[@Method]) -> Option<uint> {
|
||||||
meths.iter().position_(|m| m.ident == id)
|
meths.iter().position(|m| m.ident == id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a vector containing the indices of all type parameters that appear
|
/// Returns a vector containing the indices of all type parameters that appear
|
||||||
|
@ -3612,12 +3624,12 @@ pub fn impl_trait_ref(cx: ctxt, id: ast::def_id) -> Option<@TraitRef> {
|
||||||
debug!("(impl_trait_ref) searching for trait impl %?", id);
|
debug!("(impl_trait_ref) searching for trait impl %?", id);
|
||||||
match cx.items.find(&id.node) {
|
match cx.items.find(&id.node) {
|
||||||
Some(&ast_map::node_item(@ast::item {
|
Some(&ast_map::node_item(@ast::item {
|
||||||
node: ast::item_impl(_, opt_trait, _, _),
|
node: ast::item_impl(_, ref opt_trait, _, _),
|
||||||
_},
|
_},
|
||||||
_)) => {
|
_)) => {
|
||||||
match opt_trait {
|
match opt_trait {
|
||||||
Some(t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
|
&Some(ref t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
|
||||||
None => None
|
&None => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => None
|
_ => None
|
||||||
|
@ -3816,41 +3828,62 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
|
||||||
}, _) => {
|
}, _) => {
|
||||||
let mut disr_val = -1;
|
let mut disr_val = -1;
|
||||||
@enum_definition.variants.iter().transform(|variant| {
|
@enum_definition.variants.iter().transform(|variant| {
|
||||||
|
|
||||||
|
let ctor_ty = node_id_to_type(cx, variant.node.id);
|
||||||
|
|
||||||
match variant.node.kind {
|
match variant.node.kind {
|
||||||
ast::tuple_variant_kind(ref args) => {
|
ast::tuple_variant_kind(ref args) => {
|
||||||
let ctor_ty = node_id_to_type(cx, variant.node.id);
|
let arg_tys = if args.len() > 0u {
|
||||||
let arg_tys = {
|
ty_fn_args(ctor_ty).map(|a| *a) }
|
||||||
if args.len() > 0u {
|
else {
|
||||||
ty_fn_args(ctor_ty).map(|a| *a)
|
|
||||||
} else {
|
|
||||||
~[]
|
~[]
|
||||||
}
|
};
|
||||||
};
|
|
||||||
match variant.node.disr_expr {
|
match variant.node.disr_expr {
|
||||||
Some (ex) => {
|
Some (ex) => {
|
||||||
disr_val = match const_eval::eval_const_expr(cx,
|
disr_val = match const_eval::eval_const_expr(cx,
|
||||||
ex) {
|
ex) {
|
||||||
const_eval::const_int(val) => val as int,
|
const_eval::const_int(val) => val as int,
|
||||||
_ => cx.sess.bug("tag_variants: bad disr expr")
|
_ => cx.sess.bug("enum_variants: bad disr expr")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => disr_val += 1
|
_ => disr_val += 1
|
||||||
}
|
}
|
||||||
@VariantInfo_{args: arg_tys,
|
@VariantInfo_{
|
||||||
ctor_ty: ctor_ty,
|
args: arg_tys,
|
||||||
name: variant.node.name,
|
ctor_ty: ctor_ty,
|
||||||
id: ast_util::local_def(variant.node.id),
|
name: variant.node.name,
|
||||||
disr_val: disr_val,
|
id: ast_util::local_def(variant.node.id),
|
||||||
vis: variant.node.vis
|
disr_val: disr_val,
|
||||||
|
vis: variant.node.vis
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
ast::struct_variant_kind(_) => {
|
ast::struct_variant_kind(struct_def) => {
|
||||||
fail!("struct variant kinds unimpl in enum_variants")
|
let arg_tys =
|
||||||
|
// Is this check needed for structs too, or are they always guaranteed
|
||||||
|
// to have a valid constructor function?
|
||||||
|
if struct_def.fields.len() > 0 {
|
||||||
|
ty_fn_args(ctor_ty).map(|a| *a)
|
||||||
|
} else {
|
||||||
|
~[]
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(variant.node.disr_expr.is_none());
|
||||||
|
disr_val += 1;
|
||||||
|
|
||||||
|
@VariantInfo_{
|
||||||
|
args: arg_tys,
|
||||||
|
ctor_ty: ctor_ty,
|
||||||
|
name: variant.node.name,
|
||||||
|
id: ast_util::local_def(variant.node.id),
|
||||||
|
disr_val: disr_val,
|
||||||
|
vis: variant.node.vis
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
_ => cx.sess.bug("tag_variants: id not bound to an enum")
|
_ => cx.sess.bug("enum_variants: id not bound to an enum")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
cx.enum_var_cache.insert(id, result);
|
cx.enum_var_cache.insert(id, result);
|
||||||
|
|
|
@ -85,15 +85,15 @@ pub trait AstConv {
|
||||||
pub fn get_region_reporting_err(
|
pub fn get_region_reporting_err(
|
||||||
tcx: ty::ctxt,
|
tcx: ty::ctxt,
|
||||||
span: span,
|
span: span,
|
||||||
a_r: Option<@ast::Lifetime>,
|
a_r: &Option<ast::Lifetime>,
|
||||||
res: Result<ty::Region, RegionError>) -> ty::Region
|
res: Result<ty::Region, RegionError>) -> ty::Region
|
||||||
{
|
{
|
||||||
match res {
|
match res {
|
||||||
result::Ok(r) => r,
|
result::Ok(r) => r,
|
||||||
result::Err(ref e) => {
|
result::Err(ref e) => {
|
||||||
let descr = match a_r {
|
let descr = match a_r {
|
||||||
None => ~"anonymous lifetime",
|
&None => ~"anonymous lifetime",
|
||||||
Some(a) => fmt!("lifetime %s",
|
&Some(ref a) => fmt!("lifetime %s",
|
||||||
lifetime_to_str(a, tcx.sess.intr()))
|
lifetime_to_str(a, tcx.sess.intr()))
|
||||||
};
|
};
|
||||||
tcx.sess.span_err(
|
tcx.sess.span_err(
|
||||||
|
@ -109,19 +109,19 @@ pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Copy + 'static>(
|
||||||
this: &AC,
|
this: &AC,
|
||||||
rscope: &RS,
|
rscope: &RS,
|
||||||
default_span: span,
|
default_span: span,
|
||||||
opt_lifetime: Option<@ast::Lifetime>) -> ty::Region
|
opt_lifetime: &Option<ast::Lifetime>) -> ty::Region
|
||||||
{
|
{
|
||||||
let (span, res) = match opt_lifetime {
|
let (span, res) = match opt_lifetime {
|
||||||
None => {
|
&None => {
|
||||||
(default_span, rscope.anon_region(default_span))
|
(default_span, rscope.anon_region(default_span))
|
||||||
}
|
}
|
||||||
Some(ref lifetime) if lifetime.ident == special_idents::statik => {
|
&Some(ref lifetime) if lifetime.ident == special_idents::statik => {
|
||||||
(lifetime.span, Ok(ty::re_static))
|
(lifetime.span, Ok(ty::re_static))
|
||||||
}
|
}
|
||||||
Some(ref lifetime) if lifetime.ident == special_idents::self_ => {
|
&Some(ref lifetime) if lifetime.ident == special_idents::self_ => {
|
||||||
(lifetime.span, rscope.self_region(lifetime.span))
|
(lifetime.span, rscope.self_region(lifetime.span))
|
||||||
}
|
}
|
||||||
Some(ref lifetime) => {
|
&Some(ref lifetime) => {
|
||||||
(lifetime.span, rscope.named_region(lifetime.span,
|
(lifetime.span, rscope.named_region(lifetime.span,
|
||||||
lifetime.ident))
|
lifetime.ident))
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ fn ast_path_substs<AC:AstConv,RS:region_scope + Copy + 'static>(
|
||||||
def_id: ast::def_id,
|
def_id: ast::def_id,
|
||||||
decl_generics: &ty::Generics,
|
decl_generics: &ty::Generics,
|
||||||
self_ty: Option<ty::t>,
|
self_ty: Option<ty::t>,
|
||||||
path: @ast::Path) -> ty::substs
|
path: &ast::Path) -> ty::substs
|
||||||
{
|
{
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
|
@ -164,11 +164,11 @@ fn ast_path_substs<AC:AstConv,RS:region_scope + Copy + 'static>(
|
||||||
}
|
}
|
||||||
(&Some(_), &None) => {
|
(&Some(_), &None) => {
|
||||||
let res = rscope.anon_region(path.span);
|
let res = rscope.anon_region(path.span);
|
||||||
let r = get_region_reporting_err(this.tcx(), path.span, None, res);
|
let r = get_region_reporting_err(this.tcx(), path.span, &None, res);
|
||||||
Some(r)
|
Some(r)
|
||||||
}
|
}
|
||||||
(&Some(_), &Some(_)) => {
|
(&Some(_), &Some(_)) => {
|
||||||
Some(ast_region_to_region(this, rscope, path.span, path.rp))
|
Some(ast_region_to_region(this, rscope, path.span, &path.rp))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ fn ast_path_substs<AC:AstConv,RS:region_scope + Copy + 'static>(
|
||||||
fmt!("wrong number of type arguments: expected %u but found %u",
|
fmt!("wrong number of type arguments: expected %u but found %u",
|
||||||
decl_generics.type_param_defs.len(), path.types.len()));
|
decl_generics.type_param_defs.len(), path.types.len()));
|
||||||
}
|
}
|
||||||
let tps = path.types.map(|a_t| ast_ty_to_ty(this, rscope, *a_t));
|
let tps = path.types.map(|a_t| ast_ty_to_ty(this, rscope, a_t));
|
||||||
|
|
||||||
substs {self_r:self_r, self_ty:self_ty, tps:tps}
|
substs {self_r:self_r, self_ty:self_ty, tps:tps}
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + 'static>(
|
||||||
this: &AC,
|
this: &AC,
|
||||||
rscope: &RS,
|
rscope: &RS,
|
||||||
did: ast::def_id,
|
did: ast::def_id,
|
||||||
path: @ast::Path) -> ty_param_substs_and_ty
|
path: &ast::Path) -> ty_param_substs_and_ty
|
||||||
{
|
{
|
||||||
let tcx = this.tcx();
|
let tcx = this.tcx();
|
||||||
let ty::ty_param_bounds_and_ty {
|
let ty::ty_param_bounds_and_ty {
|
||||||
|
@ -206,7 +206,7 @@ pub fn ast_path_to_trait_ref<AC:AstConv,RS:region_scope + Copy + 'static>(
|
||||||
rscope: &RS,
|
rscope: &RS,
|
||||||
trait_def_id: ast::def_id,
|
trait_def_id: ast::def_id,
|
||||||
self_ty: Option<ty::t>,
|
self_ty: Option<ty::t>,
|
||||||
path: @ast::Path) -> @ty::TraitRef
|
path: &ast::Path) -> @ty::TraitRef
|
||||||
{
|
{
|
||||||
let trait_def =
|
let trait_def =
|
||||||
this.get_trait_def(trait_def_id);
|
this.get_trait_def(trait_def_id);
|
||||||
|
@ -228,7 +228,7 @@ pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Copy + 'static>(
|
||||||
this: &AC,
|
this: &AC,
|
||||||
rscope: &RS,
|
rscope: &RS,
|
||||||
did: ast::def_id,
|
did: ast::def_id,
|
||||||
path: @ast::Path)
|
path: &ast::Path)
|
||||||
-> ty_param_substs_and_ty
|
-> ty_param_substs_and_ty
|
||||||
{
|
{
|
||||||
// Look up the polytype of the item and then substitute the provided types
|
// Look up the polytype of the item and then substitute the provided types
|
||||||
|
@ -276,7 +276,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
|
||||||
}
|
}
|
||||||
return ty::mk_evec(tcx, mt, vst);
|
return ty::mk_evec(tcx, mt, vst);
|
||||||
}
|
}
|
||||||
ast::ty_path(path, bounds, id) => {
|
ast::ty_path(ref path, ref bounds, id) => {
|
||||||
// Note that the "bounds must be empty if path is not a trait"
|
// Note that the "bounds must be empty if path is not a trait"
|
||||||
// restriction is enforced in the below case for ty_path, which
|
// restriction is enforced in the below case for ty_path, which
|
||||||
// will run after this as long as the path isn't a trait.
|
// will run after this as long as the path isn't a trait.
|
||||||
|
@ -321,7 +321,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_path_args(tcx: ty::ctxt,
|
fn check_path_args(tcx: ty::ctxt,
|
||||||
path: @ast::Path,
|
path: &ast::Path,
|
||||||
flags: uint) {
|
flags: uint) {
|
||||||
if (flags & NO_TPS) != 0u {
|
if (flags & NO_TPS) != 0u {
|
||||||
if path.types.len() > 0u {
|
if path.types.len() > 0u {
|
||||||
|
@ -371,13 +371,13 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
|
||||||
ast::ty_ptr(ref mt) => {
|
ast::ty_ptr(ref mt) => {
|
||||||
ty::mk_ptr(tcx, ast_mt_to_mt(this, rscope, mt))
|
ty::mk_ptr(tcx, ast_mt_to_mt(this, rscope, mt))
|
||||||
}
|
}
|
||||||
ast::ty_rptr(region, ref mt) => {
|
ast::ty_rptr(ref region, ref mt) => {
|
||||||
let r = ast_region_to_region(this, rscope, ast_ty.span, region);
|
let r = ast_region_to_region(this, rscope, ast_ty.span, region);
|
||||||
mk_pointer(this, rscope, mt, ty::vstore_slice(r),
|
mk_pointer(this, rscope, mt, ty::vstore_slice(r),
|
||||||
|tmt| ty::mk_rptr(tcx, r, tmt))
|
|tmt| ty::mk_rptr(tcx, r, tmt))
|
||||||
}
|
}
|
||||||
ast::ty_tup(ref fields) => {
|
ast::ty_tup(ref fields) => {
|
||||||
let flds = fields.map(|t| ast_ty_to_ty(this, rscope, *t));
|
let flds = fields.map(|t| ast_ty_to_ty(this, rscope, t));
|
||||||
ty::mk_tup(tcx, flds)
|
ty::mk_tup(tcx, flds)
|
||||||
}
|
}
|
||||||
ast::ty_bare_fn(ref bf) => {
|
ast::ty_bare_fn(ref bf) => {
|
||||||
|
@ -398,14 +398,14 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
|
||||||
f.purity,
|
f.purity,
|
||||||
f.onceness,
|
f.onceness,
|
||||||
bounds,
|
bounds,
|
||||||
f.region,
|
&f.region,
|
||||||
&f.decl,
|
&f.decl,
|
||||||
None,
|
None,
|
||||||
&f.lifetimes,
|
&f.lifetimes,
|
||||||
ast_ty.span);
|
ast_ty.span);
|
||||||
ty::mk_closure(tcx, fn_decl)
|
ty::mk_closure(tcx, fn_decl)
|
||||||
}
|
}
|
||||||
ast::ty_path(path, bounds, id) => {
|
ast::ty_path(ref path, ref bounds, id) => {
|
||||||
let a_def = match tcx.def_map.find(&id) {
|
let a_def = match tcx.def_map.find(&id) {
|
||||||
None => tcx.sess.span_fatal(
|
None => tcx.sess.span_fatal(
|
||||||
ast_ty.span, fmt!("unbound path %s",
|
ast_ty.span, fmt!("unbound path %s",
|
||||||
|
@ -525,13 +525,13 @@ pub fn ty_of_arg<AC:AstConv,
|
||||||
RS:region_scope + Copy + 'static>(
|
RS:region_scope + Copy + 'static>(
|
||||||
this: &AC,
|
this: &AC,
|
||||||
rscope: &RS,
|
rscope: &RS,
|
||||||
a: ast::arg,
|
a: &ast::arg,
|
||||||
expected_ty: Option<ty::t>)
|
expected_ty: Option<ty::t>)
|
||||||
-> ty::t {
|
-> ty::t {
|
||||||
match a.ty.node {
|
match a.ty.node {
|
||||||
ast::ty_infer if expected_ty.is_some() => expected_ty.get(),
|
ast::ty_infer if expected_ty.is_some() => expected_ty.get(),
|
||||||
ast::ty_infer => this.ty_infer(a.ty.span),
|
ast::ty_infer => this.ty_infer(a.ty.span),
|
||||||
_ => ast_ty_to_ty(this, rscope, a.ty),
|
_ => ast_ty_to_ty(this, rscope, &a.ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,7 +553,7 @@ pub fn bound_lifetimes<AC:AstConv>(
|
||||||
let special_idents = [special_idents::statik, special_idents::self_];
|
let special_idents = [special_idents::statik, special_idents::self_];
|
||||||
let mut bound_lifetime_names = opt_vec::Empty;
|
let mut bound_lifetime_names = opt_vec::Empty;
|
||||||
ast_lifetimes.map_to_vec(|ast_lifetime| {
|
ast_lifetimes.map_to_vec(|ast_lifetime| {
|
||||||
if special_idents.iter().any_(|&i| i == ast_lifetime.ident) {
|
if special_idents.iter().any(|&i| i == ast_lifetime.ident) {
|
||||||
this.tcx().sess.span_err(
|
this.tcx().sess.span_err(
|
||||||
ast_lifetime.span,
|
ast_lifetime.span,
|
||||||
fmt!("illegal lifetime parameter name: `%s`",
|
fmt!("illegal lifetime parameter name: `%s`",
|
||||||
|
@ -621,11 +621,11 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
|
||||||
transform_self_ty(this, &rb, self_info)
|
transform_self_ty(this, &rb, self_info)
|
||||||
});
|
});
|
||||||
|
|
||||||
let input_tys = decl.inputs.map(|a| ty_of_arg(this, &rb, *a, None));
|
let input_tys = decl.inputs.map(|a| ty_of_arg(this, &rb, a, None));
|
||||||
|
|
||||||
let output_ty = match decl.output.node {
|
let output_ty = match decl.output.node {
|
||||||
ast::ty_infer => this.ty_infer(decl.output.span),
|
ast::ty_infer => this.ty_infer(decl.output.span),
|
||||||
_ => ast_ty_to_ty(this, &rb, decl.output)
|
_ => ast_ty_to_ty(this, &rb, &decl.output)
|
||||||
};
|
};
|
||||||
|
|
||||||
return (opt_transformed_self_ty,
|
return (opt_transformed_self_ty,
|
||||||
|
@ -647,7 +647,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
|
||||||
ast::sty_value => {
|
ast::sty_value => {
|
||||||
Some(self_info.untransformed_self_ty)
|
Some(self_info.untransformed_self_ty)
|
||||||
}
|
}
|
||||||
ast::sty_region(lifetime, mutability) => {
|
ast::sty_region(ref lifetime, mutability) => {
|
||||||
let region =
|
let region =
|
||||||
ast_region_to_region(this, rscope,
|
ast_region_to_region(this, rscope,
|
||||||
self_info.explicit_self.span,
|
self_info.explicit_self.span,
|
||||||
|
@ -677,7 +677,7 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
|
||||||
purity: ast::purity,
|
purity: ast::purity,
|
||||||
onceness: ast::Onceness,
|
onceness: ast::Onceness,
|
||||||
bounds: ty::BuiltinBounds,
|
bounds: ty::BuiltinBounds,
|
||||||
opt_lifetime: Option<@ast::Lifetime>,
|
opt_lifetime: &Option<ast::Lifetime>,
|
||||||
decl: &ast::fn_decl,
|
decl: &ast::fn_decl,
|
||||||
expected_sig: Option<ty::FnSig>,
|
expected_sig: Option<ty::FnSig>,
|
||||||
lifetimes: &OptVec<ast::Lifetime>,
|
lifetimes: &OptVec<ast::Lifetime>,
|
||||||
|
@ -695,10 +695,10 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
|
||||||
// resolve the function bound region in the original region
|
// resolve the function bound region in the original region
|
||||||
// scope `rscope`, not the scope of the function parameters
|
// scope `rscope`, not the scope of the function parameters
|
||||||
let bound_region = match opt_lifetime {
|
let bound_region = match opt_lifetime {
|
||||||
Some(_) => {
|
&Some(_) => {
|
||||||
ast_region_to_region(this, rscope, span, opt_lifetime)
|
ast_region_to_region(this, rscope, span, opt_lifetime)
|
||||||
}
|
}
|
||||||
None => {
|
&None => {
|
||||||
match sigil {
|
match sigil {
|
||||||
ast::OwnedSigil | ast::ManagedSigil => {
|
ast::OwnedSigil | ast::ManagedSigil => {
|
||||||
// @fn(), ~fn() default to static as the bound
|
// @fn(), ~fn() default to static as the bound
|
||||||
|
@ -724,14 +724,14 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
|
||||||
// were supplied
|
// were supplied
|
||||||
if i < e.inputs.len() {Some(e.inputs[i])} else {None}
|
if i < e.inputs.len() {Some(e.inputs[i])} else {None}
|
||||||
};
|
};
|
||||||
ty_of_arg(this, &rb, *a, expected_arg_ty)
|
ty_of_arg(this, &rb, a, expected_arg_ty)
|
||||||
}.collect();
|
}.collect();
|
||||||
|
|
||||||
let expected_ret_ty = expected_sig.map(|e| e.output);
|
let expected_ret_ty = expected_sig.map(|e| e.output);
|
||||||
let output_ty = match decl.output.node {
|
let output_ty = match decl.output.node {
|
||||||
ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.get(),
|
ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.get(),
|
||||||
ast::ty_infer => this.ty_infer(decl.output.span),
|
ast::ty_infer => this.ty_infer(decl.output.span),
|
||||||
_ => ast_ty_to_ty(this, &rb, decl.output)
|
_ => ast_ty_to_ty(this, &rb, &decl.output)
|
||||||
};
|
};
|
||||||
|
|
||||||
ty::ClosureTy {
|
ty::ClosureTy {
|
||||||
|
@ -764,7 +764,7 @@ fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option<OptVec<ast::TyParamBou
|
||||||
let mut builtin_bounds = ty::EmptyBuiltinBounds();
|
let mut builtin_bounds = ty::EmptyBuiltinBounds();
|
||||||
for bound_vec.iter().advance |ast_bound| {
|
for bound_vec.iter().advance |ast_bound| {
|
||||||
match *ast_bound {
|
match *ast_bound {
|
||||||
ast::TraitTyParamBound(b) => {
|
ast::TraitTyParamBound(ref b) => {
|
||||||
match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
|
match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
|
||||||
ast::def_trait(trait_did) => {
|
ast::def_trait(trait_did) => {
|
||||||
if try_add_builtin_trait(tcx,
|
if try_add_builtin_trait(tcx,
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue