auto merge of #14234 : alexcrichton/rust/rollup, r=alexcrichton

Let's try this again!
This commit is contained in:
bors 2014-05-15 15:56:54 -07:00
commit 0481d628b8
95 changed files with 2034 additions and 434 deletions

View File

@ -68,7 +68,7 @@
#
# * `TESTNAME=...` - Specify the name of tests to run
# * `CHECK_IGNORED=1` - Run normally-ignored tests
# * `NO_BENCH=1` - Don't run crate benchmarks (disable `--bench` flag)
# * `PLEASE_BENCH=1` - Run crate benchmarks (enable `--bench` flag)
#
# * `CFG_ENABLE_VALGRIND=1` - Run tests under valgrind
# * `VALGRIND_COMPILE=1` - Run the compiler itself under valgrind

View File

@ -51,19 +51,21 @@
TARGET_CRATES := libc std green rustuv native flate arena glob term semver \
uuid serialize sync getopts collections num test time rand \
workcache url log regex graphviz core
workcache url log regex graphviz core rlibc
HOST_CRATES := syntax rustc rustdoc fourcc hexfloat regex_macros fmt_macros
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
TOOLS := compiletest rustdoc rustc
DEPS_core :=
DEPS_rlibc :=
DEPS_std := core libc native:rustrt native:compiler-rt native:backtrace native:jemalloc
DEPS_graphviz := std
DEPS_green := std rand native:context_switch
DEPS_rustuv := std native:uv native:uv_support
DEPS_native := std
DEPS_syntax := std term serialize collections log fmt_macros
DEPS_rustc := syntax native:rustllvm flate arena serialize sync getopts \
collections time log
collections time log graphviz
DEPS_rustdoc := rustc native:hoedown serialize sync getopts collections \
test time
DEPS_flate := std native:miniz
@ -98,6 +100,7 @@ TOOL_SOURCE_rustdoc := $(S)src/driver/driver.rs
TOOL_SOURCE_rustc := $(S)src/driver/driver.rs
ONLY_RLIB_core := 1
ONLY_RLIB_rlibc := 1
################################################################################
# You should not need to edit below this line

View File

@ -30,7 +30,7 @@ DOCS := index intro tutorial guide-ffi guide-macros guide-lifetimes \
guide-tasks guide-container guide-pointers guide-testing \
guide-runtime complement-bugreport complement-cheatsheet \
complement-lang-faq complement-project-faq rust rustdoc \
guide-unsafe not_found
guide-unsafe
PDF_DOCS := tutorial rust
@ -42,10 +42,11 @@ L10N_LANGS := ja
# Generally no need to edit below here.
# The options are passed to the documentation generators.
RUSTDOC_HTML_OPTS = --markdown-css rust.css \
--markdown-before-content=doc/version_info.html \
RUSTDOC_HTML_OPTS_NO_CSS = --markdown-before-content=doc/version_info.html \
--markdown-in-header=doc/favicon.inc --markdown-after-content=doc/footer.inc
RUSTDOC_HTML_OPTS = $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css rust.css
PANDOC_BASE_OPTS := --standalone --toc --number-sections
PANDOC_TEX_OPTS = $(PANDOC_BASE_OPTS) --include-before-body=doc/version.tex \
--from=markdown --include-before-body=doc/footer.tex --to=latex
@ -152,6 +153,11 @@ doc/footer.tex: $(D)/footer.inc | doc/
@$(call E, pandoc: $@)
$(CFG_PANDOC) --from=html --to=latex $< --output=$@
# HTML (rustdoc)
DOC_TARGETS += doc/not_found.html
doc/not_found.html: $(D)/not_found.md $(HTML_DEPS) | doc/
$(RUSTDOC) $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css http://static.rust-lang.org/doc/master/rust.css $<
define DEF_DOC
# HTML (rustdoc)

View File

@ -32,7 +32,7 @@ ifdef CHECK_IGNORED
TESTARGS += --ignored
endif
TEST_BENCH = --bench
TEST_BENCH =
# Arguments to the cfail/rfail/rpass/bench tests
ifdef CFG_VALGRIND
@ -40,8 +40,8 @@ ifdef CFG_VALGRIND
TEST_BENCH =
endif
ifdef NO_BENCH
TEST_BENCH =
ifdef PLEASE_BENCH
TEST_BENCH = --bench
endif
# Arguments to the perf tests

View File

@ -1799,6 +1799,8 @@ type int8_t = i8;
- `no_start` - disable linking to the `native` crate, which specifies the
"start" language item.
- `no_std` - disable linking to the `std` crate.
- `no_builtins` - disable optimizing certain code patterns to invocations of
library functions that are assumed to exist
### Module-only attributes

View File

@ -186,6 +186,25 @@ impl<'b, T> Deref<T> for Ref<'b, T> {
}
}
/// Copy a `Ref`.
///
/// The `RefCell` is already immutably borrowed, so this cannot fail.
///
/// A `Clone` implementation would interfere with the widespread
/// use of `r.borrow().clone()` to clone the contents of a `RefCell`.
#[experimental]
pub fn clone_ref<'b, T>(orig: &Ref<'b, T>) -> Ref<'b, T> {
// Since this Ref exists, we know the borrow flag
// is not set to WRITING.
let borrow = orig.parent.borrow.get();
debug_assert!(borrow != WRITING && borrow != UNUSED);
orig.parent.borrow.set(borrow + 1);
Ref {
parent: orig.parent,
}
}
/// Wraps a mutable borrowed reference to a value in a `RefCell` box.
pub struct RefMut<'b, T> {
parent: &'b RefCell<T>
@ -307,4 +326,19 @@ mod test {
let _ = _b;
let _b = x.borrow_mut();
}
#[test]
fn clone_ref_updates_flag() {
let x = RefCell::new(0);
{
let b1 = x.borrow();
assert!(x.try_borrow_mut().is_none());
{
let _b2 = clone_ref(&b1);
assert!(x.try_borrow_mut().is_none());
}
assert!(x.try_borrow_mut().is_none());
}
assert!(x.try_borrow_mut().is_some());
}
}

View File

@ -192,7 +192,23 @@ pub fn max<T: TotalOrd>(v1: T, v2: T) -> T {
// Implementation of Eq/TotalEq for some primitive types
#[cfg(not(test))]
mod impls {
use cmp::{Ord, TotalOrd, Eq, TotalEq, Ordering};
use cmp::{Ord, TotalOrd, Eq, TotalEq, Ordering, Equal};
impl Eq for () {
#[inline]
fn eq(&self, _other: &()) -> bool { true }
#[inline]
fn ne(&self, _other: &()) -> bool { false }
}
impl TotalEq for () {}
impl Ord for () {
#[inline]
fn lt(&self, _other: &()) -> bool { false }
}
impl TotalOrd for () {
#[inline]
fn cmp(&self, _other: &()) -> Ordering { Equal }
}
// & pointers
impl<'a, T: Eq> Eq for &'a T {

View File

@ -16,6 +16,11 @@ pub trait Default {
fn default() -> Self;
}
impl Default for () {
#[inline]
fn default() -> () { () }
}
impl<T: Default + 'static> Default for @T {
fn default() -> @T { @Default::default() }
}

View File

@ -18,6 +18,9 @@
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//! often generated by LLVM. Additionally, this library can make explicit
//! calls to these funcitons. Their signatures are the same as found in C.
//! These functions are often provided by the system libc, but can also be
//! provided by `librlibc` which is distributed with the standard rust
//! distribution.
//!
//! * `rust_begin_unwind` - This function takes three arguments, a
//! `&fmt::Arguments`, a `&str`, and a `uint. These three arguments dictate
@ -100,7 +103,6 @@ pub mod container;
/* Core types and methods on primitives */
mod unicode;
mod unit;
pub mod any;
pub mod atomics;
pub mod bool;
@ -116,9 +118,6 @@ pub mod slice;
pub mod str;
pub mod tuple;
#[cfg(stage0, not(test))]
pub mod owned;
// FIXME: this module should not exist. Once owned allocations are no longer a
// language type, this module can move outside to the owned allocation
// crate.

View File

@ -1,101 +0,0 @@
// 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.
//! Operations on unique pointer types
use any::{Any, AnyRefExt};
use clone::Clone;
use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering};
use default::Default;
use intrinsics;
use mem;
use raw::TraitObject;
use result::{Ok, Err, Result};
/// A value that represents the global exchange heap. This is the default
/// place that the `box` keyword allocates into when no place is supplied.
///
/// The following two examples are equivalent:
///
/// let foo = box(HEAP) Bar::new(...);
/// let foo = box Bar::new(...);
#[lang="exchange_heap"]
pub static HEAP: () = ();
/// A type that represents a uniquely-owned value.
#[lang="owned_box"]
pub struct Box<T>(*T);
impl<T: Default> Default for Box<T> {
fn default() -> Box<T> { box Default::default() }
}
impl<T: Clone> Clone for Box<T> {
/// Return a copy of the owned box.
#[inline]
fn clone(&self) -> Box<T> { box {(**self).clone()} }
/// Perform copy-assignment from `source` by reusing the existing allocation.
#[inline]
fn clone_from(&mut self, source: &Box<T>) {
(**self).clone_from(&(**source));
}
}
// box pointers
impl<T:Eq> Eq for Box<T> {
#[inline]
fn eq(&self, other: &Box<T>) -> bool { *(*self) == *(*other) }
#[inline]
fn ne(&self, other: &Box<T>) -> bool { *(*self) != *(*other) }
}
impl<T:Ord> Ord for Box<T> {
#[inline]
fn lt(&self, other: &Box<T>) -> bool { *(*self) < *(*other) }
#[inline]
fn le(&self, other: &Box<T>) -> bool { *(*self) <= *(*other) }
#[inline]
fn ge(&self, other: &Box<T>) -> bool { *(*self) >= *(*other) }
#[inline]
fn gt(&self, other: &Box<T>) -> bool { *(*self) > *(*other) }
}
impl<T: TotalOrd> TotalOrd for Box<T> {
#[inline]
fn cmp(&self, other: &Box<T>) -> Ordering { (**self).cmp(*other) }
}
impl<T: TotalEq> TotalEq for Box<T> {}
/// Extension methods for an owning `Any` trait object
pub trait AnyOwnExt {
/// Returns the boxed value if it is of type `T`, or
/// `Err(Self)` if it isn't.
fn move<T: 'static>(self) -> Result<Box<T>, Self>;
}
impl AnyOwnExt for Box<Any> {
#[inline]
fn move<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
if self.is::<T>() {
unsafe {
// Get the raw representation of the trait object
let to: TraitObject =
*mem::transmute::<&Box<Any>, &TraitObject>(&self);
// Prevent destructor on self being run
intrinsics::forget(self);
// Extract the data pointer
Ok(mem::transmute(to.data))
}
} else {
Err(self)
}
}
}

View File

@ -1,45 +0,0 @@
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Functions for the unit type.
#[cfg(not(test))]
use default::Default;
#[cfg(not(test))]
use cmp::{Eq, Equal, Ord, Ordering, TotalEq, TotalOrd};
#[cfg(not(test))]
impl Eq for () {
#[inline]
fn eq(&self, _other: &()) -> bool { true }
#[inline]
fn ne(&self, _other: &()) -> bool { false }
}
#[cfg(not(test))]
impl Ord for () {
#[inline]
fn lt(&self, _other: &()) -> bool { false }
}
#[cfg(not(test))]
impl TotalOrd for () {
#[inline]
fn cmp(&self, _other: &()) -> Ordering { Equal }
}
#[cfg(not(test))]
impl TotalEq for () {}
#[cfg(not(test))]
impl Default for () {
#[inline]
fn default() -> () { () }
}

View File

@ -1137,11 +1137,10 @@ mod test {
fn test_schedule_home_states() {
use sleeper_list::SleeperList;
use super::{Shutdown, Scheduler, SchedHandle};
use std::unstable::run_in_bare_thread;
use std::rt::thread::Thread;
use std::sync::deque::BufferPool;
run_in_bare_thread(proc() {
Thread::start(proc() {
let sleepers = SleeperList::new();
let mut pool = BufferPool::new();
let (normal_worker, normal_stealer) = pool.deque();
@ -1260,7 +1259,7 @@ mod test {
normal_thread.join();
special_thread.join();
});
}).join();
}
//#[test]

View File

@ -493,9 +493,7 @@ fn mkstat(stat: &libc::stat) -> io::FileStat {
io::FileStat {
size: stat.st_size as u64,
kind: kind,
perm: unsafe {
io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
},
perm: io::FilePermission::from_bits_truncate(stat.st_mode as u32),
created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),

View File

@ -492,9 +492,7 @@ fn mkstat(stat: &libc::stat) -> io::FileStat {
io::FileStat {
size: stat.st_size as u64,
kind: kind,
perm: unsafe {
io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
},
perm: io::FilePermission::from_bits_truncate(stat.st_mode as u32),
created: stat.st_ctime as u64,
modified: stat.st_mtime as u64,
accessed: stat.st_atime as u64,

99
src/librlibc/lib.rs Normal file
View File

@ -0,0 +1,99 @@
// Copyright 2014 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.
//! A bare-metal library supplying functions rustc may lower code to
//!
//! This library is not intended for general use, and is superseded by a system
//! libc if one is available. In a freestanding context, however, common
//! functions such as memset, memcpy, etc are not implemented. This library
//! provides an implementation of these functions which are either required by
//! libcore or called by rustc implicitly.
//!
//! This library is never included by default, and must be manually included if
//! necessary. It is an error to include this library when also linking with
//! the system libc library.
#![crate_id = "rlibc#0.11.0-pre"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://static.rust-lang.org/doc/master")]
#![no_std]
#![experimental]
// This library is definining the builtin functions, so it would be a shame for
// LLVM to optimize these function calls to themselves!
#![no_builtins]
#[cfg(test)] extern crate std;
#[cfg(test)] extern crate native;
// Require the offset intrinsics for LLVM to properly optimize the
// implementations below. If pointer arithmetic is done through integers the
// optimizations start to break down.
extern "rust-intrinsic" {
fn offset<T>(dst: *T, offset: int) -> *T;
}
#[no_mangle]
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *u8, n: uint) -> *mut u8 {
let mut i = 0;
while i < n {
*(offset(dest as *u8, i as int) as *mut u8) = *offset(src, i as int);
i += 1;
}
return dest;
}
#[no_mangle]
pub unsafe extern "C" fn memmove(dest: *mut u8, src: *u8, n: uint) -> *mut u8 {
if src < dest as *u8 { // copy from end
let mut i = n;
while i != 0 {
i -= 1;
*(offset(dest as *u8, i as int) as *mut u8) = *offset(src, i as int);
}
} else { // copy from beginning
let mut i = 0;
while i < n {
*(offset(dest as *u8, i as int) as *mut u8) = *offset(src, i as int);
i += 1;
}
}
return dest;
}
#[no_mangle]
pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: uint) -> *mut u8 {
let mut i = 0;
while i < n {
*(offset(s as *u8, i as int) as *mut u8) = c as u8;
i += 1;
}
return s;
}
#[no_mangle]
pub unsafe extern "C" fn memcmp(s1: *u8, s2: *u8, n: uint) -> i32 {
let mut i = 0;
while i < n {
let a = *offset(s1, i as int);
let b = *offset(s2, i as int);
if a != b {
return (a - b) as i32
}
i += 1;
}
return 0;
}
#[test] fn work_on_windows() { } // FIXME #10872 needed for a happy windows

View File

@ -212,7 +212,8 @@ pub mod write {
if !sess.opts.cg.no_prepopulate_passes {
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
populate_llvm_passes(fpm, mpm, llmod, opt_level);
populate_llvm_passes(fpm, mpm, llmod, opt_level,
trans.no_builtins);
}
for pass in sess.opts.cg.passes.iter() {
@ -264,11 +265,11 @@ pub mod write {
// escape the closure itself, and the manager should only be
// used once.
fn with_codegen(tm: TargetMachineRef, llmod: ModuleRef,
f: |PassManagerRef|) {
no_builtins: bool, f: |PassManagerRef|) {
unsafe {
let cpm = llvm::LLVMCreatePassManager();
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
llvm::LLVMRustAddLibraryInfo(cpm, llmod);
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
f(cpm);
llvm::LLVMDisposePassManager(cpm);
}
@ -286,7 +287,7 @@ pub mod write {
}
OutputTypeLlvmAssembly => {
path.with_c_str(|output| {
with_codegen(tm, llmod, |cpm| {
with_codegen(tm, llmod, trans.no_builtins, |cpm| {
llvm::LLVMRustPrintModule(cpm, llmod, output);
})
})
@ -303,7 +304,7 @@ pub mod write {
needs_metadata = true;
output.temp_path(OutputTypeAssembly)
};
with_codegen(tm, llmod, |cpm| {
with_codegen(tm, llmod, trans.no_builtins, |cpm| {
WriteOutputFile(sess, tm, cpm, llmod, &path,
lib::llvm::AssemblyFile);
});
@ -321,7 +322,7 @@ pub mod write {
time(sess.time_passes(), "codegen passes", (), |()| {
match object_file {
Some(ref path) => {
with_codegen(tm, llmod, |cpm| {
with_codegen(tm, llmod, trans.no_builtins, |cpm| {
WriteOutputFile(sess, tm, cpm, llmod, path,
lib::llvm::ObjectFile);
});
@ -329,7 +330,8 @@ pub mod write {
None => {}
}
if needs_metadata {
with_codegen(tm, trans.metadata_module, |cpm| {
with_codegen(tm, trans.metadata_module,
trans.no_builtins, |cpm| {
let out = output.temp_path(OutputTypeObject)
.with_extension("metadata.o");
WriteOutputFile(sess, tm, cpm,
@ -437,7 +439,8 @@ pub mod write {
unsafe fn populate_llvm_passes(fpm: lib::llvm::PassManagerRef,
mpm: lib::llvm::PassManagerRef,
llmod: ModuleRef,
opt: lib::llvm::CodeGenOptLevel) {
opt: lib::llvm::CodeGenOptLevel,
no_builtins: bool) {
// Create the PassManagerBuilder for LLVM. We configure it with
// reasonable defaults and prepare it to actually populate the pass
// manager.
@ -461,7 +464,7 @@ pub mod write {
}
}
llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod);
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, no_builtins);
// Use the builder to populate the function/module pass managers.
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);

View File

@ -519,12 +519,13 @@ pub fn optgroups() -> Vec<getopts::OptGroup> {
optopt( "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
optflagopt("", "pretty",
"Pretty-print the input instead of compiling;
valid types are: normal (un-annotated source),
expanded (crates expanded),
typed (crates expanded, with type annotations),
or identified (fully parenthesized,
AST nodes and blocks with IDs)", "TYPE"),
"Pretty-print the input instead of compiling;
valid types are: `normal` (un-annotated source),
`expanded` (crates expanded),
`typed` (crates expanded, with type annotations),
`expanded,identified` (fully parenthesized, AST nodes with IDs), or
`flowgraph=<nodeid>` (graphviz formatted flowgraph for node)",
"TYPE"),
optflagopt("", "dep-info",
"Output dependency info to <filename> after compiling, \
in a format suitable for use by Makefiles", "FILENAME"),

View File

@ -11,12 +11,15 @@
use back::link;
use driver::session::Session;
use driver::config;
use driver::{config, PpMode};
use driver::PpmFlowGraph; // FIXME (#14221).
use front;
use lib::llvm::{ContextRef, ModuleRef};
use metadata::common::LinkMeta;
use metadata::creader;
use metadata::creader::Loader;
use middle::cfg;
use middle::cfg::graphviz::LabelledCFG;
use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
use middle::dependency_format;
use middle;
@ -24,6 +27,8 @@ use util::common::time;
use util::ppaux;
use util::nodemap::{NodeSet};
use dot = graphviz;
use serialize::{json, Encodable};
use std::io;
@ -356,6 +361,7 @@ pub struct CrateTranslation {
pub metadata: Vec<u8>,
pub reachable: Vec<StrBuf>,
pub crate_formats: dependency_format::Dependencies,
pub no_builtins: bool,
}
/// Run the translation phase to LLVM, after which the AST and analysis can
@ -581,14 +587,14 @@ impl pprust::PpAnn for TypedAnnotation {
pub fn pretty_print_input(sess: Session,
cfg: ast::CrateConfig,
input: &Input,
ppm: ::driver::PpMode,
ppm: PpMode,
ofile: Option<Path>) {
let krate = phase_1_parse_input(&sess, cfg, input);
let id = link::find_crate_id(krate.attrs.as_slice(),
input.filestem().as_slice());
let (krate, ast_map, is_expanded) = match ppm {
PpmExpanded | PpmExpandedIdentified | PpmTyped => {
PpmExpanded | PpmExpandedIdentified | PpmTyped | PpmFlowGraph(_) => {
let loader = &mut Loader::new(&sess);
let (krate, ast_map) = phase_2_configure_and_expand(&sess,
loader,
@ -643,6 +649,18 @@ pub fn pretty_print_input(sess: Session,
&annotation,
is_expanded)
}
PpmFlowGraph(nodeid) => {
let ast_map = ast_map.expect("--pretty flowgraph missing ast_map");
let node = ast_map.find(nodeid).unwrap_or_else(|| {
fail!("--pretty flowgraph=id couldn't find id: {}", id)
});
let block = match node {
syntax::ast_map::NodeBlock(block) => block,
_ => fail!("--pretty=flowgraph needs block, got {:?}", node)
};
let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map);
print_flowgraph(analysis, block, out)
}
_ => {
pprust::print_crate(sess.codemap(),
sess.diagnostic(),
@ -657,6 +675,32 @@ pub fn pretty_print_input(sess: Session,
}
fn print_flowgraph<W:io::Writer>(analysis: CrateAnalysis,
block: ast::P<ast::Block>,
mut out: W) -> io::IoResult<()> {
let ty_cx = &analysis.ty_cx;
let cfg = cfg::CFG::new(ty_cx, block);
let lcfg = LabelledCFG { ast_map: &ty_cx.map,
cfg: &cfg,
name: format!("block{}", block.id).to_strbuf(), };
debug!("cfg: {:?}", cfg);
let r = dot::render(&lcfg, &mut out);
return expand_err_details(r);
fn expand_err_details(r: io::IoResult<()>) -> io::IoResult<()> {
r.map_err(|ioerr| {
let orig_detail = ioerr.detail.clone();
let m = "graphviz::render failed";
io::IoError {
detail: Some(match orig_detail {
None => m.into_owned(), Some(d) => format!("{}: {}", m, d)
}),
..ioerr
}
})
}
}
pub fn collect_crate_types(session: &Session,
attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
// If we're generating a test executable, then ignore all other output

View File

@ -285,20 +285,32 @@ pub enum PpMode {
PpmExpanded,
PpmTyped,
PpmIdentified,
PpmExpandedIdentified
PpmExpandedIdentified,
PpmFlowGraph(ast::NodeId),
}
pub fn parse_pretty(sess: &Session, name: &str) -> PpMode {
match name {
"normal" => PpmNormal,
"expanded" => PpmExpanded,
"typed" => PpmTyped,
"expanded,identified" => PpmExpandedIdentified,
"identified" => PpmIdentified,
let mut split = name.splitn('=', 1);
let first = split.next().unwrap();
let opt_second = split.next();
match (opt_second, first) {
(None, "normal") => PpmNormal,
(None, "expanded") => PpmExpanded,
(None, "typed") => PpmTyped,
(None, "expanded,identified") => PpmExpandedIdentified,
(None, "identified") => PpmIdentified,
(Some(s), "flowgraph") => {
match from_str(s) {
Some(id) => PpmFlowGraph(id),
None => sess.fatal(format!("`pretty flowgraph=<nodeid>` needs \
an integer <nodeid>; got {}", s))
}
}
_ => {
sess.fatal("argument to `pretty` must be one of `normal`, \
`expanded`, `typed`, `identified`, \
or `expanded,identified`");
sess.fatal(format!(
"argument to `pretty` must be one of `normal`, \
`expanded`, `flowgraph=<nodeid>`, `typed`, `identified`, \
or `expanded,identified`; got {}", name));
}
}
}

View File

@ -33,6 +33,7 @@ This API is completely unstable and subject to change.
extern crate flate;
extern crate arena;
extern crate graphviz;
extern crate syntax;
extern crate serialize;
extern crate sync;
@ -122,4 +123,3 @@ pub mod lib {
pub fn main() {
std::os::set_exit_status(driver::main_args(std::os::args().as_slice()));
}

View File

@ -1755,8 +1755,10 @@ pub mod llvm {
PM: PassManagerRef,
M: ModuleRef);
pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
M: ModuleRef);
pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef);
M: ModuleRef,
DisableSimplifyLibCalls: bool);
pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef,
DisableSimplifyLibCalls: bool);
pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
pub fn LLVMRustWriteOutputFile(T: TargetMachineRef,
PM: PassManagerRef,

View File

@ -18,10 +18,10 @@ use util::nodemap::NodeMap;
struct CFGBuilder<'a> {
tcx: &'a ty::ctxt,
method_map: typeck::MethodMap,
exit_map: NodeMap<CFGIndex>,
graph: CFGGraph,
loop_scopes: Vec<LoopScope> ,
fn_exit: CFGIndex,
loop_scopes: Vec<LoopScope>,
}
struct LoopScope {
@ -31,22 +31,35 @@ struct LoopScope {
}
pub fn construct(tcx: &ty::ctxt,
method_map: typeck::MethodMap,
blk: &ast::Block) -> CFG {
let mut graph = graph::Graph::new();
let entry = add_initial_dummy_node(&mut graph);
// `fn_exit` is target of return exprs, which lies somewhere
// outside input `blk`. (Distinguishing `fn_exit` and `block_exit`
// also resolves chicken-and-egg problem that arises if you try to
// have return exprs jump to `block_exit` during construction.)
let fn_exit = add_initial_dummy_node(&mut graph);
let block_exit;
let mut cfg_builder = CFGBuilder {
exit_map: NodeMap::new(),
graph: graph::Graph::new(),
graph: graph,
fn_exit: fn_exit,
tcx: tcx,
method_map: method_map,
loop_scopes: Vec::new()
};
let entry = cfg_builder.add_node(0, []);
let exit = cfg_builder.block(blk, entry);
block_exit = cfg_builder.block(blk, entry);
cfg_builder.add_contained_edge(block_exit, fn_exit);
let CFGBuilder {exit_map, graph, ..} = cfg_builder;
CFG {exit_map: exit_map,
graph: graph,
entry: entry,
exit: exit}
exit: fn_exit}
}
fn add_initial_dummy_node(g: &mut CFGGraph) -> CFGIndex {
g.add_node(CFGNodeData { id: ast::DUMMY_NODE_ID })
}
impl<'a> CFGBuilder<'a> {
@ -327,24 +340,25 @@ impl<'a> CFGBuilder<'a> {
ast::ExprRet(v) => {
let v_exit = self.opt_expr(v, pred);
let loop_scope = *self.loop_scopes.get(0);
self.add_exiting_edge(expr, v_exit,
loop_scope, loop_scope.break_index);
self.add_node(expr.id, [])
let b = self.add_node(expr.id, [v_exit]);
self.add_returning_edge(expr, b);
self.add_node(ast::DUMMY_NODE_ID, [])
}
ast::ExprBreak(label) => {
let loop_scope = self.find_scope(expr, label);
self.add_exiting_edge(expr, pred,
let b = self.add_node(expr.id, [pred]);
self.add_exiting_edge(expr, b,
loop_scope, loop_scope.break_index);
self.add_node(expr.id, [])
self.add_node(ast::DUMMY_NODE_ID, [])
}
ast::ExprAgain(label) => {
let loop_scope = self.find_scope(expr, label);
self.add_exiting_edge(expr, pred,
let a = self.add_node(expr.id, [pred]);
self.add_exiting_edge(expr, a,
loop_scope, loop_scope.continue_index);
self.add_node(expr.id, [])
self.add_node(ast::DUMMY_NODE_ID, [])
}
ast::ExprVec(ref elems) => {
@ -453,13 +467,16 @@ impl<'a> CFGBuilder<'a> {
}
fn add_dummy_node(&mut self, preds: &[CFGIndex]) -> CFGIndex {
self.add_node(0, preds)
self.add_node(ast::DUMMY_NODE_ID, preds)
}
fn add_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex {
assert!(!self.exit_map.contains_key(&id));
let node = self.graph.add_node(CFGNodeData {id: id});
self.exit_map.insert(id, node);
if id != ast::DUMMY_NODE_ID {
assert!(!self.exit_map.contains_key(&id));
self.exit_map.insert(id, node);
}
for &pred in preds.iter() {
self.add_contained_edge(pred, node);
}
@ -488,6 +505,16 @@ impl<'a> CFGBuilder<'a> {
self.graph.add_edge(from_index, to_index, data);
}
fn add_returning_edge(&mut self,
_from_expr: @ast::Expr,
from_index: CFGIndex) {
let mut data = CFGEdgeData {exiting_scopes: vec!() };
for &LoopScope { loop_id: id, .. } in self.loop_scopes.iter().rev() {
data.exiting_scopes.push(id);
}
self.graph.add_edge(from_index, self.fn_exit, data);
}
fn find_scope(&self,
expr: @ast::Expr,
label: Option<ast::Ident>) -> LoopScope {
@ -521,6 +548,6 @@ impl<'a> CFGBuilder<'a> {
fn is_method_call(&self, expr: &ast::Expr) -> bool {
let method_call = typeck::MethodCall::expr(expr.id);
self.method_map.borrow().contains_key(&method_call)
self.tcx.method_map.borrow().contains_key(&method_call)
}
}

View File

@ -0,0 +1,116 @@
// Copyright 2014 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.
/// This module provides linkage between rustc::middle::graph and
/// libgraphviz traits.
/// For clarity, rename the graphviz crate locally to dot.
use dot = graphviz;
use syntax::ast;
use syntax::ast_map;
use middle::cfg;
pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode);
pub type Edge<'a> = &'a cfg::CFGEdge;
pub struct LabelledCFG<'a>{
pub ast_map: &'a ast_map::Map,
pub cfg: &'a cfg::CFG,
pub name: StrBuf,
}
fn replace_newline_with_backslash_l(s: StrBuf) -> StrBuf {
// Replacing newlines with \\l causes each line to be left-aligned,
// improving presentation of (long) pretty-printed expressions.
if s.as_slice().contains("\n") {
let mut s = s.replace("\n", "\\l");
// Apparently left-alignment applies to the line that precedes
// \l, not the line that follows; so, add \l at end of string
// if not already present, ensuring last line gets left-aligned
// as well.
let mut last_two : Vec<_> = s.chars().rev().take(2).collect();
last_two.reverse();
if last_two.as_slice() != ['\\', 'l'] {
s = s.append("\\l");
}
s.to_strbuf()
} else {
s
}
}
impl<'a> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a> {
fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(self.name.as_slice()) }
fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> {
dot::Id::new(format!("N{:u}", i.node_id()))
}
fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> {
if i == self.cfg.entry {
dot::LabelStr("entry".into_maybe_owned())
} else if i == self.cfg.exit {
dot::LabelStr("exit".into_maybe_owned())
} else if n.data.id == ast::DUMMY_NODE_ID {
dot::LabelStr("(dummy_node)".into_maybe_owned())
} else {
let s = self.ast_map.node_to_str(n.data.id);
// left-aligns the lines
let s = replace_newline_with_backslash_l(s);
dot::EscStr(s.into_maybe_owned())
}
}
fn edge_label(&self, e: &Edge<'a>) -> dot::LabelText<'a> {
let mut label = StrBuf::new();
let mut put_one = false;
for (i, &node_id) in e.data.exiting_scopes.iter().enumerate() {
if put_one {
label = label.append(",\\l");
} else {
put_one = true;
}
let s = self.ast_map.node_to_str(node_id);
// left-aligns the lines
let s = replace_newline_with_backslash_l(s);
label = label.append(format!("exiting scope_{} {}", i, s.as_slice()));
}
dot::EscStr(label.into_maybe_owned())
}
}
impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for &'a cfg::CFG {
fn nodes(&self) -> dot::Nodes<'a, Node<'a>> {
let mut v = Vec::new();
self.graph.each_node(|i, nd| { v.push((i, nd)); true });
dot::maybe_owned_vec::Growable(v)
}
fn edges(&self) -> dot::Edges<'a, Edge<'a>> {
self.graph.all_edges().iter().collect()
}
fn source(&self, edge: &Edge<'a>) -> Node<'a> {
let i = edge.source();
(i, self.graph.node(i))
}
fn target(&self, edge: &Edge<'a>) -> Node<'a> {
let i = edge.target();
(i, self.graph.node(i))
}
}
impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a>
{
fn nodes(&self) -> dot::Nodes<'a, Node<'a>> { self.cfg.nodes() }
fn edges(&self) -> dot::Edges<'a, Edge<'a>> { self.cfg.edges() }
fn source(&self, edge: &Edge<'a>) -> Node<'a> { self.cfg.source(edge) }
fn target(&self, edge: &Edge<'a>) -> Node<'a> { self.cfg.target(edge) }
}

View File

@ -19,25 +19,25 @@ Uses `Graph` as the underlying representation.
use middle::graph;
use middle::ty;
use middle::typeck;
use syntax::ast;
use util::nodemap::NodeMap;
mod construct;
pub mod graphviz;
pub struct CFG {
exit_map: NodeMap<CFGIndex>,
graph: CFGGraph,
entry: CFGIndex,
exit: CFGIndex,
pub exit_map: NodeMap<CFGIndex>,
pub graph: CFGGraph,
pub entry: CFGIndex,
pub exit: CFGIndex,
}
pub struct CFGNodeData {
id: ast::NodeId
pub id: ast::NodeId
}
pub struct CFGEdgeData {
exiting_scopes: Vec<ast::NodeId>
pub exiting_scopes: Vec<ast::NodeId>
}
pub type CFGIndex = graph::NodeIndex;
@ -55,8 +55,7 @@ pub struct CFGIndices {
impl CFG {
pub fn new(tcx: &ty::ctxt,
method_map: typeck::MethodMap,
blk: &ast::Block) -> CFG {
construct::construct(tcx, method_map, blk)
construct::construct(tcx, blk)
}
}

View File

@ -70,10 +70,14 @@ pub static Incoming: Direction = Direction { repr: 1 };
impl NodeIndex {
fn get(&self) -> uint { let NodeIndex(v) = *self; v }
/// Returns unique id (unique with respect to the graph holding associated node).
pub fn node_id(&self) -> uint { self.get() }
}
impl EdgeIndex {
fn get(&self) -> uint { let EdgeIndex(v) = *self; v }
/// Returns unique id (unique with respect to the graph holding associated edge).
pub fn edge_id(&self) -> uint { self.get() }
}
impl<N,E> Graph<N,E> {
@ -201,39 +205,39 @@ impl<N,E> Graph<N,E> {
///////////////////////////////////////////////////////////////////////////
// Iterating over nodes, edges
pub fn each_node(&self, f: |NodeIndex, &Node<N>| -> bool) -> bool {
pub fn each_node<'a>(&'a self, f: |NodeIndex, &'a Node<N>| -> bool) -> bool {
//! Iterates over all edges defined in the graph.
self.nodes.iter().enumerate().advance(|(i, node)| f(NodeIndex(i), node))
}
pub fn each_edge(&self, f: |EdgeIndex, &Edge<E>| -> bool) -> bool {
pub fn each_edge<'a>(&'a self, f: |EdgeIndex, &'a Edge<E>| -> bool) -> bool {
//! Iterates over all edges defined in the graph
self.edges.iter().enumerate().advance(|(i, edge)| f(EdgeIndex(i), edge))
}
pub fn each_outgoing_edge(&self,
source: NodeIndex,
f: |EdgeIndex, &Edge<E>| -> bool)
-> bool {
pub fn each_outgoing_edge<'a>(&'a self,
source: NodeIndex,
f: |EdgeIndex, &'a Edge<E>| -> bool)
-> bool {
//! Iterates over all outgoing edges from the node `from`
self.each_adjacent_edge(source, Outgoing, f)
}
pub fn each_incoming_edge(&self,
target: NodeIndex,
f: |EdgeIndex, &Edge<E>| -> bool)
-> bool {
pub fn each_incoming_edge<'a>(&'a self,
target: NodeIndex,
f: |EdgeIndex, &'a Edge<E>| -> bool)
-> bool {
//! Iterates over all incoming edges to the node `target`
self.each_adjacent_edge(target, Incoming, f)
}
pub fn each_adjacent_edge(&self,
node: NodeIndex,
dir: Direction,
f: |EdgeIndex, &Edge<E>| -> bool)
-> bool {
pub fn each_adjacent_edge<'a>(&'a self,
node: NodeIndex,
dir: Direction,
f: |EdgeIndex, &'a Edge<E>| -> bool)
-> bool {
//! Iterates over all edges adjacent to the node `node`
//! in the direction `dir` (either `Outgoing` or `Incoming)
@ -257,11 +261,11 @@ impl<N,E> Graph<N,E> {
// variables or other bitsets. This method facilitates such a
// computation.
pub fn iterate_until_fixed_point(&self,
op: |iter_index: uint,
edge_index: EdgeIndex,
edge: &Edge<E>|
-> bool) {
pub fn iterate_until_fixed_point<'a>(&'a self,
op: |iter_index: uint,
edge_index: EdgeIndex,
edge: &'a Edge<E>|
-> bool) {
let mut iteration = 0;
let mut changed = true;
while changed {

View File

@ -1050,6 +1050,7 @@ fn check_raw_ptr_deriving(cx: &mut Context, item: &ast::Item) {
static crate_attrs: &'static [&'static str] = &[
"crate_type", "feature", "no_start", "no_main", "no_std", "crate_id",
"desc", "comment", "license", "copyright", // not used in rustc now
"no_builtins",
];

View File

@ -2226,6 +2226,7 @@ pub fn trans_crate(krate: ast::Crate,
let metadata_module = ccx.metadata_llmod;
let formats = ccx.tcx.dependency_formats.borrow().clone();
let no_builtins = attr::contains_name(krate.attrs.as_slice(), "no_builtins");
(ccx.tcx, CrateTranslation {
context: llcx,
@ -2235,5 +2236,6 @@ pub fn trans_crate(krate: ast::Crate,
metadata: metadata,
reachable: reachable,
crate_formats: formats,
no_builtins: no_builtins,
})
}

View File

@ -309,6 +309,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
ast_map::NodeStmt(..) |
ast_map::NodeArg(..) |
ast_map::NodeBlock(..) |
ast_map::NodePat(..) |
ast_map::NodeLocal(..) => {
ccx.sess().bug(format!("can't monomorphize a {:?}", map_node))
}

View File

@ -1204,7 +1204,7 @@ impl Clean<Item> for ast::ForeignItem {
ForeignFunctionItem(Function {
decl: decl.clean(),
generics: generics.clean(),
fn_style: ast::NormalFn,
fn_style: ast::UnsafeFn,
})
}
ast::ForeignItemStatic(ref ty, mutbl) => {

View File

@ -285,9 +285,7 @@ impl FsRequest {
FileStat {
size: stat.st_size as u64,
kind: kind,
perm: unsafe {
io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
},
perm: io::FilePermission::from_bits_truncate(stat.st_mode as u32),
created: to_msec(stat.st_birthtim),
modified: to_msec(stat.st_mtim),
accessed: to_msec(stat.st_atim),

View File

@ -472,7 +472,7 @@ fn local_loop() -> &'static mut uvio::UvIoFactory {
#[cfg(test)]
mod test {
use std::mem::transmute;
use std::unstable::run_in_bare_thread;
use std::rt::thread::Thread;
use super::{slice_to_uv_buf, Loop};
@ -496,10 +496,10 @@ mod test {
#[test]
fn loop_smoke_test() {
run_in_bare_thread(proc() {
Thread::start(proc() {
let mut loop_ = Loop::new();
loop_.run();
loop_.close();
});
}).join();
}
}

View File

@ -27,7 +27,7 @@ use std::rt::rtio;
use std::rt::rtio::{ProcessConfig, IoFactory, EventLoop};
use ai = std::io::net::addrinfo;
#[cfg(test)] use std::unstable::run_in_bare_thread;
#[cfg(test)] use std::rt::thread::Thread;
use super::{uv_error_to_io_error, Loop};
@ -116,7 +116,7 @@ impl EventLoop for UvEventLoop {
#[test]
fn test_callback_run_once() {
run_in_bare_thread(proc() {
Thread::start(proc() {
let mut event_loop = UvEventLoop::new();
let mut count = 0;
let count_ptr: *mut int = &mut count;
@ -125,7 +125,7 @@ fn test_callback_run_once() {
});
event_loop.run();
assert_eq!(count, 1);
});
}).join();
}
pub struct UvIoFactory {

View File

@ -136,10 +136,20 @@ macro_rules! bitflags(
self.bits
}
/// Convert from underlying bit representation. Unsafe because the
/// bits are not guaranteed to represent valid flags.
pub unsafe fn from_bits(bits: $T) -> $BitFlags {
$BitFlags { bits: bits }
/// Convert from underlying bit representation, unless that
/// representation contains bits that do not correspond to a flag.
pub fn from_bits(bits: $T) -> ::std::option::Option<$BitFlags> {
if (bits & !$BitFlags::all().bits()) != 0 {
::std::option::None
} else {
::std::option::Some($BitFlags { bits: bits })
}
}
/// Convert from underlying bit representation, dropping any bits
/// that do not correspond to flags.
pub fn from_bits_truncate(bits: $T) -> $BitFlags {
$BitFlags { bits: bits } & $BitFlags::all()
}
/// Returns `true` if no flags are currently stored.
@ -209,6 +219,7 @@ macro_rules! bitflags(
#[cfg(test)]
mod tests {
use option::{Some, None};
use ops::{BitOr, BitAnd, Sub, Not};
bitflags!(
@ -231,9 +242,21 @@ mod tests {
#[test]
fn test_from_bits() {
assert!(unsafe { Flags::from_bits(0x00000000) } == Flags::empty());
assert!(unsafe { Flags::from_bits(0x00000001) } == FlagA);
assert!(unsafe { Flags::from_bits(0x00000111) } == FlagABC);
assert!(Flags::from_bits(0) == Some(Flags::empty()));
assert!(Flags::from_bits(0x1) == Some(FlagA));
assert!(Flags::from_bits(0x10) == Some(FlagB));
assert!(Flags::from_bits(0x11) == Some(FlagA | FlagB));
assert!(Flags::from_bits(0x1000) == None);
}
#[test]
fn test_from_bits_truncate() {
assert!(Flags::from_bits_truncate(0) == Flags::empty());
assert!(Flags::from_bits_truncate(0x1) == FlagA);
assert!(Flags::from_bits_truncate(0x10) == FlagB);
assert!(Flags::from_bits_truncate(0x11) == (FlagA | FlagB));
assert!(Flags::from_bits_truncate(0x1000) == Flags::empty());
assert!(Flags::from_bits_truncate(0x1001) == FlagA);
}
#[test]

View File

@ -209,7 +209,7 @@ impl<W: Writer> Writer for BufferedWriter<W> {
impl<W: Writer> Drop for BufferedWriter<W> {
fn drop(&mut self) {
if self.inner.is_some() {
// FIXME(#12628): should this error be ignored?
// dtors should not fail, so we ignore a failed flush
let _ = self.flush_buf();
}
}
@ -370,6 +370,7 @@ mod test {
use io;
use prelude::*;
use super::*;
use super::super::{IoResult, EndOfFile};
use super::super::mem::{MemReader, MemWriter, BufReader};
use self::test::Bencher;
use str::StrSlice;
@ -584,6 +585,24 @@ mod test {
assert_eq!(it.next(), None);
}
#[test]
#[should_fail]
fn dont_fail_in_drop_on_failed_flush() {
struct FailFlushWriter;
impl Writer for FailFlushWriter {
fn write(&mut self, _buf: &[u8]) -> IoResult<()> { Ok(()) }
fn flush(&mut self) -> IoResult<()> { Err(io::standard_error(EndOfFile)) }
}
let writer = FailFlushWriter;
let _writer = BufferedWriter::new(writer);
// Trigger failure. If writer fails *again* due to the flush
// error then the process will abort.
fail!();
}
#[bench]
fn bench_buffered_reader(b: &mut Bencher) {
b.iter(|| {

View File

@ -1,52 +0,0 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Some various other I/O types
// FIXME(#3660): should move to libextra
use prelude::*;
use super::*;
/// A Writer decorator that compresses using the 'deflate' scheme
pub struct DeflateWriter<W> {
priv inner_writer: W
}
impl<W: Writer> DeflateWriter<W> {
pub fn new(inner_writer: W) -> DeflateWriter<W> {
DeflateWriter {
inner_writer: inner_writer
}
}
}
impl<W: Writer> Writer for DeflateWriter<W> {
fn write(&mut self, _buf: &[u8]) { fail!() }
fn flush(&mut self) { fail!() }
}
/// A Reader decorator that decompresses using the 'deflate' scheme
pub struct InflateReader<R> {
priv inner_reader: R
}
impl<R: Reader> InflateReader<R> {
pub fn new(inner_reader: R) -> InflateReader<R> {
InflateReader {
inner_reader: inner_reader
}
}
}
impl<R: Reader> Reader for InflateReader<R> {
fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
}

View File

@ -10,7 +10,7 @@
//! Temporary files and directories
use io::fs;
use io::{fs, IoResult};
use io;
use iter::{Iterator, range};
use libc;
@ -18,13 +18,14 @@ use ops::Drop;
use option::{Option, None, Some};
use os;
use path::{Path, GenericPath};
use result::{Ok, Err, ResultUnwrap};
use result::{Ok, Err};
use sync::atomics;
/// A wrapper for a path to temporary directory implementing automatic
/// scope-based deletion.
pub struct TempDir {
path: Option<Path>
path: Option<Path>,
disarmed: bool
}
impl TempDir {
@ -48,7 +49,7 @@ impl TempDir {
let p = tmpdir.join(filename);
match fs::mkdir(&p, io::UserRWX) {
Err(..) => {}
Ok(()) => return Some(TempDir { path: Some(p) })
Ok(()) => return Some(TempDir { path: Some(p), disarmed: false })
}
}
None
@ -75,15 +76,32 @@ impl TempDir {
pub fn path<'a>(&'a self) -> &'a Path {
self.path.get_ref()
}
/// Close and remove the temporary directory
///
/// Although `TempDir` removes the directory on drop, in the destructor
/// any errors are ignored. To detect errors cleaning up the temporary
/// directory, call `close` instead.
pub fn close(mut self) -> IoResult<()> {
self.cleanup_dir()
}
fn cleanup_dir(&mut self) -> IoResult<()> {
assert!(!self.disarmed);
self.disarmed = true;
match self.path {
Some(ref p) => {
fs::rmdir_recursive(p)
}
None => Ok(())
}
}
}
impl Drop for TempDir {
fn drop(&mut self) {
for path in self.path.iter() {
if path.exists() {
// FIXME: is failing the right thing to do?
fs::rmdir_recursive(path).unwrap();
}
if !self.disarmed {
let _ = self.cleanup_dir();
}
}
}

View File

@ -133,16 +133,13 @@ extern crate core;
#[cfg(test)] pub use ops = realstd::ops;
#[cfg(test)] pub use cmp = realstd::cmp;
#[cfg(test)] pub use ty = realstd::ty;
#[cfg(not(stage0), test)] pub use owned = realstd::owned;
#[cfg(test)] pub use owned = realstd::owned;
#[cfg(not(test))] pub use cmp = core::cmp;
#[cfg(not(test))] pub use kinds = core::kinds;
#[cfg(not(test))] pub use ops = core::ops;
#[cfg(not(test))] pub use ty = core::ty;
#[cfg(stage0, test)] pub use owned = realstd::owned;
#[cfg(stage0, not(test))] pub use owned = core::owned;
pub use core::any;
pub use core::bool;
pub use core::cell;
@ -209,7 +206,7 @@ pub mod ascii;
pub mod rc;
pub mod gc;
#[cfg(not(stage0), not(test))]
#[cfg(not(test))]
pub mod owned;
/* Common traits */

View File

@ -53,24 +53,24 @@ impl Local<local_ptr::Borrowed<Task>> for Task {
#[cfg(test)]
mod test {
use option::{None, Option};
use unstable::run_in_bare_thread;
use rt::thread::Thread;
use super::*;
use owned::Box;
use rt::task::Task;
#[test]
fn thread_local_task_smoke_test() {
run_in_bare_thread(proc() {
Thread::start(proc() {
let task = box Task::new();
Local::put(task);
let task: Box<Task> = Local::take();
cleanup_task(task);
});
}).join();
}
#[test]
fn thread_local_task_two_instances() {
run_in_bare_thread(proc() {
Thread::start(proc() {
let task = box Task::new();
Local::put(task);
let task: Box<Task> = Local::take();
@ -79,12 +79,12 @@ mod test {
Local::put(task);
let task: Box<Task> = Local::take();
cleanup_task(task);
});
}).join();
}
#[test]
fn borrow_smoke_test() {
run_in_bare_thread(proc() {
Thread::start(proc() {
let task = box Task::new();
Local::put(task);
@ -93,12 +93,12 @@ mod test {
}
let task: Box<Task> = Local::take();
cleanup_task(task);
});
}).join();
}
#[test]
fn borrow_with_return() {
run_in_bare_thread(proc() {
Thread::start(proc() {
let task = box Task::new();
Local::put(task);
@ -108,12 +108,12 @@ mod test {
let task: Box<Task> = Local::take();
cleanup_task(task);
});
}).join();
}
#[test]
fn try_take() {
run_in_bare_thread(proc() {
Thread::start(proc() {
let task = box Task::new();
Local::put(task);
@ -122,7 +122,7 @@ mod test {
assert!(u.is_none());
cleanup_task(t);
});
}).join();
}
fn cleanup_task(mut t: Box<Task>) {

View File

@ -273,13 +273,8 @@ mod imp {
assert_eq!(pthread_detach(native), 0);
}
#[cfg(target_os = "macos")]
#[cfg(target_os = "android")]
pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); }
#[cfg(not(target_os = "macos"), not(target_os = "android"))]
pub unsafe fn yield_now() { assert_eq!(pthread_yield(), 0); }
// glibc >= 2.15 has a __pthread_get_minstack() function that returns
// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
// storage. We need that information to avoid blowing up when a small stack
@ -326,12 +321,7 @@ mod imp {
fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
state: libc::c_int) -> libc::c_int;
fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;
#[cfg(target_os = "macos")]
#[cfg(target_os = "android")]
fn sched_yield() -> libc::c_int;
#[cfg(not(target_os = "macos"), not(target_os = "android"))]
fn pthread_yield() -> libc::c_int;
}
}

View File

@ -564,6 +564,11 @@ impl<'a> IntoMaybeOwned<'a> for ~str {
fn into_maybe_owned(self) -> MaybeOwned<'a> { Owned(self) }
}
impl<'a> IntoMaybeOwned<'a> for StrBuf {
#[inline]
fn into_maybe_owned(self) -> MaybeOwned<'a> { Owned(self.into_owned()) }
}
impl<'a> IntoMaybeOwned<'a> for &'a str {
#[inline]
fn into_maybe_owned(self) -> MaybeOwned<'a> { Slice(self) }

View File

@ -11,7 +11,6 @@
#![doc(hidden)]
use libc::uintptr_t;
use kinds::Send;
pub use core::finally;
@ -21,36 +20,6 @@ pub mod simd;
pub mod sync;
pub mod mutex;
/**
Start a new thread outside of the current runtime context and wait
for it to terminate.
The executing thread has no access to a task pointer and will be using
a normal large stack.
*/
pub fn run_in_bare_thread(f: proc():Send) {
use rt::thread::Thread;
Thread::start(f).join()
}
#[test]
fn test_run_in_bare_thread() {
let i = 100;
run_in_bare_thread(proc() {
assert_eq!(i, 100);
});
}
#[test]
fn test_run_in_bare_thread_exchange() {
// Does the exchange heap work without the runtime?
let i = box 100;
run_in_bare_thread(proc() {
assert!(i == box 100);
});
}
/// Dynamically inquire about whether we're running under V.
/// You should usually not use this unless your test definitely
/// can't run correctly un-altered. Valgrind is there to help

View File

@ -635,14 +635,14 @@ impl<T> Vec<T> {
/// ```
pub fn truncate(&mut self, len: uint) {
unsafe {
let mut i = len;
// drop any extra elements
while i < self.len {
ptr::read(self.as_slice().unsafe_ref(i));
i += 1;
while len < self.len {
// decrement len before the read(), so a failure on Drop doesn't
// re-drop the just-failed value.
self.len -= 1;
ptr::read(self.as_slice().unsafe_ref(self.len));
}
}
self.len = len;
}
/// Work with `self` as a mutable slice.
@ -1862,4 +1862,39 @@ mod tests {
assert_eq!(b[0].x, 42);
assert_eq!(b[1].x, 84);
}
#[test]
fn test_vec_truncate_drop() {
static mut drops: uint = 0;
struct Elem(int);
impl Drop for Elem {
fn drop(&mut self) {
unsafe { drops += 1; }
}
}
let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)];
assert_eq!(unsafe { drops }, 0);
v.truncate(3);
assert_eq!(unsafe { drops }, 2);
v.truncate(0);
assert_eq!(unsafe { drops }, 5);
}
#[test]
#[should_fail]
fn test_vec_truncate_fail() {
struct BadElem(int);
impl Drop for BadElem {
fn drop(&mut self) {
let BadElem(ref mut x) = *self;
if *x == 0xbadbeef {
fail!("BadElem failure: 0xbadbeef")
}
}
}
let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)];
v.truncate(0);
}
}

View File

@ -103,6 +103,7 @@ pub enum Node {
NodeStmt(@Stmt),
NodeArg(@Pat),
NodeLocal(@Pat),
NodePat(@Pat),
NodeBlock(P<Block>),
/// NodeStructCtor represents a tuple struct.
@ -127,6 +128,7 @@ enum MapEntry {
EntryStmt(NodeId, @Stmt),
EntryArg(NodeId, @Pat),
EntryLocal(NodeId, @Pat),
EntryPat(NodeId, @Pat),
EntryBlock(NodeId, P<Block>),
EntryStructCtor(NodeId, @StructDef),
EntryLifetime(NodeId, @Lifetime),
@ -154,6 +156,7 @@ impl MapEntry {
EntryStmt(id, _) => id,
EntryArg(id, _) => id,
EntryLocal(id, _) => id,
EntryPat(id, _) => id,
EntryBlock(id, _) => id,
EntryStructCtor(id, _) => id,
EntryLifetime(id, _) => id,
@ -172,6 +175,7 @@ impl MapEntry {
EntryStmt(_, p) => NodeStmt(p),
EntryArg(_, p) => NodeArg(p),
EntryLocal(_, p) => NodeLocal(p),
EntryPat(_, p) => NodePat(p),
EntryBlock(_, p) => NodeBlock(p),
EntryStructCtor(_, p) => NodeStructCtor(p),
EntryLifetime(_, p) => NodeLifetime(p),
@ -399,6 +403,7 @@ impl Map {
Some(NodeExpr(expr)) => expr.span,
Some(NodeStmt(stmt)) => stmt.span,
Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span,
Some(NodePat(pat)) => pat.span,
Some(NodeBlock(block)) => block.span,
Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
_ => fail!("node_span: could not find span for id {}", id),
@ -513,7 +518,9 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
// Note: this is at least *potentially* a pattern...
self.insert(pat.id, EntryLocal(self.parent, pat));
}
_ => {}
_ => {
self.insert(pat.id, EntryPat(self.parent, pat));
}
}
pat
@ -704,6 +711,9 @@ fn node_id_to_str(map: &Map, id: NodeId) -> StrBuf {
(format!("local {} (id={})",
pprust::pat_to_str(pat), id)).to_strbuf()
}
Some(NodePat(pat)) => {
(format!("pat {} (id={})", pprust::pat_to_str(pat), id)).to_strbuf()
}
Some(NodeBlock(block)) => {
(format!("block {} (id={})",
pprust::block_to_str(block), id)).to_strbuf()

View File

@ -128,17 +128,27 @@ LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
// Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
// field of a PassManagerBuilder, we expose our own method of doing so.
extern "C" void
LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMB, LLVMModuleRef M) {
LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMB,
LLVMModuleRef M,
bool DisableSimplifyLibCalls) {
Triple TargetTriple(unwrap(M)->getTargetTriple());
unwrap(PMB)->LibraryInfo = new TargetLibraryInfo(TargetTriple);
TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
if (DisableSimplifyLibCalls)
TLI->disableAllFunctions();
unwrap(PMB)->LibraryInfo = TLI;
}
// Unfortunately, the LLVM C API doesn't provide a way to create the
// TargetLibraryInfo pass, so we use this method to do so.
extern "C" void
LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB, LLVMModuleRef M) {
LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB,
LLVMModuleRef M,
bool DisableSimplifyLibCalls) {
Triple TargetTriple(unwrap(M)->getTargetTriple());
unwrap(PMB)->add(new TargetLibraryInfo(TargetTriple));
TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
if (DisableSimplifyLibCalls)
TLI->disableAllFunctions();
unwrap(PMB)->add(TLI);
}
// Unfortunately, the LLVM C API doesn't provide an easy way of iterating over

View File

@ -1,3 +1,11 @@
S 2014-05-15 6a2b3d1
freebsd-x86_64 afc98b59cb819025fecdb9d145ca4463f857a477
linux-i386 d6f7a404412ea34db3d19814ca21fe6fa662b02f
linux-x86_64 3dfb54406a7ea75565a7ea3071daad885cb91775
macos-i386 bebb937551d601ad908c9e4eaa196cc7a977c503
macos-x86_64 08346ed401ad2891c7d2ba0aac0960f6e77bb78b
winnt-i386 ad8e5b8292a00f60f1f7dc2e35bd18abeb5b858d
S 2014-05-11 72fc4a5
freebsd-x86_64 82db6355b0b7c8023c8845a74e2f224da2831b50
linux-i386 91901299d5f86f5b67377d940073908a1f0e4e82

View File

@ -7,56 +7,104 @@
// <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.
#![feature(macro_rules)]
#![feature(simd)]
#![allow(experimental)]
// ignore-pretty very bad with line comments
extern crate sync;
use std::io;
use std::os;
use std::unstable::simd::f64x2;
use sync::Future;
use sync::Arc;
static ITER: int = 50;
static LIMIT: f64 = 2.0;
static WORKERS: uint = 16;
fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) {
for chunk_init_r in vec_init_r.chunks(8) {
let mut cur_byte = 0xff;
let mut cur_bitmask = 0x80;
for &init_r in chunk_init_r.iter() {
let mut cur_r = init_r;
let mut cur_i = init_i;
for _ in range(0, ITER) {
let r = cur_r;
let i = cur_i;
cur_r = r * r - i * i + init_r;
cur_i = 2.0 * r * i + init_i;
if r * r + i * i > LIMIT * LIMIT {
cur_byte &= !cur_bitmask;
break;
}
}
cur_bitmask >>= 1;
}
res.push(cur_byte);
}
}
#[inline(always)]
fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
assert!(WORKERS % 2 == 0);
// Ensure w and h are multiples of 8.
let w = (w + 7) / 8 * 8;
let h = w;
let chunk_size = h / 8;
let data: Vec<Future<Vec<u8>>> = range(0u, 8).map(|i| Future::spawn(proc () {
let vec_init_r = Vec::from_fn(w, |x| 2.0 * (x as f64) / (w as f64) - 1.5);
let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
for y in range(i * chunk_size, (i + 1) * chunk_size) {
let init_i = 2.0 * (y as f64) / (h as f64) - 1.0;
write_line(init_i, vec_init_r.as_slice(), &mut res);
}
res
})).collect();
let chunk_size = h / WORKERS;
// Account for remainders in workload division, e.g. 1000 / 16 = 62.5
let first_chunk_size = if h % WORKERS != 0 {
chunk_size + h % WORKERS
} else {
chunk_size
};
// precalc values
let inverse_w_doubled = 2.0 / w as f64;
let inverse_h_doubled = 2.0 / h as f64;
let v_inverses = f64x2(inverse_w_doubled, inverse_h_doubled);
let v_consts = f64x2(1.5, 1.0);
// A lot of this code assumes this (so do other lang benchmarks)
assert!(w == h);
let mut precalc_r = Vec::with_capacity(w);
let mut precalc_i = Vec::with_capacity(h);
let precalc_futures = Vec::from_fn(WORKERS, |i| {
Future::spawn(proc () {
let mut rs = Vec::with_capacity(w / WORKERS);
let mut is = Vec::with_capacity(w / WORKERS);
let start = i * chunk_size;
let end = if i == 0 {
first_chunk_size
} else {
(i + 1) * chunk_size
};
// This assumes w == h
for x in range(start, end) {
let xf = x as f64;
let xy = f64x2(xf, xf);
let f64x2(r, i) = xy * v_inverses - v_consts;
rs.push(r);
is.push(i);
}
(rs, is)
})
});
for res in precalc_futures.move_iter() {
let (rs, is) = res.unwrap();
precalc_r.push_all_move(rs);
precalc_i.push_all_move(is);
}
assert_eq!(precalc_r.len(), w);
assert_eq!(precalc_i.len(), h);
let arc_init_r = Arc::new(precalc_r);
let arc_init_i = Arc::new(precalc_i);
let data = Vec::from_fn(WORKERS, |i| {
let vec_init_r = arc_init_r.clone();
let vec_init_i = arc_init_i.clone();
Future::spawn(proc () {
let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
let init_r_slice = vec_init_r.as_slice();
for &init_i in vec_init_i.slice(i * chunk_size, (i + 1) * chunk_size).iter() {
write_line(init_i, init_r_slice, &mut res);
}
res
})
});
try!(writeln!(&mut out as &mut Writer, "P4\n{} {}", w, h));
for res in data.move_iter() {
@ -65,15 +113,63 @@ fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
out.flush()
}
fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) {
let v_init_i : f64x2 = f64x2(init_i, init_i);
let v_2 : f64x2 = f64x2(2.0, 2.0);
static LIMIT_SQUARED: f64 = LIMIT * LIMIT;
for chunk_init_r in vec_init_r.chunks(8) {
let mut cur_byte = 0xff;
let mut i = 0;
while i < 8 {
let v_init_r = f64x2(chunk_init_r[i], chunk_init_r[i + 1]);
let mut cur_r = v_init_r;
let mut cur_i = v_init_i;
let mut r_sq = v_init_r * v_init_r;
let mut i_sq = v_init_i * v_init_i;
let mut b = 0;
for _ in range(0, ITER) {
let r = cur_r;
let i = cur_i;
cur_i = v_2 * r * i + v_init_i;
cur_r = r_sq - i_sq + v_init_r;
let f64x2(bit1, bit2) = r_sq + i_sq;
if bit1 > LIMIT_SQUARED {
b |= 2;
if b == 3 { break; }
}
if bit2 > LIMIT_SQUARED {
b |= 1;
if b == 3 { break; }
}
r_sq = cur_r * cur_r;
i_sq = cur_i * cur_i;
}
cur_byte = (cur_byte << 2) + b;
i += 2;
}
res.push(cur_byte^-1);
}
}
fn main() {
let args = std::os::args();
let args = os::args();
let args = args.as_slice();
let res = if args.len() < 2 {
println!("Test mode: do not dump the image because it's not utf8, \
which interferes with the test runner.");
mandelbrot(1000, std::io::util::NullWriter)
mandelbrot(1000, io::util::NullWriter)
} else {
mandelbrot(from_str(args[1]).unwrap(), std::io::stdout())
mandelbrot(from_str(args[1]).unwrap(), io::stdout())
};
res.unwrap();
}

View File

@ -0,0 +1,37 @@
-include ../tools.mk
FILES=f00.rs f01.rs f02.rs f03.rs f04.rs f05.rs f06.rs f07.rs \
f08.rs f09.rs f10.rs f11.rs f12.rs f13.rs f14.rs f15.rs \
f16.rs f17.rs f18.rs f19.rs f20.rs f21.rs f22.rs
# all: $(patsubst %.rs,$(TMPDIR)/%.dot,$(FILES)) $(patsubst %.rs,$(TMPDIR)/%.pp,$(FILES))
all: $(patsubst %.rs,$(TMPDIR)/%.check,$(FILES))
RUSTC_LIB=$(RUSTC) --crate-type=lib
define FIND_LAST_BLOCK
LASTBLOCKNUM_$(1) := $(shell $(RUSTC_LIB) --pretty=expanded,identified $(1) \
| grep block
| tail -1
| sed -e 's@.*/\* block \([0-9]*\) \*/.*@\1@')
endef
ifeq ($(findstring rustc,$(RUSTC)),)
$(error Must set RUSTC)
endif
$(TMPDIR)/%.pp: %.rs
$(RUSTC_LIB) --pretty=expanded,identified $< -o $@
$(TMPDIR)/%.dot: %.rs
$(eval $(call FIND_LAST_BLOCK,$<))
$(RUSTC_LIB) --pretty flowgraph=$(LASTBLOCKNUM_$<) $< -o $@.tmp
cat $@.tmp | sed -e 's@ (id=[0-9]*)@@g' \
-e 's@\[label=""\]@@' \
-e 's@digraph [a-zA-Z0-9_]* @digraph block @' \
> $@
$(TMPDIR)/%.check: %.rs $(TMPDIR)/%.dot
diff -u $(patsubst %.rs,$(TMPDIR)/%.dot,$<) $(patsubst %.rs,%.dot-expected.dot,$<)

View File

@ -0,0 +1,7 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="block { }"];
N0 -> N2;
N2 -> N1;
}

View File

@ -0,0 +1,13 @@
// Copyright 2014 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.
pub fn empty_0() {
}

View File

@ -0,0 +1,9 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 1"];
N3[label="block { 1; }"];
N0 -> N2;
N2 -> N3;
N3 -> N1;
}

View File

@ -0,0 +1,13 @@
// Copyright 2014 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.
pub fn lit_1() {
1;
}

View File

@ -0,0 +1,9 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="local _x"];
N3[label="block { let _x: int; }"];
N0 -> N2;
N2 -> N3;
N3 -> N1;
}

View File

@ -0,0 +1,13 @@
// Copyright 2014 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.
pub fn decl_x_2() {
let _x : int;
}

View File

@ -0,0 +1,13 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 3"];
N3[label="expr 33"];
N4[label="expr 3 + 33"];
N5[label="block { 3 + 33; }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N1;
}

View File

@ -0,0 +1,13 @@
// Copyright 2014 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.
pub fn expr_add_3() {
3 + 33;
}

View File

@ -0,0 +1,11 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 4"];
N3[label="local _x"];
N4[label="block { let _x = 4; }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N1;
}

View File

@ -0,0 +1,13 @@
// Copyright 2014 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.
pub fn pat_id_4() {
let _x = 4;
}

View File

@ -0,0 +1,19 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 5"];
N3[label="expr 55"];
N4[label="expr (5, 55)"];
N5[label="local _x"];
N6[label="local _y"];
N7[label="pat (_x, _y)"];
N8[label="block { let (_x, _y) = (5, 55); }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N7;
N7 -> N8;
N8 -> N1;
}

View File

@ -0,0 +1,13 @@
// Copyright 2014 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.
pub fn pat_tup_5() {
let (_x, _y) = (5, 55);
}

View File

@ -0,0 +1,15 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 6"];
N3[label="expr S6{val: 6,}"];
N4[label="local _x"];
N5[label="pat S6{val: _x}"];
N6[label="block { let S6{val: _x} = S6{val: 6,}; }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N1;
}

View File

@ -0,0 +1,14 @@
// Copyright 2014 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.
struct S6 { val: int }
pub fn pat_struct_6() {
let S6 { val: _x } = S6{ val: 6 };
}

View File

@ -0,0 +1,33 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 7"];
N3[label="expr 77"];
N4[label="expr 777"];
N5[label="expr 7777"];
N6[label="expr [7, 77, 777, 7777]"];
N7[label="expr match [7, 77, 777, 7777] { [x, y, ..] => x + y }"];
N8[label="local x"];
N9[label="local y"];
N10[label="pat .."];
N11[label="pat [x, y, ..]"];
N12[label="expr x"];
N13[label="expr y"];
N14[label="expr x + y"];
N15[label="block { match [7, 77, 777, 7777] { [x, y, ..] => x + y }; }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N8;
N8 -> N9;
N9 -> N10;
N10 -> N11;
N11 -> N12;
N12 -> N13;
N13 -> N14;
N14 -> N7;
N7 -> N15;
N15 -> N1;
}

View File

@ -0,0 +1,15 @@
// Copyright 2014 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.
pub fn pat_vec_7() {
match [7, 77, 777, 7777] {
[x, y, ..] => x + y
};
}

View File

@ -0,0 +1,30 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 8"];
N3[label="local x"];
N4[label="local _y"];
N5[label="expr x"];
N6[label="expr 88"];
N7[label="expr x > 88"];
N8[label="expr 888"];
N9[label="expr _y"];
N10[label="expr _y = 888"];
N11[label="block { _y = 888; }"];
N12[label="expr if x > 88 { _y = 888; }"];
N13[label="block { let x = 8; let _y; if x > 88 { _y = 888; } }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N7;
N7 -> N8;
N8 -> N9;
N9 -> N10;
N10 -> N11;
N7 -> N12;
N11 -> N12;
N12 -> N13;
N13 -> N1;
}

View File

@ -0,0 +1,16 @@
// Copyright 2014 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.
pub fn expr_if_onearm_8() {
let x = 8; let _y;
if x > 88 {
_y = 888;
}
}

View File

@ -0,0 +1,44 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 91"];
N3[label="local x"];
N4[label="local _y"];
N5[label="expr x"];
N6[label="expr 92"];
N7[label="expr x > 92"];
N8[label="expr 93"];
N9[label="expr _y"];
N10[label="expr _y = 93"];
N11[label="block { _y = 93; }"];
N12[label="expr 94"];
N13[label="expr 95"];
N14[label="expr 94 + 95"];
N15[label="expr _y"];
N16[label="expr _y = 94 + 95"];
N17[label="block { _y = 94 + 95; }"];
N18[label="expr { _y = 94 + 95; }"];
N19[label="expr if x > 92 { _y = 93; } else { _y = 94 + 95; }"];
N20[label="block { let x = 91; let _y; if x > 92 { _y = 93; } else { _y = 94 + 95; } }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N7;
N7 -> N8;
N8 -> N9;
N9 -> N10;
N10 -> N11;
N7 -> N12;
N12 -> N13;
N13 -> N14;
N14 -> N15;
N15 -> N16;
N16 -> N17;
N17 -> N18;
N11 -> N19;
N18 -> N19;
N19 -> N20;
N20 -> N1;
}

View File

@ -0,0 +1,18 @@
// Copyright 2014 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.
pub fn expr_if_twoarm_9() {
let x = 91; let _y;
if x > 92 {
_y = 93;
} else {
_y = 94+95;
}
}

View File

@ -0,0 +1,30 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 10"];
N3[label="local mut x"];
N4[label="(dummy_node)"];
N5[label="expr x"];
N6[label="expr 0"];
N7[label="expr x > 0"];
N8[label="expr while x > 0 { x -= 1; }"];
N9[label="expr 1"];
N10[label="expr x"];
N11[label="expr x -= 1"];
N12[label="block { x -= 1; }"];
N13[label="block { let mut x = 10; while x > 0 { x -= 1; } }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N7;
N7 -> N8;
N7 -> N9;
N9 -> N10;
N10 -> N11;
N11 -> N12;
N12 -> N4;
N8 -> N13;
N13 -> N1;
}

View File

@ -0,0 +1,16 @@
// Copyright 2014 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.
pub fn expr_while_10() {
let mut x = 10;
while x > 0 {
x -= 1;
}
}

View File

@ -0,0 +1,25 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 11"];
N3[label="local mut _x"];
N4[label="(dummy_node)"];
N5[label="expr loop { _x -= 1; }"];
N6[label="expr 1"];
N7[label="expr _x"];
N8[label="expr _x -= 1"];
N9[label="block { _x -= 1; }"];
N10[label="expr \"unreachable\""];
N11[label="block { let mut _x = 11; loop { _x -= 1; } \"unreachable\"; }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N6;
N6 -> N7;
N7 -> N8;
N8 -> N9;
N9 -> N4;
N5 -> N10;
N10 -> N11;
N11 -> N1;
}

View File

@ -0,0 +1,18 @@
// Copyright 2014 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.
#[allow(unreachable_code)]
pub fn expr_loop_11() {
let mut _x = 11;
loop {
_x -= 1;
}
"unreachable";
}

View File

@ -0,0 +1,40 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 12"];
N3[label="local mut x"];
N4[label="(dummy_node)"];
N5[label="expr loop { x -= 1; if x == 2 { break ; \"unreachable\"; } }"];
N6[label="expr 1"];
N7[label="expr x"];
N8[label="expr x -= 1"];
N9[label="expr x"];
N10[label="expr 2"];
N11[label="expr x == 2"];
N12[label="expr break"];
N13[label="(dummy_node)"];
N14[label="expr \"unreachable\""];
N15[label="block { break ; \"unreachable\"; }"];
N16[label="expr if x == 2 { break ; \"unreachable\"; }"];
N17[label="block { x -= 1; if x == 2 { break ; \"unreachable\"; } }"];
N18[label="block { let mut x = 12; loop { x -= 1; if x == 2 { break ; \"unreachable\"; } } }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N6;
N6 -> N7;
N7 -> N8;
N8 -> N9;
N9 -> N10;
N10 -> N11;
N11 -> N12;
N12 -> N5[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if x == 2 { break ; \"unreachable\"; },\lexiting scope_4 block { x -= 1; if x == 2 { break ; \"unreachable\"; } }"];
N13 -> N14;
N14 -> N15;
N11 -> N16;
N15 -> N16;
N16 -> N17;
N17 -> N4;
N5 -> N18;
N18 -> N1;
}

View File

@ -0,0 +1,18 @@
// Copyright 2014 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.
#[allow(unreachable_code)]
pub fn expr_loop_12() {
let mut x = 12;
loop {
x -= 1;
if x == 2 { break; "unreachable"; }
}
}

View File

@ -0,0 +1,44 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr E13b"];
N3[label="expr 13"];
N4[label="expr E13b(13)"];
N5[label="local x"];
N6[label="local _y"];
N7[label="expr x"];
N8[label="expr match x { E13a => _y = 1, E13b(v) => _y = v + 1 }"];
N9[label="local E13a"];
N10[label="expr 1"];
N11[label="expr _y"];
N12[label="expr _y = 1"];
N13[label="local v"];
N14[label="pat E13b(v)"];
N15[label="expr v"];
N16[label="expr 1"];
N17[label="expr v + 1"];
N18[label="expr _y"];
N19[label="expr _y = v + 1"];
N20[label="block {\l let x = E13b(13);\l let _y;\l match x { E13a => _y = 1, E13b(v) => _y = v + 1 }\l}\l"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N7;
N7 -> N9;
N9 -> N10;
N10 -> N11;
N11 -> N12;
N12 -> N8;
N7 -> N13;
N13 -> N14;
N14 -> N15;
N15 -> N16;
N16 -> N17;
N17 -> N18;
N18 -> N19;
N19 -> N8;
N8 -> N20;
N20 -> N1;
}

View File

@ -0,0 +1,18 @@
// Copyright 2014 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.
enum E13 { E13a, E13b(int) }
pub fn expr_match_13() {
let x = E13b(13); let _y;
match x {
E13a => _y = 1,
E13b(v) => _y = v + 1,
}
}

View File

@ -0,0 +1,28 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 14"];
N3[label="local x"];
N4[label="expr x"];
N5[label="expr 1"];
N6[label="expr x > 1"];
N7[label="expr return"];
N8[label="(dummy_node)"];
N9[label="expr \"unreachable\""];
N10[label="block { return; \"unreachable\"; }"];
N11[label="expr if x > 1 { return; \"unreachable\"; }"];
N12[label="block { let x = 14; if x > 1 { return; \"unreachable\"; } }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N7;
N7 -> N1;
N8 -> N9;
N9 -> N10;
N6 -> N11;
N10 -> N11;
N11 -> N12;
N12 -> N1;
}

View File

@ -0,0 +1,18 @@
// Copyright 2014 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.
#[allow(unreachable_code)]
pub fn expr_ret_14() {
let x = 14;
if x > 1 {
return;
"unreachable";
}
}

View File

@ -0,0 +1,79 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 15"];
N3[label="local mut x"];
N4[label="expr 151"];
N5[label="local mut y"];
N6[label="(dummy_node)"];
N7[label="expr \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l y -= 4;\l x -= 5;\l }\l"];
N8[label="(dummy_node)"];
N9[label="expr \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l"];
N10[label="expr x"];
N11[label="expr 1"];
N12[label="expr x == 1"];
N13[label="expr break \'outer"];
N14[label="(dummy_node)"];
N15[label="expr \"unreachable\""];
N16[label="block { break \'outer ; \"unreachable\" }"];
N17[label="expr if x == 1 { break \'outer ; \"unreachable\" }"];
N18[label="expr y"];
N19[label="expr 2"];
N20[label="expr y >= 2"];
N21[label="expr break"];
N22[label="(dummy_node)"];
N23[label="expr \"unreachable\""];
N24[label="block { break ; \"unreachable\" }"];
N25[label="expr if y >= 2 { break ; \"unreachable\" }"];
N26[label="expr 3"];
N27[label="expr y"];
N28[label="expr y -= 3"];
N29[label="block {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l}\l"];
N30[label="expr 4"];
N31[label="expr y"];
N32[label="expr y -= 4"];
N33[label="expr 5"];
N34[label="expr x"];
N35[label="expr x -= 5"];
N36[label="block {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l y -= 4;\l x -= 5;\l}\l"];
N37[label="block {\l let mut x = 15;\l let mut y = 151;\l \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l y -= 4;\l x -= 5;\l }\l}\l"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N8;
N8 -> N10;
N10 -> N11;
N11 -> N12;
N12 -> N13;
N13 -> N7[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 block { break \'outer ; \"unreachable\" },\lexiting scope_3 expr if x == 1 { break \'outer ; \"unreachable\" },\lexiting scope_4 stmt if x == 1 { break \'outer ; \"unreachable\" },\lexiting scope_5 block {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l y -= 4;\l x -= 5;\l}\l"];
N14 -> N15;
N15 -> N16;
N12 -> N17;
N16 -> N17;
N17 -> N18;
N18 -> N19;
N19 -> N20;
N20 -> N21;
N21 -> N9[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\" },\lexiting scope_3 expr if y >= 2 { break ; \"unreachable\" },\lexiting scope_4 stmt if y >= 2 { break ; \"unreachable\" },\lexiting scope_5 block {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l}\l"];
N22 -> N23;
N23 -> N24;
N20 -> N25;
N24 -> N25;
N25 -> N26;
N26 -> N27;
N27 -> N28;
N28 -> N29;
N29 -> N8;
N9 -> N30;
N30 -> N31;
N31 -> N32;
N32 -> N33;
N33 -> N34;
N34 -> N35;
N35 -> N36;
N36 -> N6;
N7 -> N37;
N37 -> N1;
}

View File

@ -0,0 +1,30 @@
// Copyright 2014 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.
#[allow(unreachable_code)]
pub fn expr_break_label_15() {
let mut x = 15;
let mut y = 151;
'outer: loop {
'inner: loop {
if x == 1 {
break 'outer;
"unreachable"
}
if y >= 2 {
break;
"unreachable"
}
y -= 3;
}
y -= 4;
x -= 5;
}
}

View File

@ -0,0 +1,81 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 16"];
N3[label="local mut x"];
N4[label="expr 16"];
N5[label="local mut y"];
N6[label="(dummy_node)"];
N7[label="expr \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l y -= 1;\l x -= 1;\l }\l"];
N8[label="(dummy_node)"];
N9[label="expr \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l"];
N10[label="expr x"];
N11[label="expr 1"];
N12[label="expr x == 1"];
N13[label="expr continue \'outer"];
N14[label="(dummy_node)"];
N15[label="expr \"unreachable\""];
N16[label="block { continue \'outer ; \"unreachable\" }"];
N17[label="expr if x == 1 { continue \'outer ; \"unreachable\" }"];
N18[label="expr y"];
N19[label="expr 1"];
N20[label="expr y >= 1"];
N21[label="expr break"];
N22[label="(dummy_node)"];
N23[label="expr \"unreachable\""];
N24[label="block { break ; \"unreachable\" }"];
N25[label="expr if y >= 1 { break ; \"unreachable\" }"];
N26[label="expr 1"];
N27[label="expr y"];
N28[label="expr y -= 1"];
N29[label="block {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l}\l"];
N30[label="expr 1"];
N31[label="expr y"];
N32[label="expr y -= 1"];
N33[label="expr 1"];
N34[label="expr x"];
N35[label="expr x -= 1"];
N36[label="block {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l y -= 1;\l x -= 1;\l}\l"];
N37[label="expr \"unreachable\""];
N38[label="block {\l let mut x = 16;\l let mut y = 16;\l \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l y -= 1;\l x -= 1;\l }\l \"unreachable\";\l}\l"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N8;
N8 -> N10;
N10 -> N11;
N11 -> N12;
N12 -> N13;
N13 -> N6[label="exiting scope_0 expr continue \'outer,\lexiting scope_1 stmt continue \'outer ;,\lexiting scope_2 block { continue \'outer ; \"unreachable\" },\lexiting scope_3 expr if x == 1 { continue \'outer ; \"unreachable\" },\lexiting scope_4 stmt if x == 1 { continue \'outer ; \"unreachable\" },\lexiting scope_5 block {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l y -= 1;\l x -= 1;\l}\l"];
N14 -> N15;
N15 -> N16;
N12 -> N17;
N16 -> N17;
N17 -> N18;
N18 -> N19;
N19 -> N20;
N20 -> N21;
N21 -> N9[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\" },\lexiting scope_3 expr if y >= 1 { break ; \"unreachable\" },\lexiting scope_4 stmt if y >= 1 { break ; \"unreachable\" },\lexiting scope_5 block {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l}\l"];
N22 -> N23;
N23 -> N24;
N20 -> N25;
N24 -> N25;
N25 -> N26;
N26 -> N27;
N27 -> N28;
N28 -> N29;
N29 -> N8;
N9 -> N30;
N30 -> N31;
N31 -> N32;
N32 -> N33;
N33 -> N34;
N34 -> N35;
N35 -> N36;
N36 -> N6;
N7 -> N37;
N37 -> N38;
N38 -> N1;
}

View File

@ -0,0 +1,31 @@
// Copyright 2014 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.
#[allow(unreachable_code)]
pub fn expr_continue_label_16() {
let mut x = 16;
let mut y = 16;
'outer: loop {
'inner: loop {
if x == 1 {
continue 'outer;
"unreachable"
}
if y >= 1 {
break;
"unreachable"
}
y -= 1;
}
y -= 1;
x -= 1;
}
"unreachable";
}

View File

@ -0,0 +1,17 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 1"];
N3[label="expr 7"];
N4[label="expr 17"];
N5[label="expr [1, 7, 17]"];
N6[label="local _v"];
N7[label="block { let _v = [1, 7, 17]; }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N7;
N7 -> N1;
}

View File

@ -0,0 +1,13 @@
// Copyright 2014 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.
pub fn expr_vec_17() {
let _v = [1, 7, 17];
}

View File

@ -0,0 +1,17 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr inner"];
N3[label="expr inner"];
N4[label="expr 18"];
N5[label="expr inner(18)"];
N6[label="expr inner(inner(18))"];
N7[label="block {\l fn inner(x: int) -> int { x + x }\l inner(inner(18));\l}\l"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N7;
N7 -> N1;
}

View File

@ -0,0 +1,14 @@
// Copyright 2014 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.
pub fn expr_call_18() {
fn inner(x:int) -> int { x + x }
inner(inner(18));
}

View File

@ -0,0 +1,19 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 19"];
N3[label="expr S19{x: 19,}"];
N4[label="local s"];
N5[label="expr s"];
N6[label="expr s.inner()"];
N7[label="expr s.inner().inner()"];
N8[label="block {\l struct S19 {\l x: int,\l }\l impl S19 {\l fn inner(self) -> S19 { S19{x: self.x + self.x,} }\l }\l let s = S19{x: 19,};\l s.inner().inner();\l}\l"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N7;
N7 -> N8;
N8 -> N1;
}

View File

@ -0,0 +1,16 @@
// Copyright 2014 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.
pub fn expr_method_call_19() {
struct S19 { x: int }
impl S19 { fn inner(self) -> S19 { S19 { x: self.x + self.x } } }
let s = S19 { x: 19 };
s.inner().inner();
}

View File

@ -0,0 +1,23 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 2"];
N3[label="expr 0"];
N4[label="expr 20"];
N5[label="expr [2, 0, 20]"];
N6[label="local v"];
N7[label="expr v"];
N8[label="expr 20"];
N9[label="expr v[20]"];
N10[label="block { let v = [2, 0, 20]; v[20]; }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N7;
N7 -> N8;
N8 -> N9;
N9 -> N10;
N10 -> N1;
}

View File

@ -0,0 +1,14 @@
// Copyright 2014 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.
pub fn expr_index_20() {
let v = [2, 0, 20];
v[20];
}

View File

@ -0,0 +1,75 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 15"];
N3[label="local mut x"];
N4[label="expr 151"];
N5[label="local mut y"];
N6[label="(dummy_node)"];
N7[label="expr \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l \"unreachable\";\l }\l"];
N8[label="(dummy_node)"];
N9[label="expr \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l"];
N10[label="expr x"];
N11[label="expr 1"];
N12[label="expr x == 1"];
N13[label="expr break \'outer"];
N14[label="(dummy_node)"];
N15[label="expr \"unreachable\""];
N16[label="block { break \'outer ; \"unreachable\"; }"];
N17[label="expr if x == 1 { break \'outer ; \"unreachable\"; }"];
N18[label="expr y"];
N19[label="expr 2"];
N20[label="expr y >= 2"];
N21[label="expr return"];
N22[label="(dummy_node)"];
N23[label="expr \"unreachable\""];
N24[label="block { return; \"unreachable\"; }"];
N25[label="expr if y >= 2 { return; \"unreachable\"; }"];
N26[label="expr 3"];
N27[label="expr y"];
N28[label="expr y -= 3"];
N29[label="expr 5"];
N30[label="expr x"];
N31[label="expr x -= 5"];
N32[label="block {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l}\l"];
N33[label="expr \"unreachable\""];
N34[label="block {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l \"unreachable\";\l}\l"];
N35[label="block {\l let mut x = 15;\l let mut y = 151;\l \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l \"unreachable\";\l }\l}\l"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N8;
N8 -> N10;
N10 -> N11;
N11 -> N12;
N12 -> N13;
N13 -> N7[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 block { break \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1 { break \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1 { break \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l \"unreachable\";\l}\l"];
N14 -> N15;
N15 -> N16;
N12 -> N17;
N16 -> N17;
N17 -> N18;
N18 -> N19;
N19 -> N20;
N20 -> N21;
N21 -> N1[label="exiting scope_0 expr \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l,\lexiting scope_1 expr \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l \"unreachable\";\l }\l"];
N22 -> N23;
N23 -> N24;
N20 -> N25;
N24 -> N25;
N25 -> N26;
N26 -> N27;
N27 -> N28;
N28 -> N29;
N29 -> N30;
N30 -> N31;
N31 -> N32;
N32 -> N8;
N9 -> N33;
N33 -> N34;
N34 -> N6;
N7 -> N35;
N35 -> N1;
}

View File

@ -0,0 +1,30 @@
// Copyright 2014 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.
#[allow(unreachable_code)]
pub fn expr_break_label_21() {
let mut x = 15;
let mut y = 151;
'outer: loop {
'inner: loop {
if x == 1 {
break 'outer;
"unreachable";
}
if y >= 2 {
return;
"unreachable";
}
y -= 3;
x -= 5;
}
"unreachable";
}
}

View File

@ -0,0 +1,77 @@
digraph block {
N0[label="entry"];
N1[label="exit"];
N2[label="expr 15"];
N3[label="local mut x"];
N4[label="expr 151"];
N5[label="local mut y"];
N6[label="(dummy_node)"];
N7[label="expr \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l \"unreachable\";\l }\l"];
N8[label="(dummy_node)"];
N9[label="expr \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l"];
N10[label="expr x"];
N11[label="expr 1"];
N12[label="expr x == 1"];
N13[label="expr continue \'outer"];
N14[label="(dummy_node)"];
N15[label="expr \"unreachable\""];
N16[label="block { continue \'outer ; \"unreachable\"; }"];
N17[label="expr if x == 1 { continue \'outer ; \"unreachable\"; }"];
N18[label="expr y"];
N19[label="expr 2"];
N20[label="expr y >= 2"];
N21[label="expr return"];
N22[label="(dummy_node)"];
N23[label="expr \"unreachable\""];
N24[label="block { return; \"unreachable\"; }"];
N25[label="expr if y >= 2 { return; \"unreachable\"; }"];
N26[label="expr 1"];
N27[label="expr x"];
N28[label="expr x -= 1"];
N29[label="expr 3"];
N30[label="expr y"];
N31[label="expr y -= 3"];
N32[label="block {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l}\l"];
N33[label="expr \"unreachable\""];
N34[label="block {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l \"unreachable\";\l}\l"];
N35[label="expr \"unreachable\""];
N36[label="block {\l let mut x = 15;\l let mut y = 151;\l \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l \"unreachable\";\l }\l \"unreachable\";\l}\l"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
N4 -> N5;
N5 -> N6;
N6 -> N8;
N8 -> N10;
N10 -> N11;
N11 -> N12;
N12 -> N13;
N13 -> N6[label="exiting scope_0 expr continue \'outer,\lexiting scope_1 stmt continue \'outer ;,\lexiting scope_2 block { continue \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1 { continue \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1 { continue \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l \"unreachable\";\l}\l"];
N14 -> N15;
N15 -> N16;
N12 -> N17;
N16 -> N17;
N17 -> N18;
N18 -> N19;
N19 -> N20;
N20 -> N21;
N21 -> N1[label="exiting scope_0 expr \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l,\lexiting scope_1 expr \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l \"unreachable\";\l }\l"];
N22 -> N23;
N23 -> N24;
N20 -> N25;
N24 -> N25;
N25 -> N26;
N26 -> N27;
N27 -> N28;
N28 -> N29;
N29 -> N30;
N30 -> N31;
N31 -> N32;
N32 -> N8;
N9 -> N33;
N33 -> N34;
N34 -> N6;
N7 -> N35;
N35 -> N36;
N36 -> N1;
}

View File

@ -0,0 +1,31 @@
// Copyright 2014 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.
#[allow(unreachable_code)]
pub fn expr_break_label_21() {
let mut x = 15;
let mut y = 151;
'outer: loop {
'inner: loop {
if x == 1 {
continue 'outer;
"unreachable";
}
if y >= 2 {
return;
"unreachable";
}
x -= 1;
y -= 3;
}
"unreachable";
}
"unreachable";
}

View File

@ -11,7 +11,7 @@
extern crate libc;
use std::mem;
use std::unstable::run_in_bare_thread;
use std::rt::thread::Thread;
#[link(name = "rustrt")]
extern {
@ -21,10 +21,10 @@ extern {
pub fn main() {
unsafe {
run_in_bare_thread(proc() {
Thread::start(proc() {
let i = &100;
rust_dbg_call(callback, mem::transmute(i));
});
}).join();
}
}

View File

@ -74,6 +74,50 @@ fn test_rm_tempdir() {
assert!(!path.exists());
}
fn test_rm_tempdir_close() {
let (tx, rx) = channel();
let f: proc():Send = proc() {
let tmp = TempDir::new("test_rm_tempdir").unwrap();
tx.send(tmp.path().clone());
tmp.close();
fail!("fail to unwind past `tmp`");
};
task::try(f);
let path = rx.recv();
assert!(!path.exists());
let tmp = TempDir::new("test_rm_tempdir").unwrap();
let path = tmp.path().clone();
let f: proc():Send = proc() {
let tmp = tmp;
tmp.close();
fail!("fail to unwind past `tmp`");
};
task::try(f);
assert!(!path.exists());
let path;
{
let f = proc() {
TempDir::new("test_rm_tempdir").unwrap()
};
let tmp = task::try(f).ok().expect("test_rm_tmdir");
path = tmp.path().clone();
assert!(path.exists());
tmp.close();
}
assert!(!path.exists());
let path;
{
let tmp = TempDir::new("test_rm_tempdir").unwrap();
path = tmp.unwrap();
}
assert!(path.exists());
fs::rmdir_recursive(&path);
assert!(!path.exists());
}
// Ideally these would be in std::os but then core would need
// to depend on std
fn recursive_mkdir_rel() {
@ -130,6 +174,19 @@ pub fn test_rmdir_recursive_ok() {
assert!(!root.join("bar").join("blat").exists());
}
pub fn dont_double_fail() {
let r: Result<(), _> = task::try(proc() {
let tmpdir = TempDir::new("test").unwrap();
// Remove the temporary directory so that TempDir sees
// an error on drop
fs::rmdir(tmpdir.path());
// Trigger failure. If TempDir fails *again* due to the rmdir
// error then the process will abort.
fail!();
});
assert!(r.is_err());
}
fn in_tmpdir(f: ||) {
let tmpdir = TempDir::new("test").expect("can't make tmpdir");
assert!(os::change_dir(tmpdir.path()));
@ -140,8 +197,10 @@ fn in_tmpdir(f: ||) {
pub fn main() {
in_tmpdir(test_tempdir);
in_tmpdir(test_rm_tempdir);
in_tmpdir(test_rm_tempdir_close);
in_tmpdir(recursive_mkdir_rel);
in_tmpdir(recursive_mkdir_dot);
in_tmpdir(recursive_mkdir_rel_2);
in_tmpdir(test_rmdir_recursive_ok);
in_tmpdir(dont_double_fail);
}