# triples). The associated message will be printed as a warning
# during attempts to run those tests.
-CTEST_DISABLE_NONSELFHOST_rpass-full = "run-pass-full suite is unavailable when cross-compiling."
-
define DEF_CTEST_VARS
# All the per-stage build rules you might want to call from the
$$(CTEST_TESTARGS)
CTEST_DEPS_rpass_$(1)-T-$(2)-H-$(3) = $$(RPASS_TESTS)
-CTEST_DEPS_rpass-full_$(1)-T-$(2)-H-$(3) = $$(RPASS_FULL_TESTS) $$(CSREQ$(1)_T_$(2)_H_$(3))
+CTEST_DEPS_rpass-full_$(1)-T-$(2)-H-$(3) = $$(RPASS_FULL_TESTS) $$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
CTEST_DEPS_rfail_$(1)-T-$(2)-H-$(3) = $$(RFAIL_TESTS)
CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS)
CTEST_DEPS_bench_$(1)-T-$(2)-H-$(3) = $$(BENCH_TESTS)
}
#[inline]
- fn idx(&self, index: uint) -> Option<bool> {
+ fn idx(&mut self, index: uint) -> Option<bool> {
if index >= self.indexable() {
None
} else {
fn indexable(&self) -> uint { self.rindex - self.index }
#[inline]
- fn idx(&self, j: uint) -> Option<&'a T> {
+ fn idx(&mut self, j: uint) -> Option<&'a T> {
if j >= self.indexable() {
None
} else {
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);
s.push_str("0".repeat(l - ss.len()));
s.push_str(ss);
}
- s.as_slice().trim_left_chars(&'0').to_owned()
+ s.as_slice().trim_left_chars('0').to_owned()
}
}
}
let unixlibname = format!("lib{}.a", name);
let mut rustpath = filesearch::rust_path();
- rustpath.push(self.sess.filesearch().get_target_lib_path());
+ rustpath.push(self.sess.target_filesearch().get_lib_path());
let search = self.sess.opts.addl_lib_search_paths.borrow();
for path in search.iter().chain(rustpath.iter()) {
debug!("looking for {} inside {}", name, path.display());
// The default library location, we need this to find the runtime.
// The location of crates will be determined as needed.
// FIXME (#9639): This needs to handle non-utf8 paths
- let lib_path = sess.filesearch().get_target_lib_path();
+ let lib_path = sess.target_filesearch().get_lib_path();
let stage: ~str = "-L".to_owned() + lib_path.as_str().unwrap();
let mut args = vec!(stage);
debug!("preparing the RPATH!");
- let sysroot = sess.filesearch().sysroot;
+ let sysroot = sess.sysroot();
let output = out_filename;
let libs = sess.cstore.get_used_crates(cstore::RequireDynamic);
let libs = libs.move_iter().filter_map(|(_, l)| {
let time_passes = sess.time_passes();
time(time_passes, "external crate/lib resolution", (), |_|
- creader::read_crates(&sess, krate,
- session::sess_os_to_meta_os(sess.targ_cfg.os),
- token::get_ident_interner()));
+ creader::read_crates(&sess, krate));
let lang_items = time(time_passes, "language item collection", (), |_|
middle::lang_items::collect_language_items(krate, &sess));
}
}
-pub fn host_triple() -> ~str {
+pub fn host_triple() -> &'static str {
// Get the host triple out of the build environment. This ensures that our
// idea of the host triple is the same as for the set of libraries we've
// actually built. We can't just take LLVM's host triple because they
// Instead of grabbing the host triple (for the current host), we grab (at
// compile time) the target triple that this rustc is built with and
// calling that (at runtime) the host triple.
- (env!("CFG_COMPILER_HOST_TRIPLE")).to_owned()
+ env!("CFG_COMPILER_HOST_TRIPLE")
}
pub fn build_session_options(matches: &getopts::Matches) -> session::Options {
}
let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
- let target = matches.opt_str("target").unwrap_or(host_triple());
+ let target = matches.opt_str("target").unwrap_or(host_triple().to_owned());
let opt_level = {
if (debugging_opts & session::NO_OPT) != 0 {
No
pub fn show_span(&self) -> bool {
self.debugging_opt(SHOW_SPAN)
}
- pub fn filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
- let sysroot = match self.opts.maybe_sysroot {
- Some(ref sysroot) => sysroot,
+ pub fn sysroot<'a>(&'a self) -> &'a Path {
+ match self.opts.maybe_sysroot {
+ Some (ref sysroot) => sysroot,
None => self.default_sysroot.as_ref()
.expect("missing sysroot and default_sysroot in Session")
- };
+ }
+ }
+ pub fn target_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
filesearch::FileSearch::new(
- sysroot,
+ self.sysroot(),
self.opts.target_triple,
&self.opts.addl_lib_search_paths)
}
+ pub fn host_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
+ filesearch::FileSearch::new(
+ self.sysroot(),
+ host_triple(),
+ &self.opts.addl_lib_search_paths)
+ }
}
/// Some reasonable defaults
output_types: Vec::new(),
addl_lib_search_paths: RefCell::new(HashSet::new()),
maybe_sysroot: None,
- target_triple: host_triple(),
+ target_triple: host_triple().to_owned(),
cfg: Vec::new(),
test: false,
parse_only: false,
ctxt.fold_crate(krate)
}
-fn filter_view_item<'r>(cx: &Context, view_item: &'r ast::ViewItem)
+fn filter_view_item<'r>(cx: &mut Context, view_item: &'r ast::ViewItem)
-> Option<&'r ast::ViewItem> {
if view_item_in_cfg(cx, view_item) {
Some(view_item)
}
}
-fn filter_foreign_item(cx: &Context, item: @ast::ForeignItem)
+fn filter_foreign_item(cx: &mut Context, item: @ast::ForeignItem)
-> Option<@ast::ForeignItem> {
if foreign_item_in_cfg(cx, item) {
Some(item)
fold::noop_fold_item_underscore(&item, cx)
}
-fn fold_struct(cx: &Context, def: &ast::StructDef) -> @ast::StructDef {
+fn fold_struct(cx: &mut Context, def: &ast::StructDef) -> @ast::StructDef {
let mut fields = def.fields.iter().map(|c| c.clone()).filter(|m| {
(cx.in_cfg)(m.node.attrs.as_slice())
});
}
}
-fn retain_stmt(cx: &Context, stmt: @ast::Stmt) -> bool {
+fn retain_stmt(cx: &mut Context, stmt: @ast::Stmt) -> bool {
match stmt.node {
ast::StmtDecl(decl, _) => {
match decl.node {
})
}
-fn item_in_cfg(cx: &Context, item: &ast::Item) -> bool {
+fn item_in_cfg(cx: &mut Context, item: &ast::Item) -> bool {
return (cx.in_cfg)(item.attrs.as_slice());
}
-fn foreign_item_in_cfg(cx: &Context, item: &ast::ForeignItem) -> bool {
+fn foreign_item_in_cfg(cx: &mut Context, item: &ast::ForeignItem) -> bool {
return (cx.in_cfg)(item.attrs.as_slice());
}
-fn view_item_in_cfg(cx: &Context, item: &ast::ViewItem) -> bool {
+fn view_item_in_cfg(cx: &mut Context, item: &ast::ViewItem) -> bool {
return (cx.in_cfg)(item.attrs.as_slice());
}
-fn method_in_cfg(cx: &Context, meth: &ast::Method) -> bool {
+fn method_in_cfg(cx: &mut Context, meth: &ast::Method) -> bool {
return (cx.in_cfg)(meth.attrs.as_slice());
}
-fn trait_method_in_cfg(cx: &Context, meth: &ast::TraitMethod) -> bool {
+fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitMethod) -> bool {
match *meth {
ast::Required(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
ast::Provided(meth) => (cx.in_cfg)(meth.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.
pub static tag_exported_macros: uint = 0x8c;
pub static tag_macro_def: uint = 0x8d;
+pub static tag_crate_triple: uint = 0x66;
+
#[deriving(Clone, Show)]
pub struct LinkMeta {
pub crateid: CrateId,
use back::link;
use back::svh::Svh;
-use driver::{driver, session};
use driver::session::Session;
+use driver::{driver, session};
use metadata::cstore;
use metadata::cstore::CStore;
use metadata::decoder;
use metadata::loader;
-use metadata::loader::Os;
use metadata::loader::CratePaths;
use std::rc::Rc;
use syntax::codemap::{Span};
use syntax::diagnostic::SpanHandler;
use syntax::ext::base::{CrateLoader, MacroCrate};
-use syntax::parse::token::{IdentInterner, InternedString};
+use syntax::parse::token::InternedString;
use syntax::parse::token;
use syntax::crateid::CrateId;
use syntax::visit;
struct Env<'a> {
sess: &'a Session,
- os: loader::Os,
next_crate_num: ast::CrateNum,
- intr: Rc<IdentInterner>
}
// Traverses an AST, reading all the information about use'd crates and extern
// libraries necessary for later resolving, typechecking, linking, etc.
pub fn read_crates(sess: &Session,
- krate: &ast::Crate,
- os: loader::Os,
- intr: Rc<IdentInterner>) {
+ krate: &ast::Crate) {
let mut e = Env {
sess: sess,
- os: os,
next_crate_num: sess.cstore.next_crate_num(),
- intr: intr
};
visit_crate(&e, krate);
visit::walk_crate(&mut e, krate, ());
fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) {
let mut map = HashMap::new();
-
cstore.iter_crate_data(|cnum, data| {
let crateid = data.crate_id();
let key = (crateid.name.clone(), crateid.path.clone());
match extract_crate_info(e, i) {
Some(info) => {
let (cnum, _, _) = resolve_crate(e, &None, info.ident,
- &info.crate_id, None, true,
+ &info.crate_id, None,
i.span);
e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
}
return ret;
}
+fn register_crate<'a>(e: &mut Env,
+ root: &Option<CratePaths>,
+ ident: &str,
+ crate_id: &CrateId,
+ span: Span,
+ lib: loader::Library)
+ -> (ast::CrateNum, Rc<cstore::crate_metadata>,
+ cstore::CrateSource) {
+ // Claim this crate number and cache it
+ let cnum = e.next_crate_num;
+ e.next_crate_num += 1;
+
+ // Stash paths for top-most crate locally if necessary.
+ let crate_paths = if root.is_none() {
+ Some(CratePaths {
+ ident: ident.to_owned(),
+ dylib: lib.dylib.clone(),
+ rlib: lib.rlib.clone(),
+ })
+ } else {
+ None
+ };
+ // Maintain a reference to the top most crate.
+ let root = if root.is_some() { root } else { &crate_paths };
+
+ let cnum_map = resolve_crate_deps(e, root, lib.metadata.as_slice(), span);
+
+ let loader::Library{ dylib, rlib, metadata } = lib;
+
+ let cmeta = Rc::new( cstore::crate_metadata {
+ name: crate_id.name.to_owned(),
+ data: metadata,
+ cnum_map: cnum_map,
+ cnum: cnum,
+ span: span,
+ });
+
+ let source = cstore::CrateSource {
+ dylib: dylib,
+ rlib: rlib,
+ cnum: cnum,
+ };
+
+ e.sess.cstore.set_crate_data(cnum, cmeta.clone());
+ e.sess.cstore.add_used_crate_source(source.clone());
+ (cnum, cmeta, source)
+}
+
fn resolve_crate<'a>(e: &mut Env,
- root: &Option<CratePaths>,
- ident: &str,
- crate_id: &CrateId,
- hash: Option<&Svh>,
- should_link: bool,
- span: Span)
+ root: &Option<CratePaths>,
+ ident: &str,
+ crate_id: &CrateId,
+ hash: Option<&Svh>,
+ span: Span)
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
cstore::CrateSource) {
match existing_match(e, crate_id, hash) {
crate_id: crate_id,
id_hash: id_hash,
hash: hash.map(|a| &*a),
- os: e.os,
- intr: e.intr.clone(),
+ filesearch: e.sess.target_filesearch(),
+ os: session::sess_os_to_meta_os(e.sess.targ_cfg.os),
+ triple: e.sess.targ_cfg.target_strs.target_triple.as_slice(),
+ root: root,
rejected_via_hash: vec!(),
+ rejected_via_triple: vec!(),
};
- let loader::Library {
- dylib, rlib, metadata
- } = load_ctxt.load_library_crate(root);
-
- // Stash paths for top-most crate locally if necessary.
- let crate_paths = if root.is_none() {
- Some(CratePaths {
- ident: load_ctxt.ident.to_owned(),
- dylib: dylib.clone(),
- rlib: rlib.clone(),
- })
- } else {
- None
- };
- // Maintain a reference to the top most crate.
- let root = if root.is_some() { root } else { &crate_paths };
-
- // Now resolve the crates referenced by this crate
- let cnum_map = if should_link {
- resolve_crate_deps(e, root, metadata.as_slice(), span)
- } else {
- HashMap::new()
- };
-
- // Claim this crate number and cache it if we're linking to the
- // crate, otherwise it's a syntax-only crate and we don't need to
- // reserve a number
- let cnum = if should_link {
- let n = e.next_crate_num;
- e.next_crate_num += 1;
- n
- } else {
- -1
- };
-
- let cmeta = Rc::new(cstore::crate_metadata {
- name: load_ctxt.crate_id.name.to_owned(),
- data: metadata,
- cnum_map: cnum_map,
- cnum: cnum,
- span: span,
- });
-
- let source = cstore::CrateSource {
- dylib: dylib,
- rlib: rlib,
- cnum: cnum,
- };
-
- if should_link {
- e.sess.cstore.set_crate_data(cnum, cmeta.clone());
- e.sess.cstore.add_used_crate_source(source.clone());
- }
- (cnum, cmeta, source)
+ let library = load_ctxt.load_library_crate();
+ register_crate(e, root, ident, crate_id, span, library)
}
Some(cnum) => (cnum,
e.sess.cstore.get_crate_data(cnum),
dep.crate_id.name.as_slice(),
&dep.crate_id,
Some(&dep.hash),
- true,
span);
(dep.cnum, local_cnum)
}).collect()
impl<'a> Loader<'a> {
pub fn new(sess: &'a Session) -> Loader<'a> {
- let os = driver::get_os(driver::host_triple()).unwrap();
- let os = session::sess_os_to_meta_os(os);
Loader {
env: Env {
sess: sess,
- os: os,
next_crate_num: sess.cstore.next_crate_num(),
- intr: token::get_ident_interner(),
}
}
}
impl<'a> CrateLoader for Loader<'a> {
fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
let info = extract_crate_info(&self.env, krate).unwrap();
- let (_, data, library) = resolve_crate(&mut self.env, &None,
- info.ident, &info.crate_id,
- None, info.should_link,
- krate.span);
- let macros = decoder::get_exported_macros(&*data);
- let registrar = decoder::get_macro_registrar_fn(&*data).map(|id| {
- decoder::get_symbol(data.data.as_slice(), id)
+ let target_triple = self.env.sess.targ_cfg.target_strs.target_triple.as_slice();
+ let is_cross = target_triple != driver::host_triple();
+ let mut should_link = info.should_link && !is_cross;
+ let id_hash = link::crate_id_hash(&info.crate_id);
+ let os = driver::get_os(driver::host_triple()).unwrap();
+ let mut load_ctxt = loader::Context {
+ sess: self.env.sess,
+ span: krate.span,
+ ident: info.ident,
+ crate_id: &info.crate_id,
+ id_hash: id_hash,
+ hash: None,
+ filesearch: self.env.sess.host_filesearch(),
+ triple: driver::host_triple(),
+ os: session::sess_os_to_meta_os(os),
+ root: &None,
+ rejected_via_hash: vec!(),
+ rejected_via_triple: vec!(),
+ };
+ let library = match load_ctxt.maybe_load_library_crate() {
+ Some (l) => l,
+ None if is_cross => {
+ // try loading from target crates (only valid if there are
+ // no syntax extensions)
+ load_ctxt.triple = target_triple;
+ load_ctxt.os = session::sess_os_to_meta_os(self.env.sess.targ_cfg.os);
+ load_ctxt.filesearch = self.env.sess.target_filesearch();
+ let lib = load_ctxt.load_library_crate();
+ if decoder::get_macro_registrar_fn(lib.metadata.as_slice()).is_some() {
+ let message = format!("crate `{}` contains a macro_registrar fn but \
+ only a version for triple `{}` could be found (need {})",
+ info.ident, target_triple, driver::host_triple());
+ self.env.sess.span_err(krate.span, message);
+ // need to abort now because the syntax expansion
+ // code will shortly attempt to load and execute
+ // code from the found library.
+ self.env.sess.abort_if_errors();
+ }
+ should_link = info.should_link;
+ lib
+ }
+ None => { load_ctxt.report_load_errs(); unreachable!() },
+ };
+ let macros = decoder::get_exported_macros(library.metadata.as_slice());
+ let registrar = decoder::get_macro_registrar_fn(library.metadata.as_slice()).map(|id| {
+ decoder::get_symbol(library.metadata.as_slice(), id)
});
- MacroCrate {
- lib: library.dylib,
+ let mc = MacroCrate {
+ lib: library.dylib.clone(),
macros: macros.move_iter().collect(),
registrar_symbol: registrar,
+ };
+ if should_link {
+ // register crate now to avoid double-reading metadata
+ register_crate(&mut self.env, &None, info.ident.as_slice(),
+ &info.crate_id, krate.span, library);
}
+ mc
}
}
decoder::get_trait_of_method(&*cdata, def_id.node, tcx)
}
-pub fn get_macro_registrar_fn(cstore: &cstore::CStore,
- crate_num: ast::CrateNum)
- -> Option<ast::NodeId> {
- let cdata = cstore.get_crate_data(crate_num);
- decoder::get_macro_registrar_fn(&*cdata)
-}
-
-pub fn get_exported_macros(cstore: &cstore::CStore,
- crate_num: ast::CrateNum)
- -> Vec<~str> {
- let cdata = cstore.get_crate_data(crate_num);
- decoder::get_exported_macros(&*cdata)
-}
-
pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
def_id: ast::DefId)
-> Option<ast::DefId>
})
}
+pub fn get_crate_triple(data: &[u8]) -> ~str {
+ let cratedoc = reader::Doc(data);
+ let triple_doc = reader::maybe_get_doc(cratedoc, tag_crate_triple);
+ triple_doc.expect("No triple in crate").as_str()
+}
+
pub fn get_crate_id(data: &[u8]) -> CrateId {
let cratedoc = reader::Doc(data);
let hashdoc = reader::get_doc(cratedoc, tag_crate_crateid);
return result;
}
-pub fn get_macro_registrar_fn(cdata: Cmd) -> Option<ast::NodeId> {
- reader::maybe_get_doc(reader::Doc(cdata.data()), tag_macro_registrar_fn)
+pub fn get_macro_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
+ reader::maybe_get_doc(reader::Doc(data), tag_macro_registrar_fn)
.map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap())
}
-pub fn get_exported_macros(cdata: Cmd) -> Vec<~str> {
- let macros = reader::get_doc(reader::Doc(cdata.data()),
+pub fn get_exported_macros(data: &[u8]) -> Vec<~str> {
+ let macros = reader::get_doc(reader::Doc(data),
tag_exported_macros);
let mut result = Vec::new();
reader::tagged_docs(macros, tag_macro_def, |macro_doc| {
pub non_inlineable_statics: &'a RefCell<NodeSet>,
pub link_meta: &'a LinkMeta,
pub cstore: &'a cstore::CStore,
- pub encode_inlined_item: EncodeInlinedItem<'a>,
+ pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
pub type_abbrevs: tyencode::abbrev_map,
}
if num_params > 0u ||
is_default_impl ||
should_inline(ast_method.attrs.as_slice()) {
- (ecx.encode_inlined_item)(
- ecx, ebml_w, IIMethodRef(local_def(parent_id), false, ast_method));
+ encode_inlined_item(ecx, ebml_w,
+ IIMethodRef(local_def(parent_id), false, ast_method));
} else {
encode_symbol(ecx, ebml_w, m.def_id.node);
}
ebml_w.end_tag();
}
+fn encode_inlined_item(ecx: &EncodeContext,
+ ebml_w: &mut Encoder,
+ ii: InlinedItemRef) {
+ let mut eii = ecx.encode_inlined_item.borrow_mut();
+ let eii: &mut EncodeInlinedItem = &mut *eii;
+ (*eii)(ecx, ebml_w, ii)
+}
+
fn style_fn_family(s: FnStyle) -> char {
match s {
UnsafeFn => 'u',
let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
if inlineable {
- (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
+ encode_inlined_item(ecx, ebml_w, IIItemRef(item));
}
encode_visibility(ebml_w, vis);
ebml_w.end_tag();
encode_path(ebml_w, path);
encode_attributes(ebml_w, item.attrs.as_slice());
if tps_len > 0u || should_inline(item.attrs.as_slice()) {
- (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
+ encode_inlined_item(ecx, ebml_w, IIItemRef(item));
} else {
encode_symbol(ecx, ebml_w, item.id);
}
for v in (*enum_definition).variants.iter() {
encode_variant_id(ebml_w, local_def(v.node.id));
}
- (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
+ encode_inlined_item(ecx, ebml_w, IIItemRef(item));
encode_path(ebml_w, path);
// Encode inherent implementations for this enumeration.
needs to know*/
encode_struct_fields(ebml_w, fields.as_slice(), def_id);
- (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
+ encode_inlined_item(ecx, ebml_w, IIItemRef(item));
// Encode inherent implementations for this structure.
encode_inherent_implementations(ecx, ebml_w, def_id);
encode_bounds_and_type(ebml_w, ecx, &tpt);
}
encode_method_sort(ebml_w, 'p');
- (ecx.encode_inlined_item)(
- ecx, ebml_w, IIMethodRef(def_id, true, m));
+ encode_inlined_item(ecx, ebml_w,
+ IIMethodRef(def_id, true, m));
}
}
&lookup_item_type(ecx.tcx,local_def(nitem.id)));
encode_name(ebml_w, nitem.ident.name);
if abi == abi::RustIntrinsic {
- (ecx.encode_inlined_item)(ecx, ebml_w, IIForeignRef(nitem));
+ encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
} else {
encode_symbol(ecx, ebml_w, nitem.id);
}
}
}
-struct MacroDefVisitor<'a, 'b> {
- ecx: &'a EncodeContext<'a>,
- ebml_w: &'a mut Encoder<'b>
+struct MacroDefVisitor<'a, 'b, 'c> {
+ ecx: &'a EncodeContext<'b>,
+ ebml_w: &'a mut Encoder<'c>
}
-impl<'a, 'b> Visitor<()> for MacroDefVisitor<'a, 'b> {
+impl<'a, 'b, 'c> Visitor<()> for MacroDefVisitor<'a, 'b, 'c> {
fn visit_item(&mut self, item: &Item, _: ()) {
match item.node {
ItemMac(..) => {
}
}
-fn encode_macro_defs(ecx: &EncodeContext,
- krate: &Crate,
- ebml_w: &mut Encoder) {
+fn encode_macro_defs<'a>(ecx: &'a EncodeContext,
+ krate: &Crate,
+ ebml_w: &'a mut Encoder) {
ebml_w.start_tag(tag_exported_macros);
{
let mut visitor = MacroDefVisitor {
ebml_w.end_tag();
}
-struct ImplVisitor<'a,'b> {
- ecx: &'a EncodeContext<'a>,
- ebml_w: &'a mut Encoder<'b>,
+struct ImplVisitor<'a,'b,'c> {
+ ecx: &'a EncodeContext<'b>,
+ ebml_w: &'a mut Encoder<'c>,
}
-impl<'a,'b> Visitor<()> for ImplVisitor<'a,'b> {
+impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
fn visit_item(&mut self, item: &Item, _: ()) {
match item.node {
ItemImpl(_, Some(ref trait_ref), _, _) => {
/// * Destructors (implementations of the Drop trait).
///
/// * Implementations of traits not defined in this crate.
-fn encode_impls(ecx: &EncodeContext,
- krate: &Crate,
- ebml_w: &mut Encoder) {
+fn encode_impls<'a>(ecx: &'a EncodeContext,
+ krate: &Crate,
+ ebml_w: &'a mut Encoder) {
ebml_w.start_tag(tag_impls);
{
ebml_w.end_tag();
}
+fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
+ ebml_w.start_tag(tag_crate_triple);
+ ebml_w.writer.write(triple.as_bytes());
+ ebml_w.end_tag();
+}
+
// NB: Increment this as you change the metadata encoding version.
pub static metadata_encoding_version : &'static [u8] =
&[0x72, //'r' as u8,
non_inlineable_statics: non_inlineable_statics,
link_meta: link_meta,
cstore: cstore,
- encode_inlined_item: encode_inlined_item,
+ encode_inlined_item: RefCell::new(encode_inlined_item),
type_abbrevs: RefCell::new(HashMap::new()),
};
let mut ebml_w = writer::Encoder(wr);
encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
+ encode_crate_triple(&mut ebml_w, tcx.sess.targ_cfg.target_strs.target_triple);
encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
let mut i = ebml_w.writer.tell().unwrap();
pub struct FileSearch<'a> {
pub sysroot: &'a Path,
pub addl_lib_search_paths: &'a RefCell<HashSet<Path>>,
- pub target_triple: &'a str
+ pub triple: &'a str,
}
impl<'a> FileSearch<'a> {
visited_dirs.insert(path.as_vec().to_owned());
}
- debug!("filesearch: searching target lib path");
+ debug!("filesearch: searching lib path");
let tlib_path = make_target_lib_path(self.sysroot,
- self.target_triple);
+ self.triple);
if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
match f(&tlib_path) {
FileMatches => found = true,
FileDoesntMatch => ()
}
}
+
visited_dirs.insert(tlib_path.as_vec().to_owned());
// Try RUST_PATH
if !found {
let rustpath = rust_path();
for path in rustpath.iter() {
- let tlib_path = make_rustpkg_target_lib_path(
- self.sysroot, path, self.target_triple);
+ let tlib_path = make_rustpkg_lib_path(
+ self.sysroot, path, self.triple);
debug!("is {} in visited_dirs? {:?}", tlib_path.display(),
visited_dirs.contains_equiv(&tlib_path.as_vec().to_owned()));
}
}
- pub fn get_target_lib_path(&self) -> Path {
- make_target_lib_path(self.sysroot, self.target_triple)
+ pub fn get_lib_path(&self) -> Path {
+ make_target_lib_path(self.sysroot, self.triple)
}
pub fn search(&self, pick: pick) {
match fs::readdir(lib_search_path) {
Ok(files) => {
let mut rslt = FileDoesntMatch;
- let is_rlib = |p: & &Path| {
+ fn is_rlib(p: & &Path) -> bool {
p.extension_str() == Some("rlib")
- };
+ }
// Reading metadata out of rlibs is faster, and if we find both
// an rlib and a dylib we only read one of the files of
// metadata, so in the name of speed, bring all rlib files to
}
pub fn new(sysroot: &'a Path,
- target_triple: &'a str,
+ triple: &'a str,
addl_lib_search_paths: &'a RefCell<HashSet<Path>>) -> FileSearch<'a> {
- debug!("using sysroot = {}", sysroot.display());
+ debug!("using sysroot = {}, triple = {}", sysroot.display(), triple);
FileSearch {
sysroot: sysroot,
addl_lib_search_paths: addl_lib_search_paths,
- target_triple: target_triple
+ triple: triple,
}
}
}
sysroot.join(&relative_target_lib_path(sysroot, target_triple))
}
-fn make_rustpkg_target_lib_path(sysroot: &Path,
- dir: &Path,
- target_triple: &str) -> Path {
+fn make_rustpkg_lib_path(sysroot: &Path,
+ dir: &Path,
+ triple: &str) -> Path {
let mut p = dir.join(find_libdir(sysroot));
- p.push(target_triple);
+ p.push(triple);
p
}
use metadata::cstore::{MetadataBlob, MetadataVec, MetadataArchive};
use metadata::decoder;
use metadata::encoder;
-use metadata::filesearch::{FileMatches, FileDoesntMatch};
+use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
use syntax::codemap::Span;
use syntax::diagnostic::SpanHandler;
-use syntax::parse::token::IdentInterner;
use syntax::crateid::CrateId;
use syntax::attr::AttrMetaMethods;
use std::io;
use std::os::consts::{macos, freebsd, linux, android, win32};
use std::ptr;
-use std::rc::Rc;
use std::slice;
use std::str;
OsFreebsd
}
-pub struct HashMismatch {
+pub struct CrateMismatch {
path: Path,
+ got: ~str,
}
pub struct Context<'a> {
pub crate_id: &'a CrateId,
pub id_hash: &'a str,
pub hash: Option<&'a Svh>,
+ pub triple: &'a str,
pub os: Os,
- pub intr: Rc<IdentInterner>,
- pub rejected_via_hash: Vec<HashMismatch>
+ pub filesearch: FileSearch<'a>,
+ pub root: &'a Option<CratePaths>,
+ pub rejected_via_hash: Vec<CrateMismatch>,
+ pub rejected_via_triple: Vec<CrateMismatch>,
}
pub struct Library {
}
impl<'a> Context<'a> {
- pub fn load_library_crate(&mut self, root: &Option<CratePaths>) -> Library {
+ pub fn maybe_load_library_crate(&mut self) -> Option<Library> {
+ self.find_library_crate()
+ }
+
+ pub fn load_library_crate(&mut self) -> Library {
match self.find_library_crate() {
Some(t) => t,
None => {
- self.sess.abort_if_errors();
- let message = if self.rejected_via_hash.len() > 0 {
- format!("found possibly newer version of crate `{}`",
- self.ident)
- } else {
- format!("can't find crate for `{}`", self.ident)
- };
- let message = match root {
- &None => message,
- &Some(ref r) => format!("{} which `{}` depends on",
- message, r.ident)
- };
- self.sess.span_err(self.span, message);
-
- if self.rejected_via_hash.len() > 0 {
- self.sess.span_note(self.span, "perhaps this crate needs \
- to be recompiled?");
- let mismatches = self.rejected_via_hash.iter();
- for (i, &HashMismatch{ ref path }) in mismatches.enumerate() {
+ self.report_load_errs();
+ unreachable!()
+ }
+ }
+ }
+
+ pub fn report_load_errs(&mut self) {
+ let message = if self.rejected_via_hash.len() > 0 {
+ format!("found possibly newer version of crate `{}`",
+ self.ident)
+ } else if self.rejected_via_triple.len() > 0 {
+ format!("found incorrect triple for crate `{}`", self.ident)
+ } else {
+ format!("can't find crate for `{}`", self.ident)
+ };
+ let message = match self.root {
+ &None => message,
+ &Some(ref r) => format!("{} which `{}` depends on",
+ message, r.ident)
+ };
+ self.sess.span_err(self.span, message);
+
+ let mismatches = self.rejected_via_triple.iter();
+ if self.rejected_via_triple.len() > 0 {
+ self.sess.span_note(self.span, format!("expected triple of {}", self.triple));
+ for (i, &CrateMismatch{ ref path, ref got }) in mismatches.enumerate() {
+ self.sess.fileline_note(self.span,
+ format!("crate `{}` path \\#{}, triple {}: {}",
+ self.ident, i+1, got, path.display()));
+ }
+ }
+ if self.rejected_via_hash.len() > 0 {
+ self.sess.span_note(self.span, "perhaps this crate needs \
+ to be recompiled?");
+ let mismatches = self.rejected_via_hash.iter();
+ for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() {
+ self.sess.fileline_note(self.span,
+ format!("crate `{}` path \\#{}: {}",
+ self.ident, i+1, path.display()));
+ }
+ match self.root {
+ &None => {}
+ &Some(ref r) => {
+ for (i, path) in r.paths().iter().enumerate() {
self.sess.fileline_note(self.span,
format!("crate `{}` path \\#{}: {}",
- self.ident, i+1, path.display()));
- }
- match root {
- &None => {}
- &Some(ref r) => {
- for (i, path) in r.paths().iter().enumerate() {
- self.sess.fileline_note(self.span,
- format!("crate `{}` path \\#{}: {}",
- r.ident, i+1, path.display()));
- }
- }
+ r.ident, i+1, path.display()));
}
}
- self.sess.abort_if_errors();
- unreachable!()
}
}
+ self.sess.abort_if_errors();
}
fn find_library_crate(&mut self) -> Option<Library> {
- let filesearch = self.sess.filesearch();
let (dyprefix, dysuffix) = self.dylibname();
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
// of the crate id (path/name/id).
//
// The goal of this step is to look at as little metadata as possible.
- filesearch.search(|path| {
+ self.filesearch.search(|path| {
let file = match path.filename_str() {
None => return FileDoesntMatch,
Some(file) => file,
};
+ info!("file: {}", file);
if file.starts_with(rlib_prefix) && file.ends_with(".rlib") {
info!("rlib candidate: {}", path.display());
match self.try_match(file, rlib_prefix, ".rlib") {
fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> bool {
match decoder::maybe_get_crate_id(crate_data) {
Some(ref id) if self.crate_id.matches(id) => {}
- _ => return false
+ _ => { info!("Rejecting via crate_id"); return false }
}
let hash = match decoder::maybe_get_crate_hash(crate_data) {
- Some(hash) => hash, None => return false
+ Some(hash) => hash, None => {
+ info!("Rejecting via lack of crate hash");
+ return false;
+ }
};
+
+ let triple = decoder::get_crate_triple(crate_data);
+ if triple.as_slice() != self.triple {
+ info!("Rejecting via crate triple: expected {} got {}", self.triple, triple);
+ self.rejected_via_triple.push(CrateMismatch{ path: libpath.clone(),
+ got: triple.to_owned() });
+ return false;
+ }
+
match self.hash {
None => true,
Some(myhash) => {
if *myhash != hash {
- self.rejected_via_hash.push(HashMismatch{ path: libpath.clone() });
+ info!("Rejecting via hash: expected {} got {}", *myhash, hash);
+ self.rejected_via_hash.push(CrateMismatch{ path: libpath.clone(),
+ got: myhash.as_str().to_owned() });
false
} else {
true
}
}
+
// Returns the corresponding (prefix, suffix) that files need to have for
// dynamic libraries
fn dylibname(&self) -> (&'static str, &'static str) {
OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
}
}
+
}
pub fn note_crateid_attr(diag: &SpanHandler, crateid: &CrateId) {
self.bccx.loan_path_to_str(&*old_loan.loan_path))
}
- AddrOf | AutoRef | RefBinding => {
+ AddrOf | AutoRef | RefBinding | ClosureInvocation => {
format!("previous borrow of `{}` occurs here",
self.bccx.loan_path_to_str(&*old_loan.loan_path))
}
visit::walk_expr(this, ex, ());
}
+ ast::ExprCall(f, _) => {
+ let expr_ty = ty::expr_ty_adjusted(tcx, f);
+ match ty::get(expr_ty).sty {
+ ty::ty_closure(~ty::ClosureTy {
+ store: ty::RegionTraitStore(..), ..
+ }) => {
+ let scope_r = ty::ReScope(ex.id);
+ let base_cmt = this.bccx.cat_expr(f);
+ this.guarantee_valid_kind(f.id,
+ f.span,
+ base_cmt,
+ ty::UniqueImmBorrow,
+ scope_r,
+ ClosureInvocation);
+ }
+ _ => {}
+ }
+ visit::walk_expr(this, ex, ());
+ }
+
_ => {
visit::walk_expr(this, ex, ());
}
AddrOf,
AutoRef,
RefBinding,
+ ClosureInvocation,
}
#[deriving(Eq, TotalEq, Hash)]
AddrOf | RefBinding | AutoRef => {
format!("cannot borrow {} as mutable", descr)
}
+ ClosureInvocation => {
+ self.tcx.sess.span_bug(err.span,
+ "err_mutbl with a closure invocation");
+ }
}
}
err_out_of_root_scope(..) => {
BorrowViolation(RefBinding) => {
"cannot borrow data mutably"
}
+
+ BorrowViolation(ClosureInvocation) => {
+ "closure invocation"
+ }
};
match cause {
fn is_camel_case(ident: ast::Ident) -> bool {
let ident = token::get_ident(ident);
assert!(!ident.get().is_empty());
- let ident = ident.get().trim_chars(&'_');
+ let ident = ident.get().trim_chars('_');
// start with a non-lowercase letter rather than non-uppercase
// ones (some scripts don't have a concept of upper/lowercase)
/// control over anything so this forbids any mention of any visibility
fn check_all_inherited(&self, item: &ast::Item) {
let tcx = self.tcx;
- let check_inherited = |sp: Span, vis: ast::Visibility| {
+ fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
if vis != ast::Inherited {
tcx.sess.span_err(sp, "visibility has no effect inside functions");
}
- };
+ }
let check_struct = |def: &@ast::StructDef| {
for f in def.fields.iter() {
match f.node.kind {
- ast::NamedField(_, p) => check_inherited(f.span, p),
+ ast::NamedField(_, p) => check_inherited(tcx, f.span, p),
ast::UnnamedField(..) => {}
}
}
};
- check_inherited(item.span, item.vis);
+ check_inherited(tcx, item.span, item.vis);
match item.node {
ast::ItemImpl(_, _, _, ref methods) => {
for m in methods.iter() {
- check_inherited(m.span, m.vis);
+ check_inherited(tcx, m.span, m.vis);
}
}
ast::ItemForeignMod(ref fm) => {
for i in fm.items.iter() {
- check_inherited(i.span, i.vis);
+ check_inherited(tcx, i.span, i.vis);
}
}
ast::ItemEnum(ref def, _) => {
for v in def.variants.iter() {
- check_inherited(v.span, v.node.vis);
+ check_inherited(tcx, v.span, v.node.vis);
match v.node.kind {
ast::StructVariantKind(ref s) => check_struct(s),
for m in methods.iter() {
match *m {
ast::Required(..) => {}
- ast::Provided(ref m) => check_inherited(m.span, m.vis),
+ ast::Provided(ref m) => check_inherited(tcx, m.span,
+ m.vis),
}
}
}
ty::ty_bare_fn(..) => { }
ty::ty_closure(ref closure_ty) => {
let region = match closure_ty.store {
- ty::RegionTraitStore(r, _) => r,
+ ty::RegionTraitStore(r, _) => {
+ // While we're here, link the closure's region with a unique
+ // immutable borrow (gathered later in borrowck)
+ let mc = mc::MemCategorizationContext { typer: &*rcx };
+ let expr_cmt = ignore_err!(mc.cat_expr(callee_expr));
+ link_region(mc.typer, callee_expr.span, call_region,
+ ty::UniqueImmBorrow, expr_cmt);
+ r
+ }
ty::UniqTraitStore => ty::ReStatic
};
rcx.fcx.mk_subr(true, infer::InvokeClosure(callee_expr.span),
{
let mc = mc::MemCategorizationContext { typer: &*rcx };
let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
- link_region(mc.typer, deref_expr.span, r, m, self_cmt);
+ link_region(mc.typer, deref_expr.span, r,
+ ty::BorrowKind::from_mutbl(m), self_cmt);
}
// Specialized version of constrain_call.
match mc.cat_slice_pattern(sub_cmt, slice_pat) {
Ok((slice_cmt, slice_mutbl, slice_r)) => {
link_region(mc.typer, sub_pat.span, slice_r,
- slice_mutbl, slice_cmt);
+ ty::BorrowKind::from_mutbl(slice_mutbl),
+ slice_cmt);
}
Err(()) => {}
}
match *autoref {
ty::AutoPtr(r, m) => {
- link_region(mc.typer, expr.span, r, m, expr_cmt);
+ link_region(mc.typer, expr.span, r,
+ ty::BorrowKind::from_mutbl(m), expr_cmt);
}
ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => {
let cmt_index = mc.cat_index(expr, expr_cmt, autoderefs+1);
- link_region(mc.typer, expr.span, r, m, cmt_index);
+ link_region(mc.typer, expr.span, r,
+ ty::BorrowKind::from_mutbl(m), cmt_index);
}
ty::AutoBorrowObj(r, m) => {
let cmt_deref = mc.cat_deref_obj(expr, expr_cmt);
- link_region(mc.typer, expr.span, r, m, cmt_deref);
+ link_region(mc.typer, expr.span, r,
+ ty::BorrowKind::from_mutbl(m), cmt_deref);
}
ty::AutoUnsafe(_) => {}
let mc = mc::MemCategorizationContext { typer: rcx };
let expr_cmt = ignore_err!(mc.cat_expr(expr));
let region_min = ty::ReScope(callee_scope);
- link_region(mc.typer, expr.span, region_min, ast::MutImmutable, expr_cmt);
+ link_region(mc.typer, expr.span, region_min, ty::ImmBorrow, expr_cmt);
}
fn link_region_from_node_type(rcx: &Rcx,
let tcx = rcx.fcx.ccx.tcx;
debug!("rptr_ty={}", ty_to_str(tcx, rptr_ty));
let r = ty::ty_region(tcx, span, rptr_ty);
- link_region(rcx, span, r, mutbl, cmt_borrowed);
+ link_region(rcx, span, r, ty::BorrowKind::from_mutbl(mutbl),
+ cmt_borrowed);
}
}
fn link_region(rcx: &Rcx,
span: Span,
region_min: ty::Region,
- mutbl: ast::Mutability,
+ kind: ty::BorrowKind,
cmt_borrowed: mc::cmt) {
/*!
* Informs the inference engine that a borrow of `cmt`
- * must have mutability `mutbl` and lifetime `region_min`.
+ * must have the borrow kind `kind` and lifetime `region_min`.
* If `cmt` is a deref of a region pointer with
* lifetime `r_borrowed`, this will add the constraint that
* `region_min <= r_borrowed`.
// for the lifetime `region_min` for the borrow to be valid:
let mut cmt_borrowed = cmt_borrowed;
loop {
- debug!("link_region(region_min={}, mutbl={}, cmt_borrowed={})",
+ debug!("link_region(region_min={}, kind={}, cmt_borrowed={})",
region_min.repr(rcx.tcx()),
- mutbl.repr(rcx.tcx()),
+ kind.repr(rcx.tcx()),
cmt_borrowed.repr(rcx.tcx()));
match cmt_borrowed.cat.clone() {
mc::cat_deref(base, _, mc::BorrowedPtr(_, r_borrowed)) => {
adjust_upvar_borrow_kind_for_loan(
*upvar_id,
upvar_borrow,
- mutbl);
+ kind);
infer::ReborrowUpvar(span, *upvar_id)
}
None => {
r_borrowed.repr(rcx.tcx()));
rcx.fcx.mk_subr(true, cause, region_min, r_borrowed);
- if mutbl == ast::MutMutable {
+ if kind != ty::ImmBorrow {
// If this is a mutable borrow, then the thing
// being borrowed will have to be unique.
// In user code, this means it must be an `&mut`
fn adjust_upvar_borrow_kind_for_loan(upvar_id: ty::UpvarId,
upvar_borrow: &mut ty::UpvarBorrow,
- mutbl: ast::Mutability) {
+ kind: ty::BorrowKind) {
debug!("adjust_upvar_borrow_kind_for_loan: upvar_id={:?} kind={:?} -> {:?}",
- upvar_id, upvar_borrow.kind, mutbl);
+ upvar_id, upvar_borrow.kind, kind);
- adjust_upvar_borrow_kind(upvar_id, upvar_borrow,
- ty::BorrowKind::from_mutbl(mutbl))
+ adjust_upvar_borrow_kind(upvar_id, upvar_borrow, kind)
}
fn adjust_upvar_borrow_kind(upvar_id: ty::UpvarId,
pub struct TcpAcceptor {
listener: ~TcpListener,
+ timer: Option<TimerWatcher>,
+ timeout_tx: Option<Sender<()>>,
+ timeout_rx: Option<Receiver<()>>,
}
// TCP watchers (clients/streams)
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, status: c_int) {
+ assert_eq!(status, 0);
+ 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(());
+ }
+ }
}
////////////////////////////////////////////////////////////////////////////////
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) {
}
// Return result of first successful parser
- fn read_or<T>(&mut self, parsers: &[|&mut Parser| -> Option<T>])
+ fn read_or<T>(&mut self, parsers: &mut [|&mut Parser| -> Option<T>])
-> Option<T> {
- for pf in parsers.iter() {
+ for pf in parsers.mut_iter() {
match self.read_atomically(|p: &mut Parser| (*pf)(p)) {
Some(r) => return Some(r),
None => {}
fn read_ip_addr(&mut self) -> Option<IpAddr> {
let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr();
let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr();
- self.read_or([ipv4_addr, ipv6_addr])
+ self.read_or(&mut [ipv4_addr, ipv6_addr])
}
fn read_socket_addr(&mut self) -> Option<SocketAddr> {
p.read_seq_3::<char, IpAddr, char>(open_br, ip_addr, clos_br)
.map(|t| match t { (_, ip, _) => ip })
};
- p.read_or([ipv4_p, ipv6_p])
+ p.read_or(&mut [ipv4_p, ipv6_p])
};
let colon = |p: &mut Parser| p.read_given_char(':');
let port = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16);
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();
+ })
}
fn indexable(&self) -> uint;
/// Return an element at an index
- fn idx(&self, index: uint) -> Option<A>;
+ fn idx(&mut self, index: uint) -> Option<A>;
}
/// An iterator that knows its exact length
#[inline]
fn indexable(&self) -> uint { self.iter.indexable() }
#[inline]
- fn idx(&self, index: uint) -> Option<A> {
- self.iter.idx(self.indexable() - index - 1)
+ fn idx(&mut self, index: uint) -> Option<A> {
+ let amt = self.indexable();
+ self.iter.idx(amt - index - 1)
}
}
}
#[inline]
- fn idx(&self, index: uint) -> Option<A> {
+ fn idx(&mut self, index: uint) -> Option<A> {
let liter = self.iter.indexable();
let lorig = self.orig.indexable();
if lorig == 0 {
}
#[inline]
- fn idx(&self, index: uint) -> Option<A> {
+ fn idx(&mut self, index: uint) -> Option<A> {
let len = self.a.indexable();
if index < len {
self.a.idx(index)
}
#[inline]
- fn idx(&self, index: uint) -> Option<(A, B)> {
+ fn idx(&mut self, index: uint) -> Option<(A, B)> {
match self.a.idx(index) {
None => None,
Some(x) => match self.b.idx(index) {
impl<'a, A, B, T> Map<'a, A, B, T> {
#[inline]
- fn do_map(&self, elt: Option<A>) -> Option<B> {
+ fn do_map(&mut self, elt: Option<A>) -> Option<B> {
match elt {
Some(a) => Some((self.f)(a)),
_ => None
}
#[inline]
- fn idx(&self, index: uint) -> Option<B> {
- self.do_map(self.iter.idx(index))
+ fn idx(&mut self, index: uint) -> Option<B> {
+ let elt = self.iter.idx(index);
+ self.do_map(elt)
}
}
}
#[inline]
- fn idx(&self, index: uint) -> Option<(uint, A)> {
+ fn idx(&mut self, index: uint) -> Option<(uint, A)> {
match self.iter.idx(index) {
Some(a) => Some((self.count + index, a)),
_ => None,
}
#[inline]
- fn idx(&self, index: uint) -> Option<A> {
+ fn idx(&mut self, index: uint) -> Option<A> {
if index >= self.indexable() {
None
} else {
}
#[inline]
- fn idx(&self, index: uint) -> Option<A> {
+ fn idx(&mut self, index: uint) -> Option<A> {
if index >= self.n {
None
} else {
}
#[inline]
- fn idx(&self, index: uint) -> Option<A> {
+ fn idx(&mut self, index: uint) -> Option<A> {
self.iter.idx(index)
}
}
impl<'a, A, T> Inspect<'a, A, T> {
#[inline]
- fn do_inspect(&self, elt: Option<A>) -> Option<A> {
+ fn do_inspect(&mut self, elt: Option<A>) -> Option<A> {
match elt {
Some(ref a) => (self.f)(a),
None => ()
}
#[inline]
- fn idx(&self, index: uint) -> Option<A> {
- self.do_inspect(self.iter.idx(index))
+ fn idx(&mut self, index: uint) -> Option<A> {
+ let element = self.iter.idx(index);
+ self.do_inspect(element)
}
}
#[inline]
fn indexable(&self) -> uint { uint::MAX }
#[inline]
- fn idx(&self, _: uint) -> Option<A> { Some(self.element.clone()) }
+ fn idx(&mut self, _: uint) -> Option<A> { Some(self.element.clone()) }
}
/// Functions for lexicographical ordering of sequences.
let xs = [1, 2, 3, 4, 5];
// test .map and .inspect that don't implement Clone
- let it = xs.iter().inspect(|_| {});
+ let mut it = xs.iter().inspect(|_| {});
assert_eq!(xs.len(), it.indexable());
for (i, elt) in xs.iter().enumerate() {
assert_eq!(Some(elt), it.idx(i));
fn test_random_access_map() {
let xs = [1, 2, 3, 4, 5];
- let it = xs.iter().map(|x| *x);
+ let mut it = xs.iter().map(|x| *x);
assert_eq!(xs.len(), it.indexable());
for (i, elt) in xs.iter().enumerate() {
assert_eq!(Some(*elt), it.idx(i));
// String conversion functions and impl str -> num
/// Parse a byte slice as a number in the given base.
+///
+/// Yields an `Option` because `buf` may or may not actually be parseable.
+///
+/// # Examples
+///
+/// ```rust
+/// let digits = [49,50,51,52,53,54,55,56,57];
+/// let base = 10;
+/// let num = std::i64::parse_bytes(digits, base);
+/// ```
#[inline]
pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> {
strconv::from_str_bytes_common(buf, radix, true, false, false,
// String conversion functions and impl str -> num
/// Parse a byte slice as a number in the given base.
+///
+/// Yields an `Option` because `buf` may or may not actually be parseable.
+///
+/// # Examples
+///
+/// ```rust
+/// let digits = [49,50,51,52,53,54,55,56,57];
+/// let base = 10;
+/// let num = std::i64::parse_bytes(digits, base);
+/// ```
#[inline]
pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> {
strconv::from_str_bytes_common(buf, radix, false, false, false,
assert_eq!(v, None);
// test that it does not take more elements than it needs
- let functions = [|| Some(()), || None, || fail!()];
+ let mut functions = [|| Some(()), || None, || fail!()];
- let v: Option<~[()]> = collect(functions.iter().map(|f| (*f)()));
+ let v: Option<~[()]> = collect(functions.mut_iter().map(|f| (*f)()));
assert_eq!(v, None);
}
}
}
-#[allow(missing_doc)]
+#[doc(hidden)]
trait RcBoxPtr<T> {
fn inner<'a>(&'a self) -> &'a RcBox<T>;
assert_eq!(v, Err(2));
// test that it does not take more elements than it needs
- let functions = [|| Ok(()), || Err(1), || fail!()];
+ let mut functions = [|| Ok(()), || Err(1), || fail!()];
- let v: Result<~[()], int> = collect(functions.iter().map(|f| (*f)()));
+ let v: Result<~[()], int> = collect(functions.mut_iter().map(|f| (*f)()));
assert_eq!(v, Err(1));
}
Err(2));
// test that it does not take more elements than it needs
- let functions = [|| Ok(()), || Err(1), || fail!()];
+ let mut functions = [|| Ok(()), || Err(1), || fail!()];
- assert_eq!(fold_(functions.iter()
+ assert_eq!(fold_(functions.mut_iter()
.map(|f| (*f)())),
Err(1));
}
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 {
/// This function is *not* meant to be abused as a "try/catch" block. This
/// is meant to be used at the absolute boundaries of a task's lifetime, and
/// only for that purpose.
- pub fn run(~self, f: ||) -> ~Task {
+ pub fn run(~self, mut f: ||) -> ~Task {
// Need to put ourselves into TLS, but also need access to the unwinder.
// Unsafely get a handle to the task so we can continue to use it after
// putting it in tls (so we can invoke the unwinder).
return Some(self.v);
}
- let pred = &mut self.pred;
- match self.v.iter().rposition(|x| (*pred)(x)) {
+ match self.v.iter().rposition(|x| (self.pred)(x)) {
None => {
self.finished = true;
Some(self.v)
}
#[inline]
- fn idx(&self, index: uint) -> Option<&'a [T]> {
+ fn idx(&mut self, index: uint) -> Option<&'a [T]> {
if index < self.indexable() {
let lo = index * self.size;
let mut hi = lo + self.size;
}
#[inline]
- fn idx(&self, index: uint) -> Option<&'a T> {
+ fn idx(&mut self, index: uint) -> Option<&'a T> {
unsafe {
if index < self.indexable() {
transmute(self.ptr.offset(index as int))
fn next(&mut self) -> Option<&'a mut [T]> {
if self.finished { return None; }
- match self.v.iter().position(|x| (self.pred)(x)) {
+ let pred = &mut self.pred;
+ match self.v.iter().position(|x| (*pred)(x)) {
None => {
self.finished = true;
let tmp = mem::replace(&mut self.v, &mut []);
fn next_back(&mut self) -> Option<&'a mut [T]> {
if self.finished { return None; }
- match self.v.iter().rposition(|x| (self.pred)(x)) {
+ let pred = &mut self.pred;
+ match self.v.iter().rposition(|x| (*pred)(x)) {
None => {
self.finished = true;
let tmp = mem::replace(&mut self.v, &mut []);
assert_eq!(v.chunks(6).collect::<~[&[int]]>(), ~[&[1i,2,3,4,5]]);
assert_eq!(v.chunks(2).rev().collect::<~[&[int]]>(), ~[&[5i], &[3,4], &[1,2]]);
- let it = v.chunks(2);
+ let mut it = v.chunks(2);
assert_eq!(it.indexable(), 3);
assert_eq!(it.idx(0).unwrap(), &[1,2]);
assert_eq!(it.idx(1).unwrap(), &[3,4]);
/// Something that can be used to compare against a character
pub trait CharEq {
/// Determine if the splitter should split at the given character
- fn matches(&self, char) -> bool;
+ fn matches(&mut self, char) -> bool;
/// Indicate if this is only concerned about ASCII characters,
/// which can allow for a faster implementation.
fn only_ascii(&self) -> bool;
impl CharEq for char {
#[inline]
- fn matches(&self, c: char) -> bool { *self == c }
+ fn matches(&mut self, c: char) -> bool { *self == c }
#[inline]
fn only_ascii(&self) -> bool { (*self as uint) < 128 }
impl<'a> CharEq for |char|: 'a -> bool {
#[inline]
- fn matches(&self, c: char) -> bool { (*self)(c) }
+ fn matches(&mut self, c: char) -> bool { (*self)(c) }
#[inline]
fn only_ascii(&self) -> bool { false }
impl CharEq for extern "Rust" fn(char) -> bool {
#[inline]
- fn matches(&self, c: char) -> bool { (*self)(c) }
+ fn matches(&mut self, c: char) -> bool { (*self)(c) }
#[inline]
fn only_ascii(&self) -> bool { false }
}
-impl<'a, C: CharEq> CharEq for &'a [C] {
+impl<'a> CharEq for &'a [char] {
#[inline]
- fn matches(&self, c: char) -> bool {
- self.iter().any(|m| m.matches(c))
+ fn matches(&mut self, c: char) -> bool {
+ self.iter().any(|&mut m| m.matches(c))
}
#[inline]
/// # Example
///
/// ```rust
- /// assert_eq!("11foo1bar11".trim_chars(&'1'), "foo1bar")
- /// assert_eq!("12foo1bar12".trim_chars(& &['1', '2']), "foo1bar")
- /// assert_eq!("123foo1bar123".trim_chars(&|c: char| c.is_digit()), "foo1bar")
+ /// assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar")
+ /// assert_eq!("12foo1bar12".trim_chars(&['1', '2']), "foo1bar")
+ /// assert_eq!("123foo1bar123".trim_chars(|c: char| c.is_digit()), "foo1bar")
/// ```
- fn trim_chars<C: CharEq>(&self, to_trim: &C) -> &'a str;
+ fn trim_chars<C: CharEq>(&self, to_trim: C) -> &'a str;
/// Returns a string with leading `chars_to_trim` removed.
///
/// # Example
///
/// ```rust
- /// assert_eq!("11foo1bar11".trim_left_chars(&'1'), "foo1bar11")
- /// assert_eq!("12foo1bar12".trim_left_chars(& &['1', '2']), "foo1bar12")
- /// assert_eq!("123foo1bar123".trim_left_chars(&|c: char| c.is_digit()), "foo1bar123")
+ /// assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11")
+ /// assert_eq!("12foo1bar12".trim_left_chars(&['1', '2']), "foo1bar12")
+ /// assert_eq!("123foo1bar123".trim_left_chars(|c: char| c.is_digit()), "foo1bar123")
/// ```
- fn trim_left_chars<C: CharEq>(&self, to_trim: &C) -> &'a str;
+ fn trim_left_chars<C: CharEq>(&self, to_trim: C) -> &'a str;
/// Returns a string with trailing `chars_to_trim` removed.
///
/// # Example
///
/// ```rust
- /// assert_eq!("11foo1bar11".trim_right_chars(&'1'), "11foo1bar")
- /// assert_eq!("12foo1bar12".trim_right_chars(& &['1', '2']), "12foo1bar")
- /// assert_eq!("123foo1bar123".trim_right_chars(&|c: char| c.is_digit()), "123foo1bar")
+ /// assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar")
+ /// assert_eq!("12foo1bar12".trim_right_chars(&['1', '2']), "12foo1bar")
+ /// assert_eq!("123foo1bar123".trim_right_chars(|c: char| c.is_digit()), "123foo1bar")
/// ```
- fn trim_right_chars<C: CharEq>(&self, to_trim: &C) -> &'a str;
+ fn trim_right_chars<C: CharEq>(&self, to_trim: C) -> &'a str;
/// Replace all occurrences of one string with another.
///
#[inline]
fn trim_left(&self) -> &'a str {
- self.trim_left_chars(&char::is_whitespace)
+ self.trim_left_chars(char::is_whitespace)
}
#[inline]
fn trim_right(&self) -> &'a str {
- self.trim_right_chars(&char::is_whitespace)
+ self.trim_right_chars(char::is_whitespace)
}
#[inline]
- fn trim_chars<C: CharEq>(&self, to_trim: &C) -> &'a str {
- self.trim_left_chars(to_trim).trim_right_chars(to_trim)
+ fn trim_chars<C: CharEq>(&self, mut to_trim: C) -> &'a str {
+ let cur = match self.find(|c: char| !to_trim.matches(c)) {
+ None => "",
+ Some(i) => unsafe { raw::slice_bytes(*self, i, self.len()) }
+ };
+ match cur.rfind(|c: char| !to_trim.matches(c)) {
+ None => "",
+ Some(i) => {
+ let right = cur.char_range_at(i).next;
+ unsafe { raw::slice_bytes(cur, 0, right) }
+ }
+ }
}
#[inline]
- fn trim_left_chars<C: CharEq>(&self, to_trim: &C) -> &'a str {
+ fn trim_left_chars<C: CharEq>(&self, mut to_trim: C) -> &'a str {
match self.find(|c: char| !to_trim.matches(c)) {
None => "",
Some(first) => unsafe { raw::slice_bytes(*self, first, self.len()) }
}
#[inline]
- fn trim_right_chars<C: CharEq>(&self, to_trim: &C) -> &'a str {
+ fn trim_right_chars<C: CharEq>(&self, mut to_trim: C) -> &'a str {
match self.rfind(|c: char| !to_trim.matches(c)) {
None => "",
Some(last) => {
unsafe { cast::transmute(*self) }
}
- fn find<C: CharEq>(&self, search: C) -> Option<uint> {
+ fn find<C: CharEq>(&self, mut search: C) -> Option<uint> {
if search.only_ascii() {
self.bytes().position(|b| search.matches(b as char))
} else {
}
}
- fn rfind<C: CharEq>(&self, search: C) -> Option<uint> {
+ fn rfind<C: CharEq>(&self, mut search: C) -> Option<uint> {
if search.only_ascii() {
self.bytes().rposition(|b| search.matches(b as char))
} else {
#[test]
fn test_trim_left_chars() {
let v: &[char] = &[];
- assert_eq!(" *** foo *** ".trim_left_chars(&v), " *** foo *** ");
- assert_eq!(" *** foo *** ".trim_left_chars(& &['*', ' ']), "foo *** ");
- assert_eq!(" *** *** ".trim_left_chars(& &['*', ' ']), "");
- assert_eq!("foo *** ".trim_left_chars(& &['*', ' ']), "foo *** ");
+ assert_eq!(" *** foo *** ".trim_left_chars(v), " *** foo *** ");
+ assert_eq!(" *** foo *** ".trim_left_chars(&['*', ' ']), "foo *** ");
+ assert_eq!(" *** *** ".trim_left_chars(&['*', ' ']), "");
+ assert_eq!("foo *** ".trim_left_chars(&['*', ' ']), "foo *** ");
- assert_eq!("11foo1bar11".trim_left_chars(&'1'), "foo1bar11");
- assert_eq!("12foo1bar12".trim_left_chars(& &['1', '2']), "foo1bar12");
- assert_eq!("123foo1bar123".trim_left_chars(&|c: char| c.is_digit()), "foo1bar123");
+ assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11");
+ assert_eq!("12foo1bar12".trim_left_chars(&['1', '2']), "foo1bar12");
+ assert_eq!("123foo1bar123".trim_left_chars(|c: char| c.is_digit()), "foo1bar123");
}
#[test]
fn test_trim_right_chars() {
let v: &[char] = &[];
- assert_eq!(" *** foo *** ".trim_right_chars(&v), " *** foo *** ");
- assert_eq!(" *** foo *** ".trim_right_chars(& &['*', ' ']), " *** foo");
- assert_eq!(" *** *** ".trim_right_chars(& &['*', ' ']), "");
- assert_eq!(" *** foo".trim_right_chars(& &['*', ' ']), " *** foo");
+ assert_eq!(" *** foo *** ".trim_right_chars(v), " *** foo *** ");
+ assert_eq!(" *** foo *** ".trim_right_chars(&['*', ' ']), " *** foo");
+ assert_eq!(" *** *** ".trim_right_chars(&['*', ' ']), "");
+ assert_eq!(" *** foo".trim_right_chars(&['*', ' ']), " *** foo");
- assert_eq!("11foo1bar11".trim_right_chars(&'1'), "11foo1bar");
- assert_eq!("12foo1bar12".trim_right_chars(& &['1', '2']), "12foo1bar");
- assert_eq!("123foo1bar123".trim_right_chars(&|c: char| c.is_digit()), "123foo1bar");
+ assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar");
+ assert_eq!("12foo1bar12".trim_right_chars(&['1', '2']), "12foo1bar");
+ assert_eq!("123foo1bar123".trim_right_chars(|c: char| c.is_digit()), "123foo1bar");
}
#[test]
fn test_trim_chars() {
let v: &[char] = &[];
- assert_eq!(" *** foo *** ".trim_chars(&v), " *** foo *** ");
- assert_eq!(" *** foo *** ".trim_chars(& &['*', ' ']), "foo");
- assert_eq!(" *** *** ".trim_chars(& &['*', ' ']), "");
- assert_eq!("foo".trim_chars(& &['*', ' ']), "foo");
+ assert_eq!(" *** foo *** ".trim_chars(v), " *** foo *** ");
+ assert_eq!(" *** foo *** ".trim_chars(&['*', ' ']), "foo");
+ assert_eq!(" *** *** ".trim_chars(&['*', ' ']), "");
+ assert_eq!("foo".trim_chars(&['*', ' ']), "foo");
- assert_eq!("11foo1bar11".trim_chars(&'1'), "foo1bar");
- assert_eq!("12foo1bar12".trim_chars(& &['1', '2']), "foo1bar");
- assert_eq!("123foo1bar123".trim_chars(&|c: char| c.is_digit()), "foo1bar");
+ assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar");
+ assert_eq!("12foo1bar12".trim_chars(&['1', '2']), "foo1bar");
+ assert_eq!("123foo1bar123".trim_chars(|c: char| c.is_digit()), "foo1bar");
}
#[test]
fn split_unicode_not_ascii(b: &mut Bencher) {
struct NotAscii(char);
impl CharEq for NotAscii {
- fn matches(&self, c: char) -> bool {
+ fn matches(&mut self, c: char) -> bool {
let NotAscii(cc) = *self;
cc == c
}
struct NotAscii(char);
impl CharEq for NotAscii {
#[inline]
- fn matches(&self, c: char) -> bool {
+ fn matches(&mut self, c: char) -> bool {
let NotAscii(cc) = *self;
cc == c
}
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]
#[cfg(test)] use task::failing;
pub trait Finally<T> {
- fn finally(&self, dtor: ||) -> T;
+ fn finally(&mut self, dtor: ||) -> T;
}
impl<'a,T> Finally<T> for ||: 'a -> T {
- fn finally(&self, dtor: ||) -> T {
- try_finally(&mut (), (),
- |_, _| (*self)(),
+ fn finally(&mut self, dtor: ||) -> T {
+ try_finally(&mut (), self,
+ |_, f| (*f)(),
|_| dtor())
}
}
impl<T> Finally<T> for fn() -> T {
- fn finally(&self, dtor: ||) -> T {
+ fn finally(&mut self, dtor: ||) -> T {
try_finally(&mut (), (),
|_, _| (*self)(),
|_| dtor())
#[test]
fn test_retval() {
- let closure: || -> int = || 10;
+ let mut closure: || -> int = || 10;
let i = closure.finally(|| { });
assert_eq!(i, 10);
}
fn test_compact() {
fn do_some_fallible_work() {}
fn but_always_run_this_function() { }
- do_some_fallible_work.finally(
- but_always_run_this_function);
+ let mut f = do_some_fallible_work;
+ f.finally(but_always_run_this_function);
}
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();
ret_ty: Self,
attributes: attrs,
const_nonmatching: false,
- combine_substructure: |c, s, sub| cs_clone("Clone", c, s, sub)
+ combine_substructure: combine_substructure(|c, s, sub| {
+ cs_clone("Clone", c, s, sub)
+ }),
}
)
};
ret_ty: Literal(Path::new(vec!("bool"))),
attributes: attrs,
const_nonmatching: true,
- combine_substructure: $f
+ combine_substructure: combine_substructure(|a, b, c| {
+ $f(a, b, c)
+ })
}
} }
);
ret_ty: Literal(Path::new(vec!("bool"))),
attributes: attrs,
const_nonmatching: false,
- combine_substructure: |cx, span, substr| cs_op($op, $equal, cx, span, substr)
+ combine_substructure: combine_substructure(|cx, span, substr| {
+ cs_op($op, $equal, cx, span, substr)
+ })
}
} }
);
ret_ty: nil_ty(),
attributes: attrs,
const_nonmatching: true,
- combine_substructure: cs_total_eq_assert
+ combine_substructure: combine_substructure(|a, b, c| {
+ cs_total_eq_assert(a, b, c)
+ })
}
)
};
ret_ty: Literal(Path::new(vec!("std", "cmp", "Ordering"))),
attributes: attrs,
const_nonmatching: false,
- combine_substructure: cs_cmp
+ combine_substructure: combine_substructure(|a, b, c| {
+ cs_cmp(a, b, c)
+ }),
}
)
};
vec!(~Self, ~Literal(Path::new_local("__E"))), true)),
attributes: Vec::new(),
const_nonmatching: true,
- combine_substructure: decodable_substructure,
+ combine_substructure: combine_substructure(|a, b, c| {
+ decodable_substructure(a, b, c)
+ }),
})
};
ret_ty: Self,
attributes: attrs,
const_nonmatching: false,
- combine_substructure: default_substructure
+ combine_substructure: combine_substructure(|a, b, c| {
+ default_substructure(a, b, c)
+ })
})
};
trait_def.expand(cx, mitem, item, push)
true)),
attributes: Vec::new(),
const_nonmatching: true,
- combine_substructure: encodable_substructure,
+ combine_substructure: combine_substructure(|a, b, c| {
+ encodable_substructure(a, b, c)
+ }),
})
};
*/
+use std::cell::RefCell;
+
use ast;
use ast::{P, EnumDef, Expr, Ident, Generics, StructDef};
use ast_util;
/// actual enum variants, i.e. can use _ => .. match.
pub const_nonmatching: bool,
- pub combine_substructure: CombineSubstructureFunc<'a>,
+ pub combine_substructure: RefCell<CombineSubstructureFunc<'a>>,
}
/// All the data about the data structure/method being derived upon.
&[@Expr]|: 'a
-> @Expr;
+pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
+ -> RefCell<CombineSubstructureFunc<'a>> {
+ RefCell::new(f)
+}
+
impl<'a> TraitDef<'a> {
pub fn expand(&self,
nonself_args: nonself_args,
fields: fields
};
- (self.combine_substructure)(cx, trait_.span,
- &substructure)
+ let mut f = self.combine_substructure.borrow_mut();
+ let f: &mut CombineSubstructureFunc = &mut *f;
+ (*f)(cx, trait_.span, &substructure)
}
fn get_ret_ty(&self,
ret_ty: nil_ty(),
attributes: attrs,
const_nonmatching: false,
- combine_substructure: hash_substructure
+ combine_substructure: combine_substructure(|a, b, c| {
+ hash_substructure(a, b, c)
+ })
}
)
};
// #[inline] liable to cause code-bloat
attributes: attrs.clone(),
const_nonmatching: false,
- combine_substructure: |c, s, sub| cs_from("i64", c, s, sub),
+ combine_substructure: combine_substructure(|c, s, sub| {
+ cs_from("i64", c, s, sub)
+ }),
},
MethodDef {
name: "from_u64",
// #[inline] liable to cause code-bloat
attributes: attrs,
const_nonmatching: false,
- combine_substructure: |c, s, sub| cs_from("u64", c, s, sub),
+ combine_substructure: combine_substructure(|c, s, sub| {
+ cs_from("u64", c, s, sub)
+ }),
})
};
ret_ty: Self,
attributes: Vec::new(),
const_nonmatching: false,
- combine_substructure: rand_substructure
+ combine_substructure: combine_substructure(|a, b, c| {
+ rand_substructure(a, b, c)
+ })
}
)
};
ret_ty: Literal(Path::new(vec!("std", "fmt", "Result"))),
attributes: Vec::new(),
const_nonmatching: false,
- combine_substructure: show_substructure
+ combine_substructure: combine_substructure(|a, b, c| {
+ show_substructure(a, b, c)
+ })
}
)
};
ret_ty: Self,
attributes: attrs.clone(),
const_nonmatching: false,
- combine_substructure: zero_substructure
+ combine_substructure: combine_substructure(|a, b, c| {
+ zero_substructure(a, b, c)
+ })
},
MethodDef {
name: "is_zero",
ret_ty: Literal(Path::new(vec!("bool"))),
attributes: attrs,
const_nonmatching: false,
- combine_substructure: |cx, span, substr| {
+ combine_substructure: combine_substructure(|cx, span, substr| {
cs_and(|cx, span, _, _| cx.span_bug(span,
"Non-matching enum \
variant in \
deriving(Zero)"),
cx, span, substr)
- }
+ })
}
)
};
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 {
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(),
});
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.
+
+// Ensure that invoking a closure counts as a unique immutable borrow
+
+
+type Fn<'a> = ||:'a;
+
+struct Test<'a> {
+ f: ||: 'a
+}
+
+fn call(f: |Fn|) {
+ f(|| {
+ //~^ ERROR: closure requires unique access to `f` but it is already borrowed
+ f(|| {})
+ });
+}
+
+fn test1() {
+ call(|a| {
+ a();
+ });
+}
+
+fn test2(f: &||) {
+ (*f)(); //~ ERROR: closure invocation in a `&` reference
+}
+
+fn test3(f: &mut ||) {
+ (*f)();
+}
+
+fn test4(f: &Test) {
+ (f.f)() //~ ERROR: closure invocation in a `&` reference
+}
+
+fn test5(f: &mut Test) {
+ (f.f)()
+}
+
+fn test6() {
+ let f = || {};
+ (|| {
+ f();
+ })();
+}
+
+fn test7() {
+ fn foo(_: |g: |int|, b: int|) {}
+ let f = |g: |int|, b: int| {};
+ f(|a| { //~ ERROR: cannot borrow `f` as immutable because previous closure
+ foo(f); //~ ERROR: cannot move out of captured outer variable
+ }, 3);
+}
+
+fn main() {}
// aux-build:macro_crate_test.rs
// ignore-stage1
// ignore-android
-// ignore-cross-compile #12102
#![feature(phase)]
// This struct is needed to create the
// otherwise infinite type of a fn that
// accepts itself as argument:
- c: |&R, bool|: 'a
+ c: |&mut R, bool|: 'a
}
fn innocent_looking_victim() {
match x {
Some(ref msg) => {
(f.c)(f, true);
+ //~^ ERROR: cannot borrow `*f` as mutable because
println!("{:?}", msg);
},
None => fail!("oops"),
})
}
-fn conspirator(f: |&R, bool|) {
- let r = R {c: f};
- f(&r, false) //~ ERROR use of moved value
+fn conspirator(f: |&mut R, bool|) {
+ let mut r = R {c: f};
+ f(&mut r, false) //~ ERROR use of moved value
}
fn main() { innocent_looking_victim() }
// aux-build:macro_crate_test.rs
// ignore-stage1
// ignore-android
-// ignore-cross-compile #12102
#![feature(phase)]
// ignore-stage1
// ignore-pretty
-// ignore-cross-compile #12102
#![feature(phase)]
// ignore-stage1
// ignore-pretty
-// ignore-cross-compile #12102
#![feature(phase)]
// ignore-stage1
// ignore-pretty
-// ignore-cross-compile #12102
#![feature(phase)]
// ignore-stage1
// ignore-pretty
-// ignore-cross-compile #12102
#![feature(phase)]
// ignore-stage1
// ignore-pretty
-// ignore-cross-compile #12102
#![feature(phase)]
// ignore-stage1
// ignore-pretty
-// ignore-cross-compile #12102
#![feature(phase)]
// ignore-stage1
// ignore-pretty
-// ignore-cross-compile #12102
#![feature(phase)]
// 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()
}
// aux-build:issue-13560-2.rs
// aux-build:issue-13560-3.rs
// ignore-stage1
-// ignore-android
-// ignore-cross-compile #12102
// Regression test for issue #13560, the test itself is all in the dependent
// libraries. The fail which previously failed to compile is the one numbered 3.
// aux-build:macro_crate_outlive_expansion_phase.rs
// ignore-stage1
-// ignore-android
-// ignore-cross-compile #12102
#![feature(phase)]
// aux-build:macro_crate_test.rs
// ignore-stage1
-// ignore-android
-// ignore-cross-compile #12102
#![feature(phase)]
// aux-build:macro_crate_test.rs
// ignore-stage1
-// ignore-android
-// force-host
-
-// You'll note that there's lots of directives above. This is a very particular
-// test in which we're both linking to a macro crate and loading macros from it.
-// This implies that both versions are the host architecture, meaning this test
-// must also be compiled with the host arch.
+// ignore-cross-compile
//
-// because this doesn't work with that test runner, ignore-android because it
-// can't run host binaries, and force-host to make this test build as the host
-// arch.
+// macro_crate_test will not compile on a cross-compiled target because
+// libsyntax is not compiled for it.
#![feature(phase)]
// ignore-stage1
// ignore-pretty
-// ignore-cross-compile
#![feature(phase)]
// ignore-stage1
// ignore-pretty
-// ignore-cross-compile #12102
#![feature(phase)]
#[phase(syntax)]
fn f() { }
static bare_fns: &'static [fn()] = &[f, f];
struct S<'a>(||:'a);
-static mut closures: &'static [S<'static>] = &[S(f), S(f)];
+static mut closures: &'static mut [S<'static>] = &mut [S(f), S(f)];
pub fn main() {
unsafe {
for &bare_fn in bare_fns.iter() { bare_fn() }
- for closure in closures.iter() {
- let S(ref closure) = *closure;
+ for closure in closures.mut_iter() {
+ let S(ref mut closure) = *closure;
(*closure)()
}
}
// 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);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait OpInt<'a> { fn call<'a>(&'a self, int, int) -> int; }
+pub trait OpInt<'a> { fn call<'a>(&'a mut self, int, int) -> int; }
impl<'a> OpInt<'a> for |int, int|: 'a -> int {
- fn call(&self, a:int, b:int) -> int {
+ fn call(&mut self, a:int, b:int) -> int {
(*self)(a, b)
}
}
-fn squarei<'a>(x: int, op: &'a OpInt) -> int { op.call(x, x) }
+fn squarei<'a>(x: int, op: &'a mut OpInt) -> int { op.call(x, x) }
fn muli(x:int, y:int) -> int { x * y }
pub fn main() {
- let f = |x,y| muli(x,y);
+ let mut f = |x,y| muli(x,y);
{
- let g = &f;
- let h = g as &OpInt;
+ let g = &mut f;
+ let h = g as &mut OpInt;
squarei(3, h);
}
}
// 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() ());
}
// 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);
}
macro_rules! iotest (
- { fn $name:ident() $b:block $($a:attr)* } => (
+ { fn $name:ident() $b:block $(#[$a:meta])* } => (
mod $name {
#![allow(unused_imports)]
fn f() $b
- $($a)* #[test] fn green() { f() }
- $($a)* #[test] fn native() {
+ $(#[$a])* #[test] fn green() { f() }
+ $(#[$a])* #[test] fn native() {
use native;
let (tx, rx) = channel();
native::task::spawn(proc() { tx.send(f()) });
}
}
fail!("never timed out!");
-})
+} #[ignore(cfg(target_os = "freebsd"))])
iotest!(fn timeout_success() {
let addr = next_test_ip4();
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");