These are the first successful snapshots after the LLVM upgrade, built with LLVM
that requires C++11
ratchet_metrics: config.ratchet_metrics.clone(),
ratchet_noise_percent: config.ratchet_noise_percent.clone(),
save_metrics: config.save_metrics.clone(),
- test_shard: config.test_shard.clone()
+ test_shard: config.test_shard.clone(),
+ nocapture: false,
}
}
fn fatal_ProcRes(err: ~str, proc_res: &ProcRes) -> ! {
print!("\n\
error: {}\n\
+status: {}\n\
command: {}\n\
stdout:\n\
------------------------------------------\n\
{}\n\
------------------------------------------\n\
\n",
- err, proc_res.cmdline, proc_res.stdout, proc_res.stderr);
+ err, proc_res.status, proc_res.cmdline, proc_res.stdout,
+ proc_res.stderr);
fail!();
}
if prevline[len(prevline) - 1] == ","
\ && s:get_line_trimmed(a:lnum) !~ "^\\s*[\\[\\]{}]"
\ && prevline !~ "^\\s*fn\\s"
- \ && prevline !~ "\\([^\\(\\)]\+,$"
+ \ && prevline !~ "([^()]\\+,$"
" Oh ho! The previous line ended in a comma! I bet cindent will try to
" take this too far... For now, let's normally use the previous line's
" indent.
let s = match expr.node {
// expression is a literal
- ast::ExprLit(lit) => match lit.node {
+ ast::ExprLit(ref lit) => match lit.node {
// string literal
ast::LitStr(ref s, _) => {
if s.get().char_len() != 4 {
pub fn ioctlsocket(s: libc::SOCKET, cmd: libc::c_long,
argp: *mut libc::c_ulong) -> libc::c_int;
pub fn select(nfds: libc::c_int,
- readfds: *mut fd_set,
- writefds: *mut fd_set,
- exceptfds: *mut fd_set,
+ readfds: *fd_set,
+ writefds: *fd_set,
+ exceptfds: *fd_set,
timeout: *libc::timeval) -> libc::c_int;
pub fn getsockopt(sockfd: libc::SOCKET,
level: libc::c_int,
use std::io::net::ip;
use std::io;
use std::mem;
+use std::os;
use std::ptr;
use std::rt::rtio;
use std::sync::arc::UnsafeArc;
super::last_error()
}
+fn ms_to_timeval(ms: u64) -> libc::timeval {
+ libc::timeval {
+ tv_sec: (ms / 1000) as libc::time_t,
+ tv_usec: ((ms % 1000) * 1000) as libc::suseconds_t,
+ }
+}
+
+fn timeout(desc: &'static str) -> io::IoError {
+ io::IoError {
+ kind: io::TimedOut,
+ desc: desc,
+ detail: None,
+ }
+}
+
#[cfg(windows)] unsafe fn close(sock: sock_t) { let _ = libc::closesocket(sock); }
#[cfg(unix)] unsafe fn close(sock: sock_t) { let _ = libc::close(sock); }
fn connect_timeout(fd: sock_t,
addrp: *libc::sockaddr,
len: libc::socklen_t,
- timeout: u64) -> IoResult<()> {
- use std::os;
+ timeout_ms: u64) -> IoResult<()> {
#[cfg(unix)] use INPROGRESS = libc::EINPROGRESS;
#[cfg(windows)] use INPROGRESS = libc::WSAEINPROGRESS;
#[cfg(unix)] use WOULDBLOCK = libc::EWOULDBLOCK;
os::errno() as int == WOULDBLOCK as int => {
let mut set: c::fd_set = unsafe { mem::init() };
c::fd_set(&mut set, fd);
- match await(fd, &mut set, timeout) {
- 0 => Err(io::IoError {
- kind: io::TimedOut,
- desc: "connection timed out",
- detail: None,
- }),
+ match await(fd, &mut set, timeout_ms) {
+ 0 => Err(timeout("connection timed out")),
-1 => Err(last_error()),
_ => {
let err: libc::c_int = try!(
// Recalculate the timeout each iteration (it is generally
// undefined what the value of the 'tv' is after select
// returns EINTR).
- let timeout = timeout - (::io::timer::now() - start);
- let tv = libc::timeval {
- tv_sec: (timeout / 1000) as libc::time_t,
- tv_usec: ((timeout % 1000) * 1000) as libc::suseconds_t,
- };
- c::select(fd + 1, ptr::null(), set as *mut _ as *_,
- ptr::null(), &tv)
+ let tv = ms_to_timeval(timeout - (::io::timer::now() - start));
+ c::select(fd + 1, ptr::null(), &*set, ptr::null(), &tv)
})
}
#[cfg(windows)]
fn await(_fd: sock_t, set: &mut c::fd_set, timeout: u64) -> libc::c_int {
- let tv = libc::timeval {
- tv_sec: (timeout / 1000) as libc::time_t,
- tv_usec: ((timeout % 1000) * 1000) as libc::suseconds_t,
- };
- unsafe { c::select(1, ptr::mut_null(), set, ptr::mut_null(), &tv) }
+ let tv = ms_to_timeval(timeout);
+ unsafe { c::select(1, ptr::null(), &*set, ptr::null(), &tv) }
}
}
////////////////////////////////////////////////////////////////////////////////
pub struct TcpListener {
- inner: UnsafeArc<Inner>,
+ inner: Inner,
}
impl TcpListener {
let (addr, len) = addr_to_sockaddr(addr);
let addrp = &addr as *libc::sockaddr_storage;
let inner = Inner { fd: fd };
- let ret = TcpListener { inner: UnsafeArc::new(inner) };
+ let ret = TcpListener { inner: inner };
// On platforms with Berkeley-derived sockets, this allows
// to quickly rebind a socket, without needing to wait for
// the OS to clean up the previous one.
}
}
- pub fn fd(&self) -> sock_t {
- // This is just a read-only arc so the unsafety is fine
- unsafe { (*self.inner.get()).fd }
- }
+ pub fn fd(&self) -> sock_t { self.inner.fd }
pub fn native_listen(self, backlog: int) -> IoResult<TcpAcceptor> {
match unsafe { libc::listen(self.fd(), backlog as libc::c_int) } {
-1 => Err(last_error()),
- _ => Ok(TcpAcceptor { listener: self })
+ _ => Ok(TcpAcceptor { listener: self, deadline: 0 })
}
}
}
pub struct TcpAcceptor {
listener: TcpListener,
+ deadline: u64,
}
impl TcpAcceptor {
pub fn fd(&self) -> sock_t { self.listener.fd() }
pub fn native_accept(&mut self) -> IoResult<TcpStream> {
+ if self.deadline != 0 {
+ try!(self.accept_deadline());
+ }
unsafe {
let mut storage: libc::sockaddr_storage = mem::init();
let storagep = &mut storage as *mut libc::sockaddr_storage;
}
}
}
+
+ fn accept_deadline(&mut self) -> IoResult<()> {
+ let mut set: c::fd_set = unsafe { mem::init() };
+ c::fd_set(&mut set, self.fd());
+
+ match retry(|| {
+ // If we're past the deadline, then pass a 0 timeout to select() so
+ // we can poll the status of the socket.
+ let now = ::io::timer::now();
+ let ms = if self.deadline > now {0} else {self.deadline - now};
+ let tv = ms_to_timeval(ms);
+ let n = if cfg!(windows) {1} else {self.fd() as libc::c_int + 1};
+ unsafe { c::select(n, &set, ptr::null(), ptr::null(), &tv) }
+ }) {
+ -1 => Err(last_error()),
+ 0 => Err(timeout("accept timed out")),
+ _ => return Ok(()),
+ }
+ }
}
impl rtio::RtioSocket for TcpAcceptor {
fn accept_simultaneously(&mut self) -> IoResult<()> { Ok(()) }
fn dont_accept_simultaneously(&mut self) -> IoResult<()> { Ok(()) }
+ fn set_timeout(&mut self, timeout: Option<u64>) {
+ self.deadline = match timeout {
+ None => 0,
+ Some(t) => ::io::timer::now() + t,
+ };
+ }
}
////////////////////////////////////////////////////////////////////////////////
}
}
+// returns the current time (in milliseconds)
+pub fn now() -> u64 {
+ let mut ticks_per_s = 0;
+ assert_eq!(unsafe { libc::QueryPerformanceFrequency(&mut ticks_per_s) }, 1);
+ let ticks_per_s = if ticks_per_s == 0 {1} else {ticks_per_s};
+ let mut ticks = 0;
+ assert_eq!(unsafe { libc::QueryPerformanceCounter(&mut ticks) }, 1);
+
+ return (ticks as u64 * 1000) / (ticks_per_s as u64);
+}
+
impl Timer {
pub fn new() -> IoResult<Timer> {
timer_helper::boot(helper);
if cstr == ptr::null() {
sess.fatal(msg);
} else {
- let err = CString::new(cstr, false);
+ let err = CString::new(cstr, true);
let err = str::from_utf8_lossy(err.as_bytes());
sess.fatal(msg + ": " + err.as_slice());
}
pub fn find_crate_id(attrs: &[ast::Attribute], out_filestem: &str) -> CrateId {
match attr::find_crateid(attrs) {
- None => from_str(out_filestem).unwrap(),
+ None => from_str(out_filestem).unwrap_or_else(|| {
+ let mut s = out_filestem.chars().filter(|c| c.is_XID_continue());
+ from_str(s.collect::<~str>()).or(from_str("rust-out")).unwrap()
+ }),
Some(s) => s,
}
}
time(time_passes, "effect checking", (), |_|
middle::effect::check_crate(&ty_cx, krate));
- let middle::moves::MoveMaps {moves_map, moved_variables_set,
- capture_map} =
+ let middle::moves::MoveMaps {moves_map, capture_map} =
time(time_passes, "compute moves", (), |_|
middle::moves::compute_moves(&ty_cx, krate));
time(time_passes, "liveness checking", (), |_|
middle::liveness::check_crate(&ty_cx, &capture_map, krate));
- let root_map =
- time(time_passes, "borrow checking", (), |_|
- middle::borrowck::check_crate(&ty_cx, &moves_map,
- &moved_variables_set,
- &capture_map, krate));
+ time(time_passes, "borrow checking", (), |_|
+ middle::borrowck::check_crate(&ty_cx, &moves_map,
+ &capture_map, krate));
drop(moves_map);
- drop(moved_variables_set);
time(time_passes, "kind checking", (), |_|
kind::check_crate(&ty_cx, krate));
exported_items: exported_items,
public_items: public_items,
maps: astencode::Maps {
- root_map: root_map,
capture_map: RefCell::new(capture_map)
},
reachable: reachable_map
fn write_out_deps(sess: &Session,
input: &Input,
outputs: &OutputFilenames,
- krate: &ast::Crate) -> io::IoResult<()> {
+ krate: &ast::Crate) {
let id = link::find_crate_id(krate.attrs.as_slice(), outputs.out_filestem);
let mut out_filenames = Vec::new();
StrInput(..) => {
sess.warn("can not write --dep-info without a filename \
when compiling stdin.");
- return Ok(());
+ return
},
},
- _ => return Ok(()),
+ _ => return,
};
- // Build a list of files used to compile the output and
- // write Makefile-compatible dependency rules
- let files: Vec<~str> = sess.codemap().files.borrow()
- .iter().filter_map(|fmap| {
- if fmap.is_real_file() {
- Some(fmap.name.clone())
- } else {
- None
- }
- }).collect();
- let mut file = try!(io::File::create(&deps_filename));
- for path in out_filenames.iter() {
- try!(write!(&mut file as &mut Writer,
- "{}: {}\n\n", path.display(), files.connect(" ")));
+ let result = (|| {
+ // Build a list of files used to compile the output and
+ // write Makefile-compatible dependency rules
+ let files: Vec<~str> = sess.codemap().files.borrow()
+ .iter().filter(|fmap| fmap.is_real_file())
+ .map(|fmap| fmap.name.clone())
+ .collect();
+ let mut file = try!(io::File::create(&deps_filename));
+ for path in out_filenames.iter() {
+ try!(write!(&mut file as &mut Writer,
+ "{}: {}\n\n", path.display(), files.connect(" ")));
+ }
+ Ok(())
+ })();
+
+ match result {
+ Ok(()) => {}
+ Err(e) => {
+ sess.fatal(format!("error writing dependencies to `{}`: {}",
+ deps_filename.display(), e));
+ }
}
- Ok(())
}
pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &Input,
krate, &id);
(outputs, expanded_crate, ast_map)
};
- write_out_deps(&sess, input, &outputs, &expanded_crate).unwrap();
+ write_out_deps(&sess, input, &outputs, &expanded_crate);
if stop_after_phase_2(&sess) { return; }
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
fn fold_item_underscore(&mut self, item: &ast::Item_) -> ast::Item_ {
fold_item_underscore(self, item)
}
+ fn fold_expr(&mut self, expr: @ast::Expr) -> @ast::Expr {
+ fold_expr(self, expr)
+ }
}
pub fn strip_items(krate: ast::Crate,
})
}
+fn fold_expr(cx: &mut Context, expr: @ast::Expr) -> @ast::Expr {
+ let expr = match expr.node {
+ ast::ExprMatch(ref m, ref arms) => {
+ let arms = arms.iter()
+ .filter(|a| (cx.in_cfg)(a.attrs.as_slice()))
+ .map(|a| a.clone())
+ .collect();
+ @ast::Expr {
+ id: expr.id,
+ span: expr.span.clone(),
+ node: ast::ExprMatch(m.clone(), arms),
+ }
+ }
+ _ => expr.clone()
+ };
+ fold::noop_fold_expr(expr, cx)
+}
+
fn item_in_cfg(cx: &mut Context, item: &ast::Item) -> bool {
return (cx.in_cfg)(item.attrs.as_slice());
}
use std::io;
use std::os;
use std::str;
-use std::task;
+use std::task::TaskBuilder;
use syntax::ast;
use syntax::diagnostic::Emitter;
use syntax::diagnostic;
#[cfg(not(rtopt))]
static STACK_SIZE: uint = 20000000; // 20MB
- let mut task_builder = task::task().named("rustc");
+ let mut task_builder = TaskBuilder::new().named("rustc");
// FIXME: Hacks on hacks. If the env is trying to override the stack size
// then *don't* set it explicitly.
// Auxiliary maps of things to be encoded
pub struct Maps {
- pub root_map: middle::borrowck::root_map,
pub capture_map: RefCell<middle::moves::CaptureMap>,
}
}
impl<'a> GuaranteeLifetimeContext<'a> {
- fn tcx(&self) -> &'a ty::ctxt {
- self.bccx.tcx
- }
fn check(&self, cmt: &mc::cmt, discr_scope: Option<ast::NodeId>) -> R {
//! Main routine. Walks down `cmt` until we find the "guarantor".
Ok(())
}
- mc::cat_deref(ref base, derefs, mc::GcPtr) => {
- let base_scope = self.scope(base);
-
- // L-Deref-Managed-Imm-User-Root
- let omit_root =
- self.bccx.is_subregion_of(self.loan_region, base_scope) &&
- self.is_rvalue_or_immutable(base) &&
- !self.is_moved(base);
-
- if !omit_root {
- // L-Deref-Managed-Imm-Compiler-Root
- // L-Deref-Managed-Mut-Compiler-Root
- self.check_root(cmt, base, derefs, discr_scope)
- } else {
- debug!("omitting root, base={}, base_scope={:?}",
- base.repr(self.tcx()), base_scope);
- Ok(())
- }
- }
-
mc::cat_downcast(ref base) |
mc::cat_deref(ref base, _, mc::OwnedPtr) | // L-Deref-Send
- mc::cat_interior(ref base, _) => { // L-Field
+ mc::cat_interior(ref base, _) | // L-Field
+ mc::cat_deref(ref base, _, mc::GcPtr) => {
self.check(base, discr_scope)
}
}
}
- fn is_rvalue_or_immutable(&self,
- cmt: &mc::cmt) -> bool {
- //! We can omit the root on an `@T` value if the location
- //! that holds the box is either (1) an rvalue, in which case
- //! it is in a non-user-accessible temporary, or (2) an immutable
- //! lvalue.
-
- cmt.mutbl.is_immutable() || match cmt.guarantor().cat {
- mc::cat_rvalue(..) => true,
- _ => false
- }
- }
-
- fn check_root(&self,
- cmt_deref: &mc::cmt,
- cmt_base: &mc::cmt,
- derefs: uint,
- discr_scope: Option<ast::NodeId>) -> R {
- debug!("check_root(cmt_deref={}, cmt_base={}, derefs={:?}, \
- discr_scope={:?})",
- cmt_deref.repr(self.tcx()),
- cmt_base.repr(self.tcx()),
- derefs,
- discr_scope);
-
- // Make sure that the loan does not exceed the maximum time
- // that we can root the value, dynamically.
- let root_region = ty::ReScope(self.root_scope_id);
- if !self.bccx.is_subregion_of(self.loan_region, root_region) {
- return Err(self.report_error(
- err_out_of_root_scope(root_region, self.loan_region)));
- }
-
- // Extract the scope id that indicates how long the rooting is required
- let root_scope = match self.loan_region {
- ty::ReScope(id) => id,
- _ => {
- // the check above should fail for anything is not ReScope
- self.bccx.tcx.sess.span_bug(
- cmt_base.span,
- format!("cannot issue root for scope region: {:?}",
- self.loan_region));
- }
- };
-
- // If inside of a match arm, expand the rooting to the entire
- // match. See the detailed discussion in `check()` above.
- let root_scope = match discr_scope {
- None => root_scope,
- Some(id) => {
- if self.bccx.is_subscope_of(root_scope, id) {
- id
- } else {
- root_scope
- }
- }
- };
-
- // Add a record of what is required
- let rm_key = root_map_key {id: cmt_deref.id, derefs: derefs};
- let root_info = RootInfo {scope: root_scope};
-
- self.bccx.root_map.borrow_mut().insert(rm_key, root_info);
-
- debug!("root_key: {:?} root_info: {:?}", rm_key, root_info);
- Ok(())
- }
-
fn check_scope(&self, max_scope: ty::Region) -> R {
//! Reports an error if `loan_region` is larger than `valid_scope`
}
}
- fn is_moved(&self, cmt: &mc::cmt) -> bool {
- //! True if `cmt` is something that is potentially moved
- //! out of the current stack frame.
-
- match cmt.guarantor().cat {
- mc::cat_local(id) |
- mc::cat_arg(id) => {
- self.bccx.moved_variables_set.contains(&id)
- }
- mc::cat_rvalue(..) |
- mc::cat_static_item |
- mc::cat_copied_upvar(..) |
- mc::cat_deref(..) |
- mc::cat_upvar(..) => {
- false
- }
- ref r @ mc::cat_downcast(..) |
- ref r @ mc::cat_interior(..) |
- ref r @ mc::cat_discr(..) => {
- self.tcx().sess.span_bug(
- cmt.span,
- format!("illegal guarantor category: {:?}", r));
- }
- }
- }
-
fn scope(&self, cmt: &mc::cmt) -> ty::Region {
//! Returns the maximal region scope for the which the
//! lvalue `cmt` is guaranteed to be valid without any
self.extend(result, cmt.mutbl, LpInterior(i), restrictions)
}
- mc::cat_deref(cmt_base, _, pk @ mc::OwnedPtr) => {
+ mc::cat_deref(cmt_base, _, pk @ mc::OwnedPtr) |
+ mc::cat_deref(cmt_base, _, pk @ mc::GcPtr) => {
// R-Deref-Send-Pointer
//
// When we borrow the interior of an owned pointer, we
// cannot permit the base to be mutated, because that
// would cause the unique pointer to be freed.
+ //
+ // For a managed pointer, the rules are basically the
+ // same, because this could be the last ref.
+ // Eventually we should make these non-special and
+ // just rely on Deref<T> implementation.
let result = self.restrict(
cmt_base,
restrictions | RESTR_MUTATE);
Safe
}
- mc::cat_deref(_, _, mc::GcPtr) => {
- // R-Deref-Imm-Managed
- Safe
- }
-
mc::cat_deref(cmt_base, _, pk @ mc::BorrowedPtr(ty::MutBorrow, lt)) => {
// R-Deref-Mut-Borrowed
if !self.bccx.is_subregion_of(self.loan_region, lt) {
use util::nodemap::{NodeMap, NodeSet};
use util::ppaux::{note_and_explain_region, Repr, UserString};
-use std::cell::RefCell;
+use std::cell::{Cell, RefCell};
use std::ops::{BitOr, BitAnd};
use std::rc::Rc;
use std::strbuf::StrBuf;
-use collections::HashMap;
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util;
pub fn check_crate(tcx: &ty::ctxt,
moves_map: &NodeSet,
- moved_variables_set: &NodeSet,
capture_map: &moves::CaptureMap,
- krate: &ast::Crate)
- -> root_map {
+ krate: &ast::Crate) {
let mut bccx = BorrowckCtxt {
tcx: tcx,
moves_map: moves_map,
- moved_variables_set: moved_variables_set,
capture_map: capture_map,
- root_map: RefCell::new(HashMap::new())
+ stats: @BorrowStats {
+ loaned_paths_same: Cell::new(0),
+ loaned_paths_imm: Cell::new(0),
+ stable_paths: Cell::new(0),
+ guaranteed_paths: Cell::new(0),
+ }
};
visit::walk_crate(&mut bccx, krate, ());
- return bccx.root_map.unwrap();
+ if tcx.sess.borrowck_stats() {
+ println!("--- borrowck stats ---");
+ println!("paths requiring guarantees: {}",
+ bccx.stats.guaranteed_paths.get());
+ println!("paths requiring loans : {}",
+ make_stat(&bccx, bccx.stats.loaned_paths_same.get()));
+ println!("paths requiring imm loans : {}",
+ make_stat(&bccx, bccx.stats.loaned_paths_imm.get()));
+ println!("stable paths : {}",
+ make_stat(&bccx, bccx.stats.stable_paths.get()));
+ }
+
+ fn make_stat(bccx: &BorrowckCtxt, stat: uint) -> ~str {
+ let stat_f = stat as f64;
+ let total = bccx.stats.guaranteed_paths.get() as f64;
+ format!("{} ({:.0f}%)", stat , stat_f * 100.0 / total)
+ }
}
fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) {
pub struct BorrowckCtxt<'a> {
tcx: &'a ty::ctxt,
moves_map: &'a NodeSet,
- moved_variables_set: &'a NodeSet,
capture_map: &'a moves::CaptureMap,
- root_map: RefCell<root_map>,
+
+ // Statistics:
+ stats: @BorrowStats
}
-// The keys to the root map combine the `id` of the deref expression
-// with the number of types that it is *autodereferenced*. So, for
-// example, imagine I have a variable `x: @@@T` and an expression
-// `(*x).f`. This will have 3 derefs, one explicit and then two
-// autoderefs. These are the relevant `root_map_key` values that could
-// appear:
-//
-// {id:*x, derefs:0} --> roots `x` (type: @@@T, due to explicit deref)
-// {id:*x, derefs:1} --> roots `*x` (type: @@T, due to autoderef #1)
-// {id:*x, derefs:2} --> roots `**x` (type: @T, due to autoderef #2)
-//
-// Note that there is no entry with derefs:3---the type of that expression
-// is T, which is not a box.
-#[deriving(Eq, TotalEq, Hash)]
-pub struct root_map_key {
- pub id: ast::NodeId,
- pub derefs: uint
+pub struct BorrowStats {
+ loaned_paths_same: Cell<uint>,
+ loaned_paths_imm: Cell<uint>,
+ stable_paths: Cell<uint>,
+ guaranteed_paths: Cell<uint>,
}
pub type BckResult<T> = Result<T, BckError>;
}
}
-///////////////////////////////////////////////////////////////////////////
-// Rooting of managed boxes
-//
-// When we borrow the interior of a managed box, it is sometimes
-// necessary to *root* the box, meaning to stash a copy of the box
-// somewhere that the garbage collector will find it. This ensures
-// that the box is not collected for the lifetime of the borrow.
-//
-// As part of this rooting, we sometimes also freeze the box at
-// runtime, meaning that we dynamically detect when the box is
-// borrowed in incompatible ways.
-//
-// Both of these actions are driven through the `root_map`, which maps
-// from a node to the dynamic rooting action that should be taken when
-// that node executes. The node is identified through a
-// `root_map_key`, which pairs a node-id and a deref count---the
-// problem is that sometimes the box that needs to be rooted is only
-// uncovered after a certain number of auto-derefs.
-
-pub struct RootInfo {
- pub scope: ast::NodeId,
-}
-
-pub type root_map = HashMap<root_map_key, RootInfo>;
-
///////////////////////////////////////////////////////////////////////////
// Errors
#[deriving(Eq)]
pub enum bckerr_code {
err_mutbl,
- err_out_of_root_scope(ty::Region, ty::Region), // superscope, subscope
err_out_of_scope(ty::Region, ty::Region), // superscope, subscope
err_borrowed_pointer_too_short(
ty::Region, ty::Region, RestrictionSet), // loan, ptr
}
}
}
- err_out_of_root_scope(..) => {
- format!("cannot root managed value long enough")
- }
err_out_of_scope(..) => {
let msg = match opt_loan_path(&err.cmt) {
None => format!("borrowed value"),
match code {
err_mutbl(..) => { }
- err_out_of_root_scope(super_scope, sub_scope) => {
- note_and_explain_region(
- self.tcx,
- "managed value would have to be rooted for ",
- sub_scope,
- "...");
- note_and_explain_region(
- self.tcx,
- "...but can only be rooted for ",
- super_scope,
- "");
- }
-
err_out_of_scope(super_scope, sub_scope) => {
note_and_explain_region(
self.tcx,
use syntax::{ast, ast_map, ast_util};
use std::cell::RefCell;
-use collections::HashMap;
use std::rc::Rc;
//
None => {}
}
let maps = astencode::Maps {
- root_map: HashMap::new(),
capture_map: RefCell::new(NodeMap::new())
};
let e = match csearch::maybe_get_item_ast(tcx, enum_def,
None => {}
}
let maps = astencode::Maps {
- root_map: HashMap::new(),
capture_map: RefCell::new(NodeMap::new())
};
let e = match csearch::maybe_get_item_ast(tcx, def_id,
use syntax::attr;
use syntax::codemap::Span;
use syntax::owned_slice::OwnedSlice;
-use syntax::print::pprust::expr_to_str;
+use syntax::print::pprust::{expr_to_str,path_to_str};
use syntax::{visit,ast_util};
use syntax::visit::Visitor;
fn visit_ty(&mut self, t: &Ty, _: ()) {
check_ty(self, t);
}
+
fn visit_item(&mut self, i: &Item, _: ()) {
check_item(self, i);
}
+
+ fn visit_pat(&mut self, p: &Pat, _: ()) {
+ check_pat(self, p);
+ }
}
pub fn check_crate(tcx: &ty::ctxt,
}
}
}
+
+// Ensure that `ty` has a statically known size (i.e., it has the `Sized` bound).
+fn check_sized(tcx: &ty::ctxt, ty: ty::t, name: ~str, sp: Span) {
+ if !ty::type_is_sized(tcx, ty) {
+ tcx.sess.span_err(sp, format!("variable `{}` has dynamically sized type `{}`",
+ name, ty_to_str(tcx, ty)));
+ }
+}
+
+// Check that any variables in a pattern have types with statically known size.
+fn check_pat(cx: &mut Context, pat: &Pat) {
+ let var_name = match pat.node {
+ PatWild => Some("_".to_owned()),
+ PatIdent(_, ref path, _) => Some(path_to_str(path)),
+ _ => None
+ };
+
+ match var_name {
+ Some(name) => {
+ let types = cx.tcx.node_types.borrow();
+ let ty = types.find(&(pat.id as uint));
+ match ty {
+ Some(ty) => {
+ debug!("kind: checking sized-ness of variable {}: {}",
+ name, ty_to_str(cx.tcx, *ty));
+ check_sized(cx.tcx, *ty, name, pat.span);
+ }
+ None => {} // extern fn args
+ }
+ }
+ None => {}
+ }
+
+ visit::walk_pat(cx, pat, ());
+}
fn visit_view_item(&mut self, i: &ast::ViewItem, _: ()) {
self.with_lint_attrs(i.attrs.as_slice(), |cx| {
check_attrs_usage(cx, i.attrs.as_slice());
+
+ cx.visit_ids(|v| v.visit_view_item(i, ()));
+
visit::walk_view_item(cx, i, ());
})
}
expressions that are moved. It is more efficient therefore just to
store those entries.
-Sometimes though we want to know the variables that are moved (in
-particular in the borrow checker). For these cases, the set
-`moved_variables_set` just collects the ids of variables that are
-moved.
-
Finally, the `capture_map` maps from the node_id of a closure
expression to an array of `CaptureVar` structs detailing which
variables are captured and how (by ref, by copy, by move).
* pub Note: The `moves_map` stores expression ids that are moves,
* whereas this set stores the ids of the variables that are
* moved at some point */
- pub moved_variables_set: NodeSet,
pub capture_map: CaptureMap
}
tcx: tcx,
move_maps: MoveMaps {
moves_map: NodeSet::new(),
- moved_variables_set: NodeSet::new(),
capture_map: NodeMap::new()
}
};
debug!("comp_mode = {:?}", comp_mode);
match expr.node {
- ExprPath(..) => {
- match comp_mode {
- Move => {
- let def = self.tcx.def_map.borrow().get_copy(&expr.id);
- let r = moved_variable_node_id_from_def(def);
- for &id in r.iter() {
- self.move_maps.moved_variables_set.insert(id);
- }
- }
- Read => {}
- }
- }
-
ExprUnary(UnDeref, base) => { // *base
if !self.use_overloaded_operator(expr, base, []) {
// Moving out of *base moves out of base.
self.use_expr(base, Read);
}
+ ExprPath(..) |
ExprInlineAsm(..) |
ExprBreak(..) |
ExprAgain(..) |
}
Some(method) => {
debug!("(privacy checking) checking impl method");
- self.check_method(expr.span, method.origin, ident);
+ self.check_method(expr.span, method.origin, ident.node);
}
}
}
debug!("(recording candidate traits for expr) recording \
traits for {}",
expr.id);
- let traits = self.search_for_traits_containing_method(ident.name);
+ let traits = self.search_for_traits_containing_method(ident.node.name);
self.trait_map.insert(expr.id, traits);
}
_ => {
use driver::session::FullDebugInfo;
use lib::llvm::{llvm, ValueRef, BasicBlockRef};
use middle::const_eval;
-use middle::borrowck::root_map_key;
use middle::lang_items::{UniqStrEqFnLangItem, StrEqFnLangItem};
use middle::pat_util::*;
use middle::resolve::DefMap;
}
}
-fn pats_require_rooting(bcx: &Block, m: &[Match], col: uint) -> bool {
- m.iter().any(|br| {
- let pat_id = br.pats.get(col).id;
- let key = root_map_key {id: pat_id, derefs: 0u };
- bcx.ccx().maps.root_map.contains_key(&key)
- })
-}
-
// Macro for deciding whether any of the remaining matches fit a given kind of
// pattern. Note that, because the macro is well-typed, either ALL of the
// matches should fit that sort of pattern or NONE (however, some of the
}
}
- // If we are not matching against an `@T`, we should not be
- // required to root any values.
- assert!(!pats_require_rooting(bcx, m, col));
-
match collect_record_or_struct_fields(bcx, m, col) {
Some(ref rec_fields) => {
let pat_ty = node_id_type(bcx, pat_id);
}
}
}
- ast_map::NodeMethod(method) => {
+ ast_map::NodeMethod(ref method) => {
(method.ident,
method.decl,
&method.generics,
"create_function_debug_context: expected an expr_fn_block here")
}
}
- ast_map::NodeTraitMethod(trait_method) => {
- match *trait_method {
- ast::Provided(method) => {
+ ast_map::NodeTraitMethod(ref trait_method) => {
+ match **trait_method {
+ ast::Provided(ref method) => {
(method.ident,
method.decl,
&method.generics,
use middle::trans::inline;
use middle::trans::tvec;
use middle::trans::type_of;
-use middle::trans::write_guard;
use middle::ty::struct_fields;
use middle::ty::{AutoBorrowObj, AutoDerefRef, AutoAddEnv, AutoObject, AutoUnsafe};
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef};
derefs: uint)
-> DatumBlock<'a, Expr> {
let ccx = bcx.ccx();
- let bcx = write_guard::root_and_write_guard(&datum, bcx, expr.span,
- expr.id, derefs);
debug!("deref_once(expr={}, datum={}, derefs={})",
expr.repr(bcx.tcx()),
pub mod controlflow;
pub mod glue;
pub mod datum;
-pub mod write_guard;
pub mod callee;
pub mod expr;
pub mod common;
+++ /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.
-
-//! Logic relating to rooting and write guards for managed values.
-//! This code is primarily for use by datum;
-//! it exists in its own module both to keep datum.rs bite-sized
-//! and for each in debugging (e.g., so you can use
-//! `RUST_LOG=rustc::middle::trans::write_guard`).
-
-
-use middle::borrowck::{RootInfo, root_map_key};
-use middle::trans::cleanup;
-use middle::trans::common::*;
-use middle::trans::datum::*;
-use syntax::codemap::Span;
-use syntax::ast;
-
-pub fn root_and_write_guard<'a, K:KindOps>(datum: &Datum<K>,
- bcx: &'a Block<'a>,
- span: Span,
- expr_id: ast::NodeId,
- derefs: uint) -> &'a Block<'a> {
- let key = root_map_key { id: expr_id, derefs: derefs };
- debug!("write_guard::root_and_write_guard(key={:?})", key);
-
- // root the autoderef'd value, if necessary:
- //
- // (Note: root'd values are always boxes)
- let ccx = bcx.ccx();
- match ccx.maps.root_map.find(&key) {
- None => bcx,
- Some(&root_info) => root(datum, bcx, span, key, root_info)
- }
-}
-
-fn root<'a, K:KindOps>(datum: &Datum<K>,
- bcx: &'a Block<'a>,
- _span: Span,
- root_key: root_map_key,
- root_info: RootInfo) -> &'a Block<'a> {
- //! In some cases, borrowck will decide that an @T value must be
- //! rooted for the program to be safe. In that case, we will call
- //! this function, which will stash a copy away until we exit the
- //! scope `scope_id`.
-
- debug!("write_guard::root(root_key={:?}, root_info={:?}, datum={:?})",
- root_key, root_info, datum.to_str(bcx.ccx()));
-
- // Root the datum. Note that we must zero this value,
- // because sometimes we root on one path but not another.
- // See e.g. #4904.
- lvalue_scratch_datum(
- bcx, datum.ty, "__write_guard", true,
- cleanup::AstScope(root_info.scope), (),
- |(), bcx, llval| datum.shallow_copy_and_take(bcx, llval)).bcx
-}
}
_ => {
fcx.tcx().sess.span_bug(
- sp,
+ callee_expr.span,
format!("method without bare fn type"));
}
}
// Checks a method call.
fn check_method_call(fcx: &FnCtxt,
expr: &ast::Expr,
- method_name: ast::Ident,
+ method_name: ast::SpannedIdent,
args: &[@ast::Expr],
tps: &[ast::P<ast::Ty>]) {
let rcvr = args[0];
let tps = tps.iter().map(|&ast_ty| fcx.to_ty(ast_ty)).collect::<Vec<_>>();
let fn_ty = match method::lookup(fcx, expr, rcvr,
- method_name.name,
+ method_name.node.name,
expr_t, tps.as_slice(),
DontDerefArgs,
CheckTraitsAndInherentMethods,
None => {
debug!("(checking method call) failing expr is {}", expr.id);
- fcx.type_error_message(expr.span,
+ fcx.type_error_message(method_name.span,
|actual| {
- format!("type `{}` does not implement any method in scope \
- named `{}`",
- actual, token::get_ident(method_name))
+ format!("type `{}` does not implement any method in scope named `{}`",
+ actual, token::get_ident(method_name.node))
},
expr_t,
None);
};
// Call the generic checker.
- let ret_ty = check_method_argument_types(fcx, expr.span,
+ let ret_ty = check_method_argument_types(fcx, method_name.span,
fn_ty, expr, args,
DontDerefArgs);
}
mc::cat_discr(cmt_base, _) |
mc::cat_downcast(cmt_base) |
+ mc::cat_deref(cmt_base, _, mc::GcPtr(..)) |
mc::cat_deref(cmt_base, _, mc::OwnedPtr) |
mc::cat_interior(cmt_base, _) => {
// Interior or owned data requires its base to be valid
cmt_borrowed = cmt_base;
}
- mc::cat_deref(_, _, mc::GcPtr(..)) |
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
mc::cat_static_item |
mc::cat_copied_upvar(..) |
let parent = self.tcx.map.get_parent(scope_id);
let parent_node = self.tcx.map.find(parent);
let node_inner = match parent_node {
- Some(node) => match node {
- ast_map::NodeItem(item) => match item.node {
- ast::ItemFn(ref fn_decl, ref pur, _, ref gen, _) => {
- Some((fn_decl, gen, *pur, item.ident, None, item.span))
- },
- _ => None
- },
- ast_map::NodeMethod(m) => {
+ Some(ref node) => match *node {
+ ast_map::NodeItem(ref item) => {
+ match item.node {
+ ast::ItemFn(ref fn_decl, ref pur, _, ref gen, _) => {
+ Some((fn_decl, gen, *pur, item.ident, None, item.span))
+ },
+ _ => None
+ }
+ }
+ ast_map::NodeMethod(ref m) => {
Some((&m.decl, &m.generics, m.fn_style,
m.ident, Some(m.explicit_self.node), m.span))
},
fn clean(&self) -> Type {
use syntax::ast::*;
debug!("cleaning type `{:?}`", self);
- let codemap = local_data::get(super::ctxtkey, |x| *x.unwrap()).sess().codemap();
+ let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap());
+ let codemap = ctxt.sess().codemap();
debug!("span corresponds to `{}`", codemap.span_to_str(self.span));
match self.node {
TyNil => Unit,
impl Clean<Span> for syntax::codemap::Span {
fn clean(&self) -> Span {
- let cm = local_data::get(super::ctxtkey, |x| *x.unwrap()).sess().codemap();
+ let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap());
+ let cm = ctxt.sess().codemap();
let filename = cm.span_to_filename(*self);
let lo = cm.lookup_char_pos(self.lo);
let hi = cm.lookup_char_pos(self.hi);
impl ToSource for syntax::codemap::Span {
fn to_src(&self) -> ~str {
debug!("converting span {:?} to snippet", self.clean());
- let cm = local_data::get(super::ctxtkey, |x| x.unwrap().clone()).sess().codemap().clone();
+ let ctxt = local_data::get(super::ctxtkey, |x| x.unwrap().clone());
+ let cm = ctxt.sess().codemap().clone();
let sn = match cm.span_to_snippet(*self) {
Some(x) => x,
None => "".to_owned()
// except according to those terms.
use std::cast;
-use libc::c_int;
use std::rt::rtio::{Callback, RemoteCallback};
use std::unstable::sync::Exclusive;
}
}
-extern fn async_cb(handle: *uvll::uv_async_t, status: c_int) {
- assert!(status == 0);
+extern fn async_cb(handle: *uvll::uv_async_t) {
let payload: &mut Payload = unsafe {
cast::transmute(uvll::get_data_for_uv_handle(handle))
};
use std::c_str;
use std::cast::transmute;
use std::cast;
-use libc::{c_int, c_char, c_void, size_t, ssize_t};
+use libc::{c_int, c_char, c_void, ssize_t};
use libc;
use std::rt::task::BlockedTask;
use std::io::{FileStat, IoError};
} else {
offset + written as i64
};
+ let uvbuf = uvll::uv_buf_t {
+ base: buf.slice_from(written as uint).as_ptr(),
+ len: (buf.len() - written) as uvll::uv_buf_len_t,
+ };
match execute(|req, cb| unsafe {
- uvll::uv_fs_write(loop_.handle,
- req,
- fd,
- buf.as_ptr().offset(written as int) as *c_void,
- (buf.len() - written) as size_t,
- offset,
- cb)
+ uvll::uv_fs_write(loop_.handle, req, fd, &uvbuf, 1, offset, cb)
}).map(|req| req.get_result()) {
Err(e) => return Err(e),
Ok(n) => { written += n as uint; }
-> Result<int, UvError>
{
execute(|req, cb| unsafe {
- uvll::uv_fs_read(loop_.handle, req,
- fd, buf.as_ptr() as *c_void,
- buf.len() as size_t, offset, cb)
+ let uvbuf = uvll::uv_buf_t {
+ base: buf.as_ptr(),
+ len: buf.len() as uvll::uv_buf_len_t,
+ };
+ uvll::uv_fs_read(loop_.handle, req, fd, &uvbuf, 1, offset, cb)
}).map(|req| {
req.get_result() as int
})
// except according to those terms.
use std::cast;
-use libc::{c_int, c_void};
+use libc::c_void;
use uvll;
use super::{Loop, UvHandle};
assert_eq!(uvll::uv_idle_start(handle, onetime_cb), 0)
}
- extern fn onetime_cb(handle: *uvll::uv_idle_t, status: c_int) {
- assert_eq!(status, 0);
+ extern fn onetime_cb(handle: *uvll::uv_idle_t) {
unsafe {
let data = uvll::get_data_for_uv_handle(handle);
let f: ~proc() = cast::transmute(data);
fn uv_handle(&self) -> *uvll::uv_idle_t { self.handle }
}
-extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) {
- assert_eq!(status, 0);
+extern fn idle_cb(handle: *uvll::uv_idle_t) {
let idle: &mut IdleWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
idle.callback.call();
}
pub struct TcpAcceptor {
listener: ~TcpListener,
+ timer: Option<TimerWatcher>,
+ timeout_tx: Option<Sender<()>>,
+ timeout_rx: Option<Receiver<()>>,
}
// TCP watchers (clients/streams)
n => Err(UvError(n))
};
- extern fn timer_cb(handle: *uvll::uv_timer_t, status: c_int) {
+ extern fn timer_cb(handle: *uvll::uv_timer_t) {
// Don't close the corresponding tcp request, just wake up the task
// and let RAII take care of the pending watcher.
- assert_eq!(status, 0);
let cx: &mut Ctx = unsafe {
&mut *(uvll::get_data_for_uv_handle(handle) as *mut Ctx)
};
impl rtio::RtioTcpListener for TcpListener {
fn listen(~self) -> Result<~rtio::RtioTcpAcceptor:Send, IoError> {
// create the acceptor object from ourselves
- let mut acceptor = ~TcpAcceptor { listener: self };
+ let mut acceptor = ~TcpAcceptor {
+ listener: self,
+ timer: None,
+ timeout_tx: None,
+ timeout_rx: None,
+ };
let _m = acceptor.fire_homing_missile();
// FIXME: the 128 backlog should be configurable
impl rtio::RtioTcpAcceptor for TcpAcceptor {
fn accept(&mut self) -> Result<~rtio::RtioTcpStream:Send, IoError> {
- self.listener.incoming.recv()
+ match self.timeout_rx {
+ None => self.listener.incoming.recv(),
+ Some(ref rx) => {
+ use std::comm::Select;
+
+ // Poll the incoming channel first (don't rely on the order of
+ // select just yet). If someone's pending then we should return
+ // them immediately.
+ match self.listener.incoming.try_recv() {
+ Ok(data) => return data,
+ Err(..) => {}
+ }
+
+ // Use select to figure out which channel gets ready first. We
+ // do some custom handling of select to ensure that we never
+ // actually drain the timeout channel (we'll keep seeing the
+ // timeout message in the future).
+ let s = Select::new();
+ let mut timeout = s.handle(rx);
+ let mut data = s.handle(&self.listener.incoming);
+ unsafe {
+ timeout.add();
+ data.add();
+ }
+ if s.wait() == timeout.id() {
+ Err(uv_error_to_io_error(UvError(uvll::ECANCELED)))
+ } else {
+ self.listener.incoming.recv()
+ }
+ }
+ }
}
fn accept_simultaneously(&mut self) -> Result<(), IoError> {
uvll::uv_tcp_simultaneous_accepts(self.listener.handle, 0)
})
}
+
+ fn set_timeout(&mut self, ms: Option<u64>) {
+ // First, if the timeout is none, clear any previous timeout by dropping
+ // the timer and transmission channels
+ let ms = match ms {
+ None => {
+ return drop((self.timer.take(),
+ self.timeout_tx.take(),
+ self.timeout_rx.take()))
+ }
+ Some(ms) => ms,
+ };
+
+ // If we have a timeout, lazily initialize the timer which will be used
+ // to fire when the timeout runs out.
+ if self.timer.is_none() {
+ let _m = self.fire_homing_missile();
+ let loop_ = Loop::wrap(unsafe {
+ uvll::get_loop_for_uv_handle(self.listener.handle)
+ });
+ let mut timer = TimerWatcher::new_home(&loop_, self.home().clone());
+ unsafe {
+ timer.set_data(self as *mut _ as *TcpAcceptor);
+ }
+ self.timer = Some(timer);
+ }
+
+ // Once we've got a timer, stop any previous timeout, reset it for the
+ // current one, and install some new channels to send/receive data on
+ let timer = self.timer.get_mut_ref();
+ timer.stop();
+ timer.start(timer_cb, ms, 0);
+ let (tx, rx) = channel();
+ self.timeout_tx = Some(tx);
+ self.timeout_rx = Some(rx);
+
+ extern fn timer_cb(timer: *uvll::uv_timer_t) {
+ let acceptor: &mut TcpAcceptor = unsafe {
+ &mut *(uvll::get_data_for_uv_handle(timer) as *mut TcpAcceptor)
+ };
+ // This send can never fail because if this timer is active then the
+ // receiving channel is guaranteed to be alive
+ acceptor.timeout_tx.get_ref().send(());
+ }
+ }
}
////////////////////////////////////////////////////////////////////////////////
#![allow(dead_code)]
use std::cast;
-use libc::{c_void, c_int};
+use libc::c_void;
use std::rt::task::BlockedTask;
use std::unstable::mutex::NativeMutex;
use std::sync::arc::UnsafeArc;
queue: UnsafeArc<State>,
}
-extern fn async_cb(handle: *uvll::uv_async_t, status: c_int) {
- assert_eq!(status, 0);
+extern fn async_cb(handle: *uvll::uv_async_t) {
let pool: &mut QueuePool = unsafe {
cast::transmute(uvll::get_data_for_uv_handle(handle))
};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use libc::c_int;
use std::mem;
use std::rt::rtio::RtioTimer;
use std::rt::task::BlockedTask;
use homing::{HomeHandle, HomingIO};
-use super::{UvHandle, ForbidUnwind, ForbidSwitch, wait_until_woken_after};
+use super::{UvHandle, ForbidUnwind, ForbidSwitch, wait_until_woken_after, Loop};
use uvio::UvIoFactory;
use uvll;
impl TimerWatcher {
pub fn new(io: &mut UvIoFactory) -> ~TimerWatcher {
+ let handle = io.make_handle();
+ let me = ~TimerWatcher::new_home(&io.loop_, handle);
+ me.install()
+ }
+
+ pub fn new_home(loop_: &Loop, home: HomeHandle) -> TimerWatcher {
let handle = UvHandle::alloc(None::<TimerWatcher>, uvll::UV_TIMER);
- assert_eq!(unsafe {
- uvll::uv_timer_init(io.uv_loop(), handle)
- }, 0);
- let me = ~TimerWatcher {
+ assert_eq!(unsafe { uvll::uv_timer_init(loop_.handle, handle) }, 0);
+ TimerWatcher {
handle: handle,
action: None,
blocker: None,
- home: io.make_handle(),
+ home: home,
id: 0,
- };
- return me.install();
+ }
}
pub fn start(&mut self, f: uvll::uv_timer_cb, msecs: u64, period: u64) {
}
}
-extern fn timer_cb(handle: *uvll::uv_timer_t, status: c_int) {
+extern fn timer_cb(handle: *uvll::uv_timer_t) {
let _f = ForbidSwitch::new("timer callback can't switch");
- assert_eq!(status, 0);
let timer: &mut TimerWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
match timer.action.take_unwrap() {
// - https://github.com/joyent/libuv/issues/982
// - https://github.com/joyent/libuv/issues/988
let guess = unsafe { uvll::guess_handle(fd) };
- if readable && guess != uvll::UV_TTY as libc::c_int {
+ if guess != uvll::UV_TTY as libc::c_int {
return Err(UvError(uvll::EBADF));
}
use libc;
use std::path::Path;
use std::rt::rtio;
-use std::rt::rtio::IoFactory;
+use std::rt::rtio::{IoFactory, EventLoop};
use ai = std::io::net::addrinfo;
#[cfg(test)] use std::unstable::run_in_bare_thread;
// the loop is free'd (use-after-free). We also must free the uv handle
// after the loop has been closed because during the closing of the loop
// the handle is required to be used apparently.
+ //
+ // Lastly, after we've closed the pool of handles we pump the event loop
+ // one last time to run any closing callbacks to make sure the loop
+ // shuts down cleanly.
let handle = self.uvio.handle_pool.get_ref().handle();
drop(self.uvio.handle_pool.take());
+ self.run();
+
self.uvio.loop_.close();
unsafe { uvll::free_handle(handle) }
}
}
-impl rtio::EventLoop for UvEventLoop {
+impl EventLoop for UvEventLoop {
fn run(&mut self) {
self.uvio.loop_.run();
}
#[test]
fn test_callback_run_once() {
- use std::rt::rtio::EventLoop;
run_in_bare_thread(proc() {
let mut event_loop = UvEventLoop::new();
let mut count = 0;
}
}
-pub type uv_idle_cb = extern "C" fn(handle: *uv_idle_t,
- status: c_int);
+pub type uv_idle_cb = extern "C" fn(handle: *uv_idle_t);
pub type uv_alloc_cb = extern "C" fn(stream: *uv_stream_t,
suggested_size: size_t,
buf: *mut uv_buf_t);
pub type uv_close_cb = extern "C" fn(handle: *uv_handle_t);
pub type uv_walk_cb = extern "C" fn(handle: *uv_handle_t,
arg: *c_void);
-pub type uv_async_cb = extern "C" fn(handle: *uv_async_t,
- status: c_int);
+pub type uv_async_cb = extern "C" fn(handle: *uv_async_t);
pub type uv_connect_cb = extern "C" fn(handle: *uv_connect_t,
status: c_int);
pub type uv_connection_cb = extern "C" fn(handle: *uv_connection_t,
status: c_int);
-pub type uv_timer_cb = extern "C" fn(handle: *uv_timer_t,
- status: c_int);
+pub type uv_timer_cb = extern "C" fn(handle: *uv_timer_t);
pub type uv_write_cb = extern "C" fn(handle: *uv_write_t,
status: c_int);
pub type uv_getaddrinfo_cb = extern "C" fn(req: *uv_getaddrinfo_t,
flags: c_int, mode: c_int, cb: uv_fs_cb) -> c_int;
pub fn uv_fs_unlink(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char,
cb: uv_fs_cb) -> c_int;
- pub fn uv_fs_write(l: *uv_loop_t, req: *uv_fs_t, fd: c_int, buf: *c_void,
- len: size_t, offset: i64, cb: uv_fs_cb) -> c_int;
- pub fn uv_fs_read(l: *uv_loop_t, req: *uv_fs_t, fd: c_int, buf: *c_void,
- len: size_t, offset: i64, cb: uv_fs_cb) -> c_int;
+ pub fn uv_fs_write(l: *uv_loop_t, req: *uv_fs_t, fd: c_int,
+ bufs: *uv_buf_t, nbufs: c_uint,
+ offset: i64, cb: uv_fs_cb) -> c_int;
+ pub fn uv_fs_read(l: *uv_loop_t, req: *uv_fs_t, fd: c_int,
+ bufs: *uv_buf_t, nbufs: c_uint,
+ offset: i64, cb: uv_fs_cb) -> c_int;
pub fn uv_fs_close(l: *uv_loop_t, req: *uv_fs_t, fd: c_int,
cb: uv_fs_cb) -> c_int;
pub fn uv_fs_stat(l: *uv_loop_t, req: *uv_fs_t, path: *c_char,
use option::{Some, None};
use str::{Str,StrSlice};
use strbuf::StrBuf;
- use slice::{Vector, ImmutableVector, OwnedVector};
+ use slice::{Vector, ImmutableVector};
use self::test::Bencher;
use super::super::Hash;
/// Returns an iterator which will recursively walk the directory structure
/// rooted at `path`. The path given will not be iterated over, and this will
-/// perform iteration in a top-down order.
+/// perform iteration in some top-down order. The contents of unreadable
+/// subdirectories are ignored.
pub fn walk_dir(path: &Path) -> IoResult<Directories> {
Ok(Directories { stack: try!(readdir(path)) })
}
impl Iterator<Path> for Directories {
fn next(&mut self) -> Option<Path> {
- match self.stack.shift() {
+ match self.stack.pop() {
Some(path) => {
if path.is_dir() {
match readdir(&path) {
check!(rmdir(dir));
})
+ iotest!(fn file_test_walk_dir() {
+ let tmpdir = tmpdir();
+ let dir = &tmpdir.join("walk_dir");
+ check!(mkdir(dir, io::UserRWX));
+
+ let dir1 = &dir.join("01/02/03");
+ check!(mkdir_recursive(dir1, io::UserRWX));
+ check!(File::create(&dir1.join("04")));
+
+ let dir2 = &dir.join("11/12/13");
+ check!(mkdir_recursive(dir2, io::UserRWX));
+ check!(File::create(&dir2.join("14")));
+
+ let mut files = check!(walk_dir(dir));
+ let mut cur = [0u8, .. 2];
+ for f in files {
+ let stem = f.filestem_str().unwrap();
+ let root = stem[0] - ('0' as u8);
+ let name = stem[1] - ('0' as u8);
+ assert!(cur[root as uint] < name);
+ cur[root as uint] = name;
+ }
+
+ check!(rmdir_recursive(dir));
+ })
+
iotest!(fn recursive_mkdir() {
let tmpdir = tmpdir();
let dir = tmpdir.join("d1/d2");
use io::net::ip::SocketAddr;
use io::{Reader, Writer, Listener, Acceptor};
use kinds::Send;
-use option::{None, Some};
+use option::{None, Some, Option};
use rt::rtio::{IoFactory, LocalIo, RtioSocket, RtioTcpListener};
use rt::rtio::{RtioTcpAcceptor, RtioTcpStream};
obj: ~RtioTcpAcceptor:Send
}
+impl TcpAcceptor {
+ /// Prevents blocking on all future accepts after `ms` milliseconds have
+ /// elapsed.
+ ///
+ /// This function is used to set a deadline after which this acceptor will
+ /// time out accepting any connections. The argument is the relative
+ /// distance, in milliseconds, to a point in the future after which all
+ /// accepts will fail.
+ ///
+ /// If the argument specified is `None`, then any previously registered
+ /// timeout is cleared.
+ ///
+ /// A timeout of `0` can be used to "poll" this acceptor to see if it has
+ /// any pending connections. All pending connections will be accepted,
+ /// regardless of whether the timeout has expired or not (the accept will
+ /// not block in this case).
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// # #![allow(experimental)]
+ /// use std::io::net::tcp::TcpListener;
+ /// use std::io::net::ip::{SocketAddr, Ipv4Addr};
+ /// use std::io::{Listener, Acceptor, TimedOut};
+ ///
+ /// let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 8482 };
+ /// let mut a = TcpListener::bind(addr).listen().unwrap();
+ ///
+ /// // After 100ms have passed, all accepts will fail
+ /// a.set_timeout(Some(100));
+ ///
+ /// match a.accept() {
+ /// Ok(..) => println!("accepted a socket"),
+ /// Err(ref e) if e.kind == TimedOut => { println!("timed out!"); }
+ /// Err(e) => println!("err: {}", e),
+ /// }
+ ///
+ /// // Reset the timeout and try again
+ /// a.set_timeout(Some(100));
+ /// let socket = a.accept();
+ ///
+ /// // Clear the timeout and block indefinitely waiting for a connection
+ /// a.set_timeout(None);
+ /// let socket = a.accept();
+ /// ```
+ #[experimental = "the type of the argument and name of this function are \
+ subject to change"]
+ pub fn set_timeout(&mut self, ms: Option<u64>) { self.obj.set_timeout(ms); }
+}
+
impl Acceptor<TcpStream> for TcpAcceptor {
fn accept(&mut self) -> IoResult<TcpStream> {
self.obj.accept().map(TcpStream::new)
}
#[cfg(test)]
+#[allow(experimental)]
mod test {
use super::*;
use io::net::ip::SocketAddr;
assert!(s.write([1]).is_err());
assert_eq!(s.read_to_end(), Ok(vec!(1)));
})
+
+ iotest!(fn accept_timeout() {
+ let addr = next_test_ip4();
+ let mut a = TcpListener::bind(addr).unwrap().listen().unwrap();
+
+ a.set_timeout(Some(10));
+
+ // Make sure we time out once and future invocations also time out
+ let err = a.accept().err().unwrap();
+ assert_eq!(err.kind, TimedOut);
+ let err = a.accept().err().unwrap();
+ assert_eq!(err.kind, TimedOut);
+
+ // Also make sure that even though the timeout is expired that we will
+ // continue to receive any pending connections.
+ let l = TcpStream::connect(addr).unwrap();
+ for i in range(0, 1001) {
+ match a.accept() {
+ Ok(..) => break,
+ Err(ref e) if e.kind == TimedOut => {}
+ Err(e) => fail!("error: {}", e),
+ }
+ if i == 1000 { fail!("should have a pending connection") }
+ }
+ drop(l);
+
+ // Unset the timeout and make sure that this always blocks.
+ a.set_timeout(None);
+ spawn(proc() {
+ drop(TcpStream::connect(addr));
+ });
+ a.accept().unwrap();
+ })
}
}
}
-// FIXME(#11621): These constants should be deprecated once CTFE is implemented
-// in favour of calling their respective functions in `Bounded` and `Float`.
-
pub static RADIX: uint = 2u;
-pub static MANTISSA_DIGITS: uint = 53u;
-pub static DIGITS: uint = 15u;
+pub static MANTISSA_DIGITS: uint = 24u;
+pub static DIGITS: uint = 6u;
-pub static EPSILON: f64 = 2.220446e-16_f64;
+pub static EPSILON: f32 = 1.19209290e-07_f32;
-// FIXME (#1433): this is wrong, replace with hexadecimal (%a) statics
-// below.
-pub static MIN_VALUE: f64 = 2.225074e-308_f64;
-pub static MAX_VALUE: f64 = 1.797693e+308_f64;
+/// Minimum normalized f32 value
+pub static MIN_VALUE: f32 = 1.17549435e-38_f32;
+/// Maximum f32 value
+pub static MAX_VALUE: f32 = 3.40282347e+38_f32;
-pub static MIN_EXP: uint = -1021u;
-pub static MAX_EXP: uint = 1024u;
+pub static MIN_EXP: int = -125;
+pub static MAX_EXP: int = 128;
-pub static MIN_10_EXP: int = -307;
-pub static MAX_10_EXP: int = 308;
+pub static MIN_10_EXP: int = -37;
+pub static MAX_10_EXP: int = 38;
pub static NAN: f32 = 0.0_f32/0.0_f32;
pub static INFINITY: f32 = 1.0_f32/0.0_f32;
/// Various useful constants.
pub mod consts {
- // FIXME (requires Issue #1433 to fix): replace with mathematical
- // staticants from cmath.
+ // FIXME: replace with mathematical constants from cmath.
// FIXME(#11621): These constants should be deprecated once CTFE is
// implemented in favour of calling their respective functions in `Float`.
/// Archimedes' constant
pub static PI: f32 = 3.14159265358979323846264338327950288_f32;
+ /// pi * 2.0
+ pub static PI_2: f32 = 6.28318530717958647692528676655900576_f32;
+
/// pi/2.0
pub static FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;
+ /// pi/3.0
+ pub static FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32;
+
/// pi/4.0
pub static FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32;
+ /// pi/6.0
+ pub static FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32;
+
+ /// pi/8.0
+ pub static FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32;
+
/// 1.0/pi
pub static FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;
}
impl Bounded for f32 {
+ // NOTE: this is the smallest non-infinite f32 value, *not* MIN_VALUE
#[inline]
- fn min_value() -> f32 { 1.17549435e-38 }
+ fn min_value() -> f32 { -MAX_VALUE }
#[inline]
- fn max_value() -> f32 { 3.40282347e+38 }
+ fn max_value() -> f32 { MAX_VALUE }
}
impl Primitive for f32 {}
impl Float for f32 {
#[inline]
- fn nan() -> f32 { 0.0 / 0.0 }
+ fn nan() -> f32 { NAN }
#[inline]
- fn infinity() -> f32 { 1.0 / 0.0 }
+ fn infinity() -> f32 { INFINITY }
#[inline]
- fn neg_infinity() -> f32 { -1.0 / 0.0 }
+ fn neg_infinity() -> f32 { NEG_INFINITY }
#[inline]
fn neg_zero() -> f32 { -0.0 }
}
#[inline]
- fn mantissa_digits(_: Option<f32>) -> uint { 24 }
+ fn mantissa_digits(_: Option<f32>) -> uint { MANTISSA_DIGITS }
#[inline]
- fn digits(_: Option<f32>) -> uint { 6 }
+ fn digits(_: Option<f32>) -> uint { DIGITS }
#[inline]
- fn epsilon() -> f32 { 1.19209290e-07 }
+ fn epsilon() -> f32 { EPSILON }
#[inline]
- fn min_exp(_: Option<f32>) -> int { -125 }
+ fn min_exp(_: Option<f32>) -> int { MIN_EXP }
#[inline]
- fn max_exp(_: Option<f32>) -> int { 128 }
+ fn max_exp(_: Option<f32>) -> int { MAX_EXP }
#[inline]
- fn min_10_exp(_: Option<f32>) -> int { -37 }
+ fn min_10_exp(_: Option<f32>) -> int { MIN_10_EXP }
#[inline]
- fn max_10_exp(_: Option<f32>) -> int { 38 }
+ fn max_10_exp(_: Option<f32>) -> int { MAX_10_EXP }
/// Constructs a floating point number by multiplying `x` by 2 raised to the
/// power of `exp`
/// sqrt(2.0)
#[inline]
- fn sqrt2() -> f32 { 1.41421356237309504880168872420969808 }
+ fn sqrt2() -> f32 { consts::SQRT2 }
/// 1.0 / sqrt(2.0)
#[inline]
- fn frac_1_sqrt2() -> f32 { 0.707106781186547524400844362104849039 }
+ fn frac_1_sqrt2() -> f32 { consts::FRAC_1_SQRT2 }
#[inline]
fn sqrt(self) -> f32 {
/// Archimedes' constant
#[inline]
- fn pi() -> f32 { 3.14159265358979323846264338327950288 }
+ fn pi() -> f32 { consts::PI }
/// 2.0 * pi
#[inline]
- fn two_pi() -> f32 { 6.28318530717958647692528676655900576 }
+ fn two_pi() -> f32 { consts::PI_2 }
/// pi / 2.0
#[inline]
- fn frac_pi_2() -> f32 { 1.57079632679489661923132169163975144 }
+ fn frac_pi_2() -> f32 { consts::FRAC_PI_2 }
/// pi / 3.0
#[inline]
- fn frac_pi_3() -> f32 { 1.04719755119659774615421446109316763 }
+ fn frac_pi_3() -> f32 { consts::FRAC_PI_3 }
/// pi / 4.0
#[inline]
- fn frac_pi_4() -> f32 { 0.785398163397448309615660845819875721 }
+ fn frac_pi_4() -> f32 { consts::FRAC_PI_4 }
/// pi / 6.0
#[inline]
- fn frac_pi_6() -> f32 { 0.52359877559829887307710723054658381 }
+ fn frac_pi_6() -> f32 { consts::FRAC_PI_6 }
/// pi / 8.0
#[inline]
- fn frac_pi_8() -> f32 { 0.39269908169872415480783042290993786 }
+ fn frac_pi_8() -> f32 { consts::FRAC_PI_8 }
/// 1 .0/ pi
#[inline]
- fn frac_1_pi() -> f32 { 0.318309886183790671537767526745028724 }
+ fn frac_1_pi() -> f32 { consts::FRAC_1_PI }
/// 2.0 / pi
#[inline]
- fn frac_2_pi() -> f32 { 0.636619772367581343075535053490057448 }
+ fn frac_2_pi() -> f32 { consts::FRAC_2_PI }
/// 2.0 / sqrt(pi)
#[inline]
- fn frac_2_sqrtpi() -> f32 { 1.12837916709551257389615890312154517 }
+ fn frac_2_sqrtpi() -> f32 { consts::FRAC_2_SQRTPI }
#[inline]
fn sin(self) -> f32 {
/// Euler's number
#[inline]
- fn e() -> f32 { 2.71828182845904523536028747135266250 }
+ fn e() -> f32 { consts::E }
/// log2(e)
#[inline]
- fn log2_e() -> f32 { 1.44269504088896340735992468100189214 }
+ fn log2_e() -> f32 { consts::LOG2_E }
/// log10(e)
#[inline]
- fn log10_e() -> f32 { 0.434294481903251827651128918916605082 }
+ fn log10_e() -> f32 { consts::LOG10_E }
/// ln(2.0)
#[inline]
- fn ln_2() -> f32 { 0.693147180559945309417232121458176568 }
+ fn ln_2() -> f32 { consts::LN_2 }
/// ln(10.0)
#[inline]
- fn ln_10() -> f32 { 2.30258509299404568401799145468436421 }
+ fn ln_10() -> f32 { consts::LN_10 }
/// Returns the exponential of the number
#[inline]
}
}
-// FIXME (#1433): obtain these in a different way
-
// FIXME(#11621): These constants should be deprecated once CTFE is implemented
// in favour of calling their respective functions in `Bounded` and `Float`.
pub static EPSILON: f64 = 2.2204460492503131e-16_f64;
+/// Minimum normalized f64 value
pub static MIN_VALUE: f64 = 2.2250738585072014e-308_f64;
+/// Maximum f64 value
pub static MAX_VALUE: f64 = 1.7976931348623157e+308_f64;
pub static MIN_EXP: int = -1021;
pub static NEG_INFINITY: f64 = -1.0_f64/0.0_f64;
-// FIXME (#1999): add is_normal, is_subnormal, and fpclassify
-
/// Various useful constants.
pub mod consts {
- // FIXME (requires Issue #1433 to fix): replace with mathematical
- // constants from cmath.
+ // FIXME: replace with mathematical constants from cmath.
// FIXME(#11621): These constants should be deprecated once CTFE is
// implemented in favour of calling their respective functions in `Float`.
/// Archimedes' constant
pub static PI: f64 = 3.14159265358979323846264338327950288_f64;
+ /// pi * 2.0
+ pub static PI_2: f64 = 6.28318530717958647692528676655900576_f64;
+
/// pi/2.0
pub static FRAC_PI_2: f64 = 1.57079632679489661923132169163975144_f64;
+ /// pi/3.0
+ pub static FRAC_PI_3: f64 = 1.04719755119659774615421446109316763_f64;
+
/// pi/4.0
pub static FRAC_PI_4: f64 = 0.785398163397448309615660845819875721_f64;
+ /// pi/6.0
+ pub static FRAC_PI_6: f64 = 0.52359877559829887307710723054658381_f64;
+
+ /// pi/8.0
+ pub static FRAC_PI_8: f64 = 0.39269908169872415480783042290993786_f64;
+
/// 1.0/pi
pub static FRAC_1_PI: f64 = 0.318309886183790671537767526745028724_f64;
}
impl Bounded for f64 {
+ // NOTE: this is the smallest non-infinite f32 value, *not* MIN_VALUE
#[inline]
- fn min_value() -> f64 { 2.2250738585072014e-308 }
+ fn min_value() -> f64 { -MAX_VALUE }
#[inline]
- fn max_value() -> f64 { 1.7976931348623157e+308 }
+ fn max_value() -> f64 { MAX_VALUE }
}
impl Primitive for f64 {}
impl Float for f64 {
#[inline]
- fn nan() -> f64 { 0.0 / 0.0 }
+ fn nan() -> f64 { NAN }
#[inline]
- fn infinity() -> f64 { 1.0 / 0.0 }
+ fn infinity() -> f64 { INFINITY }
#[inline]
- fn neg_infinity() -> f64 { -1.0 / 0.0 }
+ fn neg_infinity() -> f64 { NEG_INFINITY }
#[inline]
fn neg_zero() -> f64 { -0.0 }
/// sqrt(2.0)
#[inline]
- fn sqrt2() -> f64 { 1.41421356237309504880168872420969808 }
+ fn sqrt2() -> f64 { consts::SQRT2 }
/// 1.0 / sqrt(2.0)
#[inline]
- fn frac_1_sqrt2() -> f64 { 0.707106781186547524400844362104849039 }
+ fn frac_1_sqrt2() -> f64 { consts::FRAC_1_SQRT2 }
#[inline]
fn sqrt(self) -> f64 {
/// Archimedes' constant
#[inline]
- fn pi() -> f64 { 3.14159265358979323846264338327950288 }
+ fn pi() -> f64 { consts::PI }
/// 2.0 * pi
#[inline]
- fn two_pi() -> f64 { 6.28318530717958647692528676655900576 }
+ fn two_pi() -> f64 { consts::PI_2 }
/// pi / 2.0
#[inline]
- fn frac_pi_2() -> f64 { 1.57079632679489661923132169163975144 }
+ fn frac_pi_2() -> f64 { consts::FRAC_PI_2 }
/// pi / 3.0
#[inline]
- fn frac_pi_3() -> f64 { 1.04719755119659774615421446109316763 }
+ fn frac_pi_3() -> f64 { consts::FRAC_PI_3 }
/// pi / 4.0
#[inline]
- fn frac_pi_4() -> f64 { 0.785398163397448309615660845819875721 }
+ fn frac_pi_4() -> f64 { consts::FRAC_PI_4 }
/// pi / 6.0
#[inline]
- fn frac_pi_6() -> f64 { 0.52359877559829887307710723054658381 }
+ fn frac_pi_6() -> f64 { consts::FRAC_PI_6 }
/// pi / 8.0
#[inline]
- fn frac_pi_8() -> f64 { 0.39269908169872415480783042290993786 }
+ fn frac_pi_8() -> f64 { consts::FRAC_PI_8 }
/// 1.0 / pi
#[inline]
- fn frac_1_pi() -> f64 { 0.318309886183790671537767526745028724 }
+ fn frac_1_pi() -> f64 { consts::FRAC_1_PI }
/// 2.0 / pi
#[inline]
- fn frac_2_pi() -> f64 { 0.636619772367581343075535053490057448 }
+ fn frac_2_pi() -> f64 { consts::FRAC_2_PI }
/// 2.0 / sqrt(pi)
#[inline]
- fn frac_2_sqrtpi() -> f64 { 1.12837916709551257389615890312154517 }
+ fn frac_2_sqrtpi() -> f64 { consts::FRAC_2_SQRTPI }
#[inline]
fn sin(self) -> f64 {
/// Euler's number
#[inline]
- fn e() -> f64 { 2.71828182845904523536028747135266250 }
+ fn e() -> f64 { consts::E }
/// log2(e)
#[inline]
- fn log2_e() -> f64 { 1.44269504088896340735992468100189214 }
+ fn log2_e() -> f64 { consts::LOG2_E }
/// log10(e)
#[inline]
- fn log10_e() -> f64 { 0.434294481903251827651128918916605082 }
+ fn log10_e() -> f64 { consts::LOG10_E }
/// ln(2.0)
#[inline]
- fn ln_2() -> f64 { 0.693147180559945309417232121458176568 }
+ fn ln_2() -> f64 { consts::LN_2 }
/// ln(10.0)
#[inline]
- fn ln_10() -> f64 { 2.30258509299404568401799145468436421 }
+ fn ln_10() -> f64 { consts::LN_10 }
/// Returns the exponential of the number
#[inline]
/// Returns the number of binary digits of mantissa that this type supports.
fn mantissa_digits(unused_self: Option<Self>) -> uint;
- /// Returns the number of binary digits of exponent that this type supports.
+ /// Returns the number of base-10 digits of precision that this type supports.
fn digits(unused_self: Option<Self>) -> uint;
- /// Returns the smallest positive number that this type can represent.
+ /// Returns the difference between 1.0 and the smallest representable number larger than 1.0.
fn epsilon() -> Self;
/// Returns the minimum binary exponent that this type can represent.
fn min_exp(unused_self: Option<Self>) -> int;
}
}
-#[allow(missing_doc)]
+#[doc(hidden)]
trait RcBoxPtr<T> {
fn inner<'a>(&'a self) -> &'a RcBox<T>;
use clone::Clone;
use option::{Option, Some, None};
use iter::Iterator;
- use str::StrSlice;
use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
use mem;
+ #[cfg(not(test))] use str::StrSlice;
#[cfg(not(test))] use ptr::RawPtr;
static mut global_args_ptr: uint = 0;
fn accept(&mut self) -> IoResult<~RtioTcpStream:Send>;
fn accept_simultaneously(&mut self) -> IoResult<()>;
fn dont_accept_simultaneously(&mut self) -> IoResult<()>;
+ fn set_timeout(&mut self, timeout: Option<u64>);
}
pub trait RtioTcpStream : RtioSocket {
nocopy: Option<marker::NoCopy>,
}
-/**
- * Generate the base configuration for spawning a task, off of which more
- * configuration methods can be chained.
- */
-pub fn task() -> TaskBuilder {
- TaskBuilder {
- opts: TaskOpts::new(),
- gen_body: None,
- nocopy: None,
+impl TaskBuilder {
+ /// Generate the base configuration for spawning a task, off of which more
+ /// configuration methods can be chained.
+ pub fn new() -> TaskBuilder {
+ TaskBuilder {
+ opts: TaskOpts::new(),
+ gen_body: None,
+ nocopy: None,
+ }
}
-}
-impl TaskBuilder {
/// Get a future representing the exit status of the task.
///
/// Taking the value of the future will block until the child task
/// Sets up a new task with its own call stack and schedules it to run
/// the provided unique closure.
///
-/// This function is equivalent to `task().spawn(f)`.
+/// This function is equivalent to `TaskBuilder::new().spawn(f)`.
pub fn spawn(f: proc():Send) {
- let task = task();
- task.spawn(f)
+ TaskBuilder::new().spawn(f)
}
+/// Execute a function in another task and return either the return value of
+/// the function or an error if the task failed
+///
+/// This is equivalent to TaskBuilder::new().try
pub fn try<T:Send>(f: proc():Send -> T) -> Result<T, ~Any:Send> {
- /*!
- * Execute a function in another task and return either the return value
- * of the function or result::err.
- *
- * This is equivalent to task().try.
- */
-
- let task = task();
- task.try(f)
+ TaskBuilder::new().try(f)
}
#[test]
fn test_owned_named_task() {
- task().named("ada lovelace".to_owned()).spawn(proc() {
+ TaskBuilder::new().named("ada lovelace".to_owned()).spawn(proc() {
with_task_name(|name| {
assert!(name.unwrap() == "ada lovelace");
})
#[test]
fn test_static_named_task() {
- task().named("ada lovelace").spawn(proc() {
+ TaskBuilder::new().named("ada lovelace").spawn(proc() {
with_task_name(|name| {
assert!(name.unwrap() == "ada lovelace");
})
#[test]
fn test_send_named_task() {
- task().named("ada lovelace".into_maybe_owned()).spawn(proc() {
+ TaskBuilder::new().named("ada lovelace".into_maybe_owned()).spawn(proc() {
with_task_name(|name| {
assert!(name.unwrap() == "ada lovelace");
})
#[test]
fn test_run_basic() {
let (tx, rx) = channel();
- task().spawn(proc() {
+ TaskBuilder::new().spawn(proc() {
tx.send(());
});
rx.recv();
#[test]
fn test_with_wrapper() {
let (tx, rx) = channel();
- task().with_wrapper(proc(body) {
+ TaskBuilder::new().with_wrapper(proc(body) {
let result: proc():Send = proc() {
body();
tx.send(());
#[test]
fn test_future_result() {
- let mut builder = task();
+ let mut builder = TaskBuilder::new();
let result = builder.future_result();
builder.spawn(proc() {});
assert!(result.recv().is_ok());
- let mut builder = task();
+ let mut builder = TaskBuilder::new();
let result = builder.future_result();
builder.spawn(proc() {
fail!();
#[test] #[should_fail]
fn test_back_to_the_future_result() {
- let mut builder = task();
+ let mut builder = TaskBuilder::new();
builder.future_result();
builder.future_result();
}
#[test]
fn test_avoid_copying_the_body_task_spawn() {
avoid_copying_the_body(|f| {
- let builder = task();
+ let builder = TaskBuilder::new();
builder.spawn(proc() {
f();
});
fn child_no(x: uint) -> proc():Send {
return proc() {
if x < generations {
- task().spawn(child_no(x+1));
+ TaskBuilder::new().spawn(child_no(x+1));
}
}
}
- task().spawn(child_no(0));
+ TaskBuilder::new().spawn(child_no(0));
}
#[test]
mod tests {
use std::comm::Empty;
use std::task;
+ use std::task::TaskBuilder;
use arc::Arc;
use super::{Mutex, Barrier, RWLock};
let mut children = Vec::new();
for _ in range(0, 5) {
let arc3 = arc.clone();
- let mut builder = task::task();
+ let mut builder = TaskBuilder::new();
children.push(builder.future_result());
builder.spawn(proc() {
let lock = arc3.read();
#[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)]
pub struct Arm {
+ pub attrs: Vec<Attribute>,
pub pats: Vec<@Pat>,
pub guard: Option<@Expr>,
pub body: @Expr,
ExprBox(@Expr, @Expr),
ExprVec(Vec<@Expr>),
ExprCall(@Expr, Vec<@Expr>),
- ExprMethodCall(Ident, Vec<P<Ty>>, Vec<@Expr>),
+ ExprMethodCall(SpannedIdent, Vec<P<Ty>>, Vec<@Expr>),
ExprTup(Vec<@Expr>),
ExprBinary(BinOp, @Expr, @Expr),
ExprUnary(UnOp, @Expr),
}
pub fn with_attrs<T>(&self, id: NodeId, f: |Option<&[Attribute]>| -> T) -> T {
- let attrs = match self.get(id) {
- NodeItem(i) => Some(i.attrs.as_slice()),
- NodeForeignItem(fi) => Some(fi.attrs.as_slice()),
- NodeTraitMethod(tm) => match *tm {
+ let node = self.get(id);
+ let attrs = match node {
+ NodeItem(ref i) => Some(i.attrs.as_slice()),
+ NodeForeignItem(ref fi) => Some(fi.attrs.as_slice()),
+ NodeTraitMethod(ref tm) => match **tm {
Required(ref type_m) => Some(type_m.attrs.as_slice()),
- Provided(m) => Some(m.attrs.as_slice())
+ Provided(ref m) => Some(m.attrs.as_slice())
},
- NodeMethod(m) => Some(m.attrs.as_slice()),
+ NodeMethod(ref m) => Some(m.attrs.as_slice()),
NodeVariant(ref v) => Some(v.node.attrs.as_slice()),
// unit/tuple structs take the attributes straight from
// the struct definition.
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
}
fn visit_view_item(&mut self, view_item: &ViewItem, env: ()) {
+ if !self.pass_through_items {
+ if self.visited_outermost {
+ return;
+ } else {
+ self.visited_outermost = true;
+ }
+ }
match view_item.node {
ViewItemExternCrate(_, _, node_id) => {
self.operation.visit_id(node_id)
}
}
}
- visit::walk_view_item(self, view_item, env)
+ visit::walk_view_item(self, view_item, env);
+ self.visited_outermost = false;
}
fn visit_foreign_item(&mut self, foreign_item: &ForeignItem, env: ()) {
use ast::{P, Ident};
use ast;
use ast_util;
-use codemap::{Span, respan, DUMMY_SP};
+use codemap::{Span, respan, Spanned, DUMMY_SP};
use ext::base::ExtCtxt;
use ext::quote::rt::*;
use fold::Folder;
expr: @ast::Expr,
ident: ast::Ident,
mut args: Vec<@ast::Expr> ) -> @ast::Expr {
+ let id = Spanned { node: ident, span: span };
args.unshift(expr);
- self.expr(span, ast::ExprMethodCall(ident, Vec::new(), args))
+ self.expr(span, ast::ExprMethodCall(id, Vec::new(), args))
}
fn expr_block(&self, b: P<ast::Block>) -> @ast::Expr {
self.expr(b.span, ast::ExprBlock(b))
fn arm(&self, _span: Span, pats: Vec<@ast::Pat> , expr: @ast::Expr) -> ast::Arm {
ast::Arm {
+ attrs: vec!(),
pats: pats,
guard: None,
body: expr
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ext::deriving::generic::*;
+use parse::token::InternedString;
pub fn expand_deriving_clone(cx: &mut ExtCtxt,
span: Span,
mitem: @MetaItem,
item: @Item,
push: |@Item|) {
+ let inline = cx.meta_word(span, InternedString::new("inline"));
+ let attrs = vec!(cx.attribute(span, inline));
let trait_def = TraitDef {
span: span,
attributes: Vec::new(),
explicit_self: borrowed_explicit_self(),
args: Vec::new(),
ret_ty: Self,
- inline: true,
+ attributes: attrs,
const_nonmatching: false,
combine_substructure: combine_substructure(|c, s, sub| {
cs_clone("Clone", c, s, sub)
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ext::deriving::generic::*;
+use parse::token::InternedString;
pub fn expand_deriving_eq(cx: &mut ExtCtxt,
span: Span,
}
macro_rules! md (
- ($name:expr, $f:ident) => {
+ ($name:expr, $f:ident) => { {
+ let inline = cx.meta_word(span, InternedString::new("inline"));
+ let attrs = vec!(cx.attribute(span, inline));
MethodDef {
name: $name,
generics: LifetimeBounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec!(borrowed_self()),
ret_ty: Literal(Path::new(vec!("bool"))),
- inline: true,
+ attributes: attrs,
const_nonmatching: true,
combine_substructure: combine_substructure(|a, b, c| {
$f(a, b, c)
})
}
- }
+ } }
);
let trait_def = TraitDef {
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ext::deriving::generic::*;
+use parse::token::InternedString;
pub fn expand_deriving_ord(cx: &mut ExtCtxt,
span: Span,
item: @Item,
push: |@Item|) {
macro_rules! md (
- ($name:expr, $op:expr, $equal:expr) => {
+ ($name:expr, $op:expr, $equal:expr) => { {
+ let inline = cx.meta_word(span, InternedString::new("inline"));
+ let attrs = vec!(cx.attribute(span, inline));
MethodDef {
name: $name,
generics: LifetimeBounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec!(borrowed_self()),
ret_ty: Literal(Path::new(vec!("bool"))),
- inline: true,
+ attributes: attrs,
const_nonmatching: false,
combine_substructure: combine_substructure(|cx, span, substr| {
cs_op($op, $equal, cx, span, substr)
})
}
- }
+ } }
);
let trait_def = TraitDef {
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ext::deriving::generic::*;
+use parse::token::InternedString;
pub fn expand_deriving_totaleq(cx: &mut ExtCtxt,
span: Span,
substr)
}
+ let inline = cx.meta_word(span, InternedString::new("inline"));
+ let hidden = cx.meta_word(span, InternedString::new("hidden"));
+ let doc = cx.meta_list(span, InternedString::new("doc"), vec!(hidden));
+ let attrs = vec!(cx.attribute(span, inline),
+ cx.attribute(span, doc));
let trait_def = TraitDef {
span: span,
attributes: Vec::new(),
explicit_self: borrowed_explicit_self(),
args: vec!(),
ret_ty: nil_ty(),
- inline: true,
+ attributes: attrs,
const_nonmatching: true,
combine_substructure: combine_substructure(|a, b, c| {
cs_total_eq_assert(a, b, c)
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ext::deriving::generic::*;
+use parse::token::InternedString;
use std::cmp::{Ordering, Equal, Less, Greater};
mitem: @MetaItem,
item: @Item,
push: |@Item|) {
+ let inline = cx.meta_word(span, InternedString::new("inline"));
+ let attrs = vec!(cx.attribute(span, inline));
let trait_def = TraitDef {
span: span,
attributes: Vec::new(),
explicit_self: borrowed_explicit_self(),
args: vec!(borrowed_self()),
ret_ty: Literal(Path::new(vec!("std", "cmp", "Ordering"))),
- inline: true,
+ attributes: attrs,
const_nonmatching: false,
combine_substructure: combine_substructure(|a, b, c| {
cs_cmp(a, b, c)
Borrowed(None, MutMutable))),
ret_ty: Literal(Path::new_(vec!("std", "result", "Result"), None,
vec!(~Self, ~Literal(Path::new_local("__E"))), true)),
- inline: false,
+ attributes: Vec::new(),
const_nonmatching: true,
combine_substructure: combine_substructure(|a, b, c| {
decodable_substructure(a, b, c)
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ext::deriving::generic::*;
+use parse::token::InternedString;
pub fn expand_deriving_default(cx: &mut ExtCtxt,
span: Span,
mitem: @MetaItem,
item: @Item,
push: |@Item|) {
+ let inline = cx.meta_word(span, InternedString::new("inline"));
+ let attrs = vec!(cx.attribute(span, inline));
let trait_def = TraitDef {
span: span,
attributes: Vec::new(),
explicit_self: None,
args: Vec::new(),
ret_ty: Self,
- inline: true,
+ attributes: attrs,
const_nonmatching: false,
combine_substructure: combine_substructure(|a, b, c| {
default_substructure(a, b, c)
vec!(~Tuple(Vec::new()),
~Literal(Path::new_local("__E"))),
true)),
- inline: false,
+ attributes: Vec::new(),
const_nonmatching: true,
combine_substructure: combine_substructure(|a, b, c| {
encodable_substructure(a, b, c)
/// Return type
pub ret_ty: Ty<'a>,
- /// Whether to mark this as #[inline]
- pub inline: bool,
+ pub attributes: Vec<ast::Attribute>,
/// if the value of the nonmatching enums is independent of the
/// actual enum variants, i.e. can use _ => .. match.
let fn_decl = cx.fn_decl(args, ret_type);
let body_block = cx.block_expr(body);
- let attrs = if self.inline {
- vec!(
- cx
- .attribute(trait_.span,
- cx
- .meta_word(trait_.span,
- InternedString::new(
- "inline")))
- )
- } else {
- Vec::new()
- };
-
// Create the method.
@ast::Method {
ident: method_ident,
- attrs: attrs,
+ attrs: self.attributes.clone(),
generics: fn_generics,
explicit_self: explicit_self,
fn_style: ast::NormalFn,
"no self match on an enum in \
generic `deriving`");
}
+
+ // `ref` inside let matches is buggy. Causes havoc wih rusc.
+ // let (variant_index, ref self_vec) = matches_so_far[0];
+ let (variant, self_vec) = match matches_so_far.get(0) {
+ &(_, v, ref s) => (v, s)
+ };
+
// we currently have a vec of vecs, where each
// subvec is the fields of one of the arguments,
// but if the variants all match, we want this as
// vec of tuples, where each tuple represents a
// field.
- let substructure;
-
// most arms don't have matching variants, so do a
// quick check to see if they match (even though
// this means iterating twice) instead of being
// optimistic and doing a pile of allocations etc.
- match matching {
+ let substructure = match matching {
Some(variant_index) => {
- // `ref` inside let matches is buggy. Causes havoc wih rusc.
- // let (variant_index, ref self_vec) = matches_so_far[0];
- let (variant, self_vec) = match matches_so_far.get(0) {
- &(_, v, ref s) => (v, s)
- };
-
let mut enum_matching_fields = Vec::from_elem(self_vec.len(), Vec::new());
for triple in matches_so_far.tail().iter() {
other: (*other).clone()
}
}).collect();
- substructure = EnumMatching(variant_index, variant, field_tuples);
+ EnumMatching(variant_index, variant, field_tuples)
}
None => {
- substructure = EnumNonMatching(matches_so_far.as_slice());
+ EnumNonMatching(matches_so_far.as_slice())
}
- }
+ };
self.call_substructure_method(cx, trait_, type_ident,
self_args, nonself_args,
&substructure)
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ext::deriving::generic::*;
+use parse::token::InternedString;
pub fn expand_deriving_hash(cx: &mut ExtCtxt,
span: Span,
LifetimeBounds::empty(),
Path::new(vec!("std", "hash", "sip", "SipState")))
};
+ let inline = cx.meta_word(span, InternedString::new("inline"));
+ let attrs = vec!(cx.attribute(span, inline));
let hash_trait_def = TraitDef {
span: span,
attributes: Vec::new(),
explicit_self: borrowed_explicit_self(),
args: vec!(Ptr(~Literal(args), Borrowed(None, MutMutable))),
ret_ty: nil_ty(),
- inline: true,
+ attributes: attrs,
const_nonmatching: false,
combine_substructure: combine_substructure(|a, b, c| {
hash_substructure(a, b, c)
mitem: @MetaItem,
item: @Item,
push: |@Item|) {
+ let inline = cx.meta_word(span, InternedString::new("inline"));
+ let attrs = vec!(cx.attribute(span, inline));
let trait_def = TraitDef {
span: span,
attributes: Vec::new(),
None,
vec!(~Self),
true)),
- // liable to cause code-bloat
- inline: true,
+ // #[inline] liable to cause code-bloat
+ attributes: attrs.clone(),
const_nonmatching: false,
combine_substructure: combine_substructure(|c, s, sub| {
cs_from("i64", c, s, sub)
None,
vec!(~Self),
true)),
- // liable to cause code-bloat
- inline: true,
+ // #[inline] liable to cause code-bloat
+ attributes: attrs,
const_nonmatching: false,
combine_substructure: combine_substructure(|c, s, sub| {
cs_from("u64", c, s, sub)
// arm for `_ if $guard => $body`
let arm = ast::Arm {
+ attrs: vec!(),
pats: vec!(cx.pat_wild(span)),
guard: Some(guard),
body: body,
// arm for `_ => None`
let arm = ast::Arm {
+ attrs: vec!(),
pats: vec!(cx.pat_wild(trait_span)),
guard: None,
body: cx.expr_none(trait_span),
Borrowed(None, ast::MutMutable))
),
ret_ty: Self,
- inline: false,
+ attributes: Vec::new(),
const_nonmatching: false,
combine_substructure: combine_substructure(|a, b, c| {
rand_substructure(a, b, c)
explicit_self: borrowed_explicit_self(),
args: vec!(fmtr),
ret_ty: Literal(Path::new(vec!("std", "fmt", "Result"))),
- inline: false,
+ attributes: Vec::new(),
const_nonmatching: false,
combine_substructure: combine_substructure(|a, b, c| {
show_substructure(a, b, c)
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ext::deriving::generic::*;
+use parse::token::InternedString;
pub fn expand_deriving_zero(cx: &mut ExtCtxt,
span: Span,
mitem: @MetaItem,
item: @Item,
push: |@Item|) {
+ let inline = cx.meta_word(span, InternedString::new("inline"));
+ let attrs = vec!(cx.attribute(span, inline));
let trait_def = TraitDef {
span: span,
attributes: Vec::new(),
explicit_self: None,
args: Vec::new(),
ret_ty: Self,
- inline: true,
+ attributes: attrs.clone(),
const_nonmatching: false,
combine_substructure: combine_substructure(|a, b, c| {
zero_substructure(a, b, c)
explicit_self: borrowed_explicit_self(),
args: Vec::new(),
ret_ty: Literal(Path::new(vec!("bool"))),
- inline: true,
+ attributes: attrs,
const_nonmatching: false,
combine_substructure: combine_substructure(|cx, span, substr| {
cs_and(|cx, span, _, _| cx.span_bug(span,
fn fold_arm(&mut self, a: &Arm) -> Arm {
Arm {
+ attrs: a.attrs.iter().map(|x| fold_attribute_(*x, self)).collect(),
pats: a.pats.iter().map(|x| self.fold_pat(*x)).collect(),
guard: a.guard.map(|x| self.fold_expr(x)),
body: self.fold_expr(a.body),
}
ExprMethodCall(i, ref tps, ref args) => {
ExprMethodCall(
- folder.fold_ident(i),
+ respan(i.span, folder.fold_ident(i.node)),
tps.iter().map(|&x| folder.fold_ty(x)).collect(),
args.iter().map(|&x| folder.fold_expr(x)).collect())
}
ExprCall(f, args)
}
- fn mk_method_call(&mut self, ident: Ident, tps: Vec<P<Ty>> , args: Vec<@Expr> ) -> ast::Expr_ {
+ fn mk_method_call(&mut self,
+ ident: ast::SpannedIdent,
+ tps: Vec<P<Ty>>,
+ args: Vec<@Expr>)
+ -> ast::Expr_ {
ExprMethodCall(ident, tps, args)
}
if self.eat(&token::DOT) {
match self.token {
token::IDENT(i, _) => {
+ let dot = self.last_span.hi;
hi = self.span.hi;
self.bump();
let (_, tys) = if self.eat(&token::MOD_SEP) {
hi = self.last_span.hi;
es.unshift(e);
- let nd = self.mk_method_call(i, tys, es);
+ let id = spanned(dot, hi, i);
+ let nd = self.mk_method_call(id, tys, es);
e = self.mk_expr(lo, hi, nd);
}
_ => {
self.commit_expr_expecting(discriminant, token::LBRACE);
let mut arms: Vec<Arm> = Vec::new();
while self.token != token::RBRACE {
+ let attrs = self.parse_outer_attributes();
let pats = self.parse_pats();
let mut guard = None;
if self.eat_keyword(keywords::If) {
self.eat(&token::COMMA);
}
- arms.push(ast::Arm { pats: pats, guard: guard, body: expr });
+ arms.push(ast::Arm {
+ attrs: attrs,
+ pats: pats,
+ guard: guard,
+ body: expr
+ });
}
let hi = self.span.hi;
self.bump();
let base_args = args.slice_from(1);
try!(self.print_expr(*args.get(0)));
try!(word(&mut self.s, "."));
- try!(self.print_ident(ident));
+ try!(self.print_ident(ident.node));
if tys.len() > 0u {
try!(word(&mut self.s, "::<"));
try!(self.commasep(Inconsistent, tys.as_slice(),
try!(self.bopen());
let len = arms.len();
for (i, arm) in arms.iter().enumerate() {
- try!(space(&mut self.s));
+ // I have no idea why this check is necessary, but here it
+ // is :(
+ if arm.attrs.is_empty() {
+ try!(space(&mut self.s));
+ }
try!(self.cbox(indent_unit));
try!(self.ibox(0u));
+ try!(self.print_outer_attributes(arm.attrs.as_slice()));
let mut first = true;
for p in arm.pats.iter() {
if first {
use std::os;
use std::str;
use std::strbuf::StrBuf;
-use std::task;
+use std::task::TaskBuilder;
// to be used by rustc to compile tests in libtest
pub mod test {
pub ratchet_noise_percent: Option<f64>,
pub save_metrics: Option<Path>,
pub test_shard: Option<(uint,uint)>,
- pub logfile: Option<Path>
+ pub logfile: Option<Path>,
+ pub nocapture: bool,
+}
+
+impl TestOpts {
+ #[cfg(test)]
+ fn new() -> TestOpts {
+ TestOpts {
+ filter: None,
+ run_ignored: false,
+ run_tests: false,
+ run_benchmarks: false,
+ ratchet_metrics: None,
+ ratchet_noise_percent: None,
+ save_metrics: None,
+ test_shard: None,
+ logfile: None,
+ nocapture: false,
+ }
+ }
}
/// Result of parsing the options.
getopts::optopt("", "logfile", "Write logs to the specified file instead \
of stdout", "PATH"),
getopts::optopt("", "test-shard", "run shard A, of B shards, worth of the testsuite",
- "A.B"))
+ "A.B"),
+ getopts::optflag("", "nocapture", "don't capture stdout/stderr of each \
+ task, allow printing directly"))
}
fn usage(binary: &str, helpstr: &str) {
By default, all tests are run in parallel. This can be altered with the
RUST_TEST_TASKS environment variable when running tests (set it to 1).
+All tests have their standard output and standard error captured by default.
+This can be overridden with the --nocapture flag or the RUST_TEST_NOCAPTURE=1
+environment variable. Logging is not captured by default.
+
Test Attributes:
#[test] - Indicates a function is a test to be run. This function
let test_shard = matches.opt_str("test-shard");
let test_shard = opt_shard(test_shard);
+ let mut nocapture = matches.opt_present("nocapture");
+ if !nocapture {
+ nocapture = os::getenv("RUST_TEST_NOCAPTURE").is_some();
+ }
+
let test_opts = TestOpts {
filter: filter,
run_ignored: run_ignored,
ratchet_noise_percent: ratchet_noise_percent,
save_metrics: save_metrics,
test_shard: test_shard,
- logfile: logfile
+ logfile: logfile,
+ nocapture: nocapture,
};
Some(Ok(test_opts))
// that hang forever.
try!(callback(TeWait(test.desc.clone(), test.testfn.padding())));
}
- run_test(!opts.run_tests, test, tx.clone());
+ run_test(opts, !opts.run_tests, test, tx.clone());
pending += 1;
}
// (this includes metric fns)
for b in filtered_benchs_and_metrics.move_iter() {
try!(callback(TeWait(b.desc.clone(), b.testfn.padding())));
- run_test(!opts.run_benchmarks, b, tx.clone());
+ run_test(opts, !opts.run_benchmarks, b, tx.clone());
let (test, result, stdout) = rx.recv();
try!(callback(TeResult(test, result, stdout)));
}
}
}
-pub fn run_test(force_ignore: bool,
+pub fn run_test(opts: &TestOpts,
+ force_ignore: bool,
test: TestDescAndFn,
monitor_ch: Sender<MonitorMsg>) {
#[allow(deprecated_owned_vector)]
fn run_test_inner(desc: TestDesc,
monitor_ch: Sender<MonitorMsg>,
+ nocapture: bool,
testfn: proc():Send) {
spawn(proc() {
let (tx, rx) = channel();
let mut reader = ChanReader::new(rx);
let stdout = ChanWriter::new(tx.clone());
let stderr = ChanWriter::new(tx);
- let mut task = task::task().named(match desc.name {
+ let mut task = TaskBuilder::new().named(match desc.name {
DynTestName(ref name) => name.clone().into_maybe_owned(),
StaticTestName(name) => name.into_maybe_owned(),
});
- task.opts.stdout = Some(~stdout as ~Writer:Send);
- task.opts.stderr = Some(~stderr as ~Writer:Send);
+ if nocapture {
+ drop((stdout, stderr));
+ } else {
+ task.opts.stdout = Some(~stdout as ~Writer:Send);
+ task.opts.stderr = Some(~stderr as ~Writer:Send);
+ }
let result_future = task.future_result();
task.spawn(testfn);
monitor_ch.send((desc, TrMetrics(mm), Vec::new()));
return;
}
- DynTestFn(f) => run_test_inner(desc, monitor_ch, f),
- StaticTestFn(f) => run_test_inner(desc, monitor_ch, proc() f())
+ DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f),
+ StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture,
+ proc() f())
}
}
testfn: DynTestFn(proc() f()),
};
let (tx, rx) = channel();
- run_test(false, desc, tx);
+ run_test(&TestOpts::new(), false, desc, tx);
let (_, res, _) = rx.recv();
assert!(res != TrOk);
}
testfn: DynTestFn(proc() f()),
};
let (tx, rx) = channel();
- run_test(false, desc, tx);
+ run_test(&TestOpts::new(), false, desc, tx);
let (_, res, _) = rx.recv();
assert!(res == TrIgnored);
}
testfn: DynTestFn(proc() f()),
};
let (tx, rx) = channel();
- run_test(false, desc, tx);
+ run_test(&TestOpts::new(), false, desc, tx);
let (_, res, _) = rx.recv();
assert!(res == TrOk);
}
testfn: DynTestFn(proc() f()),
};
let (tx, rx) = channel();
- run_test(false, desc, tx);
+ run_test(&TestOpts::new(), false, desc, tx);
let (_, res, _) = rx.recv();
assert!(res == TrFailed);
}
// When we run ignored tests the test filter should filter out all the
// unignored tests and flip the ignore flag on the rest to false
- let opts = TestOpts {
- filter: None,
- run_ignored: true,
- logfile: None,
- run_tests: true,
- run_benchmarks: false,
- ratchet_noise_percent: None,
- ratchet_metrics: None,
- save_metrics: None,
- test_shard: None
- };
+ let mut opts = TestOpts::new();
+ opts.run_tests = true;
+ opts.run_ignored = true;
let tests = vec!(
TestDescAndFn {
#[test]
pub fn sort_tests() {
- let opts = TestOpts {
- filter: None,
- run_ignored: false,
- logfile: None,
- run_tests: true,
- run_benchmarks: false,
- ratchet_noise_percent: None,
- ratchet_metrics: None,
- save_metrics: None,
- test_shard: None
- };
+ let mut opts = TestOpts::new();
+ opts.run_tests = true;
let names =
vec!("sha1::test".to_owned(), "int::test_to_str".to_owned(), "int::test_pow".to_owned(),
-Subproject commit 800b56fe6af21ffd8e56aee8cf12dd758f5bbdf1
+Subproject commit 43495892ded622de51eba7362c5ffae1ed50c9cc
# Change the contents of this file to force a full rebuild of libuv
-2014-02-16
+2014-04-18
const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(),
Error);
if (TheTarget == NULL) {
- LLVMRustError = Error.c_str();
+ LLVMRustSetLastError(Error.c_str());
return NULL;
}
raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary);
#endif
if (ErrorInfo != "") {
- LLVMRustError = ErrorInfo.c_str();
+ LLVMRustSetLastError(ErrorInfo.c_str());
return false;
}
formatted_raw_ostream FOS(OS);
using namespace llvm::sys;
using namespace llvm::object;
-const char *LLVMRustError;
+static char *LastError;
extern "C" LLVMMemoryBufferRef
LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
LLVMMemoryBufferRef MemBuf = NULL;
- LLVMCreateMemoryBufferWithContentsOfFile(Path, &MemBuf,
- const_cast<char **>(&LLVMRustError));
+ char *err = NULL;
+ LLVMCreateMemoryBufferWithContentsOfFile(Path, &MemBuf, &err);
+ if (err != NULL) {
+ LLVMRustSetLastError(err);
+ }
return MemBuf;
}
-extern "C" const char *LLVMRustGetLastError(void) {
- return LLVMRustError;
+extern "C" char *LLVMRustGetLastError(void) {
+ char *ret = LastError;
+ LastError = NULL;
+ return ret;
+}
+
+void LLVMRustSetLastError(const char *err) {
+ free((void*) LastError);
+ LastError = strdup(err);
}
extern "C" void
MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(buf, Dst->getContext());
if (!Src) {
- LLVMRustError = Src.getError().message().c_str();
+ LLVMRustSetLastError(Src.getError().message().c_str());
delete buf;
return false;
}
std::string Err;
if (Linker::LinkModules(Dst, *Src, Linker::DestroySource, &Err)) {
- LLVMRustError = Err.c_str();
+ LLVMRustSetLastError(Err.c_str());
return false;
}
return true;
std::string Err;
Module *Src = llvm::getLazyBitcodeModule(buf, Dst->getContext(), &Err);
if (!Src) {
- LLVMRustError = Err.c_str();
+ LLVMRustSetLastError(Err.c_str());
delete buf;
return false;
}
if (Linker::LinkModules(Dst, Src, Linker::DestroySource, &Err)) {
- LLVMRustError = Err.c_str();
+ LLVMRustSetLastError(Err.c_str());
return false;
}
return true;
std::unique_ptr<MemoryBuffer> buf;
error_code err = MemoryBuffer::getFile(path, buf);
if (err) {
- LLVMRustError = err.message().c_str();
+ LLVMRustSetLastError(err.message().c_str());
return NULL;
}
Archive *ret = new Archive(buf.release(), err);
if (err) {
- LLVMRustError = err.message().c_str();
+ LLVMRustSetLastError(err.message().c_str());
return NULL;
}
return ret;
OwningPtr<MemoryBuffer> buf;
error_code err = MemoryBuffer::getFile(path, buf);
if (err) {
- LLVMRustError = err.message().c_str();
+ LLVMRustSetLastError(err.message().c_str());
return NULL;
}
Archive *ret = new Archive(buf.take(), err);
if (err) {
- LLVMRustError = err.message().c_str();
+ LLVMRustSetLastError(err.message().c_str());
return NULL;
}
return ret;
#include <unistd.h>
#endif
-extern const char* LLVMRustError;
+void LLVMRustSetLastError(const char*);
use std::comm;
use std::os;
use std::task;
+use std::task::TaskBuilder;
use std::uint;
fn move_out<T>(_x: T) {}
let mut worker_results = Vec::new();
for _ in range(0u, workers) {
let to_child = to_child.clone();
- let mut builder = task::task();
+ let mut builder = TaskBuilder::new();
worker_results.push(builder.future_result());
builder.spawn(proc() {
for _ in range(0u, size / workers) {
use std::os;
use std::task;
+use std::task::TaskBuilder;
use std::uint;
fn move_out<T>(_x: T) {}
let mut worker_results = Vec::new();
let from_parent = if workers == 1 {
let (to_child, from_parent) = channel();
- let mut builder = task::task();
+ let mut builder = TaskBuilder::new();
worker_results.push(builder.future_result());
builder.spawn(proc() {
for _ in range(0u, size / workers) {
let (to_child, from_parent) = channel();
for _ in range(0u, workers) {
let to_child = to_child.clone();
- let mut builder = task::task();
+ let mut builder = TaskBuilder::new();
worker_results.push(builder.future_result());
builder.spawn(proc() {
for _ in range(0u, size / workers) {
use std::os;
use std::result::{Ok, Err};
use std::task;
+use std::task::TaskBuilder;
use std::uint;
fn fib(n: int) -> int {
fn stress(num_tasks: int) {
let mut results = Vec::new();
for i in range(0, num_tasks) {
- let mut builder = task::task();
+ let mut builder = TaskBuilder::new();
results.push(builder.future_result());
builder.spawn(proc() {
stress_task(i);
--- /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.
+
+// Verify that managed pointers scope is treated like ownoed pointers.
+// regresion test for #11586
+
+#![feature(managed_boxes)]
+
+fn foo<'a>(x: &'a @int) -> &'a int {
+ match x {
+ &ref y => {
+ &**y // Do not expect an error here
+ }
+ }
+}
+
+fn bar() {
+ let a = 3;
+ let mut y = &a;
+ if true {
+ let x = @3;
+ y = &*x; //~ ERROR `*x` does not live long enough
+ }
+}
+
+fn main() {}
--- /dev/null
+// ignore-pretty
+
+// Copyright 2012-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.
+
+// exec-env:RUST_POISON_ON_FREE=1
+
+#![feature(managed_boxes)]
+
+fn borrow(x: &int, f: |x: &int|) {
+ let before = *x;
+ f(x);
+ let after = *x;
+ assert_eq!(before, after);
+}
+
+struct F { f: ~int }
+
+pub fn main() {
+ let mut x = @F {f: ~3};
+ borrow(x.f, |b_x| {
+ //~^ ERROR cannot borrow `x` as mutable because `*x.f` is also borrowed as immutable
+ assert_eq!(*b_x, 3);
+ assert_eq!(&(*x.f) as *int, &(*b_x) as *int);
+ //~^ NOTE borrow occurs due to use of `x` in closure
+ x = @F {f: ~4};
+
+ println!("&*b_x = {:p}", &(*b_x));
+ assert_eq!(*b_x, 3);
+ assert!(&(*x.f) as *int != &(*b_x) as *int);
+ })
+}
--- /dev/null
+// ignore-pretty
+
+// Copyright 2012-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.
+
+// exec-env:RUST_POISON_ON_FREE=1
+
+#![feature(managed_boxes)]
+
+fn borrow(x: &int, f: |x: &int|) {
+ let before = *x;
+ f(x);
+ let after = *x;
+ assert_eq!(before, after);
+}
+
+struct F { f: ~int }
+
+pub fn main() {
+ let mut x = ~@F{f: ~3};
+ borrow(x.f, |b_x| {
+ //~^ ERROR cannot borrow `x` as mutable because `*x.f` is also borrowed as immutable
+ assert_eq!(*b_x, 3);
+ assert_eq!(&(*x.f) as *int, &(*b_x) as *int);
+ //~^ NOTE borrow occurs due to use of `x` in closure
+ *x = @F{f: ~4};
+
+ println!("&*b_x = {:p}", &(*b_x));
+ assert_eq!(*b_x, 3);
+ assert!(&(*x.f) as *int != &(*b_x) as *int);
+ })
+}
--- /dev/null
+// ignore-pretty
+
+// Copyright 2012-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.
+
+// exec-env:RUST_POISON_ON_FREE=1
+
+#![feature(managed_boxes)]
+
+fn borrow(x: &int, f: |x: &int|) {
+ let before = *x;
+ f(x);
+ let after = *x;
+ assert_eq!(before, after);
+}
+
+pub fn main() {
+ let mut x = @3;
+ borrow(x, |b_x| {
+ //~^ ERROR cannot borrow `x` as mutable because `*x` is also borrowed as immutable
+ assert_eq!(*b_x, 3);
+ assert_eq!(&(*x) as *int, &(*b_x) as *int);
+ //~^ NOTE borrow occurs due to use of `x` in closure
+ x = @22;
+
+ println!("&*b_x = {:p}", &(*b_x));
+ assert_eq!(*b_x, 3);
+ assert!(&(*x) as *int != &(*b_x) as *int);
+ })
+}
--- /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.
+
+// exec-env:RUST_POISON_ON_FREE=1
+
+#![feature(managed_boxes)]
+
+fn testfn(cond: bool) {
+ let mut x = @3;
+ let mut y = @4;
+
+ // borrow x and y
+ let r_x = &*x;
+ let r_y = &*y;
+ let mut r = r_x;
+ let mut exp = 3;
+
+ if cond {
+ r = r_y;
+ exp = 4;
+ }
+
+ println!("*r = {}, exp = {}", *r, exp);
+ assert_eq!(*r, exp);
+
+ x = @5; //~ERROR cannot assign to `x` because it is borrowed
+ y = @6; //~ERROR cannot assign to `y` because it is borrowed
+
+ println!("*r = {}, exp = {}", *r, exp);
+ assert_eq!(*r, exp);
+ assert_eq!(x, @5);
+ assert_eq!(y, @6);
+}
+
+pub fn main() {
+ testfn(true);
+ testfn(false);
+}
--- /dev/null
+// ignore-pretty
+
+// Copyright 2012-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.
+
+// exec-env:RUST_POISON_ON_FREE=1
+
+#![feature(managed_boxes)]
+
+fn borrow(x: &int, f: |x: &int|) {
+ let before = *x;
+ f(x);
+ let after = *x;
+ assert_eq!(before, after);
+}
+
+struct F { f: ~int }
+
+pub fn main() {
+ let mut x = @F {f: ~3};
+ borrow((*x).f, |b_x| {
+ //~^ ERROR cannot borrow `x` as mutable because `*x.f` is also borrowed as immutable
+ assert_eq!(*b_x, 3);
+ assert_eq!(&(*x.f) as *int, &(*b_x) as *int);
+ //~^ NOTE borrow occurs due to use of `x` in closure
+ x = @F {f: ~4};
+
+ println!("&*b_x = {:p}", &(*b_x));
+ assert_eq!(*b_x, 3);
+ assert!(&(*x.f) as *int != &(*b_x) as *int);
+ })
+}
--- /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.
+
+#![deny(unused_imports)]
+
+// The aim of this test is to ensure that deny/allow/warn directives
+// are applied to individual "use" statements instead of silently
+// ignored.
+
+#[allow(dead_code)]
+mod a { pub static x: int = 3; pub static y: int = 4; }
+
+mod b {
+ use a::x; //~ ERROR: unused import
+ #[allow(unused_imports)]
+ use a::y; // no error here
+}
+
+#[allow(unused_imports)]
+mod c {
+ use a::x;
+ #[deny(unused_imports)]
+ use a::y; //~ ERROR: unused import
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2012-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.
+
+// Test that parameter cardinality or missing method error gets span exactly.
+
+pub struct Foo;
+impl Foo {
+ fn zero(self) -> Foo { self }
+ fn one(self, _: int) -> Foo { self }
+ fn two(self, _: int, _: int) -> Foo { self }
+}
+
+fn main() {
+ let x = Foo;
+ x.zero(0) //~ ERROR this function takes 0 parameters but 1 parameter was supplied
+ .one() //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+ .two(0); //~ ERROR this function takes 2 parameters but 1 parameter was supplied
+
+ let y = Foo;
+ y.zero()
+ .take() //~ ERROR type `Foo` does not implement any method in scope named `take`
+ .one(0);
+}
--- /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.
+
+// Test no-special rooting is used for managed boxes
+
+#![feature(managed_boxes)]
+
+fn testfn(cond: bool) {
+ let mut x = @3;
+ let mut y = @4;
+
+ let mut a = &*x;
+
+ let mut exp = 3;
+ if cond {
+ a = &*y;
+
+ exp = 4;
+ }
+
+ x = @5; //~ERROR cannot assign to `x` because it is borrowed
+ y = @6; //~ERROR cannot assign to `y` because it is borrowed
+ assert_eq!(*a, exp);
+ assert_eq!(x, @5);
+ assert_eq!(y, @6);
+}
+
+pub fn main() {}
}
fn foo(p: @point) -> &int {
- let xc = x_coord(p); //~ ERROR cannot root
+ let xc = x_coord(p); //~ ERROR `*p` does not live long enough
assert_eq!(*xc, 3);
return xc;
}
// Here we complain because the resulting region
// of this borrow is the fn body as a whole.
- y = borrow(x); //~ ERROR cannot root
+ y = borrow(x); //~ ERROR `*x` does not live long enough
assert_eq!(*x, *y);
if cond() { break; }
--- /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.
+
+#![feature(managed_boxes)]
+
+struct Foo<'a> {
+ x: &'a int
+}
+
+pub fn main() {
+ let f = Foo { x: @3 }; //~ ERROR borrowed value does not live long enough
+ assert_eq!(*f.x, 3);
+}
// except according to those terms.
#![feature(struct_variant)]
-// Test `type` types not allowed in fields or local variables.
-
-/*trait T for type {}
-
-fn f5<type X>(x: &X) {
- let _: X; // ERROR local variable with dynamically sized type X
- let _: (int, (X, int)); // ERROR local variable with dynamically sized type (int,(X,int))
-}
-fn f6<type X: T>(x: &X) {
- let _: X; // ERROR local variable with dynamically sized type X
- let _: (int, (X, int)); // ERROR local variable with dynamically sized type (int,(X,int))
-}*/
+// Test `type` types not allowed in fields.
struct S1<type X> {
f1: X, //~ ERROR type `f1` is dynamically sized. dynamically sized types may only appear as the
--- /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.
+
+// Test `type` local variables.
+
+trait T for type {}
+
+fn f1<type X>(x: &X) {
+ let _: X; //~ERROR variable `_` has dynamically sized type `X`
+ let _: (int, (X, int)); //~ERROR variable `_` has dynamically sized type `(int,(X,int))`
+ let y: X; //~ERROR variable `y` has dynamically sized type `X`
+ let y: (int, (X, int)); //~ERROR variable `y` has dynamically sized type `(int,(X,int))`
+}
+fn f2<type X: T>(x: &X) {
+ let _: X; //~ERROR variable `_` has dynamically sized type `X`
+ let _: (int, (X, int)); //~ERROR variable `_` has dynamically sized type `(int,(X,int))`
+ let y: X; //~ERROR variable `y` has dynamically sized type `X`
+ let y: (int, (X, int)); //~ERROR variable `y` has dynamically sized type `(int,(X,int))`
+}
+
+fn f3<type X>(x1: ~X, x2: ~X, x3: ~X) {
+ let y: X = *x1; //~ERROR variable `y` has dynamically sized type `X`
+ let y = *x2; //~ERROR variable `y` has dynamically sized type `X`
+ let (y, z) = (*x3, 4); //~ERROR variable `y` has dynamically sized type `X`
+}
+fn f4<type X: T>(x1: ~X, x2: ~X, x3: ~X) {
+ let y: X = *x1; //~ERROR variable `y` has dynamically sized type `X`
+ let y = *x2; //~ERROR variable `y` has dynamically sized type `X`
+ let (y, z) = (*x3, 4); //~ERROR variable `y` has dynamically sized type `X`
+}
+
+fn g1<type X>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
+fn g2<type X: T>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
+
+pub fn main() {
+}
// error-pattern:task 'owned name' failed at 'test'
-use std::task;
+use std::task::TaskBuilder;
fn main() {
- task::task().named("owned name".to_owned()).try(proc() {
+ TaskBuilder::new().named("owned name".to_owned()).try(proc() {
fail!("test");
1
}).unwrap()
// error-pattern:task 'send name' failed at 'test'
fn main() {
- ::std::task::task().named("send name".into_maybe_owned()).try(proc() {
+ ::std::task::TaskBuilder::new().named("send name".into_maybe_owned()).try(proc() {
fail!("test");
3
}).unwrap()
// error-pattern:task 'static name' failed at 'test'
fn main() {
- ::std::task::task().named("static name").try(proc() {
+ ::std::task::TaskBuilder::new().named("static name").try(proc() {
fail!("test");
}).unwrap()
}
--- /dev/null
+-include ../tools.mk
+
+all:
+ # Let's get a nice error message
+ $(RUSTC) foo.rs --dep-info foo/bar/baz 2>&1 | \
+ grep "error writing dependencies"
+ # Make sure the filename shows up
+ $(RUSTC) foo.rs --dep-info foo/bar/baz 2>&1 | grep "baz"
--- /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.
+
+fn main() {}
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) foo.rs -o $(TMPDIR)/.foo
+ rm $(TMPDIR)/.foo
+ $(RUSTC) foo.rs -o $(TMPDIR)/.foo.bar
+ rm $(TMPDIR)/.foo.bar
+ $(RUSTC) foo.rs -o $(TMPDIR)/+foo+bar
+ rm $(TMPDIR)/+foo+bar
--- /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.
+
+fn main() {}
+++ /dev/null
-// ignore-pretty
-
-// Copyright 2012-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.
-
-// exec-env:RUST_POISON_ON_FREE=1
-
-#![feature(managed_boxes)]
-
-fn borrow(x: &int, f: |x: &int|) {
- let before = *x;
- f(x);
- let after = *x;
- assert_eq!(before, after);
-}
-
-struct F { f: ~int }
-
-pub fn main() {
- let mut x = @F {f: ~3};
- borrow(x.f, |b_x| {
- assert_eq!(*b_x, 3);
- assert_eq!(&(*x.f) as *int, &(*b_x) as *int);
- x = @F {f: ~4};
-
- println!("&*b_x = {:p}", &(*b_x));
- assert_eq!(*b_x, 3);
- assert!(&(*x.f) as *int != &(*b_x) as *int);
- })
-}
+++ /dev/null
-// ignore-pretty
-
-// Copyright 2012-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.
-
-// exec-env:RUST_POISON_ON_FREE=1
-
-#![feature(managed_boxes)]
-
-fn borrow(x: &int, f: |x: &int|) {
- let before = *x;
- f(x);
- let after = *x;
- assert_eq!(before, after);
-}
-
-struct F { f: ~int }
-
-pub fn main() {
- let mut x = ~@F{f: ~3};
- borrow(x.f, |b_x| {
- assert_eq!(*b_x, 3);
- assert_eq!(&(*x.f) as *int, &(*b_x) as *int);
- *x = @F{f: ~4};
-
- println!("&*b_x = {:p}", &(*b_x));
- assert_eq!(*b_x, 3);
- assert!(&(*x.f) as *int != &(*b_x) as *int);
- })
-}
+++ /dev/null
-// ignore-pretty
-
-// Copyright 2012-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.
-
-// exec-env:RUST_POISON_ON_FREE=1
-
-#![feature(managed_boxes)]
-
-fn borrow(x: &int, f: |x: &int|) {
- let before = *x;
- f(x);
- let after = *x;
- assert_eq!(before, after);
-}
-
-pub fn main() {
- let mut x = @3;
- borrow(x, |b_x| {
- assert_eq!(*b_x, 3);
- assert_eq!(&(*x) as *int, &(*b_x) as *int);
- x = @22;
-
- println!("&*b_x = {:p}", &(*b_x));
- assert_eq!(*b_x, 3);
- assert!(&(*x) as *int != &(*b_x) as *int);
- })
-}
+++ /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.
-
-// exec-env:RUST_POISON_ON_FREE=1
-
-#![feature(managed_boxes)]
-
-fn testfn(cond: bool) {
- let mut x = @3;
- let mut y = @4;
-
- // borrow x and y
- let r_x = &*x;
- let r_y = &*y;
- let mut r = r_x;
- let mut exp = 3;
-
- if cond {
- r = r_y;
- exp = 4;
- }
-
- println!("*r = {}, exp = {}", *r, exp);
- assert_eq!(*r, exp);
-
- x = @5;
- y = @6;
-
- println!("*r = {}, exp = {}", *r, exp);
- assert_eq!(*r, exp);
- assert_eq!(x, @5);
- assert_eq!(y, @6);
-}
-
-pub fn main() {
- testfn(true);
- testfn(false);
-}
+++ /dev/null
-// ignore-pretty
-
-// Copyright 2012-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.
-
-// exec-env:RUST_POISON_ON_FREE=1
-
-#![feature(managed_boxes)]
-
-fn borrow(x: &int, f: |x: &int|) {
- let before = *x;
- f(x);
- let after = *x;
- assert_eq!(before, after);
-}
-
-struct F { f: ~int }
-
-pub fn main() {
- let mut x = @F {f: ~3};
- borrow((*x).f, |b_x| {
- assert_eq!(*b_x, 3);
- assert_eq!(&(*x.f) as *int, &(*b_x) as *int);
- x = @F {f: ~4};
-
- println!("&*b_x = {:p}", &(*b_x));
- assert_eq!(*b_x, 3);
- assert!(&(*x.f) as *int != &(*b_x) as *int);
- })
-}
--- /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 Foo {
+ Bar,
+ Baz,
+}
+
+fn foo(f: Foo) {
+ match f {
+ Bar => {},
+ #[cfg(not(asdfa))]
+ Baz => {},
+ #[cfg(afsd)]
+ Basdfwe => {}
+ }
+}
+
+pub fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::task;
+use std::task::TaskBuilder;
static generations: uint = 1024+256+128+49;
fn spawn(f: proc():Send) {
- let mut t = task::task();
+ let mut t = TaskBuilder::new();
t.opts.stack_size = Some(32 * 1024);
t.spawn(f);
}
+++ /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.
-
-/* Tests conditional rooting of the box y */
-
-#![feature(managed_boxes)]
-
-fn testfn(cond: bool) {
- let mut x = @3;
- let mut y = @4;
-
- let mut a = &*x;
-
- let mut exp = 3;
- if cond {
- a = &*y;
-
- exp = 4;
- }
-
- x = @5;
- y = @6;
- assert_eq!(*a, exp);
- assert_eq!(x, @5);
- assert_eq!(y, @6);
-}
-
-pub fn main() {
-}
// regression test for issue #10405, make sure we don't call println! too soon.
-use std::task;
+use std::task::TaskBuilder;
pub fn main() {
- let mut t = task::task();
+ let mut t = TaskBuilder::new();
t.spawn(proc() ());
}
+++ /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.
-
-#![feature(managed_boxes)]
-
-struct Foo<'a> {
- x: &'a int
-}
-
-pub fn main() {
- let f = Foo { x: @3 };
- assert_eq!(*f.x, 3);
-}
// except according to those terms.
use std::task;
+use std::task::TaskBuilder;
pub fn main() { test00(); }
fn test00() {
let i: int = 0;
- let mut builder = task::task();
+ let mut builder = TaskBuilder::new();
let mut result = builder.future_result();
builder.spawn(proc() {
start(i)
// except according to those terms.
-use std::task;
+use std::task::TaskBuilder;
pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); }
let mut results = Vec::new();
while i < number_of_tasks {
let tx = tx.clone();
- let mut builder = task::task();
+ let mut builder = TaskBuilder::new();
results.push(builder.future_result());
builder.spawn({
let i = i;
// except according to those terms.
-use std::task;
+use std::task::TaskBuilder;
pub fn main() { test00(); }
let (tx, rx) = channel();
let number_of_messages: int = 10;
- let mut builder = task::task();
+ let mut builder = TaskBuilder::new();
let result = builder.future_result();
builder.spawn(proc() {
test00_start(&tx, number_of_messages);
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::io::net::tcp::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
-use std::task;
+use std::task::TaskBuilder;
#[start]
fn start(argc: int, argv: **u8) -> int {
let (tx, rx) = channel();
for _ in range(0, 1000) {
let tx = tx.clone();
- let mut builder = task::task();
+ let mut builder = TaskBuilder::new();
builder.opts.stack_size = Some(32 * 1024);
builder.spawn(proc() {
match TcpStream::connect(addr) {
// except according to those terms.
use std::task;
+use std::task::TaskBuilder;
pub fn main() {
- let mut builder = task::task();
+ let mut builder = TaskBuilder::new();
let mut result = builder.future_result();
builder.spawn(child);
println!("1");
// except according to those terms.
use std::task;
+use std::task::TaskBuilder;
pub fn main() {
- let mut builder = task::task();
+ let mut builder = TaskBuilder::new();
let mut result = builder.future_result();
builder.spawn(child);
println!("1");