DEPS_sync := std alloc
DEPS_getopts := std
DEPS_collections := core alloc
-DEPS_fourcc := syntax std
-DEPS_hexfloat := syntax std
+DEPS_fourcc := rustc syntax std
+DEPS_hexfloat := rustc syntax std
DEPS_num := std
DEPS_test := std getopts serialize term time regex native:rust_test_helpers
DEPS_time := std serialize sync
DEPS_url := std
DEPS_log := std sync
DEPS_regex := std
-DEPS_regex_macros = syntax std regex
+DEPS_regex_macros = rustc syntax std regex
DEPS_fmt_macros = std
TOOL_DEPS_compiletest := test green rustuv getopts
extern crate test;
extern crate getopts;
-#[phase(link, syntax)]
-extern crate log;
extern crate green;
extern crate rustuv;
+#[cfg(stage0)]
+#[phase(syntax, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
extern crate regex;
use std::os;
save_metrics: config.save_metrics.clone(),
test_shard: config.test_shard.clone(),
nocapture: false,
+ color: test::AutoColor,
}
}
use std::os;
use std::str;
use std::io::process::{ProcessExit, Command, Process, ProcessOutput};
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
fn target_env(lib_path: &str, prog: &str) -> Vec<(String, String)> {
let prog = if cfg!(windows) {prog.slice_to(prog.len() - 4)} else {prog};
### Function-only attributes
-- `macro_registrar` - when using loadable syntax extensions, mark this
- function as the registration point for the current crate's syntax
- extensions.
+- `plugin_registrar` - mark this function as the registration point for
+ compiler plugins, such as loadable syntax extensions.
- `main` - indicates that this function should be passed to the entry point,
rather than the function in the crate root named `main`.
- `start` - indicates that this function should be used as the entry point,
~~~~
#![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
fn main() {
error!("This is an error log")
"libstd/sync/spsc_queue.rs", # BSD
"libstd/sync/mpmc_bounded_queue.rs", # BSD
"libsync/mpsc_intrusive.rs", # BSD
+ "test/bench/shootout-fannkuch-redux.rs", # BSD
"test/bench/shootout-meteor.rs", # BSD
"test/bench/shootout-regex-dna.rs", # BSD
]
#![no_std]
#![feature(phase)]
+#[cfg(stage0)]
#[phase(syntax, link)]
extern crate core;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate core;
+
extern crate libc;
#[cfg(test)] extern crate debug;
#[cfg(test)] extern crate sync;
#[cfg(test)] extern crate native;
-#[cfg(test)] #[phase(syntax, link)] extern crate std;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate std;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate std;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
// Heaps provided for low-level allocation strategies
use core::prelude::*;
use core::cmp;
+use core::default::Default;
use core::fmt;
use core::iter::{Enumerate, Repeat, Map, Zip};
use core::ops;
use core::slice;
use core::uint;
+use std::hash;
+use {Collection, Mutable, Set, MutableSet};
use vec::Vec;
#[deriving(Clone)]
}
impl SmallBitv {
- pub fn new(bits: uint) -> SmallBitv {
+ fn new(bits: uint) -> SmallBitv {
SmallBitv {bits: bits}
}
#[inline]
- pub fn bits_op(&mut self,
+ fn bits_op(&mut self,
right_bits: uint,
nbits: uint,
f: |uint, uint| -> uint)
}
#[inline]
- pub fn union(&mut self, s: &SmallBitv, nbits: uint) -> bool {
+ fn union(&mut self, s: &SmallBitv, nbits: uint) -> bool {
self.bits_op(s.bits, nbits, |u1, u2| u1 | u2)
}
#[inline]
- pub fn intersect(&mut self, s: &SmallBitv, nbits: uint) -> bool {
+ fn intersect(&mut self, s: &SmallBitv, nbits: uint) -> bool {
self.bits_op(s.bits, nbits, |u1, u2| u1 & u2)
}
#[inline]
- pub fn become(&mut self, s: &SmallBitv, nbits: uint) -> bool {
+ fn become(&mut self, s: &SmallBitv, nbits: uint) -> bool {
self.bits_op(s.bits, nbits, |_u1, u2| u2)
}
#[inline]
- pub fn difference(&mut self, s: &SmallBitv, nbits: uint) -> bool {
+ fn difference(&mut self, s: &SmallBitv, nbits: uint) -> bool {
self.bits_op(s.bits, nbits, |u1, u2| u1 & !u2)
}
#[inline]
- pub fn get(&self, i: uint) -> bool {
+ fn get(&self, i: uint) -> bool {
(self.bits & (1 << i)) != 0
}
#[inline]
- pub fn set(&mut self, i: uint, x: bool) {
+ fn set(&mut self, i: uint, x: bool) {
if x {
self.bits |= 1<<i;
}
}
#[inline]
- pub fn equals(&self, b: &SmallBitv, nbits: uint) -> bool {
+ fn equals(&self, b: &SmallBitv, nbits: uint) -> bool {
let mask = small_mask(nbits);
mask & self.bits == mask & b.bits
}
#[inline]
- pub fn clear(&mut self) { self.bits = 0; }
+ fn clear(&mut self) { self.bits = 0; }
#[inline]
- pub fn set_all(&mut self) { self.bits = !0; }
+ fn set_all(&mut self) { self.bits = !0; }
#[inline]
- pub fn all(&self, nbits: uint) -> bool {
+ fn all(&self, nbits: uint) -> bool {
small_mask(nbits) & !self.bits == 0
}
#[inline]
- pub fn none(&self, nbits: uint) -> bool {
+ fn none(&self, nbits: uint) -> bool {
small_mask(nbits) & self.bits == 0
}
#[inline]
- pub fn negate(&mut self) { self.bits = !self.bits; }
+ fn negate(&mut self) { self.bits = !self.bits; }
}
#[deriving(Clone)]
}
impl BigBitv {
- pub fn new(storage: Vec<uint>) -> BigBitv {
+ fn new(storage: Vec<uint>) -> BigBitv {
BigBitv {storage: storage}
}
#[inline]
- pub fn process(&mut self,
+ fn process(&mut self,
b: &BigBitv,
nbits: uint,
op: |uint, uint| -> uint)
}
#[inline]
- pub fn each_storage(&mut self, op: |v: &mut uint| -> bool) -> bool {
+ fn each_storage(&mut self, op: |v: &mut uint| -> bool) -> bool {
self.storage.mut_iter().advance(|elt| op(elt))
}
#[inline]
- pub fn negate(&mut self) {
+ fn negate(&mut self) {
self.each_storage(|w| { *w = !*w; true });
}
#[inline]
- pub fn union(&mut self, b: &BigBitv, nbits: uint) -> bool {
+ fn union(&mut self, b: &BigBitv, nbits: uint) -> bool {
self.process(b, nbits, |w1, w2| w1 | w2)
}
#[inline]
- pub fn intersect(&mut self, b: &BigBitv, nbits: uint) -> bool {
+ fn intersect(&mut self, b: &BigBitv, nbits: uint) -> bool {
self.process(b, nbits, |w1, w2| w1 & w2)
}
#[inline]
- pub fn become(&mut self, b: &BigBitv, nbits: uint) -> bool {
+ fn become(&mut self, b: &BigBitv, nbits: uint) -> bool {
self.process(b, nbits, |_, w| w)
}
#[inline]
- pub fn difference(&mut self, b: &BigBitv, nbits: uint) -> bool {
+ fn difference(&mut self, b: &BigBitv, nbits: uint) -> bool {
self.process(b, nbits, |w1, w2| w1 & !w2)
}
#[inline]
- pub fn get(&self, i: uint) -> bool {
+ fn get(&self, i: uint) -> bool {
let w = i / uint::BITS;
let b = i % uint::BITS;
let x = 1 & self.storage.get(w) >> b;
}
#[inline]
- pub fn set(&mut self, i: uint, x: bool) {
+ fn set(&mut self, i: uint, x: bool) {
let w = i / uint::BITS;
let b = i % uint::BITS;
let flag = 1 << b;
}
#[inline]
- pub fn equals(&self, b: &BigBitv, nbits: uint) -> bool {
+ fn equals(&self, b: &BigBitv, nbits: uint) -> bool {
for (i, elt) in b.storage.iter().enumerate() {
let mask = big_mask(nbits, i);
if mask & *self.storage.get(i) != mask & *elt {
}
}
+impl<S: hash::Writer> hash::Hash<S> for Bitv {
+ fn hash(&self, state: &mut S) {
+ self.nbits.hash(state);
+ match self.rep {
+ Small(ref s) => (s.bits & small_mask(self.nbits)).hash(state),
+ Big(ref b) => {
+ for (i, ele) in b.storage.iter().enumerate() {
+ (ele & big_mask(self.nbits, i)).hash(state);
+ }
+ }
+ }
+ }
+}
+
#[inline]
fn iterate_bits(base: uint, bits: uint, f: |uint| -> bool) -> bool {
if bits == 0 {
bitv: BigBitv
}
+impl Default for BitvSet {
+ #[inline]
+ fn default() -> BitvSet { BitvSet::new() }
+}
+
impl BitvSet {
/// Creates a new bit vector set with initially no contents
pub fn new() -> BitvSet {
}
}
-impl Container for BitvSet {
+impl<S: hash::Writer> hash::Hash<S> for BitvSet {
+ fn hash(&self, state: &mut S) {
+ for pos in self.iter() {
+ pos.hash(state);
+ }
+ }
+}
+
+impl Collection for BitvSet {
#[inline]
fn len(&self) -> uint { self.size }
}
use std::rand::Rng;
use test::Bencher;
+ use {Set, Mutable, MutableSet};
use bitv::{Bitv, SmallBitv, BigBitv, BitvSet, from_bools, from_fn,
from_bytes};
use bitv;
use core::fmt;
use core::fmt::Show;
+use Collection;
use vec::Vec;
#[allow(missing_doc)]
//! Container traits for collections
-use core::prelude::*;
-
-/// A double-ended sequence that allows querying, insertion and deletion at both ends.
-pub trait Deque<T> : Mutable {
- /// Provide a reference to the front element, or None if the sequence is empty
- fn front<'a>(&'a self) -> Option<&'a T>;
-
- /// Provide a mutable reference to the front element, or None if the sequence is empty
- fn front_mut<'a>(&'a mut self) -> Option<&'a mut T>;
-
- /// Provide a reference to the back element, or None if the sequence is empty
- fn back<'a>(&'a self) -> Option<&'a T>;
-
- /// Provide a mutable reference to the back element, or None if the sequence is empty
- fn back_mut<'a>(&'a mut self) -> Option<&'a mut T>;
-
- /// Insert an element first in the sequence
- fn push_front(&mut self, elt: T);
-
- /// Insert an element last in the sequence
- fn push_back(&mut self, elt: T);
-
- /// Remove the last element and return it, or None if the sequence is empty
- fn pop_back(&mut self) -> Option<T>;
-
- /// Remove the first element and return it, or None if the sequence is empty
- fn pop_front(&mut self) -> Option<T>;
-}
-
#[cfg(test)]
pub mod bench {
use std::prelude::*;
use std::rand;
use std::rand::Rng;
use test::Bencher;
+ use MutableMap;
pub fn insert_rand_n<M:MutableMap<uint,uint>>(n: uint,
map: &mut M,
})
}
}
+
//! The DList allows pushing and popping elements at either end.
//!
//! DList implements the trait Deque. It should be imported with `use
-//! collections::deque::Deque`.
+//! collections::Deque`.
// DList is constructed like a singly-linked list over the field `next`.
// including the last link being None; each Node owns its `next` field.
use core::prelude::*;
use alloc::owned::Box;
+use core::default::Default;
use core::fmt;
use core::iter;
use core::mem;
use core::ptr;
-use deque::Deque;
+use {Collection, Mutable, Deque};
/// A doubly-linked list.
pub struct DList<T> {
Some(next)
}
-impl<T> Container for DList<T> {
+impl<T> Collection for DList<T> {
/// O(1)
#[inline]
fn is_empty(&self) -> bool {
}
}
+impl<T> Default for DList<T> {
+ #[inline]
+ fn default() -> DList<T> { DList::new() }
+}
+
impl<T> DList<T> {
/// Create an empty DList
#[inline]
use test::Bencher;
use test;
- use deque::Deque;
+ use Deque;
use super::{DList, Node, ListInsertion};
use vec::Vec;
#![feature(macro_rules, managed_boxes, default_type_params, phase, globs)]
#![no_std]
-#[phase(syntax, link)] extern crate core;
extern crate alloc;
+#[cfg(stage0)]
+#[phase(syntax, link)]
+extern crate core;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate core;
+
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate test;
#[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate std;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate std;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate std;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
+
+use core::prelude::*;
+
+pub use core::collections::Collection;
pub use bitv::{Bitv, BitvSet};
pub use btree::BTree;
-pub use deque::Deque;
pub use dlist::DList;
pub use enum_set::EnumSet;
pub use priority_queue::PriorityQueue;
pub mod bitv;
pub mod btree;
-pub mod deque;
pub mod dlist;
pub mod enum_set;
pub mod priority_queue;
// Internal unicode fiddly bits for the str module
mod unicode;
-// FIXME(#14008) should this actually exist, or should a method be added?
-fn expect<T>(a: core::option::Option<T>, b: &str) -> T {
- match a {
- core::option::Some(a) => a,
- core::option::None => fail!("{}", b),
+mod deque;
+
+/// A trait to represent mutable containers
+pub trait Mutable: Collection {
+ /// Clear the container, removing all values.
+ fn clear(&mut self);
+}
+
+/// A map is a key-value store where values may be looked up by their keys. This
+/// trait provides basic operations to operate on these stores.
+pub trait Map<K, V>: Collection {
+ /// Return a reference to the value corresponding to the key
+ fn find<'a>(&'a self, key: &K) -> Option<&'a V>;
+
+ /// Return true if the map contains a value for the specified key
+ #[inline]
+ fn contains_key(&self, key: &K) -> bool {
+ self.find(key).is_some()
+ }
+}
+
+/// This trait provides basic operations to modify the contents of a map.
+pub trait MutableMap<K, V>: Map<K, V> + Mutable {
+ /// Insert a key-value pair into the map. An existing value for a
+ /// key is replaced by the new value. Return true if the key did
+ /// not already exist in the map.
+ #[inline]
+ fn insert(&mut self, key: K, value: V) -> bool {
+ self.swap(key, value).is_none()
}
+
+ /// Remove a key-value pair from the map. Return true if the key
+ /// was present in the map, otherwise false.
+ #[inline]
+ fn remove(&mut self, key: &K) -> bool {
+ self.pop(key).is_some()
+ }
+
+ /// Insert a key-value pair from the map. If the key already had a value
+ /// present in the map, that value is returned. Otherwise None is returned.
+ fn swap(&mut self, k: K, v: V) -> Option<V>;
+
+ /// Removes a key from the map, returning the value at the key if the key
+ /// was previously in the map.
+ fn pop(&mut self, k: &K) -> Option<V>;
+
+ /// Return a mutable reference to the value corresponding to the key
+ fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V>;
+}
+
+/// A set is a group of objects which are each distinct from one another. This
+/// trait represents actions which can be performed on sets to iterate over
+/// them.
+pub trait Set<T>: Collection {
+ /// Return true if the set contains a value
+ fn contains(&self, value: &T) -> bool;
+
+ /// Return true if the set has no elements in common with `other`.
+ /// This is equivalent to checking for an empty intersection.
+ fn is_disjoint(&self, other: &Self) -> bool;
+
+ /// Return true if the set is a subset of another
+ fn is_subset(&self, other: &Self) -> bool;
+
+ /// Return true if the set is a superset of another
+ fn is_superset(&self, other: &Self) -> bool {
+ other.is_subset(self)
+ }
+
+ // FIXME #8154: Add difference, sym. difference, intersection and union iterators
+}
+
+/// This trait represents actions which can be performed on sets to mutate
+/// them.
+pub trait MutableSet<T>: Set<T> + Mutable {
+ /// Add a value to the set. Return true if the value was not already
+ /// present in the set.
+ fn insert(&mut self, value: T) -> bool;
+
+ /// Remove a value from the set. Return true if the value was
+ /// present in the set.
+ fn remove(&mut self, value: &T) -> bool;
+}
+
+/// A double-ended sequence that allows querying, insertion and deletion at both
+/// ends.
+pub trait Deque<T> : Mutable {
+ /// Provide a reference to the front element, or None if the sequence is
+ /// empty
+ fn front<'a>(&'a self) -> Option<&'a T>;
+
+ /// Provide a mutable reference to the front element, or None if the
+ /// sequence is empty
+ fn front_mut<'a>(&'a mut self) -> Option<&'a mut T>;
+
+ /// Provide a reference to the back element, or None if the sequence is
+ /// empty
+ fn back<'a>(&'a self) -> Option<&'a T>;
+
+ /// Provide a mutable reference to the back element, or None if the sequence
+ /// is empty
+ fn back_mut<'a>(&'a mut self) -> Option<&'a mut T>;
+
+ /// Insert an element first in the sequence
+ fn push_front(&mut self, elt: T);
+
+ /// Insert an element last in the sequence
+ fn push_back(&mut self, elt: T);
+
+ /// Remove the last element and return it, or None if the sequence is empty
+ fn pop_back(&mut self) -> Option<T>;
+
+ /// Remove the first element and return it, or None if the sequence is empty
+ fn pop_front(&mut self) -> Option<T>;
}
// FIXME(#14344) this shouldn't be necessary
use core::prelude::*;
+use core::default::Default;
use core::mem::{zeroed, replace, swap};
use core::ptr;
+use {Collection, Mutable};
use slice;
use vec::Vec;
data: Vec<T>,
}
-impl<T: Ord> Container for PriorityQueue<T> {
+impl<T: Ord> Collection for PriorityQueue<T> {
/// Returns the length of the queue
fn len(&self) -> uint { self.data.len() }
}
fn clear(&mut self) { self.data.truncate(0) }
}
+impl<T: Ord> Default for PriorityQueue<T> {
+ #[inline]
+ fn default() -> PriorityQueue<T> { PriorityQueue::new() }
+}
+
impl<T: Ord> PriorityQueue<T> {
/// An iterator visiting all values in underlying vector, in
/// arbitrary order.
//! A double-ended queue implemented as a circular buffer
//!
//! RingBuf implements the trait Deque. It should be imported with `use
-//! collections::deque::Deque`.
+//! collections::Deque`.
use core::prelude::*;
use core::cmp;
+use core::default::Default;
use core::fmt;
use core::iter::RandomAccessIterator;
-use deque::Deque;
+use {Deque, Collection, Mutable};
use vec::Vec;
static INITIAL_CAPACITY: uint = 8u; // 2^3
elts: Vec<Option<T>>
}
-impl<T> Container for RingBuf<T> {
+impl<T> Collection for RingBuf<T> {
/// Return the number of elements in the RingBuf
fn len(&self) -> uint { self.nelts }
}
}
}
+impl<T> Default for RingBuf<T> {
+ #[inline]
+ fn default() -> RingBuf<T> { RingBuf::new() }
+}
+
impl<T> RingBuf<T> {
/// Create an empty RingBuf
pub fn new() -> RingBuf<T> {
use test::Bencher;
use test;
- use deque::Deque;
+ use {Deque, Mutable};
use super::RingBuf;
use vec::Vec;
use core::mem;
use core::ptr;
use core::iter::{range_step, MultiplicativeIterator};
+
+use Collection;
use vec::Vec;
pub use core::slice::{ref_slice, mut_ref_slice, Splits, Windows};
let len = self.len();
let data_size = len.checked_mul(&mem::size_of::<T>());
- let data_size = ::expect(data_size, "overflow in to_owned()");
+ let data_size = data_size.expect("overflow in to_owned()");
let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
- let size = ::expect(size, "overflow in to_owned()");
+ let size = size.expect("overflow in to_owned()");
unsafe {
// this should pass the real required alignment
use std::rt;
use slice::*;
+ use Mutable;
use vec::Vec;
fn square(n: uint) -> uint { n * n }
use core::prelude::*;
+use core::default::Default;
use core::fmt;
use core::iter::{Enumerate, FilterMap};
use core::mem::replace;
+use {Collection, Mutable, Map, MutableMap};
use {vec, slice};
use vec::Vec;
v: Vec<Option<T>>,
}
-impl<V> Container for SmallIntMap<V> {
+impl<V> Collection for SmallIntMap<V> {
/// Return the number of elements in the map
fn len(&self) -> uint {
self.v.iter().filter(|elt| elt.is_some()).count()
}
}
+impl<V> Default for SmallIntMap<V> {
+ #[inline]
+ fn default() -> SmallIntMap<V> { SmallIntMap::new() }
+}
+
impl<V> SmallIntMap<V> {
/// Create an empty SmallIntMap
pub fn new() -> SmallIntMap<V> { SmallIntMap{v: vec!()} }
}
pub fn get<'a>(&'a self, key: &uint) -> &'a V {
- ::expect(self.find(key), "key not present")
+ self.find(key).expect("key not present")
}
/// An iterator visiting all key-value pairs in ascending order by the keys.
mod test_map {
use std::prelude::*;
+ use {Map, MutableMap, Mutable};
use super::SmallIntMap;
#[test]
use core::iter::AdditiveIterator;
use core::mem;
+use Collection;
use hash;
use string::String;
use vec::Vec;
}
}
-impl<'a> Container for MaybeOwned<'a> {
+impl<'a> Collection for MaybeOwned<'a> {
#[inline]
fn len(&self) -> uint { self.as_slice().len() }
}
#[test]
fn test_str_container() {
- fn sum_len<S: Container>(v: &[S]) -> uint {
+ fn sum_len<S: Collection>(v: &[S]) -> uint {
v.iter().map(|x| x.len()).sum()
}
use core::ptr;
use core::raw::Slice;
+use {Collection, Mutable};
use hash;
use str;
use str::{CharRange, StrAllocating};
}
}
-impl Container for String {
+impl Collection for String {
#[inline]
fn len(&self) -> uint {
self.vec.len()
use std::prelude::*;
use test::Bencher;
+ use Mutable;
use str::{Str, StrSlice};
use super::String;
use core::prelude::*;
use alloc::owned::Box;
+use core::default::Default;
use core::fmt;
use core::fmt::Show;
use core::iter::Peekable;
use core::mem::{replace, swap};
use core::ptr;
+use {Collection, Mutable, Set, MutableSet, MutableMap, Map};
use vec::Vec;
// This is implemented as an AA tree, which is a simplified variation of
}
}
-impl<K: Ord, V> Container for TreeMap<K, V> {
+impl<K: Ord, V> Collection for TreeMap<K, V> {
fn len(&self) -> uint { self.length }
}
}
}
+impl<K: Ord, V> Default for TreeMap<K,V> {
+ #[inline]
+ fn default() -> TreeMap<K, V> { TreeMap::new() }
+}
+
impl<K: Ord, V> TreeMap<K, V> {
/// Create an empty TreeMap
pub fn new() -> TreeMap<K, V> { TreeMap{root: None, length: 0} }
}
}
-impl<T: Ord> Container for TreeSet<T> {
+impl<T: Ord> Collection for TreeSet<T> {
#[inline]
fn len(&self) -> uint { self.map.len() }
}
fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
}
+impl<T: Ord> Default for TreeSet<T> {
+ #[inline]
+ fn default() -> TreeSet<T> { TreeSet::new() }
+}
+
impl<T: Ord> TreeSet<T> {
/// Create an empty TreeSet
#[inline]
use std::rand::Rng;
use std::rand;
+ use {Map, MutableMap, Mutable};
use super::{TreeMap, TreeNode};
#[test]
#[cfg(test)]
mod bench {
- use std::prelude::*;
use test::Bencher;
use super::TreeMap;
mod test_set {
use std::prelude::*;
+ use {Set, MutableSet, Mutable, MutableMap};
use super::{TreeMap, TreeSet};
#[test]
use core::prelude::*;
use alloc::owned::Box;
+use core::default::Default;
use core::mem::zeroed;
use core::mem;
use core::uint;
+use {Collection, Mutable, Map, MutableMap, Set, MutableSet};
use slice::{Items, MutItems};
use slice;
length: uint
}
-impl<T> Container for TrieMap<T> {
+impl<T> Collection for TrieMap<T> {
/// Return the number of elements in the map
#[inline]
fn len(&self) -> uint { self.length }
}
}
+impl<T> Default for TrieMap<T> {
+ #[inline]
+ fn default() -> TrieMap<T> { TrieMap::new() }
+}
+
impl<T> TrieMap<T> {
/// Create an empty TrieMap
#[inline]
map: TrieMap<()>
}
-impl Container for TrieSet {
+impl Collection for TrieSet {
/// Return the number of elements in the set
#[inline]
fn len(&self) -> uint { self.map.len() }
}
}
+impl Default for TrieSet {
+ #[inline]
+ fn default() -> TrieSet { TrieSet::new() }
+}
+
impl TrieSet {
/// Create an empty TrieSet
#[inline]
use std::iter::range_step;
use std::uint;
+ use {MutableMap, Map};
use super::{TrieMap, TrieNode, Internal, External, Nothing};
fn check_integrity<T>(trie: &TrieNode<T>) {
use std::rand::{weak_rng, Rng};
use test::Bencher;
+ use MutableMap;
use super::TrieMap;
#[bench]
use std::prelude::*;
use std::uint;
+ use {MutableSet, Set};
use super::TrieSet;
#[test]
use core::ptr;
use core::uint;
+use {Collection, Mutable};
use slice::{MutableOrdVector, OwnedVector, MutableVectorAllocating};
use slice::{Items, MutItems};
} else if capacity == 0 {
Vec::new()
} else {
- let size = ::expect(capacity.checked_mul(&mem::size_of::<T>()),
- "capacity overflow");
+ let size = capacity.checked_mul(&mem::size_of::<T>())
+ .expect("capacity overflow");
let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
Vec { len: 0, cap: capacity, ptr: ptr as *mut T }
}
}
}
-impl<T> Container for Vec<T> {
+impl<T> Collection for Vec<T> {
#[inline]
fn len(&self) -> uint {
self.len
if mem::size_of::<T>() == 0 { return }
if capacity > self.cap {
- let size = ::expect(capacity.checked_mul(&mem::size_of::<T>()),
- "capacity overflow");
+ let size = capacity.checked_mul(&mem::size_of::<T>())
+ .expect("capacity overflow");
unsafe {
self.ptr = alloc_or_realloc(self.ptr, size,
self.cap * mem::size_of::<T>());
pub fn push(&mut self, value: T) {
if mem::size_of::<T>() == 0 {
// zero-size types consume no memory, so we can't rely on the address space running out
- self.len = ::expect(self.len.checked_add(&1), "length overflow");
+ self.len = self.len.checked_add(&1).expect("length overflow");
unsafe { mem::forget(value); }
return
}
fn from_vec(mut v: Vec<T>) -> ~[T] {
let len = v.len();
let data_size = len.checked_mul(&mem::size_of::<T>());
- let data_size = ::expect(data_size, "overflow in from_vec()");
+ let data_size = data_size.expect("overflow in from_vec()");
let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
- let size = ::expect(size, "overflow in from_vec()");
+ let size = size.expect("overflow in from_vec()");
// In a post-DST world, we can attempt to reuse the Vec allocation by calling
// shrink_to_fit() on it. That may involve a reallocation+memcpy, but that's no
- // diffrent than what we're doing manually here.
+ // different than what we're doing manually here.
let vp = v.as_mut_ptr();
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Traits for generic collections
+
+/// A trait to represent the abstract idea of a container. The only concrete
+/// knowledge known is the number of elements contained within.
+pub trait Collection {
+ /// Return the number of elements in the container
+ fn len(&self) -> uint;
+
+ /// Return true if the container contains no elements
+ #[inline]
+ fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Traits for generic containers (including `Map` and `Set`)
-
-use option::Option;
-
-/// A trait to represent the abstract idea of a container. The only concrete
-/// knowledge known is the number of elements contained within.
-pub trait Container {
- /// Return the number of elements in the container
- fn len(&self) -> uint;
-
- /// Return true if the container contains no elements
- #[inline]
- fn is_empty(&self) -> bool {
- self.len() == 0
- }
-}
-
-/// A trait to represent mutable containers
-pub trait Mutable: Container {
- /// Clear the container, removing all values.
- fn clear(&mut self);
-}
-
-/// A map is a key-value store where values may be looked up by their keys. This
-/// trait provides basic operations to operate on these stores.
-pub trait Map<K, V>: Container {
- /// Return a reference to the value corresponding to the key
- fn find<'a>(&'a self, key: &K) -> Option<&'a V>;
-
- /// Return true if the map contains a value for the specified key
- #[inline]
- fn contains_key(&self, key: &K) -> bool {
- self.find(key).is_some()
- }
-}
-
-/// This trait provides basic operations to modify the contents of a map.
-pub trait MutableMap<K, V>: Map<K, V> + Mutable {
- /// Insert a key-value pair into the map. An existing value for a
- /// key is replaced by the new value. Return true if the key did
- /// not already exist in the map.
- #[inline]
- fn insert(&mut self, key: K, value: V) -> bool {
- self.swap(key, value).is_none()
- }
-
- /// Remove a key-value pair from the map. Return true if the key
- /// was present in the map, otherwise false.
- #[inline]
- fn remove(&mut self, key: &K) -> bool {
- self.pop(key).is_some()
- }
-
- /// Insert a key-value pair from the map. If the key already had a value
- /// present in the map, that value is returned. Otherwise None is returned.
- fn swap(&mut self, k: K, v: V) -> Option<V>;
-
- /// Removes a key from the map, returning the value at the key if the key
- /// was previously in the map.
- fn pop(&mut self, k: &K) -> Option<V>;
-
- /// Return a mutable reference to the value corresponding to the key
- fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V>;
-}
-
-/// A set is a group of objects which are each distinct from one another. This
-/// trait represents actions which can be performed on sets to iterate over
-/// them.
-pub trait Set<T>: Container {
- /// Return true if the set contains a value
- fn contains(&self, value: &T) -> bool;
-
- /// Return true if the set has no elements in common with `other`.
- /// This is equivalent to checking for an empty intersection.
- fn is_disjoint(&self, other: &Self) -> bool;
-
- /// Return true if the set is a subset of another
- fn is_subset(&self, other: &Self) -> bool;
-
- /// Return true if the set is a superset of another
- fn is_superset(&self, other: &Self) -> bool {
- other.is_subset(self)
- }
-
- // FIXME #8154: Add difference, sym. difference, intersection and union iterators
-}
-
-/// This trait represents actions which can be performed on sets to mutate
-/// them.
-pub trait MutableSet<T>: Set<T> + Mutable {
- /// Add a value to the set. Return true if the value was not already
- /// present in the set.
- fn insert(&mut self, value: T) -> bool;
-
- /// Remove a value from the set. Return true if the value was
- /// present in the set.
- fn remove(&mut self, value: &T) -> bool;
-}
#![allow(missing_doc)]
use char;
-use container::Container;
+use collections::Collection;
use fmt;
use iter::{Iterator, range, DoubleEndedIterator};
use num::{Float, FPNaN, FPInfinite, ToPrimitive, Primitive};
use any;
use cell::Cell;
use char::Char;
-use container::Container;
+use collections::Collection;
use iter::{Iterator, range};
use kinds::Copy;
use mem;
#![allow(unsigned_negate)]
-use container::Container;
+use collections::Collection;
use fmt;
use iter::{Iterator, DoubleEndedIterator};
use num::{Int, cast, zero};
#[cfg(not(test))] pub mod cmp;
pub mod clone;
pub mod default;
-pub mod container;
+pub mod collections;
/* Core types and methods on primitives */
fn deref_mut<'a>(&'a mut self) -> &'a mut Result;
}
+/// A version of the call operator that takes an immutable receiver.
+#[lang="fn"]
+pub trait Fn<Args,Result> {
+ /// This is called when the call operator is used.
+ fn call(&self, args: Args) -> Result;
+}
+
+/// A version of the call operator that takes a mutable receiver.
+#[lang="fn_mut"]
+pub trait FnMut<Args,Result> {
+ /// This is called when the call operator is used.
+ fn call_mut(&mut self, args: Args) -> Result;
+}
+
+/// A version of the call operator that takes a by-value receiver.
+#[lang="fn_once"]
+pub trait FnOnce<Args,Result> {
+ /// This is called when the call operator is used.
+ fn call_once(self, args: Args) -> Result;
+}
+
#[cfg(test)]
mod bench {
extern crate test;
pub use clone::Clone;
pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
pub use cmp::{Ordering, Less, Equal, Greater, Equiv};
-pub use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
+pub use collections::Collection;
pub use iter::{FromIterator, Extendable};
pub use iter::{Iterator, DoubleEndedIterator, RandomAccessIterator, CloneableIterator};
pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize};
// Currently, no progress has been made on this list.
use clone::Clone;
-use container::Container;
+use collections::Collection;
use finally::try_finally;
use intrinsics;
use iter::{range, Iterator};
//!
//! ## Stability Note
//!
-//! These are all experimental. The inferface may change entirely, without
+//! These are all experimental. The interface may change entirely, without
//! warning.
#![allow(non_camel_case_types)]
use mem::transmute;
use clone::Clone;
-use container::Container;
+use collections::Collection;
use cmp::{PartialEq, Ord, Ordering, Less, Equal, Greater};
use cmp;
use default::Default;
use cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering, Equiv};
use iter::order;
- use container::Container;
+ use collections::Collection;
impl<'a,T:PartialEq> PartialEq for &'a [T] {
fn eq(&self, other: & &'a [T]) -> bool {
fn as_slice<'a>(&'a self) -> &'a [T] { let v: &'a [T] = *self; v }
}
-impl<'a, T> Container for &'a [T] {
+impl<'a, T> Collection for &'a [T] {
/// Returns the length of a vector
#[inline]
fn len(&self) -> uint {
}
}
-impl<T> Container for ~[T] {
+impl<T> Collection for ~[T] {
/// Returns the length of a vector
#[inline]
fn len(&self) -> uint {
/// Operations on `[u8]`.
pub mod bytes {
- use container::Container;
+ use collections::Collection;
use ptr;
use slice::MutableVector;
use clone::Clone;
use cmp;
use cmp::{PartialEq, Eq};
-use container::Container;
+use collections::Collection;
use default::Default;
use iter::{Filter, Map, Iterator};
use iter::{DoubleEndedIterator, ExactSize};
}
/// The internal state of an iterator that searches for matches of a substring
-/// within a larger string using a dynamically chosed search algorithm
+/// within a larger string using a dynamically chosen search algorithm
#[deriving(Clone)]
enum Searcher {
Naive(NaiveSearcher),
/// Unsafe operations
pub mod raw {
use mem;
- use container::Container;
+ use collections::Collection;
use ptr::RawPtr;
use raw::Slice;
use slice::{ImmutableVector};
#[cfg(not(test))]
#[allow(missing_doc)]
pub mod traits {
- use container::Container;
use cmp::{Ord, Ordering, Less, Equal, Greater, PartialEq, PartialOrd, Equiv, Eq};
+ use collections::Collection;
use iter::Iterator;
use option::{Some, None};
use str::{Str, StrSlice, eq_slice};
fn as_slice<'a>(&'a self) -> &'a str { *self }
}
-impl<'a> Container for &'a str {
+impl<'a> Collection for &'a str {
#[inline]
fn len(&self) -> uint {
self.repr().len
///
/// That is, each returned value `(start, end)` satisfies
/// `self.slice(start, end) == sep`. For matches of `sep` within
- /// `self` that overlap, only the indicies corresponding to the
+ /// `self` that overlap, only the indices corresponding to the
/// first match are returned.
///
/// # Example
#![feature(phase)]
#![deny(deprecated_owned_vector)]
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
extern crate libc;
To load the extension and use it:
```rust,ignore
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
fn main() {
html_root_url = "http://doc.rust-lang.org/")]
#![deny(deprecated_owned_vector)]
-#![feature(macro_registrar, managed_boxes)]
+#![feature(plugin_registrar, managed_boxes)]
extern crate syntax;
+extern crate rustc;
use syntax::ast;
-use syntax::ast::Name;
use syntax::attr::contains;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
-use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
+use syntax::ext::base::{ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::InternedString;
+use rustc::plugin::Registry;
-#[macro_registrar]
-pub fn macro_registrar(register: |Name, SyntaxExtension|) {
- register(token::intern("fourcc"),
- NormalTT(box BasicMacroExpander {
- expander: expand_syntax_ext,
- span: None,
- },
- None));
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("fourcc", expand_syntax_ext);
}
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
#![deny(deprecated_owned_vector)]
#[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
use std::cmp::PartialEq;
use std::result::{Err, Ok};
* pattern - see the `glob` function for more details.
*/
pub struct Paths {
- root: Path,
dir_patterns: Vec<Pattern>,
require_dir: bool,
options: MatchOptions,
// FIXME: How do we want to handle verbatim paths? I'm inclined to return nothing,
// since we can't very well find all UNC shares with a 1-letter server name.
return Paths {
- root: root,
dir_patterns: Vec::new(),
require_dir: false,
options: options,
}
Paths {
- root: root,
dir_patterns: dir_patterns,
require_dir: require_dir,
options: options,
// stacks are disabled.
#[cfg(target_arch = "x86")]
+#[repr(C)]
struct Registers {
eax: u32, ebx: u32, ecx: u32, edx: u32,
ebp: u32, esi: u32, edi: u32, esp: u32,
//!
//! ```
//! #![feature(phase)]
-//! #[phase(syntax)] extern crate green;
+//! #[phase(plugin)] extern crate green;
//!
//! green_start!(main)
//!
#![allow(visible_private_types)]
#![deny(deprecated_owned_vector)]
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test)] #[phase(plugin, link)] extern crate log;
#[cfg(test)] extern crate rustuv;
extern crate libc;
extern crate alloc;
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax)] extern crate green;
+/// #[phase(plugin)] extern crate green;
///
/// green_start!(main)
///
To load the extension and use it:
```rust,ignore
-#[phase(syntax)]
+#[phase(plugin)]
extern crate hexfloat;
fn main() {
html_root_url = "http://doc.rust-lang.org/")]
#![deny(deprecated_owned_vector)]
-#![feature(macro_registrar, managed_boxes)]
+#![feature(plugin_registrar, managed_boxes)]
extern crate syntax;
+extern crate rustc;
use syntax::ast;
-use syntax::ast::Name;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
-use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
+use syntax::ext::base::{ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
+use rustc::plugin::Registry;
-#[macro_registrar]
-pub fn macro_registrar(register: |Name, SyntaxExtension|) {
- register(token::intern("hexfloat"),
- NormalTT(box BasicMacroExpander {
- expander: expand_syntax_ext,
- span: None,
- },
- None));
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("hexfloat", expand_syntax_ext);
}
//Check if the literal is valid (as LLVM expects),
```
#![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
fn main() {
debug!("this is a debug {}", "message");
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// log!(log::DEBUG, "this is a debug message");
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// # let error = 3;
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// # let code = 3;
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// # let ret = 3;
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// debug!("x = {x}, y = {y}", x=10, y=20);
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// # struct Point { x: int, y: int }
static FD_SETSIZE: uint = 64;
pub static MSG_DONTWAIT: libc::c_int = 0;
+#[repr(C)]
pub struct WSADATA {
pub wVersion: libc::WORD,
pub wHighVersion: libc::WORD,
pub type LPWSADATA = *mut WSADATA;
+#[repr(C)]
pub struct fd_set {
fd_count: libc::c_uint,
fd_array: [libc::SOCKET, ..FD_SETSIZE],
pub mod compat {
use std::intrinsics::{atomic_store_relaxed, transmute};
use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
- use std::os::win32::as_utf16_p;
extern "system" {
fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
// This way, calling a function in this compatibility layer (after it's loaded) shouldn't
// be any slower than a regular DLL call.
unsafe fn store_func<T: Copy>(ptr: *mut T, module: &str, symbol: &str, fallback: T) {
- as_utf16_p(module, |module| {
- symbol.with_c_str(|symbol| {
- let handle = GetModuleHandleW(module);
- let func: Option<T> = transmute(GetProcAddress(handle, symbol));
- atomic_store_relaxed(ptr, func.unwrap_or(fallback))
- })
+ let module = module.to_utf16().append_one(0);
+ symbol.with_c_str(|symbol| {
+ let handle = GetModuleHandleW(module.as_ptr());
+ let func: Option<T> = transmute(GetProcAddress(handle, symbol));
+ atomic_store_relaxed(ptr, func.unwrap_or(fallback))
})
}
use libc;
use std::c_str::CString;
use std::mem;
-use std::os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
+use std::os::win32::fill_utf16_buf_and_decode;
use std::ptr;
use std::rt::rtio;
-use std::rt::rtio::IoResult;
+use std::rt::rtio::{IoResult, IoError};
use std::str;
use std::vec;
}
}
+pub fn to_utf16(s: &CString) -> IoResult<Vec<u16>> {
+ match s.as_str() {
+ Some(s) => Ok(s.to_utf16().append_one(0)),
+ None => Err(IoError {
+ code: libc::ERROR_INVALID_NAME as uint,
+ extra: 0,
+ detail: Some("valid unicode input required".to_str()),
+ })
+ }
+}
+
pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess)
-> IoResult<FileDesc> {
// Flags passed to open_osfhandle
// Compat with unix, this allows opening directories (see libuv)
dwFlagsAndAttributes |= libc::FILE_FLAG_BACKUP_SEMANTICS;
- let handle = as_utf16_p(path.as_str().unwrap(), |buf| unsafe {
- libc::CreateFileW(buf,
+ let path = try!(to_utf16(path));
+ let handle = unsafe {
+ libc::CreateFileW(path.as_ptr(),
dwDesiredAccess,
dwShareMode,
ptr::mut_null(),
dwCreationDisposition,
dwFlagsAndAttributes,
ptr::mut_null())
- });
+ };
if handle == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
Err(super::last_error())
} else {
}
pub fn mkdir(p: &CString, _mode: uint) -> IoResult<()> {
+ let p = try!(to_utf16(p));
super::mkerr_winbool(unsafe {
// FIXME: turn mode into something useful? #2623
- as_utf16_p(p.as_str().unwrap(), |buf| {
- libc::CreateDirectoryW(buf, ptr::mut_null())
- })
+ libc::CreateDirectoryW(p.as_ptr(), ptr::mut_null())
})
}
let star = Path::new(unsafe {
CString::new(p.with_ref(|p| p), false)
}).join("*");
- as_utf16_p(star.as_str().unwrap(), |path_ptr| unsafe {
+ let path = try!(to_utf16(&star.to_c_str()));
+
+ unsafe {
let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
- let find_handle = libc::FindFirstFileW(path_ptr, wfd_ptr as libc::HANDLE);
+ let find_handle = libc::FindFirstFileW(path.as_ptr(), wfd_ptr as libc::HANDLE);
if find_handle as libc::c_int != libc::INVALID_HANDLE_VALUE {
let mut paths = vec!();
let mut more_files = 1 as libc::c_int;
} else {
Err(super::last_error())
}
- })
+ }
}
pub fn unlink(p: &CString) -> IoResult<()> {
+ let p = try!(to_utf16(p));
super::mkerr_winbool(unsafe {
- as_utf16_p(p.as_str().unwrap(), |buf| {
- libc::DeleteFileW(buf)
- })
+ libc::DeleteFileW(p.as_ptr())
})
}
pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
+ let old = try!(to_utf16(old));
+ let new = try!(to_utf16(new));
super::mkerr_winbool(unsafe {
- as_utf16_p(old.as_str().unwrap(), |old| {
- as_utf16_p(new.as_str().unwrap(), |new| {
- libc::MoveFileExW(old, new, libc::MOVEFILE_REPLACE_EXISTING)
- })
- })
+ libc::MoveFileExW(old.as_ptr(), new.as_ptr(),
+ libc::MOVEFILE_REPLACE_EXISTING)
})
}
pub fn chmod(p: &CString, mode: uint) -> IoResult<()> {
- super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::wchmod(p, mode as libc::c_int)
- }))
+ let p = try!(to_utf16(p));
+ super::mkerr_libc(unsafe {
+ libc::wchmod(p.as_ptr(), mode as libc::c_int)
+ })
}
pub fn rmdir(p: &CString) -> IoResult<()> {
- super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::wrmdir(p)
- }))
+ let p = try!(to_utf16(p));
+ super::mkerr_libc(unsafe { libc::wrmdir(p.as_ptr()) })
}
pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> {
pub fn readlink(p: &CString) -> IoResult<CString> {
// FIXME: I have a feeling that this reads intermediate symlinks as well.
use io::c::compat::kernel32::GetFinalPathNameByHandleW;
+ let p = try!(to_utf16(p));
let handle = unsafe {
- as_utf16_p(p.as_str().unwrap(), |p| {
- libc::CreateFileW(p,
- libc::GENERIC_READ,
- libc::FILE_SHARE_READ,
- ptr::mut_null(),
- libc::OPEN_EXISTING,
- libc::FILE_ATTRIBUTE_NORMAL,
- ptr::mut_null())
- })
+ libc::CreateFileW(p.as_ptr(),
+ libc::GENERIC_READ,
+ libc::FILE_SHARE_READ,
+ ptr::mut_null(),
+ libc::OPEN_EXISTING,
+ libc::FILE_ATTRIBUTE_NORMAL,
+ ptr::mut_null())
};
if handle as int == libc::INVALID_HANDLE_VALUE as int {
return Err(super::last_error())
pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> {
use io::c::compat::kernel32::CreateSymbolicLinkW;
- super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
- as_utf16_p(dst.as_str().unwrap(), |dst| {
- unsafe { CreateSymbolicLinkW(dst, src, 0) }
- }) as libc::BOOL
- }))
+ let src = try!(to_utf16(src));
+ let dst = try!(to_utf16(dst));
+ super::mkerr_winbool(unsafe {
+ CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), 0) as libc::BOOL
+ })
}
pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
- super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
- as_utf16_p(dst.as_str().unwrap(), |dst| {
- unsafe { libc::CreateHardLinkW(dst, src, ptr::mut_null()) }
- })
- }))
+ let src = try!(to_utf16(src));
+ let dst = try!(to_utf16(dst));
+ super::mkerr_winbool(unsafe {
+ libc::CreateHardLinkW(dst.as_ptr(), src.as_ptr(), ptr::mut_null())
+ })
}
fn mkstat(stat: &libc::stat) -> rtio::FileStat {
pub fn stat(p: &CString) -> IoResult<rtio::FileStat> {
let mut stat: libc::stat = unsafe { mem::zeroed() };
- as_utf16_p(p.as_str().unwrap(), |up| {
- match unsafe { libc::wstat(up, &mut stat) } {
- 0 => Ok(mkstat(&stat)),
- _ => Err(super::last_error()),
- }
- })
+ let p = try!(to_utf16(p));
+ match unsafe { libc::wstat(p.as_ptr(), &mut stat) } {
+ 0 => Ok(mkstat(&stat)),
+ _ => Err(super::last_error()),
+ }
}
pub fn lstat(_p: &CString) -> IoResult<rtio::FileStat> {
actime: (atime / 1000) as libc::time64_t,
modtime: (mtime / 1000) as libc::time64_t,
};
- super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::wutime(p, &buf)
- }))
+ let p = try!(to_utf16(p));
+ super::mkerr_libc(unsafe {
+ libc::wutime(p.as_ptr(), &buf)
+ })
}
IoError {
code: ERROR as uint,
extra: 0,
- detail: None,
+ detail: Some("not yet supported by the `native` runtime, maybe try `green`.".to_string()),
}
}
/// Implementation of rt::rtio's IoFactory trait to generate handles to the
/// native I/O functionality.
pub struct IoFactory {
- cannot_construct_outside_of_this_module: ()
+ _cannot_construct_outside_of_this_module: ()
}
impl IoFactory {
pub fn new() -> IoFactory {
net::init();
- IoFactory { cannot_construct_outside_of_this_module: () }
+ IoFactory { _cannot_construct_outside_of_this_module: () }
}
}
struct Inner {
fd: sock_t,
- lock: mutex::NativeMutex,
+
+ // Unused on Linux, where this lock is not necessary.
+ #[allow(dead_code)]
+ lock: mutex::NativeMutex
}
pub struct Guard<'a> {
struct Inner {
fd: fd_t,
- lock: mutex::NativeMutex,
+
+ // Unused on Linux, where this lock is not necessary.
+ #[allow(dead_code)]
+ lock: mutex::NativeMutex
}
impl Inner {
use libc;
use std::c_str::CString;
use std::mem;
-use std::os::win32::as_utf16_p;
use std::os;
use std::ptr;
use std::rt::rtio;
use super::c;
use super::util;
+use super::file::to_utf16;
struct Event(libc::HANDLE);
}
pub fn connect(addr: &CString, timeout: Option<u64>) -> IoResult<UnixStream> {
- as_utf16_p(addr.as_str().unwrap(), |p| {
- let start = ::io::timer::now();
- loop {
- match UnixStream::try_connect(p) {
- Some(handle) => {
- let inner = Inner::new(handle);
- let mut mode = libc::PIPE_TYPE_BYTE |
- libc::PIPE_READMODE_BYTE |
- libc::PIPE_WAIT;
- let ret = unsafe {
- libc::SetNamedPipeHandleState(inner.handle,
- &mut mode,
- ptr::mut_null(),
- ptr::mut_null())
- };
- return if ret == 0 {
- Err(super::last_error())
- } else {
- Ok(UnixStream {
- inner: Arc::new(inner),
- read: None,
- write: None,
- read_deadline: 0,
- write_deadline: 0,
- })
- }
+ let addr = try!(to_utf16(addr));
+ let start = ::io::timer::now();
+ loop {
+ match UnixStream::try_connect(addr.as_ptr()) {
+ Some(handle) => {
+ let inner = Inner::new(handle);
+ let mut mode = libc::PIPE_TYPE_BYTE |
+ libc::PIPE_READMODE_BYTE |
+ libc::PIPE_WAIT;
+ let ret = unsafe {
+ libc::SetNamedPipeHandleState(inner.handle,
+ &mut mode,
+ ptr::mut_null(),
+ ptr::mut_null())
+ };
+ return if ret == 0 {
+ Err(super::last_error())
+ } else {
+ Ok(UnixStream {
+ inner: Arc::new(inner),
+ read: None,
+ write: None,
+ read_deadline: 0,
+ write_deadline: 0,
+ })
}
- None => {}
}
+ None => {}
+ }
- // On windows, if you fail to connect, you may need to call the
- // `WaitNamedPipe` function, and this is indicated with an error
- // code of ERROR_PIPE_BUSY.
- let code = unsafe { libc::GetLastError() };
- if code as int != libc::ERROR_PIPE_BUSY as int {
- return Err(super::last_error())
- }
+ // On windows, if you fail to connect, you may need to call the
+ // `WaitNamedPipe` function, and this is indicated with an error
+ // code of ERROR_PIPE_BUSY.
+ let code = unsafe { libc::GetLastError() };
+ if code as int != libc::ERROR_PIPE_BUSY as int {
+ return Err(super::last_error())
+ }
- match timeout {
- Some(timeout) => {
- let now = ::io::timer::now();
- let timed_out = (now - start) >= timeout || unsafe {
- let ms = (timeout - (now - start)) as libc::DWORD;
- libc::WaitNamedPipeW(p, ms) == 0
- };
- if timed_out {
- return Err(util::timeout("connect timed out"))
- }
+ match timeout {
+ Some(timeout) => {
+ let now = ::io::timer::now();
+ let timed_out = (now - start) >= timeout || unsafe {
+ let ms = (timeout - (now - start)) as libc::DWORD;
+ libc::WaitNamedPipeW(addr.as_ptr(), ms) == 0
+ };
+ if timed_out {
+ return Err(util::timeout("connect timed out"))
}
+ }
- // An example I found on microsoft's website used 20
- // seconds, libuv uses 30 seconds, hence we make the
- // obvious choice of waiting for 25 seconds.
- None => {
- if unsafe { libc::WaitNamedPipeW(p, 25000) } == 0 {
- return Err(super::last_error())
- }
+ // An example I found on microsoft's website used 20
+ // seconds, libuv uses 30 seconds, hence we make the
+ // obvious choice of waiting for 25 seconds.
+ None => {
+ if unsafe { libc::WaitNamedPipeW(addr.as_ptr(), 25000) } == 0 {
+ return Err(super::last_error())
}
}
}
- })
+ }
}
fn handle(&self) -> libc::HANDLE { self.inner.handle }
// Although we technically don't need the pipe until much later, we
// create the initial handle up front to test the validity of the name
// and such.
- as_utf16_p(addr.as_str().unwrap(), |p| {
- let ret = unsafe { pipe(p, true) };
- if ret == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
- Err(super::last_error())
- } else {
- Ok(UnixListener { handle: ret, name: addr.clone() })
- }
- })
+ let addr_v = try!(to_utf16(addr));
+ let ret = unsafe { pipe(addr_v.as_ptr(), true) };
+ if ret == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
+ Err(super::last_error())
+ } else {
+ Ok(UnixListener { handle: ret, name: addr.clone() })
+ }
}
pub fn native_listen(self) -> IoResult<UnixAcceptor> {
// using the original server pipe.
let handle = self.listener.handle;
+ let name = try!(to_utf16(&self.listener.name));
+
// Once we've got a "server handle", we need to wait for a client to
// connect. The ConnectNamedPipe function will block this thread until
// someone on the other end connects. This function can "fail" if a
// Now that we've got a connected client to our handle, we need to
// create a second server pipe. If this fails, we disconnect the
// connected client and return an error (see comments above).
- let new_handle = as_utf16_p(self.listener.name.as_str().unwrap(), |p| {
- unsafe { pipe(p, false) }
- });
+ let new_handle = unsafe { pipe(name.as_ptr(), false) };
if new_handle == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
let ret = Err(super::last_error());
// If our disconnection fails, then there's not really a whole lot
lpSecurityDescriptor: ptr::mut_null(),
bInheritHandle: 1,
};
- *slot = os::win32::as_utf16_p("NUL", |filename| {
- libc::CreateFileW(filename,
- access,
- libc::FILE_SHARE_READ |
- libc::FILE_SHARE_WRITE,
- &mut sa,
- libc::OPEN_EXISTING,
- 0,
- ptr::mut_null())
- });
+ let filename = "NUL".to_utf16().append_one(0);
+ *slot = libc::CreateFileW(filename.as_ptr(),
+ access,
+ libc::FILE_SHARE_READ |
+ libc::FILE_SHARE_WRITE,
+ &mut sa,
+ libc::OPEN_EXISTING,
+ 0,
+ ptr::mut_null());
if *slot == INVALID_HANDLE_VALUE as libc::HANDLE {
return Err(super::last_error())
}
with_envp(cfg.env, |envp| {
with_dirp(cfg.cwd, |dirp| {
- os::win32::as_mut_utf16_p(cmd_str.as_slice(), |cmdp| {
- let created = CreateProcessW(ptr::null(),
- cmdp,
- ptr::mut_null(),
- ptr::mut_null(),
- TRUE,
- flags, envp, dirp,
- &mut si, &mut pi);
- if created == FALSE {
- create_err = Some(super::last_error());
- }
- })
+ let mut cmd_str = cmd_str.to_utf16().append_one(0);
+ let created = CreateProcessW(ptr::null(),
+ cmd_str.as_mut_ptr(),
+ ptr::mut_null(),
+ ptr::mut_null(),
+ TRUE,
+ flags, envp, dirp,
+ &mut si, &mut pi);
+ if created == FALSE {
+ create_err = Some(super::last_error());
+ }
})
});
Some(dir) => {
let dir_str = dir.as_str()
.expect("expected workingdirectory to be utf-8 encoded");
- os::win32::as_utf16_p(dir_str, cb)
+ let dir_str = dir_str.to_utf16().append_one(0);
+ cb(dir_str.as_ptr())
},
None => cb(ptr::null())
}
*/
use Integer;
+use rand::Rng;
-use std::cmp;
+use std::{cmp, fmt};
use std::default::Default;
-use std::fmt;
use std::from_str::FromStr;
use std::num::CheckedDiv;
use std::num::{Bitwise, ToPrimitive, FromPrimitive};
use std::num::{Zero, One, ToStrRadix, FromStrRadix};
-use rand::Rng;
use std::string::String;
-use std::uint;
-use std::{i64, u64};
+use std::{uint, i64, u64};
/**
A `BigDigit` is a `BigUint`'s composing element.
impl PartialOrd for BigUint {
#[inline]
fn lt(&self, other: &BigUint) -> bool {
- match self.cmp(other) { Less => true, _ => false}
+ self.cmp(other) == Less
}
}
impl Default for BigUint {
#[inline]
- fn default() -> BigUint { BigUint::new(Vec::new()) }
+ fn default() -> BigUint { Zero::zero() }
}
impl fmt::Show for BigUint {
impl ToStrRadix for BigUint {
fn to_str_radix(&self, radix: uint) -> String {
- assert!(1 < radix && radix <= 16);
+ assert!(1 < radix && radix <= 16, "The radix must be within (1, 16]");
let (base, max_len) = get_radix_base(radix);
if base == BigDigit::base {
return fill_concat(self.data.as_slice(), radix, max_len)
impl FromStrRadix for BigUint {
/// Creates and initializes a `BigUint`.
#[inline]
- fn from_str_radix(s: &str, radix: uint)
- -> Option<BigUint> {
+ fn from_str_radix(s: &str, radix: uint) -> Option<BigUint> {
BigUint::parse_bytes(s.as_bytes(), radix)
}
}
///
/// The digits are be in base 2^32.
#[inline]
- pub fn new(v: Vec<BigDigit>) -> BigUint {
+ pub fn new(mut digits: Vec<BigDigit>) -> BigUint {
// omit trailing zeros
- let new_len = v.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
-
- if new_len == v.len() { return BigUint { data: v }; }
- let mut v = v;
- v.truncate(new_len);
- return BigUint { data: v };
+ let new_len = digits.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
+ digits.truncate(new_len);
+ BigUint { data: digits }
}
/// Creates and initializes a `BigUint`.
/// The digits are be in base 2^32.
#[inline]
pub fn from_slice(slice: &[BigDigit]) -> BigUint {
- return BigUint::new(Vec::from_slice(slice));
+ BigUint::new(Vec::from_slice(slice))
}
/// Creates and initializes a `BigUint`.
// `DoubleBigDigit` size dependent
#[inline]
fn get_radix_base(radix: uint) -> (DoubleBigDigit, uint) {
- assert!(1 < radix && radix <= 16);
match radix {
2 => (4294967296, 32),
3 => (3486784401, 20),
14 => (1475789056, 8),
15 => (2562890625, 8),
16 => (4294967296, 8),
- _ => fail!()
+ _ => fail!("The radix must be within (1, 16]")
}
}
impl PartialEq for BigInt {
#[inline]
fn eq(&self, other: &BigInt) -> bool {
- match self.cmp(other) { Equal => true, _ => false }
+ self.cmp(other) == Equal
}
}
impl PartialOrd for BigInt {
#[inline]
fn lt(&self, other: &BigInt) -> bool {
- match self.cmp(other) { Less => true, _ => false}
+ self.cmp(other) == Less
}
}
impl Default for BigInt {
#[inline]
- fn default() -> BigInt { BigInt::new(Zero, Vec::new()) }
+ fn default() -> BigInt { Zero::zero() }
}
impl fmt::Show for BigInt {
match (self.sign, other.sign) {
(Zero, _) => other.clone(),
(_, Zero) => self.clone(),
- (Plus, Plus) => BigInt::from_biguint(Plus,
- self.data + other.data),
+ (Plus, Plus) => BigInt::from_biguint(Plus, self.data + other.data),
(Plus, Minus) => self - (-*other),
(Minus, Plus) => other - (-*self),
(Minus, Minus) => -((-self) + (-*other))
#[inline]
fn div(&self, other: &BigInt) -> BigInt {
let (q, _) = self.div_rem(other);
- return q;
+ q
}
}
#[inline]
fn rem(&self, other: &BigInt) -> BigInt {
let (_, r) = self.div_rem(other);
- return r;
+ r
}
}
#[inline]
fn div_floor(&self, other: &BigInt) -> BigInt {
let (d, _) = self.div_mod_floor(other);
- return d;
+ d
}
#[inline]
fn mod_floor(&self, other: &BigInt) -> BigInt {
let (_, m) = self.div_mod_floor(other);
- return m;
+ m
}
fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) {
let final_digit: BigDigit = self.gen();
data.push(final_digit >> (BigDigit::bits - rem));
}
- return BigUint::new(data);
+ BigUint::new(data)
}
fn gen_bigint(&mut self, bit_size: uint) -> BigInt {
} else {
Minus
};
- return BigInt::from_biguint(sign, biguint);
+ BigInt::from_biguint(sign, biguint)
}
fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
///
/// The digits are be in base 2^32.
#[inline]
- pub fn new(sign: Sign, v: Vec<BigDigit>) -> BigInt {
- BigInt::from_biguint(sign, BigUint::new(v))
+ pub fn new(sign: Sign, digits: Vec<BigDigit>) -> BigInt {
+ BigInt::from_biguint(sign, BigUint::new(digits))
}
/// Creates and initializes a `BigInt`.
if sign == Zero || data.is_zero() {
return BigInt { sign: Zero, data: Zero::zero() };
}
- return BigInt { sign: sign, data: data };
+ BigInt { sign: sign, data: data }
}
/// Creates and initializes a `BigInt`.
}
/// Creates and initializes a `BigInt`.
- pub fn parse_bytes(buf: &[u8], radix: uint)
- -> Option<BigInt> {
+ pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<BigInt> {
if buf.is_empty() { return None; }
let mut sign = Plus;
let mut start = 0;
--- /dev/null
+// Copyright 2013-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.
+
+//! Integer trait and functions
+
+pub trait Integer: Num + PartialOrd
+ + Div<Self, Self>
+ + Rem<Self, Self> {
+ /// Simultaneous truncated integer division and modulus
+ #[inline]
+ fn div_rem(&self, other: &Self) -> (Self, Self) {
+ (*self / *other, *self % *other)
+ }
+
+ /// Floored integer division
+ ///
+ /// # Examples
+ ///
+ /// ~~~
+ /// # use num::Integer;
+ /// assert!(( 8i).div_floor(& 3) == 2);
+ /// assert!(( 8i).div_floor(&-3) == -3);
+ /// assert!((-8i).div_floor(& 3) == -3);
+ /// assert!((-8i).div_floor(&-3) == 2);
+ ///
+ /// assert!(( 1i).div_floor(& 2) == 0);
+ /// assert!(( 1i).div_floor(&-2) == -1);
+ /// assert!((-1i).div_floor(& 2) == -1);
+ /// assert!((-1i).div_floor(&-2) == 0);
+ /// ~~~
+ fn div_floor(&self, other: &Self) -> Self;
+
+ /// Floored integer modulo, satisfying:
+ ///
+ /// ~~~
+ /// # use num::Integer;
+ /// # let n = 1i; let d = 1i;
+ /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n)
+ /// ~~~
+ ///
+ /// # Examples
+ ///
+ /// ~~~
+ /// # use num::Integer;
+ /// assert!(( 8i).mod_floor(& 3) == 2);
+ /// assert!(( 8i).mod_floor(&-3) == -1);
+ /// assert!((-8i).mod_floor(& 3) == 1);
+ /// assert!((-8i).mod_floor(&-3) == -2);
+ ///
+ /// assert!(( 1i).mod_floor(& 2) == 1);
+ /// assert!(( 1i).mod_floor(&-2) == -1);
+ /// assert!((-1i).mod_floor(& 2) == 1);
+ /// assert!((-1i).mod_floor(&-2) == -1);
+ /// ~~~
+ fn mod_floor(&self, other: &Self) -> Self;
+
+ /// Simultaneous floored integer division and modulus
+ fn div_mod_floor(&self, other: &Self) -> (Self, Self) {
+ (self.div_floor(other), self.mod_floor(other))
+ }
+
+ /// Greatest Common Divisor (GCD)
+ fn gcd(&self, other: &Self) -> Self;
+
+ /// Lowest Common Multiple (LCM)
+ fn lcm(&self, other: &Self) -> Self;
+
+ /// Returns `true` if `other` divides evenly into `self`
+ fn divides(&self, other: &Self) -> bool;
+
+ /// Returns `true` if the number is even
+ fn is_even(&self) -> bool;
+
+ /// Returns `true` if the number is odd
+ fn is_odd(&self) -> bool;
+}
+
+/// Simultaneous integer division and modulus
+#[inline] pub fn div_rem<T: Integer>(x: T, y: T) -> (T, T) { x.div_rem(&y) }
+/// Floored integer division
+#[inline] pub fn div_floor<T: Integer>(x: T, y: T) -> T { x.div_floor(&y) }
+/// Floored integer modulus
+#[inline] pub fn mod_floor<T: Integer>(x: T, y: T) -> T { x.mod_floor(&y) }
+/// Simultaneous floored integer division and modulus
+#[inline] pub fn div_mod_floor<T: Integer>(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) }
+
+/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The
+/// result is always positive.
+#[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
+/// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
+#[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
+
+macro_rules! impl_integer_for_int {
+ ($T:ty, $test_mod:ident) => (
+ impl Integer for $T {
+ /// Floored integer division
+ #[inline]
+ fn div_floor(&self, other: &$T) -> $T {
+ // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+ // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+ match self.div_rem(other) {
+ (d, r) if (r > 0 && *other < 0)
+ || (r < 0 && *other > 0) => d - 1,
+ (d, _) => d,
+ }
+ }
+
+ /// Floored integer modulo
+ #[inline]
+ fn mod_floor(&self, other: &$T) -> $T {
+ // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+ // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+ match *self % *other {
+ r if (r > 0 && *other < 0)
+ || (r < 0 && *other > 0) => r + *other,
+ r => r,
+ }
+ }
+
+ /// Calculates `div_floor` and `mod_floor` simultaneously
+ #[inline]
+ fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
+ // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+ // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+ match self.div_rem(other) {
+ (d, r) if (r > 0 && *other < 0)
+ || (r < 0 && *other > 0) => (d - 1, r + *other),
+ (d, r) => (d, r),
+ }
+ }
+
+ /// Calculates the Greatest Common Divisor (GCD) of the number and
+ /// `other`. The result is always positive.
+ #[inline]
+ fn gcd(&self, other: &$T) -> $T {
+ // Use Euclid's algorithm
+ let mut m = *self;
+ let mut n = *other;
+ while m != 0 {
+ let temp = m;
+ m = n % temp;
+ n = temp;
+ }
+ n.abs()
+ }
+
+ /// Calculates the Lowest Common Multiple (LCM) of the number and
+ /// `other`.
+ #[inline]
+ fn lcm(&self, other: &$T) -> $T {
+ // should not have to recalculate abs
+ ((*self * *other) / self.gcd(other)).abs()
+ }
+
+ /// Returns `true` if the number can be divided by `other` without
+ /// leaving a remainder
+ #[inline]
+ fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
+
+ /// Returns `true` if the number is divisible by `2`
+ #[inline]
+ fn is_even(&self) -> bool { self & 1 == 0 }
+
+ /// Returns `true` if the number is not divisible by `2`
+ #[inline]
+ fn is_odd(&self) -> bool { !self.is_even() }
+ }
+
+ #[cfg(test)]
+ mod $test_mod {
+ use Integer;
+
+ /// Checks that the division rule holds for:
+ ///
+ /// - `n`: numerator (dividend)
+ /// - `d`: denominator (divisor)
+ /// - `qr`: quotient and remainder
+ #[cfg(test)]
+ fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) {
+ assert_eq!(d * q + r, n);
+ }
+
+ #[test]
+ fn test_div_rem() {
+ fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
+ let (n,d) = nd;
+ let separate_div_rem = (n / d, n % d);
+ let combined_div_rem = n.div_rem(&d);
+
+ assert_eq!(separate_div_rem, qr);
+ assert_eq!(combined_div_rem, qr);
+
+ test_division_rule(nd, separate_div_rem);
+ test_division_rule(nd, combined_div_rem);
+ }
+
+ test_nd_dr(( 8, 3), ( 2, 2));
+ test_nd_dr(( 8, -3), (-2, 2));
+ test_nd_dr((-8, 3), (-2, -2));
+ test_nd_dr((-8, -3), ( 2, -2));
+
+ test_nd_dr(( 1, 2), ( 0, 1));
+ test_nd_dr(( 1, -2), ( 0, 1));
+ test_nd_dr((-1, 2), ( 0, -1));
+ test_nd_dr((-1, -2), ( 0, -1));
+ }
+
+ #[test]
+ fn test_div_mod_floor() {
+ fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
+ let (n,d) = nd;
+ let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
+ let combined_div_mod_floor = n.div_mod_floor(&d);
+
+ assert_eq!(separate_div_mod_floor, dm);
+ assert_eq!(combined_div_mod_floor, dm);
+
+ test_division_rule(nd, separate_div_mod_floor);
+ test_division_rule(nd, combined_div_mod_floor);
+ }
+
+ test_nd_dm(( 8, 3), ( 2, 2));
+ test_nd_dm(( 8, -3), (-3, -1));
+ test_nd_dm((-8, 3), (-3, 1));
+ test_nd_dm((-8, -3), ( 2, -2));
+
+ test_nd_dm(( 1, 2), ( 0, 1));
+ test_nd_dm(( 1, -2), (-1, -1));
+ test_nd_dm((-1, 2), (-1, 1));
+ test_nd_dm((-1, -2), ( 0, -1));
+ }
+
+ #[test]
+ fn test_gcd() {
+ assert_eq!((10 as $T).gcd(&2), 2 as $T);
+ assert_eq!((10 as $T).gcd(&3), 1 as $T);
+ assert_eq!((0 as $T).gcd(&3), 3 as $T);
+ assert_eq!((3 as $T).gcd(&3), 3 as $T);
+ assert_eq!((56 as $T).gcd(&42), 14 as $T);
+ assert_eq!((3 as $T).gcd(&-3), 3 as $T);
+ assert_eq!((-6 as $T).gcd(&3), 3 as $T);
+ assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
+ }
+
+ #[test]
+ fn test_lcm() {
+ assert_eq!((1 as $T).lcm(&0), 0 as $T);
+ assert_eq!((0 as $T).lcm(&1), 0 as $T);
+ assert_eq!((1 as $T).lcm(&1), 1 as $T);
+ assert_eq!((-1 as $T).lcm(&1), 1 as $T);
+ assert_eq!((1 as $T).lcm(&-1), 1 as $T);
+ assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
+ assert_eq!((8 as $T).lcm(&9), 72 as $T);
+ assert_eq!((11 as $T).lcm(&5), 55 as $T);
+ }
+
+ #[test]
+ fn test_even() {
+ assert_eq!((-4 as $T).is_even(), true);
+ assert_eq!((-3 as $T).is_even(), false);
+ assert_eq!((-2 as $T).is_even(), true);
+ assert_eq!((-1 as $T).is_even(), false);
+ assert_eq!((0 as $T).is_even(), true);
+ assert_eq!((1 as $T).is_even(), false);
+ assert_eq!((2 as $T).is_even(), true);
+ assert_eq!((3 as $T).is_even(), false);
+ assert_eq!((4 as $T).is_even(), true);
+ }
+
+ #[test]
+ fn test_odd() {
+ assert_eq!((-4 as $T).is_odd(), false);
+ assert_eq!((-3 as $T).is_odd(), true);
+ assert_eq!((-2 as $T).is_odd(), false);
+ assert_eq!((-1 as $T).is_odd(), true);
+ assert_eq!((0 as $T).is_odd(), false);
+ assert_eq!((1 as $T).is_odd(), true);
+ assert_eq!((2 as $T).is_odd(), false);
+ assert_eq!((3 as $T).is_odd(), true);
+ assert_eq!((4 as $T).is_odd(), false);
+ }
+ }
+ )
+}
+
+impl_integer_for_int!(i8, test_integer_i8)
+impl_integer_for_int!(i16, test_integer_i16)
+impl_integer_for_int!(i32, test_integer_i32)
+impl_integer_for_int!(i64, test_integer_i64)
+impl_integer_for_int!(int, test_integer_int)
+
+macro_rules! impl_integer_for_uint {
+ ($T:ty, $test_mod:ident) => (
+ impl Integer for $T {
+ /// Unsigned integer division. Returns the same result as `div` (`/`).
+ #[inline]
+ fn div_floor(&self, other: &$T) -> $T { *self / *other }
+
+ /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
+ #[inline]
+ fn mod_floor(&self, other: &$T) -> $T { *self % *other }
+
+ /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
+ #[inline]
+ fn gcd(&self, other: &$T) -> $T {
+ // Use Euclid's algorithm
+ let mut m = *self;
+ let mut n = *other;
+ while m != 0 {
+ let temp = m;
+ m = n % temp;
+ n = temp;
+ }
+ n
+ }
+
+ /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
+ #[inline]
+ fn lcm(&self, other: &$T) -> $T {
+ (*self * *other) / self.gcd(other)
+ }
+
+ /// Returns `true` if the number can be divided by `other` without leaving a remainder
+ #[inline]
+ fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
+
+ /// Returns `true` if the number is divisible by `2`
+ #[inline]
+ fn is_even(&self) -> bool { self & 1 == 0 }
+
+ /// Returns `true` if the number is not divisible by `2`
+ #[inline]
+ fn is_odd(&self) -> bool { !self.is_even() }
+ }
+
+ #[cfg(test)]
+ mod $test_mod {
+ use Integer;
+
+ #[test]
+ fn test_div_mod_floor() {
+ assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T);
+ assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T);
+ assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T));
+ assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T);
+ assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T);
+ assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T));
+ assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T);
+ assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T);
+ assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T));
+ }
+
+ #[test]
+ fn test_gcd() {
+ assert_eq!((10 as $T).gcd(&2), 2 as $T);
+ assert_eq!((10 as $T).gcd(&3), 1 as $T);
+ assert_eq!((0 as $T).gcd(&3), 3 as $T);
+ assert_eq!((3 as $T).gcd(&3), 3 as $T);
+ assert_eq!((56 as $T).gcd(&42), 14 as $T);
+ }
+
+ #[test]
+ fn test_lcm() {
+ assert_eq!((1 as $T).lcm(&0), 0 as $T);
+ assert_eq!((0 as $T).lcm(&1), 0 as $T);
+ assert_eq!((1 as $T).lcm(&1), 1 as $T);
+ assert_eq!((8 as $T).lcm(&9), 72 as $T);
+ assert_eq!((11 as $T).lcm(&5), 55 as $T);
+ assert_eq!((99 as $T).lcm(&17), 1683 as $T);
+ }
+
+ #[test]
+ fn test_divides() {
+ assert!((6 as $T).divides(&(6 as $T)));
+ assert!((6 as $T).divides(&(3 as $T)));
+ assert!((6 as $T).divides(&(1 as $T)));
+ }
+
+ #[test]
+ fn test_even() {
+ assert_eq!((0 as $T).is_even(), true);
+ assert_eq!((1 as $T).is_even(), false);
+ assert_eq!((2 as $T).is_even(), true);
+ assert_eq!((3 as $T).is_even(), false);
+ assert_eq!((4 as $T).is_even(), true);
+ }
+
+ #[test]
+ fn test_odd() {
+ assert_eq!((0 as $T).is_odd(), false);
+ assert_eq!((1 as $T).is_odd(), true);
+ assert_eq!((2 as $T).is_odd(), false);
+ assert_eq!((3 as $T).is_odd(), true);
+ assert_eq!((4 as $T).is_odd(), false);
+ }
+ }
+ )
+}
+
+impl_integer_for_uint!(u8, test_integer_u8)
+impl_integer_for_uint!(u16, test_integer_u16)
+impl_integer_for_uint!(u32, test_integer_u32)
+impl_integer_for_uint!(u64, test_integer_u64)
+impl_integer_for_uint!(uint, test_integer_uint)
extern crate rand;
+pub use bigint::{BigInt, BigUint};
+pub use rational::{Rational, BigRational};
+pub use complex::Complex;
+pub use integer::Integer;
+
pub mod bigint;
-pub mod rational;
pub mod complex;
-
-pub trait Integer: Num + PartialOrd
- + Div<Self, Self>
- + Rem<Self, Self> {
- /// Simultaneous truncated integer division and modulus
- #[inline]
- fn div_rem(&self, other: &Self) -> (Self, Self) {
- (*self / *other, *self % *other)
- }
-
- /// Floored integer division
- ///
- /// # Examples
- ///
- /// ~~~
- /// # use num::Integer;
- /// assert!(( 8i).div_floor(& 3) == 2);
- /// assert!(( 8i).div_floor(&-3) == -3);
- /// assert!((-8i).div_floor(& 3) == -3);
- /// assert!((-8i).div_floor(&-3) == 2);
- ///
- /// assert!(( 1i).div_floor(& 2) == 0);
- /// assert!(( 1i).div_floor(&-2) == -1);
- /// assert!((-1i).div_floor(& 2) == -1);
- /// assert!((-1i).div_floor(&-2) == 0);
- /// ~~~
- fn div_floor(&self, other: &Self) -> Self;
-
- /// Floored integer modulo, satisfying:
- ///
- /// ~~~
- /// # use num::Integer;
- /// # let n = 1i; let d = 1i;
- /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n)
- /// ~~~
- ///
- /// # Examples
- ///
- /// ~~~
- /// # use num::Integer;
- /// assert!(( 8i).mod_floor(& 3) == 2);
- /// assert!(( 8i).mod_floor(&-3) == -1);
- /// assert!((-8i).mod_floor(& 3) == 1);
- /// assert!((-8i).mod_floor(&-3) == -2);
- ///
- /// assert!(( 1i).mod_floor(& 2) == 1);
- /// assert!(( 1i).mod_floor(&-2) == -1);
- /// assert!((-1i).mod_floor(& 2) == 1);
- /// assert!((-1i).mod_floor(&-2) == -1);
- /// ~~~
- fn mod_floor(&self, other: &Self) -> Self;
-
- /// Simultaneous floored integer division and modulus
- fn div_mod_floor(&self, other: &Self) -> (Self, Self) {
- (self.div_floor(other), self.mod_floor(other))
- }
-
- /// Greatest Common Divisor (GCD)
- fn gcd(&self, other: &Self) -> Self;
-
- /// Lowest Common Multiple (LCM)
- fn lcm(&self, other: &Self) -> Self;
-
- /// Returns `true` if `other` divides evenly into `self`
- fn divides(&self, other: &Self) -> bool;
-
- /// Returns `true` if the number is even
- fn is_even(&self) -> bool;
-
- /// Returns `true` if the number is odd
- fn is_odd(&self) -> bool;
-}
-
-/// Simultaneous integer division and modulus
-#[inline] pub fn div_rem<T: Integer>(x: T, y: T) -> (T, T) { x.div_rem(&y) }
-/// Floored integer division
-#[inline] pub fn div_floor<T: Integer>(x: T, y: T) -> T { x.div_floor(&y) }
-/// Floored integer modulus
-#[inline] pub fn mod_floor<T: Integer>(x: T, y: T) -> T { x.mod_floor(&y) }
-/// Simultaneous floored integer division and modulus
-#[inline] pub fn div_mod_floor<T: Integer>(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) }
-
-/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The
-/// result is always positive.
-#[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
-/// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
-#[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
-
-macro_rules! impl_integer_for_int {
- ($T:ty, $test_mod:ident) => (
- impl Integer for $T {
- /// Floored integer division
- #[inline]
- fn div_floor(&self, other: &$T) -> $T {
- // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
- // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
- match self.div_rem(other) {
- (d, r) if (r > 0 && *other < 0)
- || (r < 0 && *other > 0) => d - 1,
- (d, _) => d,
- }
- }
-
- /// Floored integer modulo
- #[inline]
- fn mod_floor(&self, other: &$T) -> $T {
- // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
- // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
- match *self % *other {
- r if (r > 0 && *other < 0)
- || (r < 0 && *other > 0) => r + *other,
- r => r,
- }
- }
-
- /// Calculates `div_floor` and `mod_floor` simultaneously
- #[inline]
- fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
- // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
- // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
- match self.div_rem(other) {
- (d, r) if (r > 0 && *other < 0)
- || (r < 0 && *other > 0) => (d - 1, r + *other),
- (d, r) => (d, r),
- }
- }
-
- /// Calculates the Greatest Common Divisor (GCD) of the number and
- /// `other`. The result is always positive.
- #[inline]
- fn gcd(&self, other: &$T) -> $T {
- // Use Euclid's algorithm
- let mut m = *self;
- let mut n = *other;
- while m != 0 {
- let temp = m;
- m = n % temp;
- n = temp;
- }
- n.abs()
- }
-
- /// Calculates the Lowest Common Multiple (LCM) of the number and
- /// `other`.
- #[inline]
- fn lcm(&self, other: &$T) -> $T {
- // should not have to recalculate abs
- ((*self * *other) / self.gcd(other)).abs()
- }
-
- /// Returns `true` if the number can be divided by `other` without
- /// leaving a remainder
- #[inline]
- fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
-
- /// Returns `true` if the number is divisible by `2`
- #[inline]
- fn is_even(&self) -> bool { self & 1 == 0 }
-
- /// Returns `true` if the number is not divisible by `2`
- #[inline]
- fn is_odd(&self) -> bool { !self.is_even() }
- }
-
- #[cfg(test)]
- mod $test_mod {
- use Integer;
-
- /// Checks that the division rule holds for:
- ///
- /// - `n`: numerator (dividend)
- /// - `d`: denominator (divisor)
- /// - `qr`: quotient and remainder
- #[cfg(test)]
- fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) {
- assert_eq!(d * q + r, n);
- }
-
- #[test]
- fn test_div_rem() {
- fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
- let (n,d) = nd;
- let separate_div_rem = (n / d, n % d);
- let combined_div_rem = n.div_rem(&d);
-
- assert_eq!(separate_div_rem, qr);
- assert_eq!(combined_div_rem, qr);
-
- test_division_rule(nd, separate_div_rem);
- test_division_rule(nd, combined_div_rem);
- }
-
- test_nd_dr(( 8, 3), ( 2, 2));
- test_nd_dr(( 8, -3), (-2, 2));
- test_nd_dr((-8, 3), (-2, -2));
- test_nd_dr((-8, -3), ( 2, -2));
-
- test_nd_dr(( 1, 2), ( 0, 1));
- test_nd_dr(( 1, -2), ( 0, 1));
- test_nd_dr((-1, 2), ( 0, -1));
- test_nd_dr((-1, -2), ( 0, -1));
- }
-
- #[test]
- fn test_div_mod_floor() {
- fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
- let (n,d) = nd;
- let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
- let combined_div_mod_floor = n.div_mod_floor(&d);
-
- assert_eq!(separate_div_mod_floor, dm);
- assert_eq!(combined_div_mod_floor, dm);
-
- test_division_rule(nd, separate_div_mod_floor);
- test_division_rule(nd, combined_div_mod_floor);
- }
-
- test_nd_dm(( 8, 3), ( 2, 2));
- test_nd_dm(( 8, -3), (-3, -1));
- test_nd_dm((-8, 3), (-3, 1));
- test_nd_dm((-8, -3), ( 2, -2));
-
- test_nd_dm(( 1, 2), ( 0, 1));
- test_nd_dm(( 1, -2), (-1, -1));
- test_nd_dm((-1, 2), (-1, 1));
- test_nd_dm((-1, -2), ( 0, -1));
- }
-
- #[test]
- fn test_gcd() {
- assert_eq!((10 as $T).gcd(&2), 2 as $T);
- assert_eq!((10 as $T).gcd(&3), 1 as $T);
- assert_eq!((0 as $T).gcd(&3), 3 as $T);
- assert_eq!((3 as $T).gcd(&3), 3 as $T);
- assert_eq!((56 as $T).gcd(&42), 14 as $T);
- assert_eq!((3 as $T).gcd(&-3), 3 as $T);
- assert_eq!((-6 as $T).gcd(&3), 3 as $T);
- assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
- }
-
- #[test]
- fn test_lcm() {
- assert_eq!((1 as $T).lcm(&0), 0 as $T);
- assert_eq!((0 as $T).lcm(&1), 0 as $T);
- assert_eq!((1 as $T).lcm(&1), 1 as $T);
- assert_eq!((-1 as $T).lcm(&1), 1 as $T);
- assert_eq!((1 as $T).lcm(&-1), 1 as $T);
- assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
- assert_eq!((8 as $T).lcm(&9), 72 as $T);
- assert_eq!((11 as $T).lcm(&5), 55 as $T);
- }
-
- #[test]
- fn test_even() {
- assert_eq!((-4 as $T).is_even(), true);
- assert_eq!((-3 as $T).is_even(), false);
- assert_eq!((-2 as $T).is_even(), true);
- assert_eq!((-1 as $T).is_even(), false);
- assert_eq!((0 as $T).is_even(), true);
- assert_eq!((1 as $T).is_even(), false);
- assert_eq!((2 as $T).is_even(), true);
- assert_eq!((3 as $T).is_even(), false);
- assert_eq!((4 as $T).is_even(), true);
- }
-
- #[test]
- fn test_odd() {
- assert_eq!((-4 as $T).is_odd(), false);
- assert_eq!((-3 as $T).is_odd(), true);
- assert_eq!((-2 as $T).is_odd(), false);
- assert_eq!((-1 as $T).is_odd(), true);
- assert_eq!((0 as $T).is_odd(), false);
- assert_eq!((1 as $T).is_odd(), true);
- assert_eq!((2 as $T).is_odd(), false);
- assert_eq!((3 as $T).is_odd(), true);
- assert_eq!((4 as $T).is_odd(), false);
- }
- }
- )
-}
-
-impl_integer_for_int!(i8, test_integer_i8)
-impl_integer_for_int!(i16, test_integer_i16)
-impl_integer_for_int!(i32, test_integer_i32)
-impl_integer_for_int!(i64, test_integer_i64)
-impl_integer_for_int!(int, test_integer_int)
-
-macro_rules! impl_integer_for_uint {
- ($T:ty, $test_mod:ident) => (
- impl Integer for $T {
- /// Unsigned integer division. Returns the same result as `div` (`/`).
- #[inline]
- fn div_floor(&self, other: &$T) -> $T { *self / *other }
-
- /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
- #[inline]
- fn mod_floor(&self, other: &$T) -> $T { *self % *other }
-
- /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
- #[inline]
- fn gcd(&self, other: &$T) -> $T {
- // Use Euclid's algorithm
- let mut m = *self;
- let mut n = *other;
- while m != 0 {
- let temp = m;
- m = n % temp;
- n = temp;
- }
- n
- }
-
- /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
- #[inline]
- fn lcm(&self, other: &$T) -> $T {
- (*self * *other) / self.gcd(other)
- }
-
- /// Returns `true` if the number can be divided by `other` without leaving a remainder
- #[inline]
- fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
-
- /// Returns `true` if the number is divisible by `2`
- #[inline]
- fn is_even(&self) -> bool { self & 1 == 0 }
-
- /// Returns `true` if the number is not divisible by `2`
- #[inline]
- fn is_odd(&self) -> bool { !self.is_even() }
- }
-
- #[cfg(test)]
- mod $test_mod {
- use Integer;
-
- #[test]
- fn test_div_mod_floor() {
- assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T);
- assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T);
- assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T));
- assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T);
- assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T);
- assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T));
- assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T);
- assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T);
- assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T));
- }
-
- #[test]
- fn test_gcd() {
- assert_eq!((10 as $T).gcd(&2), 2 as $T);
- assert_eq!((10 as $T).gcd(&3), 1 as $T);
- assert_eq!((0 as $T).gcd(&3), 3 as $T);
- assert_eq!((3 as $T).gcd(&3), 3 as $T);
- assert_eq!((56 as $T).gcd(&42), 14 as $T);
- }
-
- #[test]
- fn test_lcm() {
- assert_eq!((1 as $T).lcm(&0), 0 as $T);
- assert_eq!((0 as $T).lcm(&1), 0 as $T);
- assert_eq!((1 as $T).lcm(&1), 1 as $T);
- assert_eq!((8 as $T).lcm(&9), 72 as $T);
- assert_eq!((11 as $T).lcm(&5), 55 as $T);
- assert_eq!((99 as $T).lcm(&17), 1683 as $T);
- }
-
- #[test]
- fn test_divides() {
- assert!((6 as $T).divides(&(6 as $T)));
- assert!((6 as $T).divides(&(3 as $T)));
- assert!((6 as $T).divides(&(1 as $T)));
- }
-
- #[test]
- fn test_even() {
- assert_eq!((0 as $T).is_even(), true);
- assert_eq!((1 as $T).is_even(), false);
- assert_eq!((2 as $T).is_even(), true);
- assert_eq!((3 as $T).is_even(), false);
- assert_eq!((4 as $T).is_even(), true);
- }
-
- #[test]
- fn test_odd() {
- assert_eq!((0 as $T).is_odd(), false);
- assert_eq!((1 as $T).is_odd(), true);
- assert_eq!((2 as $T).is_odd(), false);
- assert_eq!((3 as $T).is_odd(), true);
- assert_eq!((4 as $T).is_odd(), false);
- }
- }
- )
-}
-
-impl_integer_for_uint!(u8, test_integer_u8)
-impl_integer_for_uint!(u16, test_integer_u16)
-impl_integer_for_uint!(u32, test_integer_u32)
-impl_integer_for_uint!(u64, test_integer_u64)
-impl_integer_for_uint!(uint, test_integer_uint)
+pub mod integer;
+pub mod rational;
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaLargeShape {
- shape: f64,
scale: f64,
c: f64,
d: f64
fn new_raw(shape: f64, scale: f64) -> GammaLargeShape {
let d = shape - 1. / 3.;
GammaLargeShape {
- shape: shape,
scale: scale,
c: 1. / (9. * d).sqrt(),
d: d
#![no_std]
#![experimental]
+#[cfg(stage0)]
#[phase(syntax, link)]
extern crate core;
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate core;
+
+#[cfg(test, stage0)]
+#[phase(syntax, link)] extern crate std;
+
+#[cfg(test, stage0)]
+#[phase(syntax, link)] extern crate log;
+
+#[cfg(test, not(stage0))]
+#[phase(plugin, link)] extern crate std;
+
+#[cfg(test, not(stage0))]
+#[phase(plugin, link)] extern crate log;
+
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate std;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
use core::prelude::*;
//!
//! ```rust
//! #![feature(phase)]
-//! #[phase(syntax)]
+//! #[phase(plugin)]
//! extern crate regex_macros;
//! extern crate regex;
//!
//!
//! ```rust
//! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
//! # fn main() {
//! let re = regex!(r"(\d{4})-(\d{2})-(\d{2})");
//! let text = "2012-03-14, 2013-01-01 and 2014-07-05";
//!
//! ```rust
//! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
//! # fn main() {
//! let re = regex!(r"(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})");
//! let before = "2012-03-14, 2013-01-01 and 2014-07-05";
//!
//! ```rust
//! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
//! # fn main() {
//! let re = regex!(r"(?i)Δ+");
//! assert_eq!(re.find("ΔδΔ"), Some((0, 6)));
//!
//! ```rust
//! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
//! # fn main() {
//! let re = regex!(r"[\pN\p{Greek}\p{Cherokee}]+");
//! assert_eq!(re.find("abcΔᎠβⅠᏴγδⅡxyz"), Some((3, 23)));
//!
//! ```rust
//! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
//! # fn main() {
//! let re = regex!(r"(?i)a+(?-i)b+");
//! let cap = re.captures("AaAaAbbBBBb").unwrap();
/// ```rust
/// #![feature(phase)]
/// extern crate regex;
-/// #[phase(syntax)] extern crate regex_macros;
+/// #[phase(plugin)] extern crate regex_macros;
///
/// fn main() {
/// let re = regex!(r"\d+");
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let text = "I categorically deny having triskaidekaphobia.";
/// let matched = regex!(r"\b\w{13}\b").is_match(text);
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let text = "I categorically deny having triskaidekaphobia.";
/// let pos = regex!(r"\b\w{13}\b").find(text);
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let text = "Retroactively relinquishing remunerations is reprehensible.";
/// for pos in regex!(r"\b\w{13}\b").find_iter(text) {
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!(r"'([^']+)'\s+\((\d{4})\)");
/// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
/// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
/// let text = "'Citizen Kane' (1941), 'The Wizard of Oz' (1939), 'M' (1931).";
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!(r"[ \t]+");
/// let fields: Vec<&str> = re.split("a b \t c\td e").collect();
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!(r"\W+");
/// let fields: Vec<&str> = re.splitn("Hey! How are you?", 3).collect();
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!("[^01]+");
/// assert_eq!(re.replace("1078910", "").as_slice(), "1010");
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # use regex::Captures; fn main() {
/// let re = regex!(r"([^,\s]+),\s+(\S+)");
/// let result = re.replace("Springsteen, Bruce", |caps: &Captures| {
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!(r"(?P<last>[^,\s]+),\s+(?P<first>\S+)");
/// let result = re.replace("Springsteen, Bruce", "$first $last");
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// use regex::NoExpand;
///
}
}
-impl<'t> Container for Captures<'t> {
+impl<'t> Collection for Captures<'t> {
/// Returns the number of captured groups.
#[inline]
fn len(&self) -> uint {
// except according to those terms.
#[cfg(not(stage1))]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate regex_macros;
#[cfg(not(stage1))]
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/")]
-#![feature(macro_registrar, managed_boxes, quote)]
+#![feature(plugin_registrar, managed_boxes, quote)]
extern crate regex;
extern crate syntax;
+extern crate rustc;
use std::rc::Rc;
use syntax::ast;
use syntax::codemap;
use syntax::ext::build::AstBuilder;
-use syntax::ext::base::{
- SyntaxExtension, ExtCtxt, MacResult, MacExpr, DummyResult,
- NormalTT, BasicMacroExpander,
-};
+use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
use syntax::parse;
use syntax::parse::token;
use syntax::print::pprust;
+use rustc::plugin::Registry;
+
use regex::Regex;
use regex::native::{
OneChar, CharClass, Any, Save, Jump, Split,
};
/// For the `regex!` syntax extension. Do not use.
-#[macro_registrar]
+#[plugin_registrar]
#[doc(hidden)]
-pub fn macro_registrar(register: |ast::Name, SyntaxExtension|) {
- let expander = box BasicMacroExpander { expander: native, span: None };
- register(token::intern("regex"), NormalTT(expander, None))
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("regex", native);
}
/// Generates specialized code for the Pike VM for a particular regular
use lib::llvm::{ContextRef, ModuleRef};
use metadata::common::LinkMeta;
use metadata::creader;
-use metadata::creader::Loader;
use middle::cfg;
use middle::cfg::graphviz::LabelledCFG;
use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
use middle::dependency_format;
use middle;
+use plugin::load::Plugins;
+use plugin::registry::Registry;
+use plugin;
use util::common::time;
use util::ppaux;
use util::nodemap::{NodeSet};
use syntax::attr;
use syntax::attr::{AttrMetaMethods};
use syntax::crateid::CrateId;
-use syntax::ext::base::CrateLoader;
use syntax::parse;
use syntax::parse::token;
use syntax::print::{pp, pprust};
output,
krate.attrs.as_slice(),
&sess);
- let loader = &mut Loader::new(&sess);
let id = link::find_crate_id(krate.attrs.as_slice(),
outputs.out_filestem.as_slice());
let (expanded_crate, ast_map) =
- phase_2_configure_and_expand(&sess, loader, krate, &id);
+ phase_2_configure_and_expand(&sess, krate, &id);
(outputs, expanded_crate, ast_map)
};
write_out_deps(&sess, input, &outputs, &expanded_crate);
/// harness if one is to be provided and injection of a dependency on the
/// standard library and prelude.
pub fn phase_2_configure_and_expand(sess: &Session,
- loader: &mut CrateLoader,
mut krate: ast::Crate,
crate_id: &CrateId)
-> (ast::Crate, syntax::ast_map::Map) {
krate = time(time_passes, "configuration 1", krate, |krate|
front::config::strip_unconfigured_items(krate));
- krate = time(time_passes, "expansion", krate, |krate| {
- // Windows dlls do not have rpaths, so they don't know how to find their
- // dependencies. It's up to us to tell the system where to find all the
- // dependent dlls. Note that this uses cfg!(windows) as opposed to
- // targ_cfg because syntax extensions are always loaded for the host
- // compiler, not for the target.
- if cfg!(windows) {
- sess.host_filesearch().add_dylib_search_paths();
+ let Plugins { macros, registrars }
+ = time(time_passes, "plugin loading", (), |_|
+ plugin::load::load_plugins(sess, &krate));
+
+ let mut registry = Registry::new(&krate);
+
+ time(time_passes, "plugin registration", (), |_| {
+ for ®istrar in registrars.iter() {
+ registrar(&mut registry);
}
- let cfg = syntax::ext::expand::ExpansionConfig {
- loader: loader,
- deriving_hash_type_parameter: sess.features.default_type_params.get(),
- crate_id: crate_id.clone(),
- };
- syntax::ext::expand::expand_crate(&sess.parse_sess,
- cfg,
- krate)
});
+ let Registry { syntax_exts, .. } = registry;
+
+ krate = time(time_passes, "expansion", (krate, macros, syntax_exts),
+ |(krate, macros, syntax_exts)| {
+ // Windows dlls do not have rpaths, so they don't know how to find their
+ // dependencies. It's up to us to tell the system where to find all the
+ // dependent dlls. Note that this uses cfg!(windows) as opposed to
+ // targ_cfg because syntax extensions are always loaded for the host
+ // compiler, not for the target.
+ if cfg!(windows) {
+ sess.host_filesearch().add_dylib_search_paths();
+ }
+ let cfg = syntax::ext::expand::ExpansionConfig {
+ deriving_hash_type_parameter: sess.features.default_type_params.get(),
+ crate_id: crate_id.clone(),
+ };
+ syntax::ext::expand::expand_crate(&sess.parse_sess,
+ cfg,
+ macros,
+ syntax_exts,
+ krate)
+ }
+ );
+
// strip again, in case expansion added anything with a #[cfg].
krate = time(time_passes, "configuration 2", krate, |krate|
front::config::strip_unconfigured_items(krate));
time(time_passes, "looking for entry point", (),
|_| middle::entry::find_entry_point(&sess, krate, &ast_map));
- sess.macro_registrar_fn.set(
- time(time_passes, "looking for macro registrar", (), |_|
- syntax::ext::registrar::find_macro_registrar(
+ sess.plugin_registrar_fn.set(
+ time(time_passes, "looking for plugin registrar", (), |_|
+ plugin::build::find_plugin_registrar(
sess.diagnostic(), krate)));
let freevars = time(time_passes, "freevar finding", (), |_|
let (krate, ast_map, is_expanded) = match ppm {
PpmExpanded | PpmExpandedIdentified | PpmTyped | PpmFlowGraph(_) => {
- let loader = &mut Loader::new(&sess);
let (krate, ast_map) = phase_2_configure_and_expand(&sess,
- loader,
krate,
&id);
(krate, Some(ast_map), true)
// For a library crate, this is always none
pub entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
pub entry_type: Cell<Option<config::EntryFnType>>,
- pub macro_registrar_fn: Cell<Option<ast::NodeId>>,
+ pub plugin_registrar_fn: Cell<Option<ast::NodeId>>,
pub default_sysroot: Option<Path>,
// The name of the root source file of the crate, in the local file system. The path is always
// expected to be absolute. `None` means that there is no source file.
// For a library crate, this is always none
entry_fn: RefCell::new(None),
entry_type: Cell::new(None),
- macro_registrar_fn: Cell::new(None),
+ plugin_registrar_fn: Cell::new(None),
default_sysroot: default_sysroot,
local_crate_source_file: local_crate_source_file,
working_dir: os::getcwd(),
("thread_local", Active),
("link_args", Active),
("phase", Active),
- ("macro_registrar", Active),
+ ("plugin_registrar", Active),
("log_syntax", Active),
("trace_macros", Active),
("concat_idents", Active),
("quote", Active),
("linkage", Active),
("struct_inherit", Active),
+ ("overloaded_calls", Active),
+ ("unboxed_closure_sugar", Active),
("quad_precision_float", Active),
pub default_type_params: Cell<bool>,
pub quad_precision_float: Cell<bool>,
pub issue_5723_bootstrap: Cell<bool>,
+ pub overloaded_calls: Cell<bool>,
}
impl Features {
default_type_params: Cell::new(false),
quad_precision_float: Cell::new(false),
issue_5723_bootstrap: Cell::new(false),
+ overloaded_calls: Cell::new(false),
}
}
}
}
ast::ItemFn(..) => {
- if attr::contains_name(i.attrs.as_slice(), "macro_registrar") {
- self.gate_feature("macro_registrar", i.span,
- "cross-crate macro exports are \
- experimental and possibly buggy");
+ if attr::contains_name(i.attrs.as_slice(), "plugin_registrar") {
+ self.gate_feature("plugin_registrar", i.span,
+ "compiler plugins are experimental and possibly buggy");
}
}
},
ast::TyBox(_) => { self.gate_box(t.span); }
+ ast::TyUnboxedFn(_) => {
+ self.gate_feature("unboxed_closure_sugar",
+ t.span,
+ "unboxed closure trait sugar is experimental");
+ }
_ => {}
}
sess.features.default_type_params.set(cx.has_feature("default_type_params"));
sess.features.quad_precision_float.set(cx.has_feature("quad_precision_float"));
sess.features.issue_5723_bootstrap.set(cx.has_feature("issue_5723_bootstrap"));
+ sess.features.overloaded_calls.set(cx.has_feature("overloaded_calls"));
}
attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item(
InternedString::new("phase"),
vec!(
- attr::mk_word_item(InternedString::new("syntax")),
+ attr::mk_word_item(InternedString::new("plugin")),
attr::mk_word_item(InternedString::new("link")
))))),
vis: ast::Inherited,
fold.fold_crate(krate)
}
-struct PreludeInjector<'a> {
- sess: &'a Session,
-}
+struct PreludeInjector<'a>;
impl<'a> fold::Folder for PreludeInjector<'a> {
}
}
-fn inject_prelude(sess: &Session, krate: ast::Crate) -> ast::Crate {
- let mut fold = PreludeInjector {
- sess: sess,
- };
+fn inject_prelude(_: &Session, krate: ast::Crate) -> ast::Crate {
+ let mut fold = PreludeInjector;
fold.fold_crate(krate)
}
use driver::session::Session;
use front::config;
use front::std_inject::with_version;
-use metadata::creader::Loader;
use std::cell::RefCell;
use std::slice;
fn generate_test_harness(sess: &Session, krate: ast::Crate)
-> ast::Crate {
- let loader = &mut Loader::new(sess);
let mut cx: TestCtxt = TestCtxt {
sess: sess,
ext_cx: ExtCtxt::new(&sess.parse_sess, sess.opts.cfg.clone(),
ExpansionConfig {
- loader: loader,
deriving_hash_type_parameter: false,
crate_id: from_str("test").unwrap(),
}),
extern crate syntax;
extern crate time;
+#[cfg(stage0)]
#[phase(syntax, link)]
extern crate log;
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
pub mod middle {
pub mod def;
pub mod trans;
pub mod driver;
+pub mod plugin;
+
pub mod util {
pub mod common;
pub mod ppaux;
pub static tag_native_libraries_name: uint = 0x89;
pub static tag_native_libraries_kind: uint = 0x8a;
-pub static tag_macro_registrar_fn: uint = 0x8b;
+pub static tag_plugin_registrar_fn: uint = 0x8b;
pub static tag_exported_macros: uint = 0x8c;
pub static tag_macro_def: uint = 0x8d;
use metadata::decoder;
use metadata::loader;
use metadata::loader::CratePaths;
+use plugin::load::PluginMetadata;
use std::rc::Rc;
use std::collections::HashMap;
use syntax::attr::AttrMetaMethods;
use syntax::codemap::{Span};
use syntax::diagnostic::SpanHandler;
-use syntax::ext::base::{CrateLoader, MacroCrate};
use syntax::parse::token::InternedString;
use syntax::parse::token;
use syntax::crateid::CrateId;
}).collect()
}
-pub struct Loader<'a> {
+pub struct PluginMetadataReader<'a> {
env: Env<'a>,
}
-impl<'a> Loader<'a> {
- pub fn new(sess: &'a Session) -> Loader<'a> {
- Loader {
+impl<'a> PluginMetadataReader<'a> {
+ pub fn new(sess: &'a Session) -> PluginMetadataReader<'a> {
+ PluginMetadataReader {
env: Env {
sess: sess,
next_crate_num: sess.cstore.next_crate_num(),
}
}
}
-}
-impl<'a> CrateLoader for Loader<'a> {
- fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
+ pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata {
let info = extract_crate_info(&self.env, krate).unwrap();
let target_triple = self.env.sess.targ_cfg.target_strs.target_triple.as_slice();
let is_cross = target_triple != driver::host_triple();
load_ctxt.os = config::cfg_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 \
+ if decoder::get_plugin_registrar_fn(lib.metadata.as_slice()).is_some() {
+ let message = format!("crate `{}` contains a plugin_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.as_slice());
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| {
+ let registrar = decoder::get_plugin_registrar_fn(library.metadata.as_slice()).map(|id| {
decoder::get_symbol(library.metadata.as_slice(), id).to_string()
});
- let mc = MacroCrate {
+ let pc = PluginMetadata {
lib: library.dylib.clone(),
macros: macros.move_iter().map(|x| x.to_string()).collect(),
registrar_symbol: registrar,
register_crate(&mut self.env, &None, info.ident.as_slice(),
&info.crate_id, krate.span, library);
}
- mc
+ pc
}
}
let cdata = cstore.get_crate_data(cnum);
decoder::get_reachable_extern_fns(&*cdata)
}
+
+pub fn is_typedef(cstore: &cstore::CStore, did: ast::DefId) -> bool {
+ let cdata = cstore.get_crate_data(did.krate);
+ decoder::is_typedef(&*cdata, did.node)
+}
.map(|source| source.clone())
}
- pub fn dump_phase_syntax_crates(&self) {
- }
-
pub fn reset(&self) {
self.metas.borrow_mut().clear();
self.extern_mod_crate_map.borrow_mut().clear();
return result;
}
-pub fn get_macro_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
- reader::maybe_get_doc(ebml::Doc::new(data), tag_macro_registrar_fn)
+pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
+ reader::maybe_get_doc(ebml::Doc::new(data), tag_plugin_registrar_fn)
.map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap())
}
});
return ret;
}
+
+pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
+ let item_doc = lookup_item(id, cdata.data());
+ match item_family(item_doc) {
+ Type => true,
+ _ => false,
+ }
+}
ebml_w.end_tag();
}
-fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
- match ecx.tcx.sess.macro_registrar_fn.get() {
- Some(id) => { ebml_w.wr_tagged_u32(tag_macro_registrar_fn, id); }
+fn encode_plugin_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
+ match ecx.tcx.sess.plugin_registrar_fn.get() {
+ Some(id) => { ebml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
None => {}
}
}
dep_bytes: u64,
lang_item_bytes: u64,
native_lib_bytes: u64,
- macro_registrar_fn_bytes: u64,
+ plugin_registrar_fn_bytes: u64,
macro_defs_bytes: u64,
impl_bytes: u64,
misc_bytes: u64,
dep_bytes: 0,
lang_item_bytes: 0,
native_lib_bytes: 0,
- macro_registrar_fn_bytes: 0,
+ plugin_registrar_fn_bytes: 0,
macro_defs_bytes: 0,
impl_bytes: 0,
misc_bytes: 0,
encode_native_libraries(&ecx, &mut ebml_w);
stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
- // Encode the macro registrar function
+ // Encode the plugin registrar function
i = ebml_w.writer.tell().unwrap();
- encode_macro_registrar_fn(&ecx, &mut ebml_w);
- stats.macro_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
+ encode_plugin_registrar_fn(&ecx, &mut ebml_w);
+ stats.plugin_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
// Encode macro definitions
i = ebml_w.writer.tell().unwrap();
}
println!("metadata stats:");
- println!(" attribute bytes: {}", stats.attr_bytes);
- println!(" dep bytes: {}", stats.dep_bytes);
- println!(" lang item bytes: {}", stats.lang_item_bytes);
- println!(" native bytes: {}", stats.native_lib_bytes);
- println!("macro registrar bytes: {}", stats.macro_registrar_fn_bytes);
- println!(" macro def bytes: {}", stats.macro_defs_bytes);
- println!(" impl bytes: {}", stats.impl_bytes);
- println!(" misc bytes: {}", stats.misc_bytes);
- println!(" item bytes: {}", stats.item_bytes);
- println!(" index bytes: {}", stats.index_bytes);
- println!(" zero bytes: {}", stats.zero_bytes);
- println!(" total bytes: {}", stats.total_bytes);
+ println!(" attribute bytes: {}", stats.attr_bytes);
+ println!(" dep bytes: {}", stats.dep_bytes);
+ println!(" lang item bytes: {}", stats.lang_item_bytes);
+ println!(" native bytes: {}", stats.native_lib_bytes);
+ println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
+ println!(" macro def bytes: {}", stats.macro_defs_bytes);
+ println!(" impl bytes: {}", stats.impl_bytes);
+ println!(" misc bytes: {}", stats.misc_bytes);
+ println!(" item bytes: {}", stats.item_bytes);
+ println!(" index bytes: {}", stats.index_bytes);
+ println!(" zero bytes: {}", stats.zero_bytes);
+ println!(" total bytes: {}", stats.total_bytes);
}
}
use std::cell::RefCell;
use std::os;
use std::io::fs;
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
use std::collections::HashSet;
use myfs = util::fs;
}
pub struct ArchiveMetadata {
- archive: ArchiveRO,
+ _archive: ArchiveRO,
// See comments in ArchiveMetadata::new for why this is static
data: &'static [u8],
}
unsafe { mem::transmute(data) }
};
Some(ArchiveMetadata {
- archive: ar,
+ _archive: ar,
data: data,
})
}
// Extra parameters are for converting to/from def_ids in the string rep.
// Whatever format you choose should not contain pipe characters.
pub struct ty_abbrev {
- pos: uint,
- len: uint,
s: String
}
if abbrev_len < len {
// I.e. it's actually an abbreviation.
cx.abbrevs.borrow_mut().insert(t, ty_abbrev {
- pos: pos as uint,
- len: len as uint,
s: format!("\\#{:x}:{:x}\\#", pos, len)
});
}
cause: euv::LoanCause,
cmt: mc::cmt,
loan_region: ty::Region,
- loan_kind: ty::BorrowKind)
+ _: ty::BorrowKind)
-> Result<(),()> {
debug!("guarantee_lifetime(cmt={}, loan_region={})",
cmt.repr(bccx.tcx), loan_region.repr(bccx.tcx));
span: span,
cause: cause,
loan_region: loan_region,
- loan_kind: loan_kind,
cmt_original: cmt.clone()};
ctxt.check(&cmt, None)
}
span: Span,
cause: euv::LoanCause,
loan_region: ty::Region,
- loan_kind: ty::BorrowKind,
cmt_original: mc::cmt
}
Loan {
index: self.all_loans.len(),
loan_path: loan_path,
- cmt: cmt,
kind: req_kind,
gen_scope: gen_scope,
kill_scope: kill_scope,
/// This visitor walks static initializer's expressions and makes
/// sure the loans being taken are sound.
struct StaticInitializerCtxt<'a> {
- bccx: &'a BorrowckCtxt<'a>,
- item_ub: ast::NodeId,
+ bccx: &'a BorrowckCtxt<'a>
}
impl<'a> visit::Visitor<()> for StaticInitializerCtxt<'a> {
debug!("gather_loans_in_static_initializer(expr={})", expr.repr(bccx.tcx));
let mut sicx = StaticInitializerCtxt {
- bccx: bccx,
- item_ub: expr.id,
+ bccx: bccx
};
sicx.visit_expr(expr, ());
bccx: bccx,
span: span,
cause: cause,
- cmt_original: cmt.clone(),
loan_region: loan_region,
};
struct RestrictionsContext<'a> {
bccx: &'a BorrowckCtxt<'a>,
span: Span,
- cmt_original: mc::cmt,
loan_region: ty::Region,
cause: euv::LoanCause,
}
pub struct Loan {
index: uint,
loan_path: Rc<LoanPath>,
- cmt: mc::cmt,
kind: ty::BorrowKind,
restrictions: Vec<Restriction>,
gen_scope: ast::NodeId,
}
}
+ fn handle_field_access(&mut self, lhs: &ast::Expr, name: &ast::Ident) {
+ match ty::get(ty::expr_ty_adjusted(self.tcx, lhs)).sty {
+ ty::ty_struct(id, _) => {
+ let fields = ty::lookup_struct_fields(self.tcx, id);
+ let field_id = fields.iter()
+ .find(|field| field.name == name.name).unwrap().id;
+ self.live_symbols.insert(field_id.node);
+ },
+ _ => ()
+ }
+ }
+
+ fn handle_field_pattern_match(&mut self, lhs: &ast::Pat, pats: &[ast::FieldPat]) {
+ match self.tcx.def_map.borrow().get(&lhs.id) {
+ &def::DefStruct(id) | &def::DefVariant(_, id, _) => {
+ let fields = ty::lookup_struct_fields(self.tcx, id);
+ for pat in pats.iter() {
+ let field_id = fields.iter()
+ .find(|field| field.name == pat.ident.name).unwrap().id;
+ self.live_symbols.insert(field_id.node);
+ }
+ }
+ _ => ()
+ }
+ }
+
fn mark_live_symbols(&mut self) {
let mut scanned = HashSet::new();
while self.worklist.len() > 0 {
match *node {
ast_map::NodeItem(item) => {
match item.node {
+ ast::ItemStruct(struct_def, _) => {
+ let has_extern_repr = item.attrs.iter().fold(attr::ReprAny, |acc, attr| {
+ attr::find_repr_attr(self.tcx.sess.diagnostic(), attr, acc)
+ }) == attr::ReprExtern;
+ let live_fields = struct_def.fields.iter().filter(|f| {
+ has_extern_repr || match f.node.kind {
+ ast::NamedField(_, ast::Public) => true,
+ _ => false
+ }
+ });
+ self.live_symbols.extend(live_fields.map(|f| f.node.id));
+ visit::walk_item(self, item, ());
+ }
ast::ItemFn(..)
| ast::ItemTy(..)
| ast::ItemEnum(..)
- | ast::ItemStruct(..)
| ast::ItemStatic(..) => {
visit::walk_item(self, item, ());
}
ast::ExprMethodCall(..) => {
self.lookup_and_handle_method(expr.id, expr.span);
}
+ ast::ExprField(ref lhs, ref ident, _) => {
+ self.handle_field_access(*lhs, ident);
+ }
_ => ()
}
visit::walk_expr(self, expr, ())
}
+ fn visit_pat(&mut self, pat: &ast::Pat, _: ()) {
+ match pat.node {
+ ast::PatStruct(_, ref fields, _) => {
+ self.handle_field_pattern_match(pat, fields.as_slice());
+ }
+ _ => ()
+ }
+
+ visit::walk_pat(self, pat, ())
+ }
+
fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId, _: ()) {
self.lookup_and_handle_definition(&id);
visit::walk_path(self, path, ());
}
- fn visit_item(&mut self, _item: &ast::Item, _: ()) {
+ fn visit_item(&mut self, _: &ast::Item, _: ()) {
// Do not recurse into items. These items will be added to the
// worklist and recursed into manually if necessary.
}
}
impl<'a> DeadVisitor<'a> {
+ fn should_warn_about_field(&mut self, node: &ast::StructField_) -> bool {
+ let (is_named, has_leading_underscore) = match node.ident() {
+ Some(ref ident) => (true, token::get_ident(*ident).get()[0] == ('_' as u8)),
+ _ => (false, false)
+ };
+ let field_type = ty::node_id_to_type(self.tcx, node.id);
+ let is_marker_field = match ty::ty_to_def_id(field_type) {
+ Some(def_id) => self.tcx.lang_items.items().any(|(_, item)| *item == Some(def_id)),
+ _ => false
+ };
+ is_named
+ && !self.symbol_is_live(node.id, None)
+ && !has_leading_underscore
+ && !is_marker_field
+ && !has_allow_dead_code_or_lang_attr(node.attrs.as_slice())
+ }
+
// id := node id of an item's definition.
// ctor_id := `Some` if the item is a struct_ctor (tuple struct),
// `None` otherwise.
visit::walk_block(self, block, ());
}
+ fn visit_struct_field(&mut self, field: &ast::StructField, _: ()) {
+ if self.should_warn_about_field(&field.node) {
+ self.warn_dead_code(field.node.id, field.span, field.node.ident().unwrap());
+ }
+
+ visit::walk_struct_field(self, field, ());
+ }
+
// Overwrite so that we don't warn the trait method itself.
fn visit_trait_method(&mut self, trait_method: &ast::TraitMethod, _: ()) {
match *trait_method {
use middle::freevars;
use middle::pat_util;
use middle::ty;
+use middle::typeck::MethodCall;
use middle::typeck;
use syntax::ast;
use syntax::codemap::{Span};
}
}
_ => {
- self.tcx().sess.span_bug(
- callee.span,
- format!("unxpected callee type {}",
- callee_ty.repr(self.tcx())).as_slice());
+ match self.tcx()
+ .method_map
+ .borrow()
+ .find(&MethodCall::expr(call.id)) {
+ Some(_) => {
+ // FIXME(#14774, pcwalton): Implement this.
+ }
+ None => {
+ self.tcx().sess.span_bug(
+ callee.span,
+ format!("unxpected callee type {}",
+ callee_ty.repr(self.tcx())).as_slice());
+ }
+ }
}
}
}
DerefTraitLangItem, "deref", deref_trait;
DerefMutTraitLangItem, "deref_mut", deref_mut_trait;
+ FnTraitLangItem, "fn", fn_trait;
+ FnMutTraitLangItem, "fn_mut", fn_mut_trait;
+ FnOnceTraitLangItem, "fn_once", fn_once_trait;
+
EqTraitLangItem, "eq", eq_trait;
OrdTraitLangItem, "ord", ord_trait;
!ident.char_at(0).is_lowercase() && !ident.contains_char('_')
}
+ fn to_camel_case(s: &str) -> String {
+ s.split('_').flat_map(|word| word.chars().enumerate().map(|(i, c)|
+ if i == 0 { c.to_uppercase() }
+ else { c }
+ )).collect()
+ }
+
fn check_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
+ let s = token::get_ident(ident);
+
if !is_camel_case(ident) {
cx.span_lint(
NonCamelCaseTypes, span,
- format!("{} `{}` should have a camel case identifier",
- sort, token::get_ident(ident)).as_slice());
+ format!("{} `{}` should have a camel case name such as `{}`",
+ sort, s, to_camel_case(s.get())).as_slice());
}
}
})
}
+ fn to_snake_case(str: &str) -> String {
+ let mut words = vec![];
+ for s in str.split('_') {
+ let mut buf = String::new();
+ if s.is_empty() { continue; }
+ for ch in s.chars() {
+ if !buf.is_empty() && ch.is_uppercase() {
+ words.push(buf);
+ buf = String::new();
+ }
+ buf.push_char(ch.to_lowercase());
+ }
+ words.push(buf);
+ }
+ words.connect("_")
+ }
+
+ let s = token::get_ident(ident);
+
if !is_snake_case(ident) {
cx.span_lint(NonSnakeCaseFunctions, span,
- format!("{} `{}` should have a snake case identifier",
- sort, token::get_ident(ident)).as_slice());
+ format!("{} `{}` should have a snake case name such as `{}`",
+ sort, s, to_snake_case(s.get())).as_slice());
}
}
// upper/lowercase)
if s.get().chars().any(|c| c.is_lowercase()) {
cx.span_lint(NonUppercaseStatics, it.span,
- "static constant should have an uppercase identifier");
+ format!("static constant `{}` should have an uppercase name \
+ such as `{}`", s.get(),
+ s.get().chars().map(|c| c.to_uppercase())
+ .collect::<String>().as_slice()).as_slice());
}
}
_ => {}
let s = token::get_ident(ident);
if s.get().chars().any(|c| c.is_lowercase()) {
cx.span_lint(NonUppercasePatternStatics, path.span,
- "static constant in pattern should be all caps");
+ format!("static constant in pattern `{}` should have an uppercase \
+ name such as `{}`", s.get(),
+ s.get().chars().map(|c| c.to_uppercase())
+ .collect::<String>().as_slice()).as_slice());
}
}
_ => {}
use middle::def::*;
use middle::freevars;
use middle::lint::{UnusedVariable, DeadAssignment};
+use middle::mem_categorization::Typer;
use middle::pat_util;
use middle::ty;
use util::nodemap::NodeMap;
struct CaptureInfo {
ln: LiveNode,
- is_move: bool,
var_nid: NodeId
}
-enum LocalKind {
- FromMatch(BindingMode),
- FromLetWithInitializer,
- FromLetNoInitializer
-}
-
struct LocalInfo {
id: NodeId,
- ident: Ident,
- is_mutbl: bool,
- kind: LocalKind,
+ ident: Ident
}
enum VarKind {
}
fn visit_local(ir: &mut IrMaps, local: &Local) {
- pat_util::pat_bindings(&ir.tcx.def_map, local.pat, |bm, p_id, sp, path| {
+ pat_util::pat_bindings(&ir.tcx.def_map, local.pat, |_, p_id, sp, path| {
debug!("adding local variable {}", p_id);
let name = ast_util::path_to_ident(path);
ir.add_live_node_for_node(p_id, VarDefNode(sp));
- let kind = match local.init {
- Some(_) => FromLetWithInitializer,
- None => FromLetNoInitializer
- };
- let mutbl = match bm {
- BindByValue(MutMutable) => true,
- _ => false
- };
ir.add_variable(Local(LocalInfo {
id: p_id,
- ident: name,
- is_mutbl: mutbl,
- kind: kind
+ ident: name
}));
});
visit::walk_local(ir, local, ());
debug!("adding local variable {} from match with bm {:?}",
p_id, bm);
let name = ast_util::path_to_ident(path);
- let mutbl = match bm {
- BindByValue(MutMutable) => true,
- _ => false
- };
ir.add_live_node_for_node(p_id, VarDefNode(sp));
ir.add_variable(Local(LocalInfo {
id: p_id,
- ident: name,
- is_mutbl: mutbl,
- kind: FromMatch(bm)
+ ident: name
}));
})
}
// in better error messages than just pointing at the closure
// construction site.
let mut call_caps = Vec::new();
- let fv_mode = freevars::get_capture_mode(ir.tcx, expr.id);
freevars::with_freevars(ir.tcx, expr.id, |freevars| {
for fv in freevars.iter() {
match moved_variable_node_id_from_def(fv.def) {
Some(rv) => {
let fv_ln = ir.add_live_node(FreeVarNode(fv.span));
- let fv_id = fv.def.def_id().node;
- let fv_ty = ty::node_id_to_type(ir.tcx, fv_id);
- let is_move = match fv_mode {
- // var must be dead afterwards
- freevars::CaptureByValue => {
- ty::type_moves_by_default(ir.tcx, fv_ty)
- }
-
- // var can still be used
- freevars::CaptureByRef => {
- false
- }
- };
call_caps.push(CaptureInfo {ln: fv_ln,
- is_move: is_move,
var_nid: rv});
}
None => {}
ExprCall(f, ref args) => {
// calling a fn with bot return type means that the fn
// will fail, and hence the successors can be ignored
- let t_ret = ty::ty_fn_ret(ty::expr_ty(self.ir.tcx, f));
- let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln}
- else {succ};
+ let is_bot = !self.ir.tcx.is_method_call(expr.id) && {
+ let t_ret = ty::ty_fn_ret(ty::expr_ty(self.ir.tcx, f));
+ ty::type_is_bot(t_ret)
+ };
+ let succ = if is_bot {
+ self.s.exit_ln
+ } else {
+ succ
+ };
let succ = self.propagate_through_exprs(args.as_slice(), succ);
self.propagate_through_expr(f, succ)
}
struct PrivacyVisitor<'a> {
tcx: &'a ty::ctxt,
curitem: ast::NodeId,
- in_fn: bool,
in_foreign: bool,
parents: NodeMap<ast::NodeId>,
external_exports: resolve::ExternalExports,
// Use the parent map to check the privacy of everything
let mut visitor = PrivacyVisitor {
curitem: ast::DUMMY_NODE_ID,
- in_fn: false,
in_foreign: false,
tcx: tcx,
parents: visitor.parents,
/// The main resolver class.
struct Resolver<'a> {
session: &'a Session,
- lang_items: &'a LanguageItems,
graph_root: NameBindings,
// The idents for the primitive types.
primitive_type_table: PrimitiveTypeTable,
- // The four namespaces.
- namespaces: Vec<Namespace> ,
-
def_map: DefMap,
export_map2: ExportMap2,
trait_map: TraitMap,
}
impl<'a> Resolver<'a> {
- fn new(session: &'a Session, lang_items: &'a LanguageItems, crate_span: Span) -> Resolver<'a> {
+ fn new(session: &'a Session, crate_span: Span) -> Resolver<'a> {
let graph_root = NameBindings::new();
graph_root.define_module(NoParentLink,
Resolver {
session: session,
- lang_items: lang_items,
// The outermost module has def ID 0; this is not reflected in the
// AST.
primitive_type_table: PrimitiveTypeTable::new(),
- namespaces: vec!(TypeNS, ValueNS),
-
def_map: RefCell::new(NodeMap::new()),
export_map2: RefCell::new(NodeMap::new()),
trait_map: NodeMap::new(),
}
fn resolve_type_parameter_bound(&mut self,
- id: NodeId,
- type_parameter_bound: &TyParamBound) {
+ id: NodeId,
+ type_parameter_bound: &TyParamBound) {
match *type_parameter_bound {
TraitTyParamBound(ref tref) => {
self.resolve_trait_reference(id, tref, TraitBoundingTypeParameter)
}
- StaticRegionTyParamBound => {}
- OtherRegionTyParamBound(_) => {}
+ UnboxedFnTyParamBound(ref unboxed_function) => {
+ for argument in unboxed_function.decl.inputs.iter() {
+ self.resolve_type(argument.ty);
+ }
+
+ self.resolve_type(unboxed_function.decl.output);
+ }
+ StaticRegionTyParamBound | OtherRegionTyParamBound(_) => {}
}
}
/// Entry point to crate resolution.
pub fn resolve_crate(session: &Session,
- lang_items: &LanguageItems,
+ _: &LanguageItems,
krate: &Crate)
-> CrateMap {
- let mut resolver = Resolver::new(session, lang_items, krate.span);
+ let mut resolver = Resolver::new(session, krate.span);
resolver.resolve(krate);
let Resolver { def_map, export_map2, trait_map, last_private,
external_exports, .. } = resolver;
#![allow(unsigned_negate)]
-use std::container::Map;
use libc::c_ulonglong;
use std::num::{Bitwise};
use std::rc::Rc;
task_local_insn_key.replace(Some(RefCell::new(Vec::new())));
}
-pub struct _InsnCtxt { _x: () }
+pub struct _InsnCtxt {
+ _cannot_construct_outside_of_this_module: ()
+}
#[unsafe_destructor]
impl Drop for _InsnCtxt {
Some(ctx) => ctx.borrow_mut().push(s),
None => {}
}
- _InsnCtxt { _x: () }
+ _InsnCtxt { _cannot_construct_outside_of_this_module: () }
}
pub struct StatRecorder<'a> {
use metadata::csearch;
use middle::def;
use middle::lang_items::MallocFnLangItem;
+use middle::mem_categorization::Typer;
use middle::trans::_match;
use middle::trans::adt;
use middle::trans::asm;
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef};
use middle::ty;
use middle::typeck::MethodCall;
+use middle::typeck;
use util::common::indenter;
use util::ppaux::Repr;
use util::nodemap::NodeMap;
closure::trans_expr_fn(bcx, store, decl, body, expr.id, dest)
}
ast::ExprCall(f, ref args) => {
- callee::trans_call(bcx, expr, f, callee::ArgExprs(args.as_slice()), dest)
+ if bcx.tcx().is_method_call(expr.id) {
+ let callee_datum = unpack_datum!(bcx, trans(bcx, f));
+ trans_overloaded_call(bcx,
+ expr,
+ callee_datum,
+ args.as_slice(),
+ Some(dest))
+ } else {
+ callee::trans_call(bcx,
+ expr,
+ f,
+ callee::ArgExprs(args.as_slice()),
+ dest)
+ }
}
ast::ExprMethodCall(_, _, ref args) => {
callee::trans_method_call(bcx,
dest)
}
+fn trans_overloaded_call<'a>(
+ mut bcx: &'a Block<'a>,
+ expr: &ast::Expr,
+ callee: Datum<Expr>,
+ args: &[@ast::Expr],
+ dest: Option<Dest>)
+ -> &'a Block<'a> {
+ // Evaluate and tuple the arguments.
+ let tuple_type = ty::mk_tup(bcx.tcx(),
+ args.iter()
+ .map(|e| expr_ty(bcx, *e))
+ .collect());
+ let repr = adt::represent_type(bcx.ccx(), tuple_type);
+ let numbered_fields: Vec<(uint, @ast::Expr)> =
+ args.iter().enumerate().map(|(i, arg)| (i, *arg)).collect();
+ let argument_scope = bcx.fcx.push_custom_cleanup_scope();
+ let tuple_datum =
+ unpack_datum!(bcx,
+ lvalue_scratch_datum(bcx,
+ tuple_type,
+ "tupled_arguments",
+ false,
+ cleanup::CustomScope(
+ argument_scope),
+ (),
+ |(), bcx, addr| {
+ trans_adt(bcx,
+ &*repr,
+ 0,
+ numbered_fields.as_slice(),
+ None,
+ SaveIn(addr))
+ }));
+
+ let method_call = typeck::MethodCall::expr(expr.id);
+ let method_type = bcx.tcx()
+ .method_map
+ .borrow()
+ .get(&method_call)
+ .ty;
+ let callee_rvalue = unpack_datum!(bcx,
+ callee.to_rvalue_datum(bcx, "callee"));
+ let tuple_datum = tuple_datum.to_expr_datum();
+ let tuple_rvalue = unpack_datum!(bcx,
+ tuple_datum.to_rvalue_datum(bcx,
+ "tuple"));
+ let argument_values = [
+ callee_rvalue.add_clean(bcx.fcx,
+ cleanup::CustomScope(argument_scope)),
+ tuple_rvalue.add_clean(bcx.fcx, cleanup::CustomScope(argument_scope))
+ ];
+ unpack_result!(bcx,
+ callee::trans_call_inner(bcx,
+ Some(expr_info(expr)),
+ monomorphize_type(bcx,
+ method_type),
+ |bcx, arg_cleanup_scope| {
+ meth::trans_method_callee(
+ bcx,
+ method_call,
+ None,
+ arg_cleanup_scope)
+ },
+ callee::ArgVals(argument_values),
+ dest));
+
+ bcx.fcx.pop_custom_cleanup_scope(argument_scope);
+ bcx
+}
+
fn int_cast(bcx: &Block,
lldsttype: Type,
llsrctype: Type,
// function, because the foreign function may opt to return via an
// out pointer.
llret_ty: Type,
-
- // True if *Rust* would use an outpointer for this function.
- sret: bool,
}
let llret_ty = type_of::type_of(ccx, fn_sig.output);
LlvmSignature {
llarg_tys: llarg_tys,
- llret_ty: llret_ty,
- sret: type_of::return_uses_outptr(ccx, fn_sig.output),
+ llret_ty: llret_ty
}
}
use middle::const_eval;
use middle::def;
-use middle::subst;
+use middle::lang_items::FnMutTraitLangItem;
use middle::subst::{Subst, Substs};
-use middle::ty::{ty_param_substs_and_ty};
+use middle::subst;
+use middle::ty::ty_param_substs_and_ty;
use middle::ty;
-use middle::typeck::rscope;
-use middle::typeck::rscope::{RegionScope};
use middle::typeck::lookup_def_tcx;
+use middle::typeck::rscope::RegionScope;
+use middle::typeck::rscope;
use util::ppaux::Repr;
use std::rc::Rc;
ty::mt {ty: ast_ty_to_ty(this, rscope, ty), mutbl: ast::MutImmutable}
}
+pub fn trait_ref_for_unboxed_function<AC:AstConv,
+ RS:RegionScope>(
+ this: &AC,
+ rscope: &RS,
+ unboxed_function: &ast::UnboxedFnTy)
+ -> ty::TraitRef {
+ let fn_mut_trait_did = this.tcx()
+ .lang_items
+ .require(FnMutTraitLangItem)
+ .unwrap();
+ let input_types =
+ unboxed_function.decl
+ .inputs
+ .iter()
+ .map(|input| {
+ ast_ty_to_ty(this, rscope, input.ty)
+ }).collect::<Vec<_>>();
+ let input_tuple = ty::mk_tup(this.tcx(), input_types);
+ let output_type = ast_ty_to_ty(this,
+ rscope,
+ unboxed_function.decl.output);
+ let substs = subst::Substs {
+ self_ty: None,
+ tps: vec!(input_tuple, output_type),
+ regions: subst::NonerasedRegions(Vec::new()),
+ };
+ ty::TraitRef {
+ def_id: fn_mut_trait_did,
+ substs: substs,
+ }
+}
+
// Handle `~`, `Box`, and `&` being able to mean strs and vecs.
// If a_seq_ty is a str or a vec, make it a str/vec.
// Also handle first-class trait types.
}
return constr(ty::mk_vec(tcx, mt, None));
}
+ ast::TyUnboxedFn(ref unboxed_function) => {
+ let trait_store = match ptr_ty {
+ Uniq => ty::UniqTraitStore,
+ RPtr(r) => {
+ ty::RegionTraitStore(r, a_seq_ty.mutbl)
+ }
+ _ => {
+ tcx.sess.span_err(
+ a_seq_ty.ty.span,
+ "~trait or &trait are the only supported \
+ forms of casting-to-trait");
+ return ty::mk_err();
+ }
+ };
+ let ty::TraitRef {
+ def_id,
+ substs
+ } = trait_ref_for_unboxed_function(this,
+ rscope,
+ *unboxed_function);
+ return ty::mk_trait(this.tcx(),
+ def_id,
+ substs,
+ trait_store,
+ ty::empty_builtin_bounds());
+ }
ast::TyPath(ref path, ref bounds, id) => {
// Note that the "bounds must be empty if path is not a trait"
// restriction is enforced in the below case for ty_path, which
return ty::mk_err();
}
};
- let bounds = conv_builtin_bounds(this.tcx(), bounds, trait_store);
+ let bounds = conv_builtin_bounds(this.tcx(),
+ path.span,
+ bounds,
+ trait_store);
return ty::mk_trait(tcx,
result.def_id,
result.substs.clone(),
// Use corresponding trait store to figure out default bounds
// if none were specified.
- let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, store);
+ let bounds = conv_builtin_bounds(this.tcx(),
+ ast_ty.span,
+ &f.bounds,
+ store);
let fn_decl = ty_of_closure(this,
ast_ty.id,
ast::TyProc(ref f) => {
// Use corresponding trait store to figure out default bounds
// if none were specified.
- let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, ty::UniqTraitStore);
+ let bounds = conv_builtin_bounds(this.tcx(),
+ ast_ty.span,
+ &f.bounds,
+ ty::UniqTraitStore);
let fn_decl = ty_of_closure(this,
ast_ty.id,
None);
ty::mk_closure(tcx, fn_decl)
}
+ ast::TyUnboxedFn(_) => {
+ tcx.sess.span_err(ast_ty.span,
+ "cannot use unboxed functions here");
+ ty::mk_err()
+ }
ast::TyPath(ref path, ref bounds, id) => {
let a_def = match tcx.def_map.borrow().find(&id) {
None => {
}
}
-fn conv_builtin_bounds(tcx: &ty::ctxt, ast_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
+fn conv_builtin_bounds(tcx: &ty::ctxt,
+ span: Span,
+ ast_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
store: ty::TraitStore)
-> ty::BuiltinBounds {
//! Converts a list of bounds from the AST into a `BuiltinBounds`
ast::StaticRegionTyParamBound => {
builtin_bounds.add(ty::BoundStatic);
}
+ ast::UnboxedFnTyParamBound(_) => {
+ tcx.sess.span_err(span,
+ "unboxed functions are not allowed \
+ here");
+ }
ast::OtherRegionTyParamBound(span) => {
if !tcx.sess.features.issue_5723_bootstrap.get() {
tcx.sess.span_err(
(ty::mk_err(), 0, None)
}
+/// Attempts to resolve a call expression as an overloaded call.
+fn try_overloaded_call(fcx: &FnCtxt,
+ call_expression: &ast::Expr,
+ callee: @ast::Expr,
+ callee_type: ty::t,
+ args: &[@ast::Expr])
+ -> bool {
+ // Try `FnOnce`, then `FnMut`, then `Fn`.
+ for &(maybe_function_trait, method_name) in [
+ (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
+ (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
+ (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
+ ].iter() {
+ let function_trait = match maybe_function_trait {
+ None => continue,
+ Some(function_trait) => function_trait,
+ };
+ let method_callee = match method::lookup_in_trait(
+ fcx,
+ call_expression.span,
+ Some(&*callee),
+ method_name,
+ function_trait,
+ callee_type,
+ [],
+ DontAutoderefReceiver,
+ IgnoreStaticMethods) {
+ None => continue,
+ Some(method_callee) => method_callee,
+ };
+ let method_call = MethodCall::expr(call_expression.id);
+ let output_type = check_method_argument_types(fcx,
+ call_expression.span,
+ method_callee.ty,
+ call_expression,
+ args,
+ DontDerefArgs,
+ TupleArguments);
+ fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
+ write_call(fcx, call_expression, output_type);
+
+ if !fcx.tcx().sess.features.overloaded_calls.get() {
+ fcx.tcx().sess.span_err(call_expression.span,
+ "overloaded calls are experimental");
+ fcx.tcx().sess.span_note(call_expression.span,
+ "add `#[feature(overloaded_calls)]` to \
+ the crate attributes to enable");
+ }
+
+ return true
+ }
+
+ false
+}
+
fn try_overloaded_deref(fcx: &FnCtxt,
span: Span,
method_call: Option<MethodCall>,
}
}
+fn check_method_argument_types(fcx: &FnCtxt,
+ sp: Span,
+ method_fn_ty: ty::t,
+ callee_expr: &ast::Expr,
+ args: &[@ast::Expr],
+ deref_args: DerefArgs,
+ tuple_arguments: TupleArgumentsFlag)
+ -> ty::t {
+ // HACK(eddyb) ignore provided self (it has special typeck rules).
+ let args = if tuple_arguments == DontTupleArguments {
+ args.slice_from(1)
+ } else {
+ args
+ };
+ if ty::type_is_error(method_fn_ty) {
+ let err_inputs = err_args(args.len());
+ check_argument_types(fcx,
+ sp,
+ err_inputs.as_slice(),
+ callee_expr,
+ args,
+ deref_args,
+ false,
+ tuple_arguments);
+ method_fn_ty
+ } else {
+ match ty::get(method_fn_ty).sty {
+ ty::ty_bare_fn(ref fty) => {
+ // HACK(eddyb) ignore self in the definition (see above).
+ check_argument_types(fcx,
+ sp,
+ fty.sig.inputs.slice_from(1),
+ callee_expr,
+ args,
+ deref_args,
+ fty.sig.variadic,
+ tuple_arguments);
+ fty.sig.output
+ }
+ _ => {
+ fcx.tcx().sess.span_bug(callee_expr.span,
+ "method without bare fn type");
+ }
+ }
+ }
+}
+
+fn check_argument_types(fcx: &FnCtxt,
+ sp: Span,
+ fn_inputs: &[ty::t],
+ callee_expr: &ast::Expr,
+ args: &[@ast::Expr],
+ deref_args: DerefArgs,
+ variadic: bool,
+ tuple_arguments: TupleArgumentsFlag) {
+ /*!
+ *
+ * Generic function that factors out common logic from
+ * function calls, method calls and overloaded operators.
+ */
+
+ let tcx = fcx.ccx.tcx;
+
+ // Grab the argument types, supplying fresh type variables
+ // if the wrong number of arguments were supplied
+ let supplied_arg_count = if tuple_arguments == DontTupleArguments {
+ args.len()
+ } else {
+ 1
+ };
+
+ let expected_arg_count = fn_inputs.len();
+ let formal_tys = if tuple_arguments == TupleArguments {
+ let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
+ match ty::get(tuple_type).sty {
+ ty::ty_tup(ref arg_types) => {
+ if arg_types.len() != args.len() {
+ let msg = format!(
+ "this function takes \
+ {nexpected, plural, =1{# parameter} \
+ other{# parameters}} \
+ but {nsupplied, plural, =1{# parameter was} \
+ other{# parameters were}} supplied",
+ nexpected = arg_types.len(),
+ nsupplied = args.len());
+ tcx.sess.span_err(sp, msg.as_slice());
+ err_args(args.len())
+ } else {
+ (*arg_types).clone()
+ }
+ }
+ ty::ty_nil => {
+ if args.len() != 0 {
+ let msg = format!(
+ "this function takes 0 parameters \
+ but {nsupplied, plural, =1{# parameter was} \
+ other{# parameters were}} supplied",
+ nsupplied = args.len());
+ tcx.sess.span_err(sp, msg.as_slice());
+ }
+ Vec::new()
+ }
+ _ => {
+ tcx.sess
+ .span_err(sp,
+ "cannot use call notation; the first type \
+ parameter for the function trait is neither a \
+ tuple nor unit");
+ err_args(supplied_arg_count)
+ }
+ }
+ } else if expected_arg_count == supplied_arg_count {
+ fn_inputs.iter().map(|a| *a).collect()
+ } else if variadic {
+ if supplied_arg_count >= expected_arg_count {
+ fn_inputs.iter().map(|a| *a).collect()
+ } else {
+ let msg = format!(
+ "this function takes at least {nexpected, plural, =1{# parameter} \
+ other{# parameters}} \
+ but {nsupplied, plural, =1{# parameter was} \
+ other{# parameters were}} supplied",
+ nexpected = expected_arg_count,
+ nsupplied = supplied_arg_count);
+
+ tcx.sess.span_err(sp, msg.as_slice());
+
+ err_args(supplied_arg_count)
+ }
+ } else {
+ let msg = format!(
+ "this function takes {nexpected, plural, =1{# parameter} \
+ other{# parameters}} \
+ but {nsupplied, plural, =1{# parameter was} \
+ other{# parameters were}} supplied",
+ nexpected = expected_arg_count,
+ nsupplied = supplied_arg_count);
+
+ tcx.sess.span_err(sp, msg.as_slice());
+
+ err_args(supplied_arg_count)
+ };
+
+ debug!("check_argument_types: formal_tys={:?}",
+ formal_tys.iter().map(|t| fcx.infcx().ty_to_str(*t)).collect::<Vec<String>>());
+
+ // Check the arguments.
+ // We do this in a pretty awful way: first we typecheck any arguments
+ // that are not anonymous functions, then we typecheck the anonymous
+ // functions. This is so that we have more information about the types
+ // of arguments when we typecheck the functions. This isn't really the
+ // right way to do this.
+ let xs = [false, true];
+ for check_blocks in xs.iter() {
+ let check_blocks = *check_blocks;
+ debug!("check_blocks={}", check_blocks);
+
+ // More awful hacks: before we check the blocks, try to do
+ // an "opportunistic" vtable resolution of any trait
+ // bounds on the call.
+ if check_blocks {
+ vtable::early_resolve_expr(callee_expr, fcx, true);
+ }
+
+ // For variadic functions, we don't have a declared type for all of
+ // the arguments hence we only do our usual type checking with
+ // the arguments who's types we do know.
+ let t = if variadic {
+ expected_arg_count
+ } else if tuple_arguments == TupleArguments {
+ args.len()
+ } else {
+ supplied_arg_count
+ };
+ for (i, arg) in args.iter().take(t).enumerate() {
+ let is_block = match arg.node {
+ ast::ExprFnBlock(..) |
+ ast::ExprProc(..) => true,
+ _ => false
+ };
+
+ if is_block == check_blocks {
+ debug!("checking the argument");
+ let mut formal_ty = *formal_tys.get(i);
+
+ match deref_args {
+ DoDerefArgs => {
+ match ty::get(formal_ty).sty {
+ ty::ty_rptr(_, mt) => formal_ty = mt.ty,
+ ty::ty_err => (),
+ _ => {
+ // So we hit this case when one implements the
+ // operator traits but leaves an argument as
+ // just T instead of &T. We'll catch it in the
+ // mismatch impl/trait method phase no need to
+ // ICE here.
+ // See: #11450
+ formal_ty = ty::mk_err();
+ }
+ }
+ }
+ DontDerefArgs => {}
+ }
+
+ check_expr_coercable_to_type(fcx, *arg, formal_ty);
+
+ }
+ }
+ }
+
+ // We also need to make sure we at least write the ty of the other
+ // arguments which we skipped above.
+ if variadic {
+ for arg in args.iter().skip(expected_arg_count) {
+ check_expr(fcx, *arg);
+
+ // There are a few types which get autopromoted when passed via varargs
+ // in C but we just error out instead and require explicit casts.
+ let arg_ty = structurally_resolved_type(fcx, arg.span, fcx.expr_ty(*arg));
+ match ty::get(arg_ty).sty {
+ ty::ty_float(ast::TyF32) => {
+ fcx.type_error_message(arg.span,
+ |t| {
+ format!("can't pass an {} to variadic \
+ function, cast to c_double", t)
+ }, arg_ty, None);
+ }
+ ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
+ fcx.type_error_message(arg.span, |t| {
+ format!("can't pass {} to variadic \
+ function, cast to c_int",
+ t)
+ }, arg_ty, None);
+ }
+ ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
+ fcx.type_error_message(arg.span, |t| {
+ format!("can't pass {} to variadic \
+ function, cast to c_uint",
+ t)
+ }, arg_ty, None);
+ }
+ _ => {}
+ }
+ }
+ }
+}
+
+fn err_args(len: uint) -> Vec<ty::t> {
+ Vec::from_fn(len, |_| ty::mk_err())
+}
+
+fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
+ fcx.write_ty(call_expr.id, output);
+}
+
// AST fragment checking
pub fn check_lit(fcx: &FnCtxt, lit: &ast::Lit) -> ty::t {
let tcx = fcx.ccx.tcx;
DoDerefArgs
}
+/// Controls whether the arguments are tupled. This is used for the call
+/// operator.
+///
+/// Tupling means that all call-side arguments are packed into a tuple and
+/// passed as a single parameter. For example, if tupling is enabled, this
+/// function:
+///
+/// fn f(x: (int, int))
+///
+/// Can be called as:
+///
+/// f(1, 2);
+///
+/// Instead of:
+///
+/// f((1, 2));
+#[deriving(Clone, Eq, PartialEq)]
+enum TupleArgumentsFlag {
+ DontTupleArguments,
+ TupleArguments,
+}
+
// Given the provenance of a static method, returns the generics of the static
// method's container.
fn generics_of_static_method_container(type_context: &ty::ctxt,
unifier: ||) {
debug!(">> typechecking");
- fn check_method_argument_types(
- fcx: &FnCtxt,
- sp: Span,
- method_fn_ty: ty::t,
- callee_expr: &ast::Expr,
- args: &[@ast::Expr],
- deref_args: DerefArgs) -> ty::t {
- // HACK(eddyb) ignore provided self (it has special typeck rules).
- let args = args.slice_from(1);
- if ty::type_is_error(method_fn_ty) {
- let err_inputs = err_args(args.len());
- check_argument_types(fcx, sp, err_inputs.as_slice(), callee_expr,
- args, deref_args, false);
- method_fn_ty
- } else {
- match ty::get(method_fn_ty).sty {
- ty::ty_bare_fn(ref fty) => {
- // HACK(eddyb) ignore self in the definition (see above).
- check_argument_types(fcx, sp, fty.sig.inputs.slice_from(1),
- callee_expr, args, deref_args,
- fty.sig.variadic);
- fty.sig.output
- }
- _ => {
- fcx.tcx().sess.span_bug(callee_expr.span,
- "method without bare fn type");
- }
- }
- }
- }
-
- fn check_argument_types(fcx: &FnCtxt,
- sp: Span,
- fn_inputs: &[ty::t],
- callee_expr: &ast::Expr,
- args: &[@ast::Expr],
- deref_args: DerefArgs,
- variadic: bool) {
- /*!
- *
- * Generic function that factors out common logic from
- * function calls, method calls and overloaded operators.
- */
-
- let tcx = fcx.ccx.tcx;
-
- // Grab the argument types, supplying fresh type variables
- // if the wrong number of arguments were supplied
- let supplied_arg_count = args.len();
- let expected_arg_count = fn_inputs.len();
- let formal_tys = if expected_arg_count == supplied_arg_count {
- fn_inputs.iter().map(|a| *a).collect()
- } else if variadic {
- if supplied_arg_count >= expected_arg_count {
- fn_inputs.iter().map(|a| *a).collect()
- } else {
- let msg = format!(
- "this function takes at least {nexpected, plural, =1{# parameter} \
- other{# parameters}} \
- but {nsupplied, plural, =1{# parameter was} \
- other{# parameters were}} supplied",
- nexpected = expected_arg_count,
- nsupplied = supplied_arg_count);
-
- tcx.sess.span_err(sp, msg.as_slice());
-
- err_args(supplied_arg_count)
- }
- } else {
- let msg = format!(
- "this function takes {nexpected, plural, =1{# parameter} \
- other{# parameters}} \
- but {nsupplied, plural, =1{# parameter was} \
- other{# parameters were}} supplied",
- nexpected = expected_arg_count,
- nsupplied = supplied_arg_count);
-
- tcx.sess.span_err(sp, msg.as_slice());
-
- err_args(supplied_arg_count)
- };
-
- debug!("check_argument_types: formal_tys={:?}",
- formal_tys.iter().map(|t| fcx.infcx().ty_to_str(*t)).collect::<Vec<String>>());
-
- // Check the arguments.
- // We do this in a pretty awful way: first we typecheck any arguments
- // that are not anonymous functions, then we typecheck the anonymous
- // functions. This is so that we have more information about the types
- // of arguments when we typecheck the functions. This isn't really the
- // right way to do this.
- let xs = [false, true];
- for check_blocks in xs.iter() {
- let check_blocks = *check_blocks;
- debug!("check_blocks={}", check_blocks);
-
- // More awful hacks: before we check the blocks, try to do
- // an "opportunistic" vtable resolution of any trait
- // bounds on the call.
- if check_blocks {
- vtable::early_resolve_expr(callee_expr, fcx, true);
- }
-
- // For variadic functions, we don't have a declared type for all of
- // the arguments hence we only do our usual type checking with
- // the arguments who's types we do know.
- let t = if variadic {
- expected_arg_count
- } else {
- supplied_arg_count
- };
- for (i, arg) in args.iter().take(t).enumerate() {
- let is_block = match arg.node {
- ast::ExprFnBlock(..) |
- ast::ExprProc(..) => true,
- _ => false
- };
-
- if is_block == check_blocks {
- debug!("checking the argument");
- let mut formal_ty = *formal_tys.get(i);
-
- match deref_args {
- DoDerefArgs => {
- match ty::get(formal_ty).sty {
- ty::ty_rptr(_, mt) => formal_ty = mt.ty,
- ty::ty_err => (),
- _ => {
- // So we hit this case when one implements the
- // operator traits but leaves an argument as
- // just T instead of &T. We'll catch it in the
- // mismatch impl/trait method phase no need to
- // ICE here.
- // See: #11450
- formal_ty = ty::mk_err();
- }
- }
- }
- DontDerefArgs => {}
- }
-
- check_expr_coercable_to_type(fcx, *arg, formal_ty);
-
- }
- }
- }
-
- // We also need to make sure we at least write the ty of the other
- // arguments which we skipped above.
- if variadic {
- for arg in args.iter().skip(expected_arg_count) {
- check_expr(fcx, *arg);
-
- // There are a few types which get autopromoted when passed via varargs
- // in C but we just error out instead and require explicit casts.
- let arg_ty = structurally_resolved_type(fcx, arg.span, fcx.expr_ty(*arg));
- match ty::get(arg_ty).sty {
- ty::ty_float(ast::TyF32) => {
- fcx.type_error_message(arg.span,
- |t| {
- format!("can't pass an {} to variadic \
- function, cast to c_double", t)
- }, arg_ty, None);
- }
- ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
- fcx.type_error_message(arg.span, |t| {
- format!("can't pass {} to variadic \
- function, cast to c_int",
- t)
- }, arg_ty, None);
- }
- ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
- fcx.type_error_message(arg.span, |t| {
- format!("can't pass {} to variadic \
- function, cast to c_uint",
- t)
- }, arg_ty, None);
- }
- _ => {}
- }
- }
- }
- }
-
- fn err_args(len: uint) -> Vec<ty::t> {
- Vec::from_fn(len, |_| ty::mk_err())
- }
-
- fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
- fcx.write_ty(call_expr.id, output);
- }
-
// A generic function for doing all of the checking for call expressions
fn check_call(fcx: &FnCtxt,
call_expr: &ast::Expr,
f: &ast::Expr,
args: &[@ast::Expr]) {
- // Index expressions need to be handled separately, to inform them
- // that they appear in call position.
- check_expr(fcx, f);
-
// Store the type of `f` as the type of the callee
let fn_ty = fcx.expr_ty(f);
});
// Call the generic checker.
- check_argument_types(fcx, call_expr.span, fn_sig.inputs.as_slice(), f,
- args, DontDerefArgs, fn_sig.variadic);
+ check_argument_types(fcx,
+ call_expr.span,
+ fn_sig.inputs.as_slice(),
+ f,
+ args,
+ DontDerefArgs,
+ fn_sig.variadic,
+ DontTupleArguments);
write_call(fcx, call_expr, fn_sig.output);
}
};
// Call the generic checker.
- let ret_ty = check_method_argument_types(fcx, method_name.span,
- fn_ty, expr, args,
- DontDerefArgs);
+ let ret_ty = check_method_argument_types(fcx,
+ method_name.span,
+ fn_ty,
+ expr,
+ args,
+ DontDerefArgs,
+ DontTupleArguments);
write_call(fcx, expr, ret_ty);
}
// HACK(eddyb) Fully qualified path to work around a resolve bug.
let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
fcx.inh.method_map.borrow_mut().insert(method_call, method);
- check_method_argument_types(fcx, op_ex.span,
- method_ty, op_ex,
- args, DoDerefArgs)
+ check_method_argument_types(fcx,
+ op_ex.span,
+ method_ty,
+ op_ex,
+ args,
+ DoDerefArgs,
+ DontTupleArguments)
}
None => {
unbound_method();
// Check the args anyway
// so we get all the error messages
let expected_ty = ty::mk_err();
- check_method_argument_types(fcx, op_ex.span,
- expected_ty, op_ex,
- args, DoDerefArgs);
+ check_method_argument_types(fcx,
+ op_ex.span,
+ expected_ty,
+ op_ex,
+ args,
+ DoDerefArgs,
+ DontTupleArguments);
ty::mk_err()
}
}
fcx.write_ty(id, fcx.node_ty(b.id));
}
ast::ExprCall(f, ref args) => {
- check_call(fcx, expr, f, args.as_slice());
+ // Index expressions need to be handled separately, to inform them
+ // that they appear in call position.
+ check_expr(fcx, f);
let f_ty = fcx.expr_ty(f);
- let (args_bot, args_err) = args.iter().fold((false, false),
- |(rest_bot, rest_err), a| {
- // is this not working?
- let a_ty = fcx.expr_ty(*a);
- (rest_bot || ty::type_is_bot(a_ty),
- rest_err || ty::type_is_error(a_ty))});
- if ty::type_is_error(f_ty) || args_err {
- fcx.write_error(id);
- }
- else if ty::type_is_bot(f_ty) || args_bot {
- fcx.write_bot(id);
+
+ if !try_overloaded_call(fcx, expr, f, f_ty, args.as_slice()) {
+ check_call(fcx, expr, f, args.as_slice());
+ let (args_bot, args_err) = args.iter().fold((false, false),
+ |(rest_bot, rest_err), a| {
+ // is this not working?
+ let a_ty = fcx.expr_ty(*a);
+ (rest_bot || ty::type_is_bot(a_ty),
+ rest_err || ty::type_is_error(a_ty))});
+ if ty::type_is_error(f_ty) || args_err {
+ fcx.write_error(id);
+ }
+ else if ty::type_is_bot(f_ty) || args_bot {
+ fcx.write_bot(id);
+ }
}
}
ast::ExprMethodCall(ident, ref tps, ref args) => {
match expr.node {
ast::ExprCall(callee, ref args) => {
- constrain_callee(rcx, callee.id, expr, callee);
- constrain_call(rcx,
- Some(callee.id),
- expr,
- None,
- args.as_slice(),
- false);
+ if !has_method_map {
+ constrain_callee(rcx, callee.id, expr, callee);
+ constrain_call(rcx,
+ Some(callee.id),
+ expr,
+ None,
+ args.as_slice(),
+ false);
+ }
visit::walk_expr(rcx, expr, ());
}
use std::rc::Rc;
struct UniversalQuantificationResult {
- monotype: t,
- type_variables: Vec<ty::t> ,
- type_param_defs: Rc<Vec<ty::TypeParameterDef> >
+ monotype: t
}
fn get_base_type(inference_context: &InferCtxt,
let monotype = polytype.ty.subst(self.crate_context.tcx, &substitutions);
UniversalQuantificationResult {
- monotype: monotype,
- type_variables: substitutions.tps,
- type_param_defs: polytype.generics.type_param_defs.clone()
+ monotype: monotype
}
}
use util::ppaux;
use util::ppaux::Repr;
-use std::rc::Rc;
use std::collections::{HashMap, HashSet};
-
+use std::rc::Rc;
use syntax::abi;
-use syntax::ast::{StaticRegionTyParamBound, OtherRegionTyParamBound,
- TraitTyParamBound};
+use syntax::ast::{StaticRegionTyParamBound, OtherRegionTyParamBound};
+use syntax::ast::{TraitTyParamBound, UnboxedFnTyParamBound};
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util::{local_def, split_trait_methods};
use syntax::codemap::Span;
use syntax::codemap;
+use syntax::owned_slice::OwnedSlice;
use syntax::parse::token::special_idents;
use syntax::parse::token;
use syntax::print::pprust::{path_to_str};
use syntax::visit;
-use syntax::owned_slice::OwnedSlice;
struct CollectItemTypesVisitor<'a> {
ccx: &'a CrateCtxt<'a>
param_bounds.builtin_bounds.add(ty::BoundStatic);
}
+ UnboxedFnTyParamBound(ref unboxed_function) => {
+ let rscope = ExplicitRscope;
+ let mut trait_ref =
+ astconv::trait_ref_for_unboxed_function(
+ ccx,
+ &rscope,
+ unboxed_function);
+ let self_ty = ty::mk_param(ccx.tcx,
+ param_ty.idx,
+ param_ty.def_id);
+ trait_ref.substs.self_ty = Some(self_ty);
+ param_bounds.trait_bounds.push(Rc::new(trait_ref));
+ }
+
OtherRegionTyParamBound(span) => {
if !ccx.tcx.sess.features.issue_5723_bootstrap.get() {
ccx.tcx.sess.span_err(
match tpb {
&ast::StaticRegionTyParamBound => ast::StaticRegionTyParamBound,
&ast::OtherRegionTyParamBound(s) => ast::OtherRegionTyParamBound(s),
+ &ast::UnboxedFnTyParamBound(unboxed_function_type) => {
+ ast::UnboxedFnTyParamBound(unboxed_function_type)
+ }
&ast::TraitTyParamBound(ref tr) => {
let last_seg = tr.path.segments.last().unwrap();
let mut insert = Vec::new();
struct InferredInfo<'a> {
item_id: ast::NodeId,
kind: ParamKind,
- index: uint,
param_id: ast::NodeId,
term: VarianceTermPtr<'a>,
}
let term = self.arena.alloc(|| InferredTerm(inf_index));
self.inferred_infos.push(InferredInfo { item_id: item_id,
kind: kind,
- index: index,
param_id: param_id,
term: term });
let newly_added = self.inferred_map.insert(param_id, inf_index);
--- /dev/null
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Used by `rustc` when compiling a plugin crate.
+
+use syntax::ast;
+use syntax::attr;
+use syntax::codemap::Span;
+use syntax::diagnostic;
+use syntax::visit;
+use syntax::visit::Visitor;
+
+struct RegistrarFinder {
+ registrars: Vec<(ast::NodeId, Span)> ,
+}
+
+impl Visitor<()> for RegistrarFinder {
+ fn visit_item(&mut self, item: &ast::Item, _: ()) {
+ match item.node {
+ ast::ItemFn(..) => {
+ if attr::contains_name(item.attrs.as_slice(),
+ "plugin_registrar") {
+ self.registrars.push((item.id, item.span));
+ }
+ }
+ _ => {}
+ }
+
+ visit::walk_item(self, item, ());
+ }
+}
+
+/// Find the function marked with `#[plugin_registrar]`, if any.
+pub fn find_plugin_registrar(diagnostic: &diagnostic::SpanHandler,
+ krate: &ast::Crate) -> Option<ast::NodeId> {
+ let mut finder = RegistrarFinder { registrars: Vec::new() };
+ visit::walk_crate(&mut finder, krate, ());
+
+ match finder.registrars.len() {
+ 0 => None,
+ 1 => {
+ let (node_id, _) = finder.registrars.pop().unwrap();
+ Some(node_id)
+ },
+ _ => {
+ diagnostic.handler().err("multiple plugin registration functions found");
+ for &(_, span) in finder.registrars.iter() {
+ diagnostic.span_note(span, "one is here");
+ }
+ diagnostic.handler().abort_if_errors();
+ unreachable!();
+ }
+ }
+}
--- /dev/null
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Used by `rustc` when loading a plugin.
+
+use driver::session::Session;
+use metadata::creader::PluginMetadataReader;
+use plugin::registry::Registry;
+
+use std::mem;
+use std::os;
+use std::dynamic_lib::DynamicLibrary;
+use syntax::ast;
+use syntax::attr;
+use syntax::visit;
+use syntax::visit::Visitor;
+use syntax::ext::expand::ExportedMacros;
+use syntax::attr::AttrMetaMethods;
+
+/// Plugin-related crate metadata.
+pub struct PluginMetadata {
+ /// Source code of macros exported by the crate.
+ pub macros: Vec<String>,
+ /// Path to the shared library file.
+ pub lib: Option<Path>,
+ /// Symbol name of the plugin registrar function.
+ pub registrar_symbol: Option<String>,
+}
+
+/// Pointer to a registrar function.
+pub type PluginRegistrarFun =
+ fn(&mut Registry);
+
+/// Information about loaded plugins.
+pub struct Plugins {
+ /// Source code of exported macros.
+ pub macros: Vec<ExportedMacros>,
+ /// Registrars, as function pointers.
+ pub registrars: Vec<PluginRegistrarFun>,
+}
+
+struct PluginLoader<'a> {
+ sess: &'a Session,
+ reader: PluginMetadataReader<'a>,
+ plugins: Plugins,
+}
+
+impl<'a> PluginLoader<'a> {
+ fn new(sess: &'a Session) -> PluginLoader<'a> {
+ PluginLoader {
+ sess: sess,
+ reader: PluginMetadataReader::new(sess),
+ plugins: Plugins {
+ macros: vec!(),
+ registrars: vec!(),
+ },
+ }
+ }
+}
+
+/// Read plugin metadata and dynamically load registrar functions.
+pub fn load_plugins(sess: &Session, krate: &ast::Crate) -> Plugins {
+ let mut loader = PluginLoader::new(sess);
+ visit::walk_crate(&mut loader, krate, ());
+ loader.plugins
+}
+
+impl<'a> Visitor<()> for PluginLoader<'a> {
+ fn visit_view_item(&mut self, vi: &ast::ViewItem, _: ()) {
+ match vi.node {
+ ast::ViewItemExternCrate(name, _, _) => {
+ let mut plugin_phase = false;
+
+ for attr in vi.attrs.iter().filter(|a| a.check_name("phase")) {
+ let phases = attr.meta_item_list().unwrap_or(&[]);
+ if attr::contains_name(phases, "plugin") {
+ plugin_phase = true;
+ }
+ if attr::contains_name(phases, "syntax") {
+ plugin_phase = true;
+ self.sess.span_warn(attr.span,
+ "phase(syntax) is a deprecated synonym for phase(plugin)");
+ }
+ }
+
+ if !plugin_phase { return; }
+
+ let PluginMetadata { macros, lib, registrar_symbol } =
+ self.reader.read_plugin_metadata(vi);
+
+ self.plugins.macros.push(ExportedMacros {
+ crate_name: name,
+ macros: macros,
+ });
+
+ match (lib, registrar_symbol) {
+ (Some(lib), Some(symbol))
+ => self.dylink_registrar(vi, lib, symbol),
+ _ => (),
+ }
+ }
+ _ => (),
+ }
+ }
+}
+
+impl<'a> PluginLoader<'a> {
+ // Dynamically link a registrar function into the compiler process.
+ fn dylink_registrar(&mut self, vi: &ast::ViewItem, path: Path, symbol: String) {
+ // Make sure the path contains a / or the linker will search for it.
+ let path = os::make_absolute(&path);
+
+ let lib = match DynamicLibrary::open(Some(&path)) {
+ Ok(lib) => lib,
+ // this is fatal: there are almost certainly macros we need
+ // inside this crate, so continue would spew "macro undefined"
+ // errors
+ Err(err) => self.sess.span_fatal(vi.span, err.as_slice())
+ };
+
+ unsafe {
+ let registrar: PluginRegistrarFun =
+ match lib.symbol(symbol.as_slice()) {
+ Ok(registrar) => registrar,
+ // again fatal if we can't register macros
+ Err(err) => self.sess.span_fatal(vi.span, err.as_slice())
+ };
+
+ self.plugins.registrars.push(registrar);
+
+ // Intentionally leak the dynamic library. We can't ever unload it
+ // since the library can make things that will live arbitrarily long
+ // (e.g. an @-box cycle or a task).
+ mem::forget(lib);
+
+ }
+ }
+}
--- /dev/null
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+ * Infrastructure for compiler plugins.
+ *
+ * Plugins are Rust libraries which extend the behavior of `rustc`
+ * in various ways.
+ *
+ * Plugin authors will use the `Registry` type re-exported by
+ * this module, along with its methods. The rest of the module
+ * is for use by `rustc` itself.
+ *
+ * To define a plugin, build a dylib crate with a
+ * `#[plugin_registrar]` function:
+ *
+ * ```rust,ignore
+ * #![crate_id = "myplugin"]
+ * #![crate_type = "dylib"]
+ * #![feature(plugin_registrar)]
+ *
+ * extern crate rustc;
+ *
+ * use rustc::plugin::Registry;
+ *
+ * #[plugin_registrar]
+ * pub fn plugin_registrar(reg: &mut Registry) {
+ * reg.register_macro("mymacro", expand_mymacro);
+ * }
+ *
+ * fn expand_mymacro(...) { // details elided
+ * ```
+ *
+ * WARNING: We currently don't check that the registrar function
+ * has the appropriate type!
+ *
+ * To use a plugin while compiling another crate:
+ *
+ * ```rust
+ * #![feature(phase)]
+ *
+ * #[phase(plugin)]
+ * extern crate myplugin;
+ * ```
+ *
+ * If you also need the plugin crate available at runtime, use
+ * `phase(plugin, link)`.
+ *
+ * See `src/test/auxiliary/macro_crate_test.rs` and `src/libfourcc`
+ * for examples of syntax extension plugins.
+ */
+
+pub use self::registry::Registry;
+
+pub mod registry;
+pub mod load;
+pub mod build;
--- /dev/null
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Used by plugin crates to tell `rustc` about the plugins they provide.
+
+use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
+use syntax::ext::base::{IdentTT, ItemDecorator, ItemModifier, BasicMacroExpander};
+use syntax::ext::base::{MacroExpanderFn};
+use syntax::codemap::Span;
+use syntax::parse::token;
+use syntax::ast;
+
+/// Structure used to register plugins.
+///
+/// A plugin registrar function takes an `&mut Registry` and should call
+/// methods to register its plugins.
+///
+/// This struct has public fields and other methods for use by `rustc`
+/// itself. They are not documented here, and plugin authors should
+/// not use them.
+pub struct Registry {
+ #[doc(hidden)]
+ pub krate_span: Span,
+
+ #[doc(hidden)]
+ pub syntax_exts: Vec<NamedSyntaxExtension>,
+}
+
+impl Registry {
+ #[doc(hidden)]
+ pub fn new(krate: &ast::Crate) -> Registry {
+ Registry {
+ krate_span: krate.span,
+ syntax_exts: vec!(),
+ }
+ }
+
+ /// Register a syntax extension of any kind.
+ ///
+ /// This is the most general hook into `libsyntax`'s expansion behavior.
+ pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
+ self.syntax_exts.push((name, match extension {
+ NormalTT(ext, _) => NormalTT(ext, Some(self.krate_span)),
+ IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
+ ItemDecorator(ext) => ItemDecorator(ext),
+ ItemModifier(ext) => ItemModifier(ext),
+ }));
+ }
+
+ /// Register a macro of the usual kind.
+ ///
+ /// This is a convenience wrapper for `register_syntax_extension`.
+ /// It builds for you a `NormalTT` with a `BasicMacroExpander`,
+ /// and also takes care of interning the macro's name.
+ pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
+ self.register_syntax_extension(
+ token::intern(name),
+ NormalTT(box BasicMacroExpander {
+ expander: expander,
+ span: None,
+ }, None));
+ }
+}
r
}
-pub struct _indenter {
- _i: (),
+pub struct Indenter {
+ _cannot_construct_outside_of_this_module: ()
}
-impl Drop for _indenter {
+impl Drop for Indenter {
fn drop(&mut self) { debug!("<<"); }
}
-pub fn _indenter(_i: ()) -> _indenter {
- _indenter {
- _i: ()
- }
-}
-
-pub fn indenter() -> _indenter {
+pub fn indenter() -> Indenter {
debug!(">>");
- _indenter(())
+ Indenter { _cannot_construct_outside_of_this_module: () }
}
struct LoopQueryVisitor<'a> {
fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
let t = ty::lookup_item_type(tcx, did);
match ty::get(t.ty).sty {
- ty::ty_enum(edid, _) => {
+ ty::ty_enum(edid, _) if !csearch::is_typedef(&tcx.sess.cstore, did) => {
return clean::EnumItem(clean::Enum {
generics: t.generics.clean(),
variants_stripped: false,
match *self {
ast::StaticRegionTyParamBound => RegionBound,
ast::OtherRegionTyParamBound(_) => RegionBound,
+ ast::UnboxedFnTyParamBound(_) => {
+ // FIXME(pcwalton): Wrong.
+ RegionBound
+ }
ast::TraitTyParamBound(ref t) => TraitBound(t.clean()),
}
}
use rustc;
use rustc::{driver, middle};
-use rustc::metadata::creader::Loader;
use rustc::middle::privacy;
use rustc::middle::lint;
}
let krate = phase_1_parse_input(&sess, cfg, &input);
- let (krate, ast_map) = phase_2_configure_and_expand(&sess, &mut Loader::new(&sess),
- krate, &from_str("rustdoc").unwrap());
+ let (krate, ast_map) = phase_2_configure_and_expand(&sess, krate,
+ &from_str("rustdoc").unwrap());
let driver::driver::CrateAnalysis {
exported_items, public_items, ty_cx, ..
} = phase_3_run_analysis_passes(sess, &krate, ast_map);
mod imp {
use libc;
use std::mem;
- use std::os::win32::as_utf16_p;
use std::os;
use std::ptr;
impl Lock {
pub fn new(p: &Path) -> Lock {
- let handle = as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::CreateFileW(p,
+ let p_16 = p.as_str().unwrap().to_utf16().append_one(0);
+ let handle = unsafe {
+ libc::CreateFileW(p_16.as_ptr(),
libc::FILE_GENERIC_READ |
libc::FILE_GENERIC_WRITE,
libc::FILE_SHARE_READ |
libc::CREATE_ALWAYS,
libc::FILE_ATTRIBUTE_NORMAL,
ptr::mut_null())
- });
+ };
if handle as uint == libc::INVALID_HANDLE_VALUE as uint {
fail!("create file error: {}", os::last_os_error());
}
//! // ... something using html
//! ```
+#![allow(dead_code)]
#![allow(non_camel_case_types)]
use libc;
extern crate debug;
extern crate getopts;
extern crate libc;
-#[phase(syntax, link)]
-extern crate log;
extern crate rustc;
extern crate serialize;
extern crate sync;
extern crate testing = "test";
extern crate time;
+#[cfg(stage0)]
+#[phase(syntax, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
use std::io;
use std::io::{File, MemWriter};
use std::str;
use clean;
-use dl = std::unstable::dynamic_lib;
+use dl = std::dynamic_lib;
use serialize::json;
use std::string::String;
use std::os;
use std::str;
use std::string::String;
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
use std::collections::{HashSet, HashMap};
use testing;
use rustc::driver::config;
use rustc::driver::driver;
use rustc::driver::session;
-use rustc::metadata::creader::Loader;
use syntax::ast;
use syntax::codemap::{CodeMap, dummy_spanned};
use syntax::diagnostic;
@dummy_spanned(ast::MetaWord(cfg_))
}));
let krate = driver::phase_1_parse_input(&sess, cfg, &input);
- let (krate, _) = driver::phase_2_configure_and_expand(&sess, &mut Loader::new(&sess), krate,
+ let (krate, _) = driver::phase_2_configure_and_expand(&sess, krate,
&from_str("rustdoc-test").unwrap());
let ctx = @core::DocContext {
}
}
-impl Container for CString {
+impl Collection for CString {
/// Return the number of bytes in the CString (not including the NUL terminator).
///
/// # Failure
#![no_std]
#![experimental]
+#[cfg(stage0)]
#[phase(syntax, link)]
extern crate core;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate core;
+
extern crate alloc;
extern crate libc;
extern crate collections;
#[cfg(test)] extern crate realrustrt = "rustrt";
#[cfg(test)] extern crate test;
#[cfg(test)] extern crate native;
-#[cfg(test)] #[phase(syntax, link)] extern crate std;
+
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate std;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate std;
pub use self::util::{Stdio, Stdout, Stderr};
pub use self::unwind::{begin_unwind, begin_unwind_fmt};
static _PTHREAD_MUTEX_SIG_init: libc::c_long = 0x32AAABA7;
static _PTHREAD_COND_SIG_init: libc::c_long = 0x3CB0B1BB;
+ #[repr(C)]
pub struct pthread_mutex_t {
__sig: libc::c_long,
__opaque: [u8, ..__PTHREAD_MUTEX_SIZE__],
}
+ #[repr(C)]
pub struct pthread_cond_t {
__sig: libc::c_long,
__opaque: [u8, ..__PTHREAD_COND_SIZE__],
#[cfg(target_arch = "mips")]
static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
+ #[repr(C)]
pub struct pthread_mutex_t {
__align: libc::c_longlong,
size: [u8, ..__SIZEOF_PTHREAD_MUTEX_T],
}
+ #[repr(C)]
pub struct pthread_cond_t {
__align: libc::c_longlong,
size: [u8, ..__SIZEOF_PTHREAD_COND_T],
mod os {
use libc;
+ #[repr(C)]
pub struct pthread_mutex_t { value: libc::c_int }
+ #[repr(C)]
pub struct pthread_cond_t { value: libc::c_int }
pub static PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
pub struct IdleWatcher {
handle: *uvll::uv_idle_t,
idle_flag: bool,
- closed: bool,
callback: Box<Callback:Send>,
}
let me = box IdleWatcher {
handle: handle,
idle_flag: false,
- closed: false,
callback: cb,
};
return me.install();
pub struct TcpListener {
home: HomeHandle,
handle: *uvll::uv_pipe_t,
- closing_task: Option<BlockedTask>,
outgoing: Sender<Result<Box<rtio::RtioTcpStream:Send>, IoError>>,
incoming: Receiver<Result<Box<rtio::RtioTcpStream:Send>, IoError>>,
}
let l = box TcpListener {
home: io.make_handle(),
handle: handle,
- closing_task: None,
outgoing: tx,
incoming: rx,
};
// These fields are private because they must be interfaced with through the
// functions below.
+#[repr(C)]
pub struct uv_stdio_container_t {
flags: libc::c_int,
stream: *uv_stream_t,
ParseObject(bool),
// Parse ',' or ']' after an element in an object.
ParseObjectComma,
- // Initialial state.
+ // Initial state.
ParseStart,
// Expecting the stream to end.
ParseBeforeFinish,
// We maintain a stack representing where we are in the logical structure
// of the JSON stream.
stack: Stack,
- // A state machine is kept to make it possible to interupt and resume parsing.
+ // A state machine is kept to make it possible to interrupt and resume parsing.
state: ParserState,
}
// information to return a JsonEvent.
// Manages an internal state so that parsing can be interrupted and resumed.
// Also keeps track of the position in the logical structure of the json
- // stream int the form of a stack that can be queried by the user usng the
+ // stream int the form of a stack that can be queried by the user using the
// stack() method.
fn parse(&mut self) -> JsonEvent {
loop {
// test harness access
#[cfg(test)]
extern crate test;
+
+#[cfg(stage0)]
#[phase(syntax, link)]
extern crate log;
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
pub use self::serialize::{Decoder, Encoder, Decodable, Encodable,
DecoderHelpers, EncoderHelpers};
//! Operations on ASCII strings and characters
-use container::Container;
+use collections::Collection;
use fmt;
use iter::Iterator;
use mem;
//! handled correctly, i.e. that allocated memory is eventually freed
//! if necessary.
-use container::Container;
+use collections::Collection;
use kinds::Send;
use mem;
use ops::Drop;
}
}
-impl<T> Container for CVec<T> {
+impl<T> Collection for CVec<T> {
fn len(&self) -> uint { self.len }
}
use clone::Clone;
use cmp::{max, Eq, Equiv, PartialEq};
-use container::{Container, Mutable, Set, MutableSet, Map, MutableMap};
+use collections::{Collection, Mutable, Set, MutableSet, Map, MutableMap};
use default::Default;
use fmt::Show;
use fmt;
}
pub fn move_iter(self) -> MoveEntries<K, V> {
- MoveEntries { table: self, idx: 0, elems_seen: 0 }
+ MoveEntries { table: self, idx: 0 }
}
}
/// Iterator over the entries in a table, consuming the table.
pub struct MoveEntries<K, V> {
table: RawTable<K, V>,
- idx: uint,
- elems_seen: uint,
+ idx: uint
}
impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
}
}
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Container for HashMap<K, V, H> {
+impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Collection for HashMap<K, V, H> {
/// Return the number of elements in the map
fn len(&self) -> uint { self.table.size() }
}
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {}
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> Container for HashSet<T, H> {
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> Collection for HashSet<T, H> {
fn len(&self) -> uint { self.map.len() }
}
use prelude::*;
use super::HashSet;
- use container::Container;
use slice::ImmutableEqVector;
+ use collections::Collection;
#[test]
fn test_disjoint() {
//! ```
use cmp::{PartialEq, Eq};
-use collections::HashMap;
-use container::{Container, Mutable, MutableMap};
+use collections::{HashMap, Collection, Mutable, MutableMap};
use fmt;
use hash::Hash;
use iter::{range, Iterator};
}
}
-impl<K: Hash + Eq, V> Container for LruCache<K, V> {
+impl<K: Hash + Eq, V> Collection for LruCache<K, V> {
/// Return the number of key-value pairs in the cache.
fn len(&self) -> uint {
self.map.len()
* Collection types.
*/
-pub use core_collections::{Bitv, BitvSet, BTree, Deque, DList, EnumSet};
+pub use core_collections::{Collection, Mutable, Map, MutableMap};
+pub use core_collections::{Set, MutableSet, Deque};
+pub use core_collections::{Bitv, BitvSet, BTree, DList, EnumSet};
pub use core_collections::{PriorityQueue, RingBuf, SmallIntMap};
pub use core_collections::{TreeMap, TreeSet, TrieMap, TrieSet};
-pub use core_collections::{bitv, btree, deque, dlist, enum_set};
+pub use core_collections::{bitv, btree, dlist, enum_set};
pub use core_collections::{priority_queue, ringbuf, smallintmap, treemap, trie};
pub use self::hashmap::{HashMap, HashSet};
/// of a synchronous channel. There are a few branches for the unbuffered case,
/// but they're mostly just relevant to blocking senders.
-use container::Container;
+use collections::Collection;
use iter::Iterator;
use kinds::Send;
use mem;
--- /dev/null
+// Copyright 2013-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.
+
+/*!
+
+Dynamic library facilities.
+
+A simple wrapper over the platform's dynamic library facilities
+
+*/
+
+#![experimental]
+#![allow(missing_doc)]
+
+use clone::Clone;
+use c_str::ToCStr;
+use iter::Iterator;
+use mem;
+use ops::*;
+use option::*;
+use os;
+use path::{Path,GenericPath};
+use result::*;
+use slice::{Vector,ImmutableVector};
+use str;
+use string::String;
+use vec::Vec;
+
+pub struct DynamicLibrary { handle: *u8}
+
+impl Drop for DynamicLibrary {
+ fn drop(&mut self) {
+ match dl::check_for_errors_in(|| {
+ unsafe {
+ dl::close(self.handle)
+ }
+ }) {
+ Ok(()) => {},
+ Err(str) => fail!("{}", str)
+ }
+ }
+}
+
+impl DynamicLibrary {
+ // FIXME (#12938): Until DST lands, we cannot decompose &str into
+ // & and str, so we cannot usefully take ToCStr arguments by
+ // reference (without forcing an additional & around &str). So we
+ // are instead temporarily adding an instance for &Path, so that
+ // we can take ToCStr as owned. When DST lands, the &Path instance
+ // should be removed, and arguments bound by ToCStr should be
+ // passed by reference. (Here: in the `open` method.)
+
+ /// Lazily open a dynamic library. When passed None it gives a
+ /// handle to the calling process
+ pub fn open<T: ToCStr>(filename: Option<T>)
+ -> Result<DynamicLibrary, String> {
+ unsafe {
+ let mut filename = filename;
+ let maybe_library = dl::check_for_errors_in(|| {
+ match filename.take() {
+ Some(name) => dl::open_external(name),
+ None => dl::open_internal()
+ }
+ });
+
+ // The dynamic library must not be constructed if there is
+ // an error opening the library so the destructor does not
+ // run.
+ match maybe_library {
+ Err(err) => Err(err),
+ Ok(handle) => Ok(DynamicLibrary { handle: handle })
+ }
+ }
+ }
+
+ /// Prepends a path to this process's search path for dynamic libraries
+ pub fn prepend_search_path(path: &Path) {
+ let mut search_path = DynamicLibrary::search_path();
+ search_path.insert(0, path.clone());
+ let newval = DynamicLibrary::create_path(search_path.as_slice());
+ os::setenv(DynamicLibrary::envvar(),
+ str::from_utf8(newval.as_slice()).unwrap());
+ }
+
+ /// From a slice of paths, create a new vector which is suitable to be an
+ /// environment variable for this platforms dylib search path.
+ pub fn create_path(path: &[Path]) -> Vec<u8> {
+ let mut newvar = Vec::new();
+ for (i, path) in path.iter().enumerate() {
+ if i > 0 { newvar.push(DynamicLibrary::separator()); }
+ newvar.push_all(path.as_vec());
+ }
+ return newvar;
+ }
+
+ /// Returns the environment variable for this process's dynamic library
+ /// search path
+ pub fn envvar() -> &'static str {
+ if cfg!(windows) {
+ "PATH"
+ } else if cfg!(target_os = "macos") {
+ "DYLD_LIBRARY_PATH"
+ } else {
+ "LD_LIBRARY_PATH"
+ }
+ }
+
+ fn separator() -> u8 {
+ if cfg!(windows) {';' as u8} else {':' as u8}
+ }
+
+ /// Returns the current search path for dynamic libraries being used by this
+ /// process
+ pub fn search_path() -> Vec<Path> {
+ let mut ret = Vec::new();
+ match os::getenv_as_bytes(DynamicLibrary::envvar()) {
+ Some(env) => {
+ for portion in
+ env.as_slice()
+ .split(|a| *a == DynamicLibrary::separator()) {
+ ret.push(Path::new(portion));
+ }
+ }
+ None => {}
+ }
+ return ret;
+ }
+
+ /// Access the value at the symbol of the dynamic library
+ pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, String> {
+ // This function should have a lifetime constraint of 'a on
+ // T but that feature is still unimplemented
+
+ let maybe_symbol_value = dl::check_for_errors_in(|| {
+ symbol.with_c_str(|raw_string| {
+ dl::symbol(self.handle, raw_string)
+ })
+ });
+
+ // The value must not be constructed if there is an error so
+ // the destructor does not run.
+ match maybe_symbol_value {
+ Err(err) => Err(err),
+ Ok(symbol_value) => Ok(mem::transmute(symbol_value))
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use prelude::*;
+ use libc;
+
+ #[test]
+ #[ignore(cfg(windows))] // FIXME #8818
+ #[ignore(cfg(target_os="android"))] // FIXME(#10379)
+ fn test_loading_cosine() {
+ // The math library does not need to be loaded since it is already
+ // statically linked in
+ let none: Option<Path> = None; // appease the typechecker
+ let libm = match DynamicLibrary::open(none) {
+ Err(error) => fail!("Could not load self as module: {}", error),
+ Ok(libm) => libm
+ };
+
+ let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
+ match libm.symbol("cos") {
+ Err(error) => fail!("Could not load function cos: {}", error),
+ Ok(cosine) => cosine
+ }
+ };
+
+ let argument = 0.0;
+ let expected_result = 1.0;
+ let result = cosine(argument);
+ if result != expected_result {
+ fail!("cos({:?}) != {:?} but equaled {:?} instead", argument,
+ expected_result, result)
+ }
+ }
+
+ #[test]
+ #[cfg(target_os = "linux")]
+ #[cfg(target_os = "macos")]
+ #[cfg(target_os = "freebsd")]
+ fn test_errors_do_not_crash() {
+ // Open /dev/null as a library to get an error, and make sure
+ // that only causes an error, and not a crash.
+ let path = Path::new("/dev/null");
+ match DynamicLibrary::open(Some(&path)) {
+ Err(_) => {}
+ Ok(_) => fail!("Successfully opened the empty library.")
+ }
+ }
+}
+
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
+#[cfg(target_os = "macos")]
+#[cfg(target_os = "freebsd")]
+pub mod dl {
+ use prelude::*;
+
+ use c_str::{CString, ToCStr};
+ use libc;
+ use ptr;
+ use result::*;
+ use str::StrAllocating;
+ use string::String;
+
+ pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
+ filename.with_c_str(|raw_name| {
+ dlopen(raw_name, Lazy as libc::c_int) as *u8
+ })
+ }
+
+ pub unsafe fn open_internal() -> *u8 {
+ dlopen(ptr::null(), Lazy as libc::c_int) as *u8
+ }
+
+ pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
+ use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
+ static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
+ unsafe {
+ // dlerror isn't thread safe, so we need to lock around this entire
+ // sequence
+ let _guard = lock.lock();
+ let _old_error = dlerror();
+
+ let result = f();
+
+ let last_error = dlerror();
+ let ret = if ptr::null() == last_error {
+ Ok(result)
+ } else {
+ Err(CString::new(last_error, false).as_str()
+ .unwrap()
+ .to_string())
+ };
+
+ ret
+ }
+ }
+
+ pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
+ dlsym(handle as *libc::c_void, symbol) as *u8
+ }
+ pub unsafe fn close(handle: *u8) {
+ dlclose(handle as *libc::c_void); ()
+ }
+
+ pub enum RTLD {
+ Lazy = 1,
+ Now = 2,
+ Global = 256,
+ Local = 0,
+ }
+
+ #[link_name = "dl"]
+ extern {
+ fn dlopen(filename: *libc::c_char, flag: libc::c_int) -> *libc::c_void;
+ fn dlerror() -> *libc::c_char;
+ fn dlsym(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void;
+ fn dlclose(handle: *libc::c_void) -> libc::c_int;
+ }
+}
+
+#[cfg(target_os = "win32")]
+pub mod dl {
+ use c_str::ToCStr;
+ use libc;
+ use os;
+ use ptr;
+ use result::{Ok, Err, Result};
+ use str::StrAllocating;
+ use str;
+ use string::String;
+
+ pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
+ // Windows expects Unicode data
+ let filename_cstr = filename.to_c_str();
+ let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
+ let filename_str = filename_str.to_utf16().append_one(0);
+ LoadLibraryW(filename_str.as_ptr() as *libc::c_void) as *u8
+ }
+
+ pub unsafe fn open_internal() -> *u8 {
+ let handle = ptr::null();
+ GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
+ handle as *u8
+ }
+
+ pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
+ unsafe {
+ SetLastError(0);
+
+ let result = f();
+
+ let error = os::errno();
+ if 0 == error {
+ Ok(result)
+ } else {
+ Err(format!("Error code {}", error))
+ }
+ }
+ }
+
+ pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
+ GetProcAddress(handle as *libc::c_void, symbol) as *u8
+ }
+ pub unsafe fn close(handle: *u8) {
+ FreeLibrary(handle as *libc::c_void); ()
+ }
+
+ #[allow(non_snake_case_functions)]
+ extern "system" {
+ fn SetLastError(error: libc::size_t);
+ fn LoadLibraryW(name: *libc::c_void) -> *libc::c_void;
+ fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
+ handle: **libc::c_void) -> *libc::c_void;
+ fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
+ fn FreeLibrary(handle: *libc::c_void);
+ }
+}
//! Buffering wrappers for I/O traits
use cmp;
-use container::Container;
+use collections::Collection;
use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult};
use iter::ExactSize;
use ops::Drop;
use clone::Clone;
use cmp;
-use container::Container;
+use collections::Collection;
use comm::{Sender, Receiver};
use io;
use option::{None, Option, Some};
use result::{Ok, Err};
use super::{Reader, Writer, IoResult};
use str::StrSlice;
-use slice::{bytes, CloneableVector, MutableVector, ImmutableVector};
+use slice::{bytes, MutableVector, ImmutableVector};
+use vec::Vec;
/// Allows reading from a rx.
///
/// # drop(tx);
/// let mut reader = ChanReader::new(rx);
///
-/// let mut buf = ~[0u8, ..100];
+/// let mut buf = [0u8, ..100];
/// match reader.read(buf) {
/// Ok(nread) => println!("Read {} bytes", nread),
/// Err(e) => println!("read error: {}", e),
/// }
/// ```
pub struct ChanReader {
- buf: Option<~[u8]>, // A buffer of bytes received but not consumed.
- pos: uint, // How many of the buffered bytes have already be consumed.
- rx: Receiver<~[u8]>, // The rx to pull data from.
- closed: bool, // Whether the pipe this rx connects to has been closed.
+ buf: Option<Vec<u8>>, // A buffer of bytes received but not consumed.
+ pos: uint, // How many of the buffered bytes have already be consumed.
+ rx: Receiver<Vec<u8>>, // The Receiver to pull data from.
+ closed: bool, // Whether the channel this Receiver connects to has been closed.
}
impl ChanReader {
/// Wraps a `Port` in a `ChanReader` structure
- pub fn new(rx: Receiver<~[u8]>) -> ChanReader {
+ pub fn new(rx: Receiver<Vec<u8>>) -> ChanReader {
ChanReader {
buf: None,
pos: 0,
/// writer.write("hello, world".as_bytes());
/// ```
pub struct ChanWriter {
- tx: Sender<~[u8]>,
+ tx: Sender<Vec<u8>>,
}
impl ChanWriter {
/// Wraps a channel in a `ChanWriter` structure
- pub fn new(tx: Sender<~[u8]>) -> ChanWriter {
+ pub fn new(tx: Sender<Vec<u8>>) -> ChanWriter {
ChanWriter { tx: tx }
}
}
impl Writer for ChanWriter {
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
- self.tx.send_opt(buf.to_owned()).map_err(|_| {
+ self.tx.send_opt(Vec::from_slice(buf)).map_err(|_| {
io::IoError {
kind: io::BrokenPipe,
desc: "Pipe closed",
fn test_rx_reader() {
let (tx, rx) = channel();
task::spawn(proc() {
- tx.send(box [1u8, 2u8]);
- tx.send(box []);
- tx.send(box [3u8, 4u8]);
- tx.send(box [5u8, 6u8]);
- tx.send(box [7u8, 8u8]);
+ tx.send(vec![1u8, 2u8]);
+ tx.send(vec![]);
+ tx.send(vec![3u8, 4u8]);
+ tx.send(vec![5u8, 6u8]);
+ tx.send(vec![7u8, 8u8]);
});
let mut reader = ChanReader::new(rx);
- let mut buf = box [0u8, ..3];
+ let mut buf = [0u8, ..3];
assert_eq!(Ok(0), reader.read([]));
assert_eq!(Ok(3), reader.read(buf));
- assert_eq!(box [1,2,3], buf);
+ assert_eq!(&[1,2,3], buf.as_slice());
assert_eq!(Ok(3), reader.read(buf));
- assert_eq!(box [4,5,6], buf);
+ assert_eq!(&[4,5,6], buf.as_slice());
assert_eq!(Ok(2), reader.read(buf));
- assert_eq!(box [7,8,6], buf);
+ assert_eq!(&[7,8,6], buf.as_slice());
match reader.read(buf) {
Ok(..) => fail!(),
Err(e) => assert_eq!(e.kind, io::EndOfFile),
}
- assert_eq!(box [7,8,6], buf);
+ assert_eq!(&[7,8,6], buf.as_slice());
// Ensure it continues to fail in the same way.
match reader.read(buf) {
Ok(..) => fail!(),
Err(e) => assert_eq!(e.kind, io::EndOfFile),
}
- assert_eq!(box [7,8,6], buf);
+ assert_eq!(&[7,8,6], buf.as_slice());
}
#[test]
let mut writer = ChanWriter::new(tx);
writer.write_be_u32(42).unwrap();
- let wanted = box [0u8, 0u8, 0u8, 42u8];
+ let wanted = vec![0u8, 0u8, 0u8, 42u8];
let got = task::try(proc() { rx.recv() }).unwrap();
assert_eq!(wanted, got);
// FIXME: Not sure how this should be structured
// FIXME: Iteration should probably be considered separately
-use container::Container;
+use collections::Collection;
use iter::Iterator;
use option::{Option, Some, None};
use result::{Ok, Err};
mod bench {
extern crate test;
- use container::Container;
+ use collections::Collection;
use prelude::*;
use self::test::Bencher;
use c_str::ToCStr;
use clone::Clone;
-use container::Container;
+use collections::Collection;
use io;
use iter::Iterator;
use kinds::Send;
//! Readers and Writers for in-memory buffers
use cmp::min;
-use container::Container;
+use collections::Collection;
use option::None;
use result::{Err, Ok};
use io;
* Make a simple TCP client connection and request
- ```rust,should_fail
+ ```rust
# #![allow(unused_must_use)]
use std::io::net::tcp::TcpStream;
+ # // connection doesn't fail if a server is running on 8080
+ # // locally, we still want to be type checking this code, so lets
+ # // just stop it running (#11576)
+ # if false {
let mut socket = TcpStream::connect("127.0.0.1", 8080).unwrap();
socket.write(bytes!("GET / HTTP/1.0\n\n"));
let response = socket.read_to_end();
+ # }
```
* Make a simple TCP server
#![deny(unused_must_use)]
use char::Char;
-use container::Container;
+use collections::Collection;
use fmt;
use int;
use iter::Iterator;
/// Returns a slice of `v` between `start` and `end`.
///
-/// Similar to `slice()` except this function only bounds the sclie on the
+/// Similar to `slice()` except this function only bounds the slice on the
/// capacity of `v`, not the length.
///
/// # Failure
#![allow(missing_doc)]
-use container::Container;
+use collections::Collection;
use fmt;
use from_str::FromStr;
use iter::Iterator;
pub fn sleeper() -> Process {
// There's a `timeout` command on windows, but it doesn't like having
// its output piped, so instead just ping ourselves a few times with
- // gaps inbetweeen so we're sure this process is alive for awhile
+ // gaps in between so we're sure this process is alive for awhile
Command::new("ping").arg("127.0.0.1").arg("-n").arg("1000").spawn().unwrap()
}
pub fn stdin() -> BufferedReader<StdReader> {
// The default buffer capacity is 64k, but apparently windows doesn't like
// 64k reads on stdin. See #13304 for details, but the idea is that on
- // windows we use a slighly smaller buffer that's been seen to be
+ // windows we use a slightly smaller buffer that's been seen to be
// acceptable.
if cfg!(windows) {
BufferedReader::with_capacity(8 * 1024, stdin_raw())
iotest!(fn test_io_timer_oneshot_then_sleep() {
let mut timer = Timer::new().unwrap();
let rx = timer.oneshot(100000000000);
- timer.sleep(1); // this should inalidate rx
+ timer.sleep(1); // this should invalidate rx
assert_eq!(rx.recv_opt(), Err(()));
})
let mut timer1 = Timer::new().unwrap();
timer1.oneshot(1);
let mut timer2 = Timer::new().unwrap();
- // while sleeping, the prevous timer should fire and not have its
+ // while sleeping, the previous timer should fire and not have its
// callback do something terrible.
timer2.sleep(2);
})
let mut timer1 = Timer::new().unwrap();
timer1.periodic(1);
let mut timer2 = Timer::new().unwrap();
- // while sleeping, the prevous timer should fire and not have its
+ // while sleeping, the previous timer should fire and not have its
// callback do something terrible.
timer2.sleep(2);
})
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate green;
#[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
extern crate alloc;
extern crate core;
pub use core::char;
pub use core::clone;
#[cfg(not(test))] pub use core::cmp;
-pub use core::container;
pub use core::default;
pub use core::finally;
pub use core::intrinsics;
/* Runtime and platform support */
pub mod c_vec;
+pub mod dynamic_lib;
pub mod os;
pub mod io;
pub mod path;
pub mod fmt;
-// Private APIs
-#[unstable]
-pub mod unstable;
-
// FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable'
// but name resolution doesn't work without it being pub.
#[unstable]
// The test runner requires std::slice::Vector, so re-export std::slice just for it.
#[cfg(test)] pub use slice;
}
+
+#[deprecated]
+#[allow(missing_doc)]
+#[doc(hiden)]
+pub mod unstable {
+ #[deprecated = "use std::dynamic_lib"]
+ pub use dynamic_lib;
+}
/// # Example
///
/// ```rust
- /// let user: &'static str = env!("USER");
- /// println!("the user who compiled this code is: {}", user);
+ /// let home: &'static str = env!("HOME");
+ /// println!("the home directory at the time of compiling was: {}", home);
/// ```
#[macro_export]
macro_rules! env( ($name:expr) => ({ /* compiler built-in */ }) )
use char;
use clone::Clone;
-use container::Container;
+use collections::Collection;
use num::{NumCast, Zero, One, cast, Int};
use num::{Float, FPNaN, FPInfinite, ToPrimitive};
use num;
if accum_positive && accum <= last_accum { return NumStrConv::inf(); }
if !accum_positive && accum >= last_accum { return NumStrConv::neg_inf(); }
- // Detect overflow by reversing the shift-and-add proccess
+ // Detect overflow by reversing the shift-and-add process
if accum_positive &&
(last_accum != ((accum - cast(digit as int).unwrap())/radix_gen.clone())) {
return NumStrConv::inf();
#![allow(non_snake_case_functions)]
use clone::Clone;
-use container::Container;
+use collections::Collection;
use fmt;
use iter::Iterator;
use libc::{c_void, c_int};
use os::TMPBUF_SZ;
use slice::{MutableVector, ImmutableVector};
use string::String;
- use str::{StrSlice, StrAllocating};
+ use str::StrSlice;
use str;
use vec::Vec;
return res;
}
}
-
- pub fn as_utf16_p<T>(s: &str, f: |*u16| -> T) -> T {
- as_mut_utf16_p(s, |t| { f(t as *u16) })
- }
-
- pub fn as_mut_utf16_p<T>(s: &str, f: |*mut u16| -> T) -> T {
- let mut t = s.to_utf16();
- // Null terminate before passing on.
- t.push(0u16);
- f(t.as_mut_ptr())
- }
}
/*
/// let key = "HOME";
/// match std::os::getenv(key) {
/// Some(val) => println!("{}: {}", key, val),
-/// None => println!("{} is not defined in the environnement.", key)
+/// None => println!("{} is not defined in the environment.", key)
/// }
/// ```
pub fn getenv(n: &str) -> Option<String> {
pub fn getenv(n: &str) -> Option<String> {
unsafe {
with_env_lock(|| {
- use os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
- as_utf16_p(n, |u| {
- fill_utf16_buf_and_decode(|buf, sz| {
- libc::GetEnvironmentVariableW(u, buf, sz)
- })
+ use os::win32::{fill_utf16_buf_and_decode};
+ let n = n.to_utf16().append_one(0);
+ fill_utf16_buf_and_decode(|buf, sz| {
+ libc::GetEnvironmentVariableW(n.as_ptr(), buf, sz)
})
})
}
/// Sets the environment variable `n` to the value `v` for the currently running
/// process
pub fn setenv(n: &str, v: &str) {
+ let n = n.to_utf16().append_one(0);
+ let v = v.to_utf16().append_one(0);
unsafe {
with_env_lock(|| {
- use os::win32::as_utf16_p;
- as_utf16_p(n, |nbuf| {
- as_utf16_p(v, |vbuf| {
- libc::SetEnvironmentVariableW(nbuf, vbuf);
- })
- })
+ libc::SetEnvironmentVariableW(n.as_ptr(), v.as_ptr());
})
}
}
}
#[cfg(windows)]
fn _unsetenv(n: &str) {
+ let n = n.to_utf16().append_one(0);
unsafe {
with_env_lock(|| {
- use os::win32::as_utf16_p;
- as_utf16_p(n, |nbuf| {
- libc::SetEnvironmentVariableW(nbuf, ptr::null());
- })
+ libc::SetEnvironmentVariableW(n.as_ptr(), ptr::null());
})
}
}
#[cfg(windows)]
fn chdir(p: &Path) -> bool {
+ let p = match p.as_str() {
+ Some(s) => s.to_utf16().append_one(0),
+ None => return false,
+ };
unsafe {
- use os::win32::as_utf16_p;
- return as_utf16_p(p.as_str().unwrap(), |buf| {
- libc::SetCurrentDirectoryW(buf) != (0 as libc::BOOL)
- });
+ libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL)
}
}
#![deny(deprecated_owned_vector)]
-use container::Container;
+use collections::Collection;
use c_str::CString;
use clone::Clone;
use fmt;
use c_str::{CString, ToCStr};
use clone::Clone;
use cmp::{PartialEq, Eq};
-use container::Container;
+use collections::Collection;
use from_str::FromStr;
use hash;
use io::Writer;
use c_str::{CString, ToCStr};
use clone::Clone;
use cmp::{PartialEq, Eq};
-use container::Container;
+use collections::Collection;
use from_str::FromStr;
use hash;
use io::Writer;
ret
}
- /// See `GenericPathUnsafe::set_filename_unchecekd`.
+ /// See `GenericPathUnsafe::set_filename_unchecked`.
///
/// # Failure
///
#[doc(no_inline)] pub use clone::Clone;
#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
#[doc(no_inline)] pub use cmp::{Ordering, Less, Equal, Greater, Equiv};
-#[doc(no_inline)] pub use container::{Container, Mutable, Map, MutableMap};
-#[doc(no_inline)] pub use container::{Set, MutableSet};
+#[doc(no_inline)] pub use collections::{Collection, Mutable, Map, MutableMap};
+#[doc(no_inline)] pub use collections::{Set, MutableSet};
#[doc(no_inline)] pub use iter::{FromIterator, Extendable, ExactSize};
#[doc(no_inline)] pub use iter::{Iterator, DoubleEndedIterator};
#[doc(no_inline)] pub use iter::{RandomAccessIterator, CloneableIterator};
mod imp {
extern crate libc;
- use container::Container;
+ use core_collections::Collection;
use io::{IoResult, IoError};
use mem;
use ops::Drop;
//! A wrapper around any Reader to treat it as an RNG.
-use container::Container;
+use collections::Collection;
use io::Reader;
use rand::Rng;
use result::{Ok, Err};
#![allow(non_camel_case_types)]
use char::Char;
-use container::Container;
+use collections::Collection;
use from_str::from_str;
use io::{IoResult, Writer};
use iter::Iterator;
#[cfg(target_os = "macos")]
fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> {
use intrinsics;
+ #[repr(C)]
struct Dl_info {
dli_fname: *libc::c_char,
dli_fbase: *libc::c_void,
#[cfg(not(target_os = "macos"))]
fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> {
- use container::Container;
+ use collections::Collection;
use iter::Iterator;
use os;
use path::GenericPath;
#[allow(dead_code, uppercase_variables)]
mod imp {
use c_str::CString;
- use container::Container;
+ use core_collections::Collection;
use intrinsics;
use io::{IoResult, Writer};
use libc;
use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
use slice::ImmutableVector;
use str::StrSlice;
- use unstable::dynamic_lib::DynamicLibrary;
+ use dynamic_lib::DynamicLibrary;
#[allow(non_snake_case_functions)]
extern "system" {
// EINVAL means |stack_size| is either too small or not a
// multiple of the system page size. Because it's definitely
// >= PTHREAD_STACK_MIN, it must be an alignment issue.
- // Round up to the neareast page and try again.
+ // Round up to the nearest page and try again.
let page_size = os::page_size();
let stack_size = (stack_size + page_size - 1) & (-(page_size - 1) - 1);
assert_eq!(pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t), 0);
/// Options to spawn the new task with
pub opts: TaskOpts,
gen_body: Option<proc(v: proc():Send):Send -> proc():Send>,
- nocopy: Option<marker::NoCopy>,
+ nocopy: marker::NoCopy,
}
impl TaskBuilder {
TaskBuilder {
opts: TaskOpts::new(),
gen_body: None,
- nocopy: None,
+ nocopy: marker::NoCopy,
}
}
+++ /dev/null
-// Copyright 2013-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.
-
-/*!
-
-Dynamic library facilities.
-
-A simple wrapper over the platform's dynamic library facilities
-
-*/
-
-use clone::Clone;
-use c_str::ToCStr;
-use iter::Iterator;
-use mem;
-use ops::*;
-use option::*;
-use os;
-use path::{Path,GenericPath};
-use result::*;
-use slice::{Vector,ImmutableVector};
-use str;
-use string::String;
-use vec::Vec;
-
-pub struct DynamicLibrary { handle: *u8}
-
-impl Drop for DynamicLibrary {
- fn drop(&mut self) {
- match dl::check_for_errors_in(|| {
- unsafe {
- dl::close(self.handle)
- }
- }) {
- Ok(()) => {},
- Err(str) => fail!("{}", str)
- }
- }
-}
-
-impl DynamicLibrary {
- // FIXME (#12938): Until DST lands, we cannot decompose &str into
- // & and str, so we cannot usefully take ToCStr arguments by
- // reference (without forcing an additional & around &str). So we
- // are instead temporarily adding an instance for &Path, so that
- // we can take ToCStr as owned. When DST lands, the &Path instance
- // should be removed, and arguments bound by ToCStr should be
- // passed by reference. (Here: in the `open` method.)
-
- /// Lazily open a dynamic library. When passed None it gives a
- /// handle to the calling process
- pub fn open<T: ToCStr>(filename: Option<T>)
- -> Result<DynamicLibrary, String> {
- unsafe {
- let mut filename = filename;
- let maybe_library = dl::check_for_errors_in(|| {
- match filename.take() {
- Some(name) => dl::open_external(name),
- None => dl::open_internal()
- }
- });
-
- // The dynamic library must not be constructed if there is
- // an error opening the library so the destructor does not
- // run.
- match maybe_library {
- Err(err) => Err(err),
- Ok(handle) => Ok(DynamicLibrary { handle: handle })
- }
- }
- }
-
- /// Prepends a path to this process's search path for dynamic libraries
- pub fn prepend_search_path(path: &Path) {
- let mut search_path = DynamicLibrary::search_path();
- search_path.insert(0, path.clone());
- let newval = DynamicLibrary::create_path(search_path.as_slice());
- os::setenv(DynamicLibrary::envvar(),
- str::from_utf8(newval.as_slice()).unwrap());
- }
-
- /// From a slice of paths, create a new vector which is suitable to be an
- /// environment variable for this platforms dylib search path.
- pub fn create_path(path: &[Path]) -> Vec<u8> {
- let mut newvar = Vec::new();
- for (i, path) in path.iter().enumerate() {
- if i > 0 { newvar.push(DynamicLibrary::separator()); }
- newvar.push_all(path.as_vec());
- }
- return newvar;
- }
-
- /// Returns the environment variable for this process's dynamic library
- /// search path
- pub fn envvar() -> &'static str {
- if cfg!(windows) {
- "PATH"
- } else if cfg!(target_os = "macos") {
- "DYLD_LIBRARY_PATH"
- } else {
- "LD_LIBRARY_PATH"
- }
- }
-
- fn separator() -> u8 {
- if cfg!(windows) {';' as u8} else {':' as u8}
- }
-
- /// Returns the current search path for dynamic libraries being used by this
- /// process
- pub fn search_path() -> Vec<Path> {
- let mut ret = Vec::new();
- match os::getenv_as_bytes(DynamicLibrary::envvar()) {
- Some(env) => {
- for portion in
- env.as_slice()
- .split(|a| *a == DynamicLibrary::separator()) {
- ret.push(Path::new(portion));
- }
- }
- None => {}
- }
- return ret;
- }
-
- /// Access the value at the symbol of the dynamic library
- pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, String> {
- // This function should have a lifetime constraint of 'a on
- // T but that feature is still unimplemented
-
- let maybe_symbol_value = dl::check_for_errors_in(|| {
- symbol.with_c_str(|raw_string| {
- dl::symbol(self.handle, raw_string)
- })
- });
-
- // The value must not be constructed if there is an error so
- // the destructor does not run.
- match maybe_symbol_value {
- Err(err) => Err(err),
- Ok(symbol_value) => Ok(mem::transmute(symbol_value))
- }
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
- use prelude::*;
- use libc;
-
- #[test]
- #[ignore(cfg(windows))] // FIXME #8818
- #[ignore(cfg(target_os="android"))] // FIXME(#10379)
- fn test_loading_cosine() {
- // The math library does not need to be loaded since it is already
- // statically linked in
- let none: Option<Path> = None; // appease the typechecker
- let libm = match DynamicLibrary::open(none) {
- Err(error) => fail!("Could not load self as module: {}", error),
- Ok(libm) => libm
- };
-
- let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
- match libm.symbol("cos") {
- Err(error) => fail!("Could not load function cos: {}", error),
- Ok(cosine) => cosine
- }
- };
-
- let argument = 0.0;
- let expected_result = 1.0;
- let result = cosine(argument);
- if result != expected_result {
- fail!("cos({:?}) != {:?} but equaled {:?} instead", argument,
- expected_result, result)
- }
- }
-
- #[test]
- #[cfg(target_os = "linux")]
- #[cfg(target_os = "macos")]
- #[cfg(target_os = "freebsd")]
- fn test_errors_do_not_crash() {
- // Open /dev/null as a library to get an error, and make sure
- // that only causes an error, and not a crash.
- let path = Path::new("/dev/null");
- match DynamicLibrary::open(Some(&path)) {
- Err(_) => {}
- Ok(_) => fail!("Successfully opened the empty library.")
- }
- }
-}
-
-#[cfg(target_os = "linux")]
-#[cfg(target_os = "android")]
-#[cfg(target_os = "macos")]
-#[cfg(target_os = "freebsd")]
-pub mod dl {
- use prelude::*;
-
- use c_str::{CString, ToCStr};
- use libc;
- use ptr;
- use result::*;
- use str::StrAllocating;
- use string::String;
-
- pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
- filename.with_c_str(|raw_name| {
- dlopen(raw_name, Lazy as libc::c_int) as *u8
- })
- }
-
- pub unsafe fn open_internal() -> *u8 {
- dlopen(ptr::null(), Lazy as libc::c_int) as *u8
- }
-
- pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
- use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
- static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
- unsafe {
- // dlerror isn't thread safe, so we need to lock around this entire
- // sequence
- let _guard = lock.lock();
- let _old_error = dlerror();
-
- let result = f();
-
- let last_error = dlerror();
- let ret = if ptr::null() == last_error {
- Ok(result)
- } else {
- Err(CString::new(last_error, false).as_str()
- .unwrap()
- .to_string())
- };
-
- ret
- }
- }
-
- pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
- dlsym(handle as *libc::c_void, symbol) as *u8
- }
- pub unsafe fn close(handle: *u8) {
- dlclose(handle as *libc::c_void); ()
- }
-
- pub enum RTLD {
- Lazy = 1,
- Now = 2,
- Global = 256,
- Local = 0,
- }
-
- #[link_name = "dl"]
- extern {
- fn dlopen(filename: *libc::c_char, flag: libc::c_int) -> *libc::c_void;
- fn dlerror() -> *libc::c_char;
- fn dlsym(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void;
- fn dlclose(handle: *libc::c_void) -> libc::c_int;
- }
-}
-
-#[cfg(target_os = "win32")]
-pub mod dl {
- use libc;
- use os;
- use ptr;
- use result::{Ok, Err, Result};
- use string::String;
- use str;
- use c_str::ToCStr;
-
- pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
- // Windows expects Unicode data
- let filename_cstr = filename.to_c_str();
- let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
- os::win32::as_utf16_p(filename_str, |raw_name| {
- LoadLibraryW(raw_name as *libc::c_void) as *u8
- })
- }
-
- pub unsafe fn open_internal() -> *u8 {
- let handle = ptr::null();
- GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
- handle as *u8
- }
-
- pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
- unsafe {
- SetLastError(0);
-
- let result = f();
-
- let error = os::errno();
- if 0 == error {
- Ok(result)
- } else {
- Err(format!("Error code {}", error))
- }
- }
- }
-
- pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
- GetProcAddress(handle as *libc::c_void, symbol) as *u8
- }
- pub unsafe fn close(handle: *u8) {
- FreeLibrary(handle as *libc::c_void); ()
- }
-
- #[allow(non_snake_case_functions)]
- extern "system" {
- fn SetLastError(error: libc::size_t);
- fn LoadLibraryW(name: *libc::c_void) -> *libc::c_void;
- fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
- handle: **libc::c_void) -> *libc::c_void;
- fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
- fn FreeLibrary(handle: *libc::c_void);
- }
-}
+++ /dev/null
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![doc(hidden)]
-
-pub mod dynamic_lib;
#![deny(missing_doc)]
-#[cfg(test)]
+#[cfg(test, stage0)]
#[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))]
+#[phase(plugin, link)] extern crate log;
+
extern crate alloc;
pub use comm::{DuplexStream, duplex};
/// dropped, this value will release the resource back to the semaphore.
#[must_use]
pub struct SemaphoreGuard<'a> {
- guard: SemGuard<'a, ()>,
+ _guard: SemGuard<'a, ()>,
}
impl Semaphore {
/// Acquire a resource of this semaphore, returning an RAII guard which will
/// release the resource when dropped.
pub fn access<'a>(&'a self) -> SemaphoreGuard<'a> {
- SemaphoreGuard { guard: self.sem.access() }
+ SemaphoreGuard { _guard: self.sem.access() }
}
}
/// corresponding mutex is also unlocked.
#[must_use]
pub struct MutexGuard<'a> {
- guard: SemGuard<'a, Vec<WaitQueue>>,
+ _guard: SemGuard<'a, Vec<WaitQueue>>,
/// Inner condition variable which is connected to the outer mutex, and can
/// be used for atomic-unlock-and-deschedule.
pub cond: Condvar<'a>,
/// also be accessed through the returned guard.
pub fn lock<'a>(&'a self) -> MutexGuard<'a> {
let SemCondGuard { guard, cvar } = self.sem.access_cond();
- MutexGuard { guard: guard, cond: cvar }
+ MutexGuard { _guard: guard, cond: cvar }
}
}
pub enum TyParamBound {
TraitTyParamBound(TraitRef),
StaticRegionTyParamBound,
+ UnboxedFnTyParamBound(UnboxedFnTy),
OtherRegionTyParamBound(Span) // FIXME -- just here until work for #5723 lands
}
pub decl: P<FnDecl>
}
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+pub struct UnboxedFnTy {
+ pub decl: P<FnDecl>,
+}
+
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
pub enum Ty_ {
TyNil,
TyClosure(@ClosureTy, Option<Lifetime>),
TyProc(@ClosureTy),
TyBareFn(@BareFnTy),
+ TyUnboxedFn(@UnboxedFnTy),
TyTup(Vec<P<Ty>> ),
TyPath(Path, Option<OwnedSlice<TyParamBound>>, NodeId), // for #7264; see above
TyTypeof(@Expr),
pub attrs: Vec<Attribute>,
}
+impl StructField_ {
+ pub fn ident(&self) -> Option<Ident> {
+ match self.kind {
+ NamedField(ref ident, _) => Some(ident.clone()),
+ UnnamedField(_) => None
+ }
+ }
+}
+
pub type StructField = Spanned<StructField_>;
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
pub type IdentMacroExpanderFn =
fn(&mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult>;
-pub type MacroCrateRegistrationFun =
- fn(|ast::Name, SyntaxExtension|);
-
/// The result of a macro expansion. The return values of the various
/// methods are spliced into the AST at the callsite of the macro (or
/// just into the compiler's internal macro table, for `make_def`).
IdentTT(Box<IdentMacroExpander:'static>, Option<Span>),
}
+pub type NamedSyntaxExtension = (Name, SyntaxExtension);
+
pub struct BlockInfo {
// should macros escape from this scope?
pub macros_escape: bool,
syntax_expanders
}
-pub struct MacroCrate {
- pub lib: Option<Path>,
- pub macros: Vec<String>,
- pub registrar_symbol: Option<String>,
-}
-
-pub trait CrateLoader {
- fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate;
-}
-
// One of these is made during expansion and incrementally updated as we go;
// when a macro expansion occurs, the resulting nodes have the backtrace()
// -> expn_info of their expansion context stored into their span.
pub parse_sess: &'a parse::ParseSess,
pub cfg: ast::CrateConfig,
pub backtrace: Option<@ExpnInfo>,
- pub ecfg: expand::ExpansionConfig<'a>,
+ pub ecfg: expand::ExpansionConfig,
pub mod_path: Vec<ast::Ident> ,
pub trace_mac: bool,
impl<'a> ExtCtxt<'a> {
pub fn new<'a>(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig,
- ecfg: expand::ExpansionConfig<'a>) -> ExtCtxt<'a> {
+ ecfg: expand::ExpansionConfig) -> ExtCtxt<'a> {
ExtCtxt {
parse_sess: parse_sess,
cfg: cfg,
use parse::token::InternedString;
use parse::token;
-pub struct Field {
- ident: ast::Ident,
- ex: @ast::Expr
-}
-
// Transitional reexports so qquote can find the paths it is looking for
mod syntax {
pub use ext;
}
}
-struct Duplicator<'a> {
- cx: &'a ExtCtxt<'a>,
-}
+struct Duplicator<'a>;
impl<'a> Folder for Duplicator<'a> {
fn new_id(&mut self, _: NodeId) -> NodeId {
}
impl Duplicate for @ast::Expr {
- fn duplicate(&self, cx: &ExtCtxt) -> @ast::Expr {
- let mut folder = Duplicator {
- cx: cx,
- };
+ fn duplicate(&self, _: &ExtCtxt) -> @ast::Expr {
+ let mut folder = Duplicator;
folder.fold_expr(*self)
}
}
use visit::Visitor;
use util::small_vector::SmallVector;
-use std::mem;
-use std::os;
-use std::unstable::dynamic_lib::DynamicLibrary;
-
pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
match e.node {
// expr_mac should really be expr_ext or something; it's the
return items;
}
-// load macros from syntax-phase crates
-pub fn expand_view_item(vi: &ast::ViewItem,
- fld: &mut MacroExpander)
- -> ast::ViewItem {
- match vi.node {
- ast::ViewItemExternCrate(..) => {
- let should_load = vi.attrs.iter().any(|attr| {
- attr.check_name("phase") &&
- attr.meta_item_list().map_or(false, |phases| {
- attr::contains_name(phases, "syntax")
- })
- });
-
- if should_load {
- load_extern_macros(vi, fld);
- }
- }
- ast::ViewItemUse(_) => {}
- }
-
- noop_fold_view_item(vi, fld)
-}
-
-fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
- let MacroCrate { lib, macros, registrar_symbol } =
- fld.cx.ecfg.loader.load_crate(krate);
-
- let crate_name = match krate.node {
- ast::ViewItemExternCrate(name, _, _) => name,
- _ => unreachable!()
- };
- let name = format!("<{} macros>", token::get_ident(crate_name));
- let name = name.to_string();
-
- for source in macros.iter() {
- let item = parse::parse_item_from_source_str(name.clone(),
- (*source).clone(),
- fld.cx.cfg(),
- fld.cx.parse_sess())
- .expect("expected a serialized item");
- expand_item_mac(item, fld);
- }
-
- let path = match lib {
- Some(path) => path,
- None => return
- };
- // Make sure the path contains a / or the linker will search for it.
- let path = os::make_absolute(&path);
-
- let registrar = match registrar_symbol {
- Some(registrar) => registrar,
- None => return
- };
-
- debug!("load_extern_macros: mapped crate {} to path {} and registrar {:s}",
- crate_name, path.display(), registrar);
-
- let lib = match DynamicLibrary::open(Some(&path)) {
- Ok(lib) => lib,
- // this is fatal: there are almost certainly macros we need
- // inside this crate, so continue would spew "macro undefined"
- // errors
- Err(err) => fld.cx.span_fatal(krate.span, err.as_slice())
- };
-
- unsafe {
- let registrar: MacroCrateRegistrationFun =
- match lib.symbol(registrar.as_slice()) {
- Ok(registrar) => registrar,
- // again fatal if we can't register macros
- Err(err) => fld.cx.span_fatal(krate.span, err.as_slice())
- };
- registrar(|name, extension| {
- let extension = match extension {
- NormalTT(ext, _) => NormalTT(ext, Some(krate.span)),
- IdentTT(ext, _) => IdentTT(ext, Some(krate.span)),
- ItemDecorator(ext) => ItemDecorator(ext),
- ItemModifier(ext) => ItemModifier(ext),
- };
- fld.extsbox.insert(name, extension);
- });
-
- // Intentionally leak the dynamic library. We can't ever unload it
- // since the library can do things that will outlive the expansion
- // phase (e.g. make an @-box cycle or launch a task).
- mem::forget(lib);
- }
-}
-
// expand a stmt
pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
// why the copying here and not in expand_expr?
expand_item(item, self)
}
- fn fold_view_item(&mut self, vi: &ast::ViewItem) -> ast::ViewItem {
- expand_view_item(vi, self)
- }
-
fn fold_stmt(&mut self, stmt: &ast::Stmt) -> SmallVector<@ast::Stmt> {
expand_stmt(stmt, self)
}
}
}
-pub struct ExpansionConfig<'a> {
- pub loader: &'a mut CrateLoader,
+pub struct ExpansionConfig {
pub deriving_hash_type_parameter: bool,
pub crate_id: CrateId,
}
+pub struct ExportedMacros {
+ pub crate_name: Ident,
+ pub macros: Vec<String>,
+}
+
pub fn expand_crate(parse_sess: &parse::ParseSess,
cfg: ExpansionConfig,
+ macros: Vec<ExportedMacros>,
+ user_exts: Vec<NamedSyntaxExtension>,
c: Crate) -> Crate {
let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg);
let mut expander = MacroExpander {
cx: &mut cx,
};
+ for ExportedMacros { crate_name, macros } in macros.move_iter() {
+ let name = format!("<{} macros>", token::get_ident(crate_name))
+ .into_string();
+
+ for source in macros.move_iter() {
+ let item = parse::parse_item_from_source_str(name.clone(),
+ source,
+ expander.cx.cfg(),
+ expander.cx.parse_sess())
+ .expect("expected a serialized item");
+ expand_item_mac(item, &mut expander);
+ }
+ }
+
+ for (name, extension) in user_exts.move_iter() {
+ expander.extsbox.insert(name, extension);
+ }
+
let ret = expander.fold_crate(c);
parse_sess.span_diagnostic.handler().abort_if_errors();
return ret;
use attr;
use codemap;
use codemap::Spanned;
- use ext::base::{CrateLoader, MacroCrate};
use ext::mtwt;
use parse;
use parse::token;
}
}
- struct ErrLoader;
-
- impl CrateLoader for ErrLoader {
- fn load_crate(&mut self, _: &ast::ViewItem) -> MacroCrate {
- fail!("lolwut")
- }
- }
-
// these following tests are quite fragile, in that they don't test what
// *kind* of failure occurs.
src,
Vec::new(), &sess);
// should fail:
- let mut loader = ErrLoader;
let cfg = ::syntax::ext::expand::ExpansionConfig {
- loader: &mut loader,
deriving_hash_type_parameter: false,
crate_id: from_str("test").unwrap(),
};
- expand_crate(&sess,cfg,crate_ast);
+ expand_crate(&sess,cfg,vec!(),vec!(),crate_ast);
}
// make sure that macros can leave scope for modules
"<test>".to_string(),
src,
Vec::new(), &sess);
- // should fail:
- let mut loader = ErrLoader;
let cfg = ::syntax::ext::expand::ExpansionConfig {
- loader: &mut loader,
deriving_hash_type_parameter: false,
crate_id: from_str("test").unwrap(),
};
- expand_crate(&sess,cfg,crate_ast);
+ expand_crate(&sess,cfg,vec!(),vec!(),crate_ast);
}
// macro_escape modules shouldn't cause macros to leave scope
src,
Vec::new(), &sess);
// should fail:
- let mut loader = ErrLoader;
let cfg = ::syntax::ext::expand::ExpansionConfig {
- loader: &mut loader,
deriving_hash_type_parameter: false,
crate_id: from_str("test").unwrap(),
};
- expand_crate(&sess, cfg, crate_ast);
+ expand_crate(&sess, cfg, vec!(), vec!(), crate_ast);
}
#[test] fn test_contains_flatten (){
let ps = parse::new_parse_sess();
let crate_ast = string_to_parser(&ps, crate_str).parse_crate_mod();
// the cfg argument actually does matter, here...
- let mut loader = ErrLoader;
let cfg = ::syntax::ext::expand::ExpansionConfig {
- loader: &mut loader,
deriving_hash_type_parameter: false,
crate_id: from_str("test").unwrap(),
};
- expand_crate(&ps,cfg,crate_ast)
+ expand_crate(&ps,cfg,vec!(),vec!(),crate_ast)
}
//fn expand_and_resolve(crate_str: @str) -> ast::crate {
+++ /dev/null
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use ast;
-use attr;
-use codemap::Span;
-use diagnostic;
-use visit;
-use visit::Visitor;
-
-struct MacroRegistrarContext {
- registrars: Vec<(ast::NodeId, Span)> ,
-}
-
-impl Visitor<()> for MacroRegistrarContext {
- fn visit_item(&mut self, item: &ast::Item, _: ()) {
- match item.node {
- ast::ItemFn(..) => {
- if attr::contains_name(item.attrs.as_slice(),
- "macro_registrar") {
- self.registrars.push((item.id, item.span));
- }
- }
- _ => {}
- }
-
- visit::walk_item(self, item, ());
- }
-}
-
-pub fn find_macro_registrar(diagnostic: &diagnostic::SpanHandler,
- krate: &ast::Crate) -> Option<ast::NodeId> {
- let mut ctx = MacroRegistrarContext { registrars: Vec::new() };
- visit::walk_crate(&mut ctx, krate, ());
-
- match ctx.registrars.len() {
- 0 => None,
- 1 => {
- let (node_id, _) = ctx.registrars.pop().unwrap();
- Some(node_id)
- },
- _ => {
- diagnostic.handler().err("multiple macro registration functions found");
- for &(_, span) in ctx.registrars.iter() {
- diagnostic.span_note(span, "one is here");
- }
- diagnostic.handler().abort_if_errors();
- unreachable!();
- }
- }
-}
decl: self.fold_fn_decl(f.decl)
})
}
+ TyUnboxedFn(ref f) => {
+ TyUnboxedFn(@UnboxedFnTy {
+ decl: self.fold_fn_decl(f.decl),
+ })
+ }
TyTup(ref tys) => TyTup(tys.iter().map(|&ty| self.fold_ty(ty)).collect()),
TyPath(ref path, ref bounds, id) => {
let id = self.new_id(id);
match *tpb {
TraitTyParamBound(ref ty) => TraitTyParamBound(fold_trait_ref(ty, fld)),
StaticRegionTyParamBound => StaticRegionTyParamBound,
+ UnboxedFnTyParamBound(ref unboxed_function_type) => {
+ UnboxedFnTyParamBound(UnboxedFnTy {
+ decl: fld.fold_fn_decl(unboxed_function_type.decl),
+ })
+ }
OtherRegionTyParamBound(s) => OtherRegionTyParamBound(s)
}
}
extern crate serialize;
extern crate term;
+
+#[cfg(stage0)]
#[phase(syntax, link)]
extern crate log;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
extern crate fmt_macros;
extern crate debug;
pub mod asm;
pub mod base;
pub mod expand;
- pub mod registrar;
pub mod quote;
impl<T: Eq> Eq for OwnedSlice<T> {}
-impl<T> Container for OwnedSlice<T> {
+impl<T> Collection for OwnedSlice<T> {
fn len(&self) -> uint { self.len }
}
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
use ast::{TyTypeof, TyInfer, TypeMethod};
use ast::{TyNil, TyParam, TyParamBound, TyPath, TyPtr, TyRptr};
-use ast::{TyTup, TyU32, TyUniq, TyVec, UnUniq};
-use ast::{UnnamedField, UnsafeBlock, UnsafeFn, ViewItem};
-use ast::{ViewItem_, ViewItemExternCrate, ViewItemUse};
+use ast::{TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq};
+use ast::{UnboxedFnTy, UnboxedFnTyParamBound, UnnamedField, UnsafeBlock};
+use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use ast::Visibility;
use ast;
Vec::new()
};
- let inputs = if self.eat(&token::OROR) {
- Vec::new()
+ let (is_unboxed, inputs) = if self.eat(&token::OROR) {
+ (false, Vec::new())
} else {
self.expect_or();
+
+ let is_unboxed = self.token == token::BINOP(token::AND) &&
+ self.look_ahead(1, |t| {
+ token::is_keyword(keywords::Mut, t)
+ }) &&
+ self.look_ahead(2, |t| *t == token::COLON);
+ if is_unboxed {
+ self.bump();
+ self.bump();
+ self.bump();
+ }
+
let inputs = self.parse_seq_to_before_or(
&token::COMMA,
|p| p.parse_arg_general(false));
self.expect_or();
- inputs
+ (is_unboxed, inputs)
};
let (region, bounds) = self.parse_optional_ty_param_bounds(true);
variadic: false
});
- TyClosure(@ClosureTy {
- fn_style: fn_style,
- onceness: onceness,
- bounds: bounds,
- decl: decl,
- lifetimes: lifetimes,
- }, region)
+ if is_unboxed {
+ TyUnboxedFn(@UnboxedFnTy {
+ decl: decl,
+ })
+ } else {
+ TyClosure(@ClosureTy {
+ fn_style: fn_style,
+ onceness: onceness,
+ bounds: bounds,
+ decl: decl,
+ lifetimes: lifetimes,
+ }, region)
+ }
}
pub fn parse_unsafety(&mut self) -> FnStyle {
})
}
+ fn parse_unboxed_function_type(&mut self) -> UnboxedFnTy {
+ let inputs = if self.eat(&token::OROR) {
+ Vec::new()
+ } else {
+ self.expect_or();
+
+ if self.token == token::BINOP(token::AND) &&
+ self.look_ahead(1, |t| {
+ token::is_keyword(keywords::Mut, t)
+ }) &&
+ self.look_ahead(2, |t| *t == token::COLON) {
+ self.bump();
+ self.bump();
+ self.bump();
+ }
+
+ let inputs = self.parse_seq_to_before_or(&token::COMMA,
+ |p| {
+ p.parse_arg_general(false)
+ });
+ self.expect_or();
+ inputs
+ };
+
+ let (return_style, output) = self.parse_ret_ty();
+ UnboxedFnTy {
+ decl: P(FnDecl {
+ inputs: inputs,
+ output: output,
+ cf: return_style,
+ variadic: false,
+ })
+ }
+ }
+
// matches optbounds = ( ( : ( boundseq )? )? )
// where boundseq = ( bound + boundseq ) | bound
// and bound = 'static | ty
let tref = self.parse_trait_ref();
result.push(TraitTyParamBound(tref));
}
+ token::BINOP(token::OR) | token::OROR => {
+ let unboxed_function_type =
+ self.parse_unboxed_function_type();
+ result.push(UnboxedFnTyParamBound(unboxed_function_type));
+ }
_ => break,
}
use abi;
use ast::{P, StaticRegionTyParamBound, OtherRegionTyParamBound,
- TraitTyParamBound, Required, Provided};
+ TraitTyParamBound, UnboxedFnTyParamBound, Required, Provided};
use ast;
use ast_util;
use owned_slice::OwnedSlice;
use codemap;
use diagnostic;
use parse::classify::expr_is_simple_block;
-use parse::token::IdentInterner;
use parse::token;
use parse::lexer::comments;
use parse;
use std::io::{IoResult, MemWriter};
use std::io;
use std::mem;
-use std::rc::Rc;
use std::str;
use std::string::String;
pub struct State<'a> {
pub s: pp::Printer,
cm: Option<&'a CodeMap>,
- intr: Rc<token::IdentInterner>,
comments: Option<Vec<comments::Comment> >,
literals: Option<Vec<comments::Literal> >,
cur_cmnt_and_lit: CurrentCommentAndLiteral,
State {
s: pp::mk_printer(writer, default_columns),
cm: None,
- intr: token::get_ident_interner(),
comments: None,
literals: None,
cur_cmnt_and_lit: CurrentCommentAndLiteral {
let mut s = State {
s: pp::mk_printer(out, default_columns),
cm: Some(cm),
- intr: token::get_ident_interner(),
comments: Some(cmnts),
// If the code is post expansion, don't use the table of
// literals, since it doesn't correspond with the literals
lifetimes: f.lifetimes.clone(),
ty_params: OwnedSlice::empty()
};
- try!(self.print_ty_fn(Some(f.abi), None, &None,
- f.fn_style, ast::Many, f.decl, None, &None,
- Some(&generics), None));
+ try!(self.print_ty_fn(Some(f.abi),
+ None,
+ &None,
+ f.fn_style,
+ ast::Many,
+ f.decl,
+ None,
+ &None,
+ Some(&generics),
+ None,
+ false));
}
ast::TyClosure(f, ref region) => {
let generics = ast::Generics {
lifetimes: f.lifetimes.clone(),
ty_params: OwnedSlice::empty()
};
- try!(self.print_ty_fn(None, Some('&'), region, f.fn_style,
- f.onceness, f.decl, None, &f.bounds,
- Some(&generics), None));
+ try!(self.print_ty_fn(None,
+ Some('&'),
+ region,
+ f.fn_style,
+ f.onceness,
+ f.decl,
+ None,
+ &f.bounds,
+ Some(&generics),
+ None,
+ false));
}
ast::TyProc(f) => {
let generics = ast::Generics {
lifetimes: f.lifetimes.clone(),
ty_params: OwnedSlice::empty()
};
- try!(self.print_ty_fn(None, Some('~'), &None, f.fn_style,
- f.onceness, f.decl, None, &f.bounds,
- Some(&generics), None));
+ try!(self.print_ty_fn(None,
+ Some('~'),
+ &None,
+ f.fn_style,
+ f.onceness,
+ f.decl,
+ None,
+ &f.bounds,
+ Some(&generics),
+ None,
+ false));
+ }
+ ast::TyUnboxedFn(f) => {
+ try!(self.print_ty_fn(None,
+ None,
+ &None,
+ ast::NormalFn,
+ ast::Many,
+ f.decl,
+ None,
+ &None,
+ None,
+ None,
+ true));
}
ast::TyPath(ref path, ref bounds, _) => {
try!(self.print_bounded_path(path, bounds));
Some(m.ident),
&None,
Some(&m.generics),
- Some(m.explicit_self.node)));
+ Some(m.explicit_self.node),
+ false));
word(&mut self.s, ";")
}
try!(match *bound {
TraitTyParamBound(ref tref) => self.print_trait_ref(tref),
StaticRegionTyParamBound => word(&mut self.s, "'static"),
+ UnboxedFnTyParamBound(ref unboxed_function_type) => {
+ self.print_ty_fn(None,
+ None,
+ &None,
+ ast::NormalFn,
+ ast::Many,
+ unboxed_function_type.decl,
+ None,
+ &None,
+ None,
+ None,
+ true)
+ }
OtherRegionTyParamBound(_) => Ok(())
})
}
id: Option<ast::Ident>,
opt_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
generics: Option<&ast::Generics>,
- opt_explicit_self: Option<ast::ExplicitSelf_>)
- -> IoResult<()> {
+ opt_explicit_self: Option<ast::ExplicitSelf_>,
+ is_unboxed: bool)
+ -> IoResult<()> {
try!(self.ibox(indent_unit));
// Duplicates the logic in `print_fn_header_info()`. This is because that
try!(self.print_fn_style(fn_style));
try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi));
try!(self.print_onceness(onceness));
- try!(word(&mut self.s, "fn"));
+ if !is_unboxed {
+ try!(word(&mut self.s, "fn"));
+ }
}
match id {
match generics { Some(g) => try!(self.print_generics(g)), _ => () }
try!(zerobreak(&mut self.s));
- if opt_sigil == Some('&') {
+ if is_unboxed || opt_sigil == Some('&') {
try!(word(&mut self.s, "|"));
} else {
try!(self.popen());
}
+ if is_unboxed {
+ try!(word(&mut self.s, "&mut"));
+ try!(self.word_space(":"));
+ }
+
try!(self.print_fn_args(decl, opt_explicit_self));
- if opt_sigil == Some('&') {
+ if is_unboxed || opt_sigil == Some('&') {
try!(word(&mut self.s, "|"));
} else {
if decl.variadic {
Many(Vec<T> ),
}
-impl<T> Container for SmallVector<T> {
+impl<T> Collection for SmallVector<T> {
fn len(&self) -> uint {
match self.repr {
Zero => 0,
walk_lifetime_decls(visitor, &function_declaration.lifetimes,
env.clone());
}
+ TyUnboxedFn(ref function_declaration) => {
+ for argument in function_declaration.decl.inputs.iter() {
+ visitor.visit_ty(argument.ty, env.clone())
+ }
+ visitor.visit_ty(function_declaration.decl.output, env.clone());
+ }
TyPath(ref path, ref bounds, id) => {
visitor.visit_path(path, id, env.clone());
for bounds in bounds.iter() {
walk_trait_ref_helper(visitor, typ, env.clone())
}
StaticRegionTyParamBound => {}
+ UnboxedFnTyParamBound(ref function_declaration) => {
+ for argument in function_declaration.decl.inputs.iter() {
+ visitor.visit_ty(argument.ty, env.clone())
+ }
+ visitor.visit_ty(function_declaration.decl.output,
+ env.clone());
+ }
OtherRegionTyParamBound(..) => {}
}
}
#![deny(missing_doc)]
-#[phase(syntax, link)] extern crate log;
+#[cfg(stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(not(stage0))] #[phase(plugin, link)] extern crate log;
pub use terminfo::TerminfoTerminal;
#[cfg(windows)]
tests)
}
+pub enum ColorConfig {
+ AutoColor,
+ AlwaysColor,
+ NeverColor,
+}
+
pub struct TestOpts {
pub filter: Option<Regex>,
pub run_ignored: bool,
pub test_shard: Option<(uint,uint)>,
pub logfile: Option<Path>,
pub nocapture: bool,
+ pub color: ColorConfig,
}
impl TestOpts {
test_shard: None,
logfile: None,
nocapture: false,
+ color: AutoColor,
}
}
}
getopts::optopt("", "test-shard", "run shard A, of B shards, worth of the testsuite",
"A.B"),
getopts::optflag("", "nocapture", "don't capture stdout/stderr of each \
- task, allow printing directly"))
+ task, allow printing directly"),
+ getopts::optopt("", "color", "Configure coloring of output:
+ auto = colorize if stdout is a tty and tests are run on serially (default);
+ always = always colorize output;
+ never = never colorize output;", "auto|always|never"))
}
fn usage(binary: &str) {
nocapture = os::getenv("RUST_TEST_NOCAPTURE").is_some();
}
+ let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
+ Some("auto") | None => AutoColor,
+ Some("always") => AlwaysColor,
+ Some("never") => NeverColor,
+
+ Some(v) => return Some(Err(format!("argument for --color must be \
+ auto, always, or never (was {})",
+ v))),
+ };
+
let test_opts = TestOpts {
filter: filter,
run_ignored: run_ignored,
test_shard: test_shard,
logfile: logfile,
nocapture: nocapture,
+ color: color,
};
Some(Ok(test_opts))
Ok(ConsoleTestState {
out: out,
log_out: log_out,
- use_color: use_color(),
+ use_color: use_color(opts),
total: 0u,
passed: 0u,
failed: 0u,
assert!(apos < bpos);
}
-fn use_color() -> bool {
- get_concurrency() == 1 && io::stdout().get_ref().isatty()
+fn use_color(opts: &TestOpts) -> bool {
+ match opts.color {
+ AutoColor => get_concurrency() == 1 && io::stdout().get_ref().isatty(),
+ AlwaysColor => true,
+ NeverColor => false,
+ }
}
#[deriving(Clone)]
#![deny(deprecated_owned_vector)]
#[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
extern crate serialize;
extern crate libc;
#![crate_type = "rlib"]
#![feature(phase)]
-#[phase(syntax)] extern crate t1 = "issue-13560-1";
-#[phase(syntax, link)] extern crate t2 = "issue-13560-2";
+#[phase(plugin)] extern crate t1 = "issue-13560-1";
+#[phase(plugin, link)] extern crate t2 = "issue-13560-2";
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
#[no_mangle]
pub fn foo() { bar(); }
// except according to those terms.
#![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
extern crate debug;
pub fn foo<T>() {
+++ /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.
-
-// force-host
-
-#![feature(macro_registrar)]
-
-extern crate syntax;
-
-use std::any::Any;
-use syntax::ast::Name;
-use syntax::ext::base::SyntaxExtension;
-
-struct Foo {
- foo: int
-}
-
-impl Drop for Foo {
- fn drop(&mut self) {}
-}
-
-#[macro_registrar]
-pub fn registrar(_: |Name, SyntaxExtension|) {
- local_data_key!(foo: Box<Any:Send>);
- foo.replace(Some(box Foo { foo: 10 } as Box<Any:Send>));
-}
-
// force-host
-#![feature(globs, macro_registrar, macro_rules, quote, managed_boxes)]
+#![feature(globs, plugin_registrar, macro_rules, quote, managed_boxes)]
extern crate syntax;
+extern crate rustc;
-use syntax::ast::{Name, TokenTree, Item, MetaItem};
+use syntax::ast::{TokenTree, Item, MetaItem};
use syntax::codemap::Span;
use syntax::ext::base::*;
use syntax::parse::token;
+use rustc::plugin::Registry;
#[macro_export]
macro_rules! exported_macro (() => (2))
macro_rules! unexported_macro (() => (3))
-#[macro_registrar]
-pub fn macro_registrar(register: |Name, SyntaxExtension|) {
- register(token::intern("make_a_1"),
- NormalTT(box BasicMacroExpander {
- expander: expand_make_a_1,
- span: None,
- },
- None));
- register(token::intern("into_foo"), ItemModifier(expand_into_foo));
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("make_a_1", expand_make_a_1);
+ reg.register_syntax_extension(
+ token::intern("into_foo"),
+ ItemModifier(expand_into_foo));
}
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
--- /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.
+
+// force-host
+
+#![feature(plugin_registrar)]
+
+extern crate rustc;
+
+use std::any::Any;
+use rustc::plugin::Registry;
+
+struct Foo {
+ foo: int
+}
+
+impl Drop for Foo {
+ fn drop(&mut self) {}
+}
+
+#[plugin_registrar]
+pub fn registrar(_: &mut Registry) {
+ local_data_key!(foo: Box<Any:Send>);
+ foo.replace(Some(box Foo { foo: 10 } as Box<Any:Send>));
+}
+
// no-prefer-dynamic
#![crate_type = "dylib"]
-#![feature(macro_registrar, quote, globs)]
+#![feature(plugin_registrar, quote, globs)]
extern crate other = "syntax-extension-with-dll-deps-1";
extern crate syntax;
+extern crate rustc;
-use syntax::ast::{Name, TokenTree, Item, MetaItem};
+use syntax::ast::{TokenTree, Item, MetaItem};
use syntax::codemap::Span;
use syntax::ext::base::*;
-use syntax::parse::token;
+use rustc::plugin::Registry;
-#[macro_registrar]
-pub fn macro_registrar(register: |Name, SyntaxExtension|) {
- register(token::intern("foo"),
- NormalTT(box BasicMacroExpander {
- expander: expand_foo,
- span: None,
- },
- None));
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("foo", expand_foo);
}
fn expand_foo(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
#![feature(phase)]
#![crate_type = "rlib"]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate core;
struct A;
// no-pretty-expanded
#![feature(phase)]
-#[phase(syntax)] extern crate green;
+#[phase(plugin)] extern crate green;
use std::string::String;
use std::fmt;
-// 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.
+// The Computer Language Benchmarks Game
+// http://benchmarksgame.alioth.debian.org/
//
-// 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.
+// contributed by the Rust Project Developers
+
+// Copyright (c) 2014 The Rust Project Developers
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// - Neither the name of "The Computer Language Benchmarks Game" nor
+// the name of "The Computer Language Shootout Benchmarks" nor the
+// names of its contributors may be used to endorse or promote
+// products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
use std::cmp::max;
// OF THE POSSIBILITY OF SUCH DAMAGE.
#![feature(phase)]
-#[phase(syntax)] extern crate green;
+#[phase(plugin)] extern crate green;
extern crate sync;
use sync::Arc;
#![feature(macro_rules, phase)]
extern crate regex;
-#[phase(syntax)]extern crate regex_macros;
+#[phase(plugin)]extern crate regex_macros;
extern crate sync;
use std::io;
#![feature(phase)]
#![allow(non_snake_case_functions)]
-#[phase(syntax)] extern crate green;
+#[phase(plugin)] extern crate green;
extern crate sync;
use std::from_str::FromStr;
// except according to those terms.
#![feature(phase)]
-#[phase(syntax)] extern crate green;
+#[phase(plugin)] extern crate green;
green_start!(main)
fn start(n_tasks: int, token: int) {
// aux-build:macro_crate_test.rs
// ignore-stage1
-#[phase(syntax)]
+#[phase(plugin)]
//~^ ERROR compile time crate loading is experimental and possibly buggy
extern crate macro_crate_test;
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate macro_crate_test;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate doesnt_exist; //~ ERROR can't find crate
fn main() {}
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate macro_crate_test;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate hexfloat;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate hexfloat;
fn main() {
#![feature(phase)]
extern crate regex;
-#[phase(syntax)] extern crate regex_macros;
+#[phase(plugin)] extern crate regex_macros;
// Tests to make sure that `regex!` will produce a compile error when given
// an invalid regular expression.
#![feature(phase)]
extern crate regex;
-#[phase(syntax)] extern crate regex_macros;
+#[phase(plugin)] extern crate regex_macros;
#[deny(unused_variable)]
#[deny(dead_code)]
#![feature(phase)]
extern crate regex;
-#[phase(syntax)] extern crate regex_macros;
+#[phase(plugin)] extern crate regex_macros;
#[deny(unused_variable)]
#[deny(dead_code)]
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// the registration function isn't typechecked yet
-#[macro_registrar]
-pub fn registrar() {} //~ ERROR cross-crate macro exports are experimental
-
-fn main() {}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// the registration function isn't typechecked yet
+#[plugin_registrar]
+pub fn registrar() {} //~ ERROR compiler plugins are experimental
+
+fn main() {}
--- /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.
+
+
+// Used to cause ICE
+
+static VEC: [u32, ..256] = vec!(); //~ ERROR mismatched types
+
+fn main() {}
+
pub type typ = *UsedStruct4;
pub struct PubStruct();
struct PrivStruct; //~ ERROR: code is never used
-struct UsedStruct1 { x: int }
+struct UsedStruct1 {
+ #[allow(dead_code)]
+ x: int
+}
struct UsedStruct2(int);
struct UsedStruct3;
struct UsedStruct4;
struct StructUsedInEnum;
struct StructUsedInGeneric;
pub struct PubStruct2 {
+ #[allow(dead_code)]
struct_used_as_field: *StructUsedAsField
}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(struct_variant)]
+#![allow(unused_variable)]
+#![allow(non_camel_case_types)]
+#![deny(dead_code)]
+
+extern crate libc;
+
+use std::num;
+
+struct Foo {
+ x: uint,
+ b: bool, //~ ERROR: code is never used
+ marker: std::kinds::marker::NoCopy
+}
+
+fn field_read(f: Foo) -> uint {
+ num::pow(f.x, 2)
+}
+
+enum XYZ {
+ X,
+ Y {
+ a: String,
+ b: int //~ ERROR: code is never used
+ },
+ Z
+}
+
+fn field_match_in_patterns(b: XYZ) -> String {
+ match b {
+ Y { a: a, .. } => a,
+ _ => "".to_string()
+ }
+}
+
+struct Bar {
+ x: uint, //~ ERROR: code is never used
+ b: bool,
+ _guard: ()
+}
+
+#[repr(C)]
+struct Baz {
+ x: libc::c_uint
+}
+
+fn field_match_in_let(f: Bar) -> bool {
+ let Bar { b, .. } = f;
+ b
+}
+
+fn main() {
+ field_read(Foo { x: 1, b: false, marker: std::kinds::marker::NoCopy });
+ field_match_in_patterns(Z);
+ field_match_in_let(Bar { x: 42u, b: true, _guard: () });
+ let _ = Baz { x: 0 };
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![allow(dead_code)]
#![feature(managed_boxes)]
#![forbid(managed_heap_memory)]
#![forbid(non_camel_case_types)]
#![allow(dead_code)]
-struct foo { //~ ERROR type `foo` should have a camel case identifier
+struct foo { //~ ERROR type `foo` should have a camel case name such as `Foo`
bar: int,
}
-enum foo2 { //~ ERROR type `foo2` should have a camel case identifier
+enum foo2 { //~ ERROR type `foo2` should have a camel case name such as `Foo2`
Bar
}
-struct foo3 { //~ ERROR type `foo3` should have a camel case identifier
+struct foo3 { //~ ERROR type `foo3` should have a camel case name such as `Foo3`
bar: int
}
-type foo4 = int; //~ ERROR type `foo4` should have a camel case identifier
+type foo4 = int; //~ ERROR type `foo4` should have a camel case name such as `Foo4`
enum Foo5 {
- bar //~ ERROR variant `bar` should have a camel case identifier
+ bar //~ ERROR variant `bar` should have a camel case name such as `Bar`
}
-trait foo6 { //~ ERROR trait `foo6` should have a camel case identifier
+trait foo6 { //~ ERROR trait `foo6` should have a camel case name such as `Foo6`
}
fn main() { }
impl Foo {
fn Foo_Method() {}
- //~^ ERROR method `Foo_Method` should have a snake case identifier
+ //~^ ERROR method `Foo_Method` should have a snake case name such as `foo_method`
// Don't allow two underscores in a row
fn foo__method(&self) {}
- //~^ ERROR method `foo__method` should have a snake case identifier
+ //~^ ERROR method `foo__method` should have a snake case name such as `foo_method`
pub fn xyZ(&mut self) {}
- //~^ ERROR method `xyZ` should have a snake case identifier
+ //~^ ERROR method `xyZ` should have a snake case name such as `xy_z`
}
trait X {
fn ABC();
- //~^ ERROR trait method `ABC` should have a snake case identifier
+ //~^ ERROR trait method `ABC` should have a snake case name such as `a_b_c`
fn a_b_C(&self) {}
- //~^ ERROR trait method `a_b_C` should have a snake case identifier
+ //~^ ERROR trait method `a_b_C` should have a snake case name such as `a_b_c`
fn something__else(&mut self);
- //~^ ERROR trait method `something__else` should have a snake case identifier
+ //~^ ERROR trait method `something__else` should have a snake case name such as `something_else`
}
impl X for Foo {
}
fn Cookie() {}
-//~^ ERROR function `Cookie` should have a snake case identifier
+//~^ ERROR function `Cookie` should have a snake case name such as `cookie`
pub fn bi_S_Cuit() {}
-//~^ ERROR function `bi_S_Cuit` should have a snake case identifier
+//~^ ERROR function `bi_S_Cuit` should have a snake case name such as `bi_s_cuit`
fn main() { }
#![forbid(non_uppercase_statics)]
#![allow(dead_code)]
-static foo: int = 1; //~ ERROR static constant should have an uppercase identifier
+static foo: int = 1; //~ ERROR static constant `foo` should have an uppercase name such as `FOO`
fn main() { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![allow(dead_code)]
#![forbid(owned_heap_memory)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![allow(dead_code)]
#![deny(uppercase_variables)]
use std::io::File;
let x: Box<HashMap<int, int>> = box HashMap::new();
let x: Box<Map<int, int>> = x;
let y: Box<Map<uint, int>> = box x;
- //~^ ERROR failed to find an implementation of trait core::container::Map<uint,int>
- // for ~core::container::Map<int,int>:Send
+ //~^ ERROR failed to find an implementation of trait collections::Map<uint,int>
+ // for ~collections::Map<int,int>:Send
}
fn f() {
let r = match (0,0) {
(0, a) => 0,
- //~^ ERROR static constant in pattern should be all caps
+ //~^ ERROR static constant in pattern `a` should have an uppercase name such as `A`
(x, y) => 1 + x + y,
};
assert!(r == 1);
use self::m::aha;
let r = match (0,0) {
(0, aha) => 0,
- //~^ ERROR static constant in pattern should be all caps
+ //~^ ERROR static constant in pattern `aha` should have an uppercase name such as `AHA`
(x, y) => 1 + x + y,
};
assert!(r == 1);
use not_okay = self::n::OKAY;
let r = match (0,0) {
(0, not_okay) => 0,
- //~^ ERROR static constant in pattern should be all caps
+//~^ ERROR static constant in pattern `not_okay` should have an uppercase name such as `NOT_OKAY`
(x, y) => 1 + x + y,
};
assert!(r == 1);
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern: multiple macro registration functions found
-
-#![feature(macro_registrar)]
-
-// the registration function isn't typechecked yet
-#[macro_registrar]
-pub fn one() {}
-
-#[macro_registrar]
-pub fn two() {}
-
-fn main() {}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern: multiple plugin registration functions found
+
+#![feature(plugin_registrar)]
+
+// the registration function isn't typechecked yet
+#[plugin_registrar]
+pub fn one() {}
+
+#[plugin_registrar]
+pub fn two() {}
+
+fn main() {}
--- /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.
+
+#![feature(overloaded_calls)]
+
+use std::ops::FnMut;
+
+struct S {
+ x: int,
+ y: int,
+}
+
+impl FnMut<(int,),int> for S {
+ fn call_mut(&mut self, (z,): (int,)) -> int {
+ self.x * self.y * z
+ }
+}
+
+fn main() {
+ let mut s = S {
+ x: 3,
+ y: 3,
+ };
+ let ans = s("what"); //~ ERROR mismatched types
+ let ans = s(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+ let ans = s("burma", "shave");
+ //~^ ERROR this function takes 1 parameter but 2 parameters were supplied
+}
--- /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.
+
+#![feature(overloaded_calls)]
+
+use std::ops::FnMut;
+
+struct S {
+ x: int,
+ y: int,
+}
+
+impl FnMut<int,int> for S {
+ fn call_mut(&mut self, z: int) -> int {
+ self.x + self.y + z
+ }
+}
+
+fn main() {
+ let mut s = S {
+ x: 1,
+ y: 2,
+ };
+ drop(s(3)) //~ ERROR cannot use call notation
+}
+
// error-pattern:whatever
#![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
use std::os;
fn main() {
// error-pattern:whatever
#![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
use std::os;
use std::task;
// error-pattern:whatever
#![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
use std::os;
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
use std::os;
pub fn main() {
#![feature(phase)]
extern crate lib;
-#[phase(syntax)] extern crate fourcc;
+#[phase(plugin)] extern crate fourcc;
fn main() {
fourcc!("1234");
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:macro_crate_outlive_expansion_phase.rs
+// aux-build:plugin_crate_outlive_expansion_phase.rs
// ignore-stage1
#![feature(phase)]
-#[phase(syntax)]
-extern crate macro_crate_outlive_expansion_phase;
+#[phase(plugin)]
+extern crate plugin_crate_outlive_expansion_phase;
pub fn main() {}
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate macro_crate_test;
#[into_foo]
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate macro_crate_test;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
static static_val: u32 = fourcc!("foo ");
// ignore-pretty
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate hexfloat;
pub fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate extension = "syntax-extension-with-dll-deps-2";
fn main() {
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate log;
extern crate native;
}
}
-impl<T> Container for cat<T> {
+impl<T> Collection for cat<T> {
fn len(&self) -> uint { self.meows as uint }
fn is_empty(&self) -> bool { self.meows == 0 }
}
// exec-env:RUST_LOG=conditional-debug-macro-off=4
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate log;
extern crate debug;
--- /dev/null
+// Copyright 2013-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(phase)]
+
+//~ WARNING phase(syntax) is a deprecated synonym for phase(plugin)
+#[phase(syntax, link)]
+extern crate log;
+
+fn main() {
+ debug!("foo");
+}
--- /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(unboxed_closure_sugar)]
+
+use std::ops::FnMut;
+
+struct S;
+
+impl FnMut<(int,),int> for S {
+ fn call_mut(&mut self, (x,): (int,)) -> int {
+ x * x
+ }
+}
+
+fn call_it<F:|int|->int>(mut f: F, x: int) -> int {
+ f.call_mut((x,)) + 3
+}
+
+fn call_box(f: &mut |&mut: int|->int, x: int) -> int {
+ f.call_mut((x,)) + 3
+}
+
+fn main() {
+ let x = call_it(S, 1);
+ let y = call_box(&mut S, 1);
+ assert!(x == 4);
+ assert!(y == 4);
+}
+
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate green;
extern crate native;
// aux-build:linkage-visibility.rs
// ignore-android: FIXME(#10379)
-// ignore-win32: std::unstable::dynamic_lib does not work on win32 well
+// ignore-win32: std::dynamic_lib does not work on win32 well
extern crate foo = "linkage-visibility";
// exec-env:RUST_LOG=logging-enabled-debug=debug
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate log;
pub fn main() {
// exec-env:RUST_LOG=logging-enabled=info
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate log;
pub fn main() {
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate log;
use std::io::Command;
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate macro_crate_def_only;
pub fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate macro_export_inner_module;
pub fn main() {
--- /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.
+
+#![feature(overloaded_calls)]
+
+use std::ops::{Fn, FnMut, FnOnce};
+
+struct S1 {
+ x: int,
+ y: int,
+}
+
+impl FnMut<(int,),int> for S1 {
+ fn call_mut(&mut self, (z,): (int,)) -> int {
+ self.x * self.y * z
+ }
+}
+
+struct S2 {
+ x: int,
+ y: int,
+}
+
+impl Fn<(int,),int> for S2 {
+ fn call(&self, (z,): (int,)) -> int {
+ self.x * self.y * z
+ }
+}
+
+struct S3 {
+ x: int,
+ y: int,
+}
+
+impl FnOnce<(int,int),int> for S3 {
+ fn call_once(self, (z,zz): (int,int)) -> int {
+ self.x * self.y * z * zz
+ }
+}
+
+fn main() {
+ let mut s = S1 {
+ x: 3,
+ y: 3,
+ };
+ let ans = s(3);
+ assert_eq!(ans, 27);
+
+ let s = S2 {
+ x: 3,
+ y: 3,
+ };
+ let ans = s(3);
+ assert_eq!(ans, 27);
+
+ let s = S3 {
+ x: 3,
+ y: 3,
+ };
+ let ans = s(3, 1);
+ assert_eq!(ans, 27);
+}
+
--- /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.
+
+#![feature(overloaded_calls)]
+
+use std::ops::{FnMut};
+
+struct S {
+ x: int,
+ y: int,
+}
+
+impl FnMut<(),int> for S {
+ fn call_mut(&mut self, (): ()) -> int {
+ self.x * self.y
+ }
+}
+
+fn main() {
+ let mut s = S {
+ x: 3,
+ y: 3,
+ };
+ let ans = s();
+ assert_eq!(ans, 9);
+}
+
+
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
use std::mem;
fn main() {}
extern crate collections;
-use std::container::{Map, MutableMap};
+use std::collections::{Map, MutableMap};
use std::str::{SendStr, Owned, Slice};
use std::collections::HashMap;
use std::option::Some;
extern crate collections;
-use std::container::{ Map, MutableMap};
+use std::collections::{ Map, MutableMap};
use std::str::{SendStr, Owned, Slice};
use std::to_str::ToStr;
use self::collections::TreeMap;
// exec-env:RUST_LOG=debug
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate log;
extern crate libc;
extern crate green;