#
# * `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
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
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
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
# 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
@$(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)
TESTARGS += --ignored
endif
-TEST_BENCH = --bench
+TEST_BENCH =
# Arguments to the cfail/rfail/rpass/bench tests
ifdef CFG_VALGRIND
TEST_BENCH =
endif
-ifdef NO_BENCH
- TEST_BENCH =
+ifdef PLEASE_BENCH
+ TEST_BENCH = --bench
endif
# Arguments to the perf tests
- `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
}
}
+/// 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>
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());
+ }
}
// 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 {
fn default() -> Self;
}
+impl Default for () {
+ #[inline]
+ fn default() -> () { () }
+}
+
impl<T: Default + 'static> Default for @T {
fn default() -> @T { @Default::default() }
}
//! * `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
/* Core types and methods on primitives */
mod unicode;
-mod unit;
pub mod any;
pub mod atomics;
pub mod bool;
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.
+++ /dev/null
-// 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)
- }
- }
-}
+++ /dev/null
-// 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() -> () { () }
-}
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();
normal_thread.join();
special_thread.join();
- });
+ }).join();
}
//#[test]
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),
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,
--- /dev/null
+// 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
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() {
// 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);
}
}
OutputTypeLlvmAssembly => {
path.with_c_str(|output| {
- with_codegen(tm, llmod, |cpm| {
+ with_codegen(tm, llmod, trans.no_builtins, |cpm| {
llvm::LLVMRustPrintModule(cpm, llmod, output);
})
})
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);
});
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);
});
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,
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.
}
}
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);
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"),
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;
use util::ppaux;
use util::nodemap::{NodeSet};
+use dot = graphviz;
+
use serialize::{json, Encodable};
use std::io;
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
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,
&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(),
}
+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
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));
}
}
}
extern crate flate;
extern crate arena;
+extern crate graphviz;
extern crate syntax;
extern crate serialize;
extern crate sync;
pub fn main() {
std::os::set_exit_status(driver::main_args(std::os::args().as_slice()));
}
-
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,
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 {
}
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> {
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) => {
}
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);
}
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 {
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)
}
}
--- /dev/null
+// 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) }
+}
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;
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)
}
}
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> {
///////////////////////////////////////////////////////////////////////////
// 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)
// 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 {
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",
];
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,
metadata: metadata,
reachable: reachable,
crate_formats: formats,
+ no_builtins: no_builtins,
})
}
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))
}
ForeignFunctionItem(Function {
decl: decl.clean(),
generics: generics.clean(),
- fn_style: ast::NormalFn,
+ fn_style: ast::UnsafeFn,
})
}
ast::ForeignItemStatic(ref ty, mutbl) => {
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),
#[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};
#[test]
fn loop_smoke_test() {
- run_in_bare_thread(proc() {
+ Thread::start(proc() {
let mut loop_ = Loop::new();
loop_.run();
loop_.close();
- });
+ }).join();
}
}
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};
#[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;
});
event_loop.run();
assert_eq!(count, 1);
- });
+ }).join();
}
pub struct UvIoFactory {
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.
#[cfg(test)]
mod tests {
+ use option::{Some, None};
use ops::{BitOr, BitAnd, Sub, Not};
bitflags!(
#[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]
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();
}
}
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;
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(|| {
+++ /dev/null
-// 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!() }
-}
//! Temporary files and directories
-use io::fs;
+use io::{fs, IoResult};
use io;
use iter::{Iterator, range};
use libc;
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 {
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
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();
}
}
}
#[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;
pub mod rc;
pub mod gc;
-#[cfg(not(stage0), not(test))]
+#[cfg(not(test))]
pub mod owned;
/* Common traits */
#[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();
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);
}
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);
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);
assert!(u.is_none());
cleanup_task(t);
- });
+ }).join();
}
fn cleanup_task(mut t: Box<Task>) {
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
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;
}
}
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) }
#![doc(hidden)]
use libc::uintptr_t;
-use kinds::Send;
pub use core::finally;
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
/// ```
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.
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);
+ }
}
NodeStmt(@Stmt),
NodeArg(@Pat),
NodeLocal(@Pat),
+ NodePat(@Pat),
NodeBlock(P<Block>),
/// NodeStructCtor represents a tuple struct.
EntryStmt(NodeId, @Stmt),
EntryArg(NodeId, @Pat),
EntryLocal(NodeId, @Pat),
+ EntryPat(NodeId, @Pat),
EntryBlock(NodeId, P<Block>),
EntryStructCtor(NodeId, @StructDef),
EntryLifetime(NodeId, @Lifetime),
EntryStmt(id, _) => id,
EntryArg(id, _) => id,
EntryLocal(id, _) => id,
+ EntryPat(id, _) => id,
EntryBlock(id, _) => id,
EntryStructCtor(id, _) => id,
EntryLifetime(id, _) => id,
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),
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),
// 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
(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()
// 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
+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
// <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;
+
+#[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 / 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() {
+ try!(out.write(res.unwrap().as_slice()));
+ }
+ 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 cur_bitmask = 0x80;
- for &init_r in chunk_init_r.iter() {
- let mut cur_r = init_r;
- let mut cur_i = init_i;
+ 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_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_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_bitmask >>= 1;
- }
- res.push(cur_byte);
- }
-}
-fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
- // 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);
+ cur_byte = (cur_byte << 2) + b;
+ i += 2;
}
- res
- })).collect();
- try!(writeln!(&mut out as &mut Writer, "P4\n{} {}", w, h));
- for res in data.move_iter() {
- try!(out.write(res.unwrap().as_slice()));
+ res.push(cur_byte^-1);
}
- out.flush()
}
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();
}
--- /dev/null
+-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,$<)
--- /dev/null
+digraph block {
+ N0[label="entry"];
+ N1[label="exit"];
+ N2[label="block { }"];
+ N0 -> N2;
+ N2 -> N1;
+}
--- /dev/null
+// 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() {
+
+}
--- /dev/null
+digraph block {
+ N0[label="entry"];
+ N1[label="exit"];
+ N2[label="expr 1"];
+ N3[label="block { 1; }"];
+ N0 -> N2;
+ N2 -> N3;
+ N3 -> N1;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+digraph block {
+ N0[label="entry"];
+ N1[label="exit"];
+ N2[label="local _x"];
+ N3[label="block { let _x: int; }"];
+ N0 -> N2;
+ N2 -> N3;
+ N3 -> N1;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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);
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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 };
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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
+ };
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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;
+ }
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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;
+ }
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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;
+ }
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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";
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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"; }
+ }
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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,
+ }
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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";
+ }
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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;
+ }
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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";
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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];
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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));
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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();
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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];
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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";
+ }
+}
--- /dev/null
+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;
+}
--- /dev/null
+// 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";
+}
extern crate libc;
use std::mem;
-use std::unstable::run_in_bare_thread;
+use std::rt::thread::Thread;
#[link(name = "rustrt")]
extern {
pub fn main() {
unsafe {
- run_in_bare_thread(proc() {
+ Thread::start(proc() {
let i = &100;
rust_dbg_call(callback, mem::transmute(i));
- });
+ }).join();
}
}
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() {
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()));
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);
}