--- /dev/null
+# i686-unknown-freebsd configuration
+CC_i686-unknown-freebsd=$(CC)
+CXX_i686-unknown-freebsd=$(CXX)
+CPP_i686-unknown-freebsd=$(CPP)
+AR_i686-unknown-freebsd=$(AR)
+CFG_LIB_NAME_i686-unknown-freebsd=lib$(1).so
+CFG_STATIC_LIB_NAME_i686-unknown-freebsd=lib$(1).a
+CFG_LIB_GLOB_i686-unknown-freebsd=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_i686-unknown-freebsd=$(1)-*.dylib.dSYM
+CFG_JEMALLOC_CFLAGS_i686-unknown-freebsd := -m32 -arch i386 -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_i686-unknown-freebsd := -Wall -Werror -g -fPIC -m32 -arch i386 -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_LINK_FLAGS_i686-unknown-freebsd := -m32 -shared -fPIC -g -pthread -lrt
+CFG_GCCISH_DEF_FLAG_i686-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
+CFG_LLC_FLAGS_i686-unknown-freebsd :=
+CFG_INSTALL_NAME_i686-unknown-freebsd =
+CFG_EXE_SUFFIX_i686-unknown-freebsd :=
+CFG_WINDOWSY_i686-unknown-freebsd :=
+CFG_UNIXY_i686-unknown-freebsd := 1
+CFG_LDPATH_i686-unknown-freebsd :=
+CFG_RUN_i686-unknown-freebsd=$(2)
+CFG_RUN_TARG_i686-unknown-freebsd=$(call CFG_RUN_i686-unknown-freebsd,,$(2))
+CFG_GNU_TRIPLE_i686-unknown-freebsd := i686-unknown-freebsd
#![feature(libc)]
#![feature(path_ext)]
#![feature(rustc_private)]
-#![feature(slice_extras)]
+#![feature(slice_splits)]
#![feature(str_char)]
#![feature(test)]
#![feature(vec_push_all)]
optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH"),
optflag("h", "help", "show this message"));
- assert!(!args.is_empty());
- let argv0 = args[0].clone();
- let args_ = args.tail();
+ let (argv0, args_) = args.split_first().unwrap();
if args[1] == "-h" || args[1] == "--help" {
let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
println!("{}", getopts::usage(&message, &groups));
/// The following two examples are equivalent:
///
/// ```
-/// # #![feature(box_heap)]
+/// #![feature(box_heap)]
/// #![feature(box_syntax)]
/// use std::boxed::HEAP;
///
///
/// # Examples
/// ```
-/// # #![feature(box_raw)]
+/// #![feature(box_raw)]
/// use std::boxed;
///
/// let seventeen = Box::new(17u32);
/// Returns all but the first element of a slice.
#[unstable(feature = "slice_extras", reason = "likely to be renamed")]
+ #[deprecated(since = "1.3.0", reason = "superseded by split_first")]
#[inline]
pub fn tail(&self) -> &[T] {
core_slice::SliceExt::tail(self)
}
+ /// Returns the first and all the rest of the elements of a slice.
+ #[unstable(feature = "slice_splits", reason = "new API")]
+ #[inline]
+ pub fn split_first(&self) -> Option<(&T, &[T])> {
+ core_slice::SliceExt::split_first(self)
+ }
+
/// Returns all but the first element of a mutable slice
- #[unstable(feature = "slice_extras",
- reason = "likely to be renamed or removed")]
+ #[unstable(feature = "slice_extras", reason = "likely to be renamed or removed")]
+ #[deprecated(since = "1.3.0", reason = "superseded by split_first_mut")]
#[inline]
pub fn tail_mut(&mut self) -> &mut [T] {
core_slice::SliceExt::tail_mut(self)
}
+ /// Returns the first and all the rest of the elements of a slice.
+ #[unstable(feature = "slice_splits", reason = "new API")]
+ #[inline]
+ pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
+ core_slice::SliceExt::split_first_mut(self)
+ }
+
/// Returns all but the last element of a slice.
#[unstable(feature = "slice_extras", reason = "likely to be renamed")]
+ #[deprecated(since = "1.3.0", reason = "superseded by split_last")]
#[inline]
pub fn init(&self) -> &[T] {
core_slice::SliceExt::init(self)
}
+ /// Returns the last and all the rest of the elements of a slice.
+ #[unstable(feature = "slice_splits", reason = "new API")]
+ #[inline]
+ pub fn split_last(&self) -> Option<(&T, &[T])> {
+ core_slice::SliceExt::split_last(self)
+
+ }
+
/// Returns all but the last element of a mutable slice
- #[unstable(feature = "slice_extras",
- reason = "likely to be renamed or removed")]
+ #[unstable(feature = "slice_extras", reason = "likely to be renamed or removed")]
+ #[deprecated(since = "1.3.0", reason = "superseded by split_last_mut")]
#[inline]
pub fn init_mut(&mut self) -> &mut [T] {
core_slice::SliceExt::init_mut(self)
}
+ /// Returns the last and all the rest of the elements of a slice.
+ #[unstable(feature = "slice_splits", since = "1.3.0")]
+ #[inline]
+ pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
+ core_slice::SliceExt::split_last_mut(self)
+ }
+
/// Returns the last element of a slice, or `None` if it is empty.
///
/// # Examples
use core::str as core_str;
use core::str::pattern::Pattern;
use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
+use core::mem;
use rustc_unicode::str::{UnicodeStr, Utf16Encoder};
use vec_deque::VecDeque;
use rustc_unicode;
use vec::Vec;
use slice::SliceConcatExt;
+use boxed::Box;
pub use core::str::{FromStr, Utf8Error};
pub use core::str::{Lines, LinesAny, CharRange};
pub use rustc_unicode::str::{SplitWhitespace, Words, Graphemes, GraphemeIndices};
pub use core::str::pattern;
-/*
-Section: Creating a string
-*/
-
impl<S: Borrow<str>> SliceConcatExt<str> for [S] {
type Output = String;
}
}
-/*
-Section: Iterators
-*/
-
// Helper functions used for Unicode normalization
fn canonical_sort(comb: &mut [(char, u8)]) {
let len = comb.len();
fn size_hint(&self) -> (usize, Option<usize>) { self.encoder.size_hint() }
}
-/*
-Section: Misc
-*/
-
// Return the initial codepoint accumulator for the first byte.
// The first byte is special, only want bottom 5 bits for width 2, 4 bits
// for width 3, and 3 bits for width 4
}
}
-/*
-Section: CowString
-*/
-
-/*
-Section: Trait implementations
-*/
-
-
/// Any string that can be represented as a slice.
#[lang = "str"]
#[cfg(not(test))]
pub fn escape_unicode(&self) -> String {
self.chars().flat_map(|c| c.escape_unicode()).collect()
}
+
+ /// Converts the `Box<str>` into a `String` without copying or allocating.
+ #[unstable(feature = "box_str",
+ reason = "recently added, matches RFC")]
+ pub fn into_string(self: Box<str>) -> String {
+ unsafe {
+ let slice = mem::transmute::<Box<str>, Box<[u8]>>(self);
+ String::from_utf8_unchecked(slice.into_vec())
+ }
+ }
}
use range::RangeArgument;
use str::{self, FromStr, Utf8Error, Chars};
use vec::{DerefVec, Vec, as_vec};
+use boxed::Box;
/// A growable string stored as a UTF-8 encoded buffer.
#[derive(Clone, PartialOrd, Eq, Ord)]
string: self_ptr,
}
}
+
+ /// Converts the string into `Box<str>`.
+ ///
+ /// Note that this will drop any excess capacity.
+ #[unstable(feature = "box_str",
+ reason = "recently added, matches RFC")]
+ pub fn into_boxed_slice(self) -> Box<str> {
+ let slice = self.vec.into_boxed_slice();
+ unsafe { mem::transmute::<Box<[u8]>, Box<str>>(slice) }
+ }
}
impl FromUtf8Error {
ptr::write(self.ptr.offset(off as isize), t);
}
- /// Returns true iff the buffer is at capacity
+ /// Returns true if and only if the buffer is at capacity
#[inline]
fn is_full(&self) -> bool { self.cap - self.len() == 1 }
#![feature(rustc_private)]
#![feature(slice_bytes)]
#![feature(slice_chars)]
-#![feature(slice_extras)]
+#![feature(slice_splits)]
#![feature(slice_position_elem)]
#![feature(split_off)]
#![feature(step_by)]
#![feature(str_escape)]
#![feature(str_match_indices)]
#![feature(str_utf16)]
+#![feature(box_str)]
#![feature(subslice_offset)]
#![feature(test)]
#![feature(unboxed_closures)]
#![feature(vec_deque_retain)]
#![feature(vec_from_raw_buf)]
#![feature(vec_push_all)]
-#![feature(vec_split_off)]
#![feature(vecmap)]
+#![allow(deprecated)]
+
#[macro_use] extern crate log;
extern crate collections;
}
#[test]
-fn test_tail() {
+fn test_split_first() {
let mut a = vec![11];
let b: &[i32] = &[];
- assert_eq!(a.tail(), b);
+ assert!(b.split_first().is_none());
+ assert_eq!(a.split_first(), Some((&11, b)));
a = vec![11, 12];
let b: &[i32] = &[12];
- assert_eq!(a.tail(), b);
+ assert_eq!(a.split_first(), Some((&11, b)));
}
#[test]
-fn test_tail_mut() {
+fn test_split_first_mut() {
let mut a = vec![11];
let b: &mut [i32] = &mut [];
- assert!(a.tail_mut() == b);
+ assert!(b.split_first_mut().is_none());
+ assert!(a.split_first_mut() == Some((&mut 11, b)));
a = vec![11, 12];
let b: &mut [_] = &mut [12];
- assert!(a.tail_mut() == b);
+ assert!(a.split_first_mut() == Some((&mut 11, b)));
}
#[test]
-#[should_panic]
-fn test_tail_empty() {
- let a = Vec::<i32>::new();
- a.tail();
-}
-
-#[test]
-#[should_panic]
-fn test_tail_mut_empty() {
- let mut a = Vec::<i32>::new();
- a.tail_mut();
-}
-
-#[test]
-fn test_init() {
+fn test_split_last() {
let mut a = vec![11];
let b: &[i32] = &[];
- assert_eq!(a.init(), b);
+ assert!(b.split_last().is_none());
+ assert_eq!(a.split_last(), Some((&11, b)));
a = vec![11, 12];
let b: &[_] = &[11];
- assert_eq!(a.init(), b);
+ assert_eq!(a.split_last(), Some((&12, b)));
}
#[test]
-fn test_init_mut() {
+fn test_split_last_mut() {
let mut a = vec![11];
let b: &mut [i32] = &mut [];
- assert!(a.init_mut() == b);
+ assert!(b.split_last_mut().is_none());
+ assert!(a.split_last_mut() == Some((&mut 11, b)));
+
a = vec![11, 12];
let b: &mut [_] = &mut [11];
- assert!(a.init_mut() == b);
-}
-
-#[test]
-#[should_panic]
-fn test_init_empty() {
- let a = Vec::<i32>::new();
- a.init();
-}
-
-#[test]
-#[should_panic]
-fn test_init_mut_empty() {
- let mut a = Vec::<i32>::new();
- a.init_mut();
+ assert!(a.split_last_mut() == Some((&mut 12, b)));
}
#[test]
assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
}
+#[test]
+fn test_into_string() {
+ // The only way to acquire a Box<str> in the first place is through a String, so just
+ // test that we can round-trip between Box<str> and String.
+ let string = String::from("Some text goes here");
+ assert_eq!(string.clone().into_boxed_slice().into_string(), string);
+}
+
mod pattern {
use std::str::pattern::Pattern;
use std::str::pattern::{Searcher, ReverseSearcher};
assert_eq!(&a, "foobar");
}
+#[test]
+fn test_into_boxed_slice() {
+ let xs = String::from("hello my name is bob");
+ let ys = xs.into_boxed_slice();
+ assert_eq!(&*ys, "hello my name is bob");
+}
+
#[bench]
fn bench_with_capacity(b: &mut Bencher) {
b.iter(|| {
fn is_pretty(&self) -> bool {
self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
}
+
+ /// Returns the wrapped `Formatter`.
+ #[unstable(feature = "debug_builder_formatter", reason = "recently added")]
+ pub fn formatter(&mut self) -> &mut fmt::Formatter<'b> {
+ &mut self.fmt
+ }
}
struct DebugInner<'a, 'b: 'a> {
impl<$($name:Debug),*> Debug for ($($name,)*) {
#[allow(non_snake_case, unused_assignments)]
fn fmt(&self, f: &mut Formatter) -> Result {
- try!(write!(f, "("));
+ let mut builder = f.debug_tuple("");
let ($(ref $name,)*) = *self;
let mut n = 0;
$(
- if n > 0 {
- try!(write!(f, ", "));
- }
- try!(write!(f, "{:?}", *$name));
+ builder.field($name);
n += 1;
)*
+
if n == 1 {
- try!(write!(f, ","));
+ try!(write!(builder.formatter(), ","));
}
- write!(f, ")")
+
+ builder.finish()
}
}
peel! { $($name,)* }
acc
}
- /// Returns `true` iff `self == 2^k` for some `k`.
+ /// Returns `true` if and only if `self == 2^k` for some `k`.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_power_of_two(self) -> bool {
//! // The division was valid
//! Some(x) => println!("Result: {}", x),
//! // The division was invalid
-//! None => println!("Cannot divide by 0")
+//! None => println!("Cannot divide by 0"),
//! }
//! ```
//!
//! fn check_optional(optional: &Option<Box<i32>>) {
//! match *optional {
//! Some(ref p) => println!("have value {}", p),
-//! None => println!("have no value")
+//! None => println!("have no value"),
//! }
//! }
//! ```
//! // Take a reference to the contained string
//! match msg {
//! Some(ref m) => println!("{}", *m),
-//! None => ()
+//! None => (),
//! }
//!
//! // Remove the contained string, destroying the Option
//! let unwrapped_msg = match msg {
//! Some(m) => m,
-//! None => "default message"
+//! None => "default message",
//! };
//! ```
//!
//!
//! match name_of_biggest_animal {
//! Some(name) => println!("the biggest animal is {}", name),
-//! None => println!("there are no animals :(")
+//! None => println!("there are no animals :("),
//! }
//! ```
pub fn is_some(&self) -> bool {
match *self {
Some(_) => true,
- None => false
+ None => false,
}
}
pub fn as_ref<'r>(&'r self) -> Option<&'r T> {
match *self {
Some(ref x) => Some(x),
- None => None
+ None => None,
}
}
pub fn as_mut<'r>(&'r mut self) -> Option<&'r mut T> {
match *self {
Some(ref mut x) => Some(x),
- None => None
+ None => None,
}
}
pub fn unwrap_or(self, def: T) -> T {
match self {
Some(x) => x,
- None => def
+ None => def,
}
}
pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
match self {
Some(x) => x,
- None => f()
+ None => f(),
}
}
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
match self {
Some(x) => Some(f(x)),
- None => None
+ None => None,
}
}
pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U {
match self {
Some(t) => f(t),
- None => default()
+ None => default(),
}
}
pub fn or(self, optb: Option<T>) -> Option<T> {
match self {
Some(_) => self,
- None => optb
+ None => optb,
}
}
pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> {
match self {
Some(_) => self,
- None => f()
+ None => f(),
}
}
pub fn unwrap_or_default(self) -> T {
match self {
Some(x) => x,
- None => Default::default()
+ None => Default::default(),
}
}
}
fn first<'a>(&'a self) -> Option<&'a Self::Item>;
fn tail<'a>(&'a self) -> &'a [Self::Item];
fn init<'a>(&'a self) -> &'a [Self::Item];
+ fn split_first<'a>(&'a self) -> Option<(&'a Self::Item, &'a [Self::Item])>;
+ fn split_last<'a>(&'a self) -> Option<(&'a Self::Item, &'a [Self::Item])>;
fn last<'a>(&'a self) -> Option<&'a Self::Item>;
unsafe fn get_unchecked<'a>(&'a self, index: usize) -> &'a Self::Item;
fn as_ptr(&self) -> *const Self::Item;
fn first_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>;
fn tail_mut<'a>(&'a mut self) -> &'a mut [Self::Item];
fn init_mut<'a>(&'a mut self) -> &'a mut [Self::Item];
+ fn split_first_mut<'a>(&'a mut self) -> Option<(&'a mut Self::Item, &'a mut [Self::Item])>;
+ fn split_last_mut<'a>(&'a mut self) -> Option<(&'a mut Self::Item, &'a mut [Self::Item])>;
fn last_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>;
fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
fn tail(&self) -> &[T] { &self[1..] }
#[inline]
- fn init(&self) -> &[T] {
- &self[..self.len() - 1]
+ fn split_first(&self) -> Option<(&T, &[T])> {
+ if self.is_empty() { None } else { Some((&self[0], &self[1..])) }
+ }
+
+ #[inline]
+ fn init(&self) -> &[T] { &self[..self.len() - 1] }
+
+ #[inline]
+ fn split_last(&self) -> Option<(&T, &[T])> {
+ let len = self.len();
+ if len == 0 { None } else { Some((&self[len - 1], &self[..(len - 1)])) }
}
#[inline]
}
#[inline]
- fn tail_mut(&mut self) -> &mut [T] {
- &mut self[1 ..]
+ fn tail_mut(&mut self) -> &mut [T] { &mut self[1 ..] }
+
+ #[inline]
+ fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
+ if self.is_empty() { None } else {
+ let split = self.split_at_mut(1);
+ Some((&mut split.0[0], split.1))
+ }
}
#[inline]
&mut self[.. (len - 1)]
}
+ #[inline]
+ fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
+ let len = self.len();
+ if len == 0 { None } else {
+ let split = self.split_at_mut(len - 1);
+ Some((&mut split.1[0], split.0))
+ }
+ }
+
#[inline]
fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
SplitMut { v: self, pred: pred, finished: false }
//! optopt("o", "", "set output file name", "NAME"),
//! optflag("h", "help", "print this help menu")
//! ];
-//! let matches = match getopts(args.tail(), opts) {
+//! let matches = match getopts(args[1..], opts) {
//! Ok(m) => { m }
//! Err(f) => { panic!(f.to_string()) }
//! };
}
}
+ #[cfg(target_arch = "x86")]
+ pub mod arch {
+ pub mod c95 {
+ pub type c_char = i8;
+ pub type c_schar = i8;
+ pub type c_uchar = u8;
+ pub type c_short = i16;
+ pub type c_ushort = u16;
+ pub type c_int = i32;
+ pub type c_uint = u32;
+ pub type c_long = i32;
+ pub type c_ulong = u32;
+ pub type c_float = f32;
+ pub type c_double = f64;
+ pub type size_t = u32;
+ pub type ptrdiff_t = i32;
+ pub type clock_t = i32;
+ pub type time_t = i32;
+ pub type suseconds_t = i32;
+ pub type wchar_t = i32;
+ }
+ pub mod c99 {
+ pub type c_longlong = i64;
+ pub type c_ulonglong = u64;
+ pub type intptr_t = i32;
+ pub type uintptr_t = u32;
+ pub type intmax_t = i64;
+ pub type uintmax_t = u64;
+ }
+ pub mod posix88 {
+ pub type off_t = i64;
+ pub type dev_t = u32;
+ pub type ino_t = u32;
+ pub type pid_t = i32;
+ pub type uid_t = u32;
+ pub type gid_t = u32;
+ pub type useconds_t = u32;
+ pub type mode_t = u16;
+ pub type ssize_t = i32;
+ }
+ pub mod posix01 {
+ use types::common::c95::{c_void};
+ use types::common::c99::{uint8_t, uint32_t, int32_t};
+ use types::os::arch::c95::{c_long, time_t};
+ use types::os::arch::posix88::{dev_t, gid_t, ino_t};
+ use types::os::arch::posix88::{mode_t, off_t};
+ use types::os::arch::posix88::{uid_t};
+
+ pub type nlink_t = u16;
+ pub type blksize_t = i32;
+ pub type blkcnt_t = i64;
+ pub type fflags_t = u32;
+ #[repr(C)]
+ #[derive(Copy, Clone)] pub struct stat {
+ pub st_dev: dev_t,
+ pub st_ino: ino_t,
+ pub st_mode: mode_t,
+ pub st_nlink: nlink_t,
+ pub st_uid: uid_t,
+ pub st_gid: gid_t,
+ pub st_rdev: dev_t,
+ pub st_atime: time_t,
+ pub st_atime_nsec: c_long,
+ pub st_mtime: time_t,
+ pub st_mtime_nsec: c_long,
+ pub st_ctime: time_t,
+ pub st_ctime_nsec: c_long,
+ pub st_size: off_t,
+ pub st_blocks: blkcnt_t,
+ pub st_blksize: blksize_t,
+ pub st_flags: fflags_t,
+ pub st_gen: uint32_t,
+ pub st_lspare: int32_t,
+ pub st_birthtime: time_t,
+ pub st_birthtime_nsec: c_long,
+ pub __unused: [uint8_t; 2],
+ }
+
+ #[repr(C)]
+ #[derive(Copy, Clone)] pub struct utimbuf {
+ pub actime: time_t,
+ pub modtime: time_t,
+ }
+
+ pub type pthread_attr_t = *mut c_void;
+ }
+ pub mod posix08 {
+ }
+ pub mod bsd44 {
+ }
+ pub mod extra {
+ }
+ }
+
#[cfg(target_arch = "x86_64")]
pub mod arch {
pub mod c95 {
pub const F_GETFL : c_int = 3;
pub const F_SETFL : c_int = 4;
+ pub const O_ACCMODE : c_int = 3;
+
pub const SIGTRAP : c_int = 5;
pub const SIG_IGN: size_t = 1;
pub const O_DSYNC : c_int = 4194304;
pub const O_SYNC : c_int = 128;
pub const O_NONBLOCK : c_int = 4;
+ pub const F_GETPATH : c_int = 50;
pub const F_FULLFSYNC : c_int = 51;
pub const MAP_COPY : c_int = 0x0002;
pub const SO_DONTTRUNC: c_int = 0x2000;
pub const SO_WANTMORE: c_int = 0x4000;
pub const SO_WANTOOBFLAG: c_int = 0x8000;
+
+ pub const PATH_MAX: c_int = 1024;
}
pub mod sysconf {
use types::os::arch::c95::c_int;
fn bar(&self);
}
-// we now declare a function which takes an object with Foo trait implemented
-// as parameter
+// we now declare a function which takes an object implementing the Foo trait
fn some_func<T: Foo>(foo: T) {
foo.bar();
}
E0308: r##"
This error occurs when the compiler was unable to infer the concrete type of a
-variable. This error can occur for several cases, the most common of which is a
+variable. It can occur for several cases, the most common of which is a
mismatch in the expected type that the compiler inferred for a variable's
initializing expression, and the actual type explicitly assigned to the
variable.
#![feature(rustc_private)]
#![feature(scoped_tls)]
#![feature(slice_bytes)]
-#![feature(slice_extras)]
+#![feature(slice_splits)]
#![feature(slice_patterns)]
#![feature(slice_position_elem)]
#![feature(staged_api)]
pub fn get_struct_fields(cstore: &cstore::CStore,
def: ast::DefId)
- -> Vec<ty::field_ty> {
+ -> Vec<ty::FieldTy> {
let cdata = cstore.get_crate_data(def.krate);
decoder::get_struct_fields(cstore.intr.clone(), &*cdata, def.node)
}
-> csearch::FoundAst<'tcx> {
debug!("Looking up item: {}", id);
let item_doc = lookup_item(id, cdata.data());
- let path = item_path(item_doc).init().to_vec();
+ let path = item_path(item_doc).split_last().unwrap().1.to_vec();
match decode_inlined_item(cdata, tcx, path, item_doc) {
Ok(ii) => csearch::FoundAst::Found(ii),
Err(path) => {
}
pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
- -> Vec<ty::field_ty> {
+ -> Vec<ty::FieldTy> {
let data = cdata.data();
let item = lookup_item(id, data);
reader::tagged_docs(item, tag_item_field).filter_map(|an_item| {
let did = item_def_id(an_item, cdata);
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
let origin_id = translated_def_id(cdata, tagdoc);
- Some(ty::field_ty {
+ Some(ty::FieldTy {
name: name,
id: did,
vis: struct_field_family_to_visibility(f),
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
let f = item_family(an_item);
let origin_id = translated_def_id(cdata, tagdoc);
- ty::field_ty {
+ ty::FieldTy {
name: special_idents::unnamed_field.name,
id: did,
vis: struct_field_family_to_visibility(f),
}
fn encode_struct_fields(rbml_w: &mut Encoder,
- fields: &[ty::field_ty],
+ fields: &[ty::FieldTy],
origin: DefId) {
for f in fields {
if f.name == special_idents::unnamed_field.name {
/* Returns an index of items in this class */
fn encode_info_for_struct(ecx: &EncodeContext,
rbml_w: &mut Encoder,
- fields: &[ty::field_ty],
+ fields: &[ty::FieldTy],
global_index: &mut Vec<entry<i64>>)
-> Vec<entry<i64>> {
/* Each class has its own index, since different classes
assert_eq!(next(st), ':');
let len = parse_hex(st);
assert_eq!(next(st), '#');
- let key = ty::creader_cache_key {cnum: st.krate,
+ let key = ty::CReaderCacheKey {cnum: st.krate,
pos: pos,
len: len };
}
}
-fn parse_mt_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> ty::mt<'tcx> where
+fn parse_mt_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> ty::TypeAndMut<'tcx> where
F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
{
let m = parse_mutability(st);
- ty::mt { ty: parse_ty_(st, conv), mutbl: m }
+ ty::TypeAndMut { ty: parse_ty_(st, conv), mutbl: m }
}
fn parse_def_<F>(st: &mut PState, source: DefIdSource, conv: &mut F) -> ast::DefId where
}
fn enc_mt<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
- mt: ty::mt<'tcx>) {
+ mt: ty::TypeAndMut<'tcx>) {
enc_mutability(w, mt.mutbl);
enc_ty(w, cx, mt.ty);
}
/// Function Pointers
FnPtr,
/// Raw pointers
- Ptr(&'tcx ty::mt<'tcx>),
+ Ptr(&'tcx ty::TypeAndMut<'tcx>),
/// References
- RPtr(&'tcx ty::mt<'tcx>),
+ RPtr(&'tcx ty::TypeAndMut<'tcx>),
}
/// Cast Kind. See RFC 401 (or librustc_typeck/check/cast.rs)
}
}
- ty::TyRef(_, ty::mt { ty, mutbl }) => {
+ ty::TyRef(_, ty::TypeAndMut { ty, mutbl }) => {
match ty.sty {
ty::TyArray(_, n) => match ctor {
&Single => {
ty::TyBool =>
[true, false].iter().map(|b| ConstantValue(ConstVal::Bool(*b))).collect(),
- ty::TyRef(_, ty::mt { ty, .. }) => match ty.sty {
+ ty::TyRef(_, ty::TypeAndMut { ty, .. }) => match ty.sty {
ty::TySlice(_) =>
range_inclusive(0, max_slice_length).map(|length| Slice(length)).collect(),
_ => vec!(Single)
Some(constructor) => {
let matrix = rows.iter().filter_map(|r| {
if pat_is_binding_or_wild(&cx.tcx.def_map, raw_pat(r[0])) {
- Some(r.tail().to_vec())
+ Some(r[1..].to_vec())
} else {
None
}
}).collect();
- match is_useful(cx, &matrix, v.tail(), witness) {
+ match is_useful(cx, &matrix, &v[1..], witness) {
UsefulWithWitness(pats) => {
let arity = constructor_arity(cx, &constructor, left_ty);
let wild_pats = vec![DUMMY_WILD_PAT; arity];
match ty.sty {
ty::TyTuple(ref fs) => fs.len(),
ty::TyBox(_) => 1,
- ty::TyRef(_, ty::mt { ty, .. }) => match ty.sty {
+ ty::TyRef(_, ty::TypeAndMut { ty, .. }) => match ty.sty {
ty::TySlice(_) => match *ctor {
Slice(length) => length,
ConstantValue(_) => 0,
// are properly handled.
self.walk_expr(with_expr);
- fn contains_field_named(field: &ty::field,
+ fn contains_field_named(field: &ty::Field,
fields: &Vec<ast::Field>)
-> bool
{
ty::TyArray(t, _) |
ty::TySlice(t) |
- ty::TyRawPtr(ty::mt { ty: t, .. }) |
+ ty::TyRawPtr(ty::TypeAndMut { ty: t, .. }) |
ty::TyBox(t) => {
self.accumulate_from_ty(t)
}
use middle::ty::{TyVar};
use middle::ty::{IntType, UintType};
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, TypeError};
use middle::ty_fold;
use middle::ty_fold::{TypeFolder, TypeFoldable};
use middle::ty_relate::{self, Relate, RelateResult, TypeRelation};
// All other cases of inference are errors
(&ty::TyInfer(_), _) |
(_, &ty::TyInfer(_)) => {
- Err(ty::terr_sorts(ty_relate::expected_found(relation, &a, &b)))
+ Err(TypeError::Sorts(ty_relate::expected_found(relation, &a, &b)))
}
};
let u = ty.fold_with(&mut generalize);
if generalize.cycle_detected {
- Err(ty::terr_cyclic_ty)
+ Err(TypeError::CyclicTy)
} else {
Ok(u)
}
pub trait RelateResultCompare<'tcx, T> {
fn compare<F>(&self, t: T, f: F) -> RelateResult<'tcx, T> where
- F: FnOnce() -> ty::type_err<'tcx>;
+ F: FnOnce() -> ty::TypeError<'tcx>;
}
impl<'tcx, T:Clone + PartialEq> RelateResultCompare<'tcx, T> for RelateResult<'tcx, T> {
fn compare<F>(&self, t: T, f: F) -> RelateResult<'tcx, T> where
- F: FnOnce() -> ty::type_err<'tcx>,
+ F: FnOnce() -> ty::TypeError<'tcx>,
{
self.clone().and_then(|s| {
if s == t {
}
fn int_unification_error<'tcx>(a_is_expected: bool, v: (ty::IntVarValue, ty::IntVarValue))
- -> ty::type_err<'tcx>
+ -> ty::TypeError<'tcx>
{
let (a, b) = v;
- ty::terr_int_mismatch(ty_relate::expected_found_bool(a_is_expected, &a, &b))
+ TypeError::IntMismatch(ty_relate::expected_found_bool(a_is_expected, &a, &b))
}
fn float_unification_error<'tcx>(a_is_expected: bool,
v: (ast::FloatTy, ast::FloatTy))
- -> ty::type_err<'tcx>
+ -> ty::TypeError<'tcx>
{
let (a, b) = v;
- ty::terr_float_mismatch(ty_relate::expected_found_bool(a_is_expected, &a, &b))
+ TypeError::FloatMismatch(ty_relate::expected_found_bool(a_is_expected, &a, &b))
}
use middle::infer;
use middle::region;
use middle::subst;
-use middle::ty::{self, Ty, HasTypeFlags};
+use middle::ty::{self, Ty, TypeError, HasTypeFlags};
use middle::ty::{Region, ReFree};
use std::cell::{Cell, RefCell};
fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
-> Vec<RegionResolutionError<'tcx>>;
- fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::type_err<'tcx>);
+ fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::TypeError<'tcx>);
fn report_and_explain_type_error(&self,
trace: TypeTrace<'tcx>,
- terr: &ty::type_err<'tcx>);
+ terr: &ty::TypeError<'tcx>);
fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String>;
fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + HasTypeFlags>(
&self,
- exp_found: &ty::expected_found<T>)
+ exp_found: &ty::ExpectedFound<T>)
-> Option<String>;
fn report_concrete_failure(&self,
fn report_processed_errors(&self,
var_origin: &[RegionVariableOrigin],
- trace_origin: &[(TypeTrace<'tcx>, ty::type_err<'tcx>)],
+ trace_origin: &[(TypeTrace<'tcx>, ty::TypeError<'tcx>)],
same_regions: &[SameRegions]);
fn give_suggestion(&self, same_regions: &[SameRegions]);
match free_regions_from_same_fn(self.tcx, sub, sup) {
Some(ref same_frs) if trace.is_some() => {
let trace = trace.unwrap();
- let terr = ty::terr_regions_does_not_outlive(sup,
- sub);
+ let terr = TypeError::RegionsDoesNotOutlive(sup,
+ sub);
trace_origins.push((trace, terr));
append_to_same_regions(&mut same_regions, same_frs);
}
}
}
- fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::type_err<'tcx>) {
+ fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::TypeError<'tcx>) {
let expected_found_str = match self.values_str(&trace.values) {
Some(v) => v,
None => {
fn report_and_explain_type_error(&self,
trace: TypeTrace<'tcx>,
- terr: &ty::type_err<'tcx>) {
+ terr: &ty::TypeError<'tcx>) {
let span = trace.origin.span();
self.report_type_error(trace, terr);
self.tcx.note_and_explain_type_err(terr, span);
fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + HasTypeFlags>(
&self,
- exp_found: &ty::expected_found<T>)
+ exp_found: &ty::ExpectedFound<T>)
-> Option<String>
{
let expected = exp_found.expected.resolve(self);
match origin {
infer::Subtype(trace) |
infer::DefaultExistentialBound(trace) => {
- let terr = ty::terr_regions_does_not_outlive(sup, sub);
+ let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
self.report_and_explain_type_error(trace, &terr);
}
infer::Reborrow(span) => {
fn report_processed_errors(&self,
var_origins: &[RegionVariableOrigin],
- trace_origins: &[(TypeTrace<'tcx>, ty::type_err<'tcx>)],
+ trace_origins: &[(TypeTrace<'tcx>, ty::TypeError<'tcx>)],
same_regions: &[SameRegions]) {
for vo in var_origins {
self.report_inference_failure(vo.clone());
parameters: new_parameters
};
let mut new_segs = Vec::new();
- new_segs.push_all(path.segments.init());
+ new_segs.push_all(path.segments.split_last().unwrap().1);
new_segs.push(new_seg);
ast::Path {
span: path.span,
use super::combine::CombineFields;
use middle::subst;
-use middle::ty::{self, Binder};
+use middle::ty::{self, TypeError, Binder};
use middle::ty_fold::{self, TypeFoldable};
use middle::ty_relate::{Relate, RelateResult, TypeRelation};
use syntax::codemap::Span;
Err((skol_br, tainted_region)) => {
if self.a_is_expected {
debug!("Not as polymorphic!");
- return Err(ty::terr_regions_insufficiently_polymorphic(skol_br,
+ return Err(TypeError::RegionsInsufficientlyPolymorphic(skol_br,
tainted_region));
} else {
debug!("Overly polymorphic!");
- return Err(ty::terr_regions_overly_polymorphic(skol_br,
+ return Err(TypeError::RegionsOverlyPolymorphic(skol_br,
tainted_region));
}
}
//! See the Book for more information.
-#![allow(non_camel_case_types)]
-
pub use self::LateBoundRegionConversionTime::*;
pub use self::RegionVariableOrigin::*;
pub use self::SubregionOrigin::*;
pub use self::TypeOrigin::*;
pub use self::ValuePairs::*;
-pub use self::fixup_err::*;
pub use middle::ty::IntVarValue;
pub use self::freshen::TypeFreshener;
pub use self::region_inference::GenericKind;
use middle::traits::{self, FulfillmentContext, Normalized,
SelectionContext, ObligationCause};
use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric};
-use middle::ty::{self, Ty, HasTypeFlags};
+use middle::ty::{self, Ty, TypeError, HasTypeFlags};
use middle::ty_fold::{self, TypeFolder, TypeFoldable};
use middle::ty_relate::{Relate, RelateResult, TypeRelation};
use rustc_data_structures::unify::{self, UnificationTable};
pub type Bound<T> = Option<T>;
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
-pub type fres<T> = Result<T, fixup_err>; // "fixup result"
+pub type FixupResult<T> = Result<T, FixupError>; // "fixup result"
pub struct InferCtxt<'a, 'tcx: 'a> {
pub tcx: &'a ty::ctxt<'tcx>,
/// See `error_reporting.rs` for more details
#[derive(Clone, Debug)]
pub enum ValuePairs<'tcx> {
- Types(ty::expected_found<Ty<'tcx>>),
- TraitRefs(ty::expected_found<ty::TraitRef<'tcx>>),
- PolyTraitRefs(ty::expected_found<ty::PolyTraitRef<'tcx>>),
+ Types(ty::ExpectedFound<Ty<'tcx>>),
+ TraitRefs(ty::ExpectedFound<ty::TraitRef<'tcx>>),
+ PolyTraitRefs(ty::ExpectedFound<ty::PolyTraitRef<'tcx>>),
}
/// The trace designates the path through inference that we took to
}
#[derive(Copy, Clone, Debug)]
-pub enum fixup_err {
- unresolved_int_ty(IntVid),
- unresolved_float_ty(FloatVid),
- unresolved_ty(TyVid)
+pub enum FixupError {
+ UnresolvedIntTy(IntVid),
+ UnresolvedFloatTy(FloatVid),
+ UnresolvedTy(TyVid)
}
-pub fn fixup_err_to_string(f: fixup_err) -> String {
+pub fn fixup_err_to_string(f: FixupError) -> String {
+ use self::FixupError::*;
+
match f {
- unresolved_int_ty(_) => {
+ UnresolvedIntTy(_) => {
"cannot determine the type of this integer; add a suffix to \
specify the type explicitly".to_string()
}
- unresolved_float_ty(_) => {
+ UnresolvedFloatTy(_) => {
"cannot determine the type of this number; add a suffix to specify \
the type explicitly".to_string()
}
- unresolved_ty(_) => "unconstrained type".to_string(),
+ UnresolvedTy(_) => "unconstrained type".to_string(),
}
}
fn expected_found<T>(a_is_expected: bool,
a: T,
b: T)
- -> ty::expected_found<T>
+ -> ty::ExpectedFound<T>
{
if a_is_expected {
- ty::expected_found {expected: a, found: b}
+ ty::ExpectedFound {expected: a, found: b}
} else {
- ty::expected_found {expected: b, found: a}
+ ty::ExpectedFound {expected: b, found: a}
}
}
match higher_ranked::leak_check(self, skol_map, snapshot) {
Ok(()) => Ok(()),
- Err((br, r)) => Err(ty::terr_regions_insufficiently_polymorphic(br, r))
+ Err((br, r)) => Err(TypeError::RegionsInsufficientlyPolymorphic(br, r))
}
}
if ty.has_infer_types() || ty.references_error() { Err(()) } else { Ok(ty) }
}
- pub fn fully_resolve<T:TypeFoldable<'tcx>>(&self, value: &T) -> fres<T> {
+ pub fn fully_resolve<T:TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<T> {
/*!
* Attempts to resolve all type/region variables in
* `value`. Region inference must have been run already (e.g.,
sp: Span,
mk_msg: M,
actual_ty: String,
- err: Option<&ty::type_err<'tcx>>) where
+ err: Option<&ty::TypeError<'tcx>>) where
M: FnOnce(Option<String>, String) -> String,
{
self.type_error_message_str_with_expected(sp, mk_msg, None, actual_ty, err)
mk_msg: M,
expected_ty: Option<Ty<'tcx>>,
actual_ty: String,
- err: Option<&ty::type_err<'tcx>>) where
+ err: Option<&ty::TypeError<'tcx>>) where
M: FnOnce(Option<String>, String) -> String,
{
debug!("hi! expected_ty = {:?}, actual_ty = {}", expected_ty, actual_ty);
sp: Span,
mk_msg: M,
actual_ty: Ty<'tcx>,
- err: Option<&ty::type_err<'tcx>>) where
+ err: Option<&ty::TypeError<'tcx>>) where
M: FnOnce(String) -> String,
{
let actual_ty = self.resolve_type_vars_if_possible(&actual_ty);
span: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
- err: &ty::type_err<'tcx>) {
+ err: &ty::TypeError<'tcx>) {
let trace = TypeTrace {
origin: Misc(span),
- values: Types(ty::expected_found {
+ values: Types(ty::ExpectedFound {
expected: expected,
found: actual
})
pub fn dummy(tcx: &ty::ctxt<'tcx>) -> TypeTrace<'tcx> {
TypeTrace {
origin: Misc(codemap::DUMMY_SP),
- values: Types(ty::expected_found {
+ values: Types(ty::ExpectedFound {
expected: tcx.types.err,
found: tcx.types.err,
})
use rustc_data_structures::graph::{self, Direction, NodeIndex};
use middle::free_region::FreeRegionMap;
use middle::region;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, TypeError};
use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound};
use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
/// should put a lifetime. In those cases we process and put those errors
/// into `ProcessedErrors` before we do any reporting.
ProcessedErrors(Vec<RegionVariableOrigin>,
- Vec<(TypeTrace<'tcx>, ty::type_err<'tcx>)>,
+ Vec<(TypeTrace<'tcx>, ty::TypeError<'tcx>)>,
Vec<SameRegions>),
}
if self.tcx.region_maps.nearest_common_ancestor(fr_scope, s_id) == fr_scope {
Ok(s)
} else {
- Err(ty::terr_regions_no_overlap(b, a))
+ Err(TypeError::RegionsNoOverlap(b, a))
}
}
if a == b {
Ok(a)
} else {
- Err(ty::terr_regions_no_overlap(b, a))
+ Err(TypeError::RegionsNoOverlap(b, a))
}
}
}
} else if r_id == scope_b {
Ok(ReScope(scope_a))
} else {
- Err(ty::terr_regions_no_overlap(region_a, region_b))
+ Err(TypeError::RegionsNoOverlap(region_a, region_b))
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use super::{InferCtxt, fixup_err, fres, unresolved_ty, unresolved_int_ty, unresolved_float_ty};
+use super::{InferCtxt, FixupError, FixupResult};
use middle::ty::{self, Ty, HasTypeFlags};
use middle::ty_fold::{self, TypeFoldable};
/// Full type resolution replaces all type and region variables with
/// their concrete results. If any variable cannot be replaced (never unified, etc)
/// then an `Err` result is returned.
-pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a,'tcx>, value: &T) -> fres<T>
+pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a,'tcx>, value: &T) -> FixupResult<T>
where T : TypeFoldable<'tcx>
{
let mut full_resolver = FullTypeResolver { infcx: infcx, err: None };
// `err` field is not enforcable otherwise.
struct FullTypeResolver<'a, 'tcx:'a> {
infcx: &'a InferCtxt<'a, 'tcx>,
- err: Option<fixup_err>,
+ err: Option<FixupError>,
}
impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
let t = self.infcx.shallow_resolve(t);
match t.sty {
ty::TyInfer(ty::TyVar(vid)) => {
- self.err = Some(unresolved_ty(vid));
+ self.err = Some(FixupError::UnresolvedTy(vid));
self.tcx().types.err
}
ty::TyInfer(ty::IntVar(vid)) => {
- self.err = Some(unresolved_int_ty(vid));
+ self.err = Some(FixupError::UnresolvedIntTy(vid));
self.tcx().types.err
}
ty::TyInfer(ty::FloatVar(vid)) => {
- self.err = Some(unresolved_float_ty(vid));
+ self.err = Some(FixupError::UnresolvedFloatTy(vid));
self.tcx().types.err
}
ty::TyInfer(_) => {
fn element_kind(t: Ty) -> ElementKind {
match t.sty {
- ty::TyRef(_, ty::mt{ty, ..}) |
+ ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
ty::TyBox(ty) => match ty.sty {
ty::TySlice(_) => VecElement,
_ => OtherElement
Unimplemented,
OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>,
ty::PolyTraitRef<'tcx>,
- ty::type_err<'tcx>),
+ ty::TypeError<'tcx>),
TraitNotObjectSafe(ast::DefId),
}
#[derive(Clone)]
pub struct MismatchedProjectionTypes<'tcx> {
- pub err: ty::type_err<'tcx>
+ pub err: ty::TypeError<'tcx>
}
#[derive(PartialEq, Eq, Debug)]
}
}
- ty::TyRef(_, ty::mt { ty: _, mutbl }) => {
+ ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl }) => {
// &mut T or &T
match bound {
ty::BoundCopy => {
Some(vec![referent_ty])
}
- ty::TyRawPtr(ty::mt { ty: element_ty, ..}) |
- ty::TyRef(_, ty::mt { ty: element_ty, ..}) => {
+ ty::TyRawPtr(ty::TypeAndMut { ty: element_ty, ..}) |
+ ty::TyRef(_, ty::TypeAndMut { ty: element_ty, ..}) => {
Some(vec![element_ty])
},
for &i in &ty_params {
new_substs.types.get_mut_slice(TypeSpace)[i] = tcx.types.err;
}
- for &ty in fields.init() {
+ for &ty in fields.split_last().unwrap().1 {
if ty.subst(tcx, &new_substs).references_error() {
return Err(Unimplemented);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// FIXME: (@jroesch) @eddyb should remove this when he renames ctxt
#![allow(non_camel_case_types)]
-pub use self::terr_vstore_kind::*;
-pub use self::type_err::*;
pub use self::InferTy::*;
pub use self::InferRegion::*;
pub use self::ImplOrTraitItemId::*;
}
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub struct field<'tcx> {
+pub struct Field<'tcx> {
pub name: ast::Name,
- pub mt: mt<'tcx>
+ pub mt: TypeAndMut<'tcx>
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
-pub struct mt<'tcx> {
+pub struct TypeAndMut<'tcx> {
pub ty: Ty<'tcx>,
pub mutbl: ast::Mutability,
}
#[derive(Clone, Copy, Debug)]
-pub struct field_ty {
+pub struct FieldTy {
pub name: Name,
pub id: DefId,
pub vis: ast::Visibility,
// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub struct creader_cache_key {
+pub struct CReaderCacheKey {
pub cnum: CrateNum,
pub pos: usize,
pub len: usize
pub map: ast_map::Map<'tcx>,
pub freevars: RefCell<FreevarMap>,
pub tcache: RefCell<DefIdMap<TypeScheme<'tcx>>>,
- pub rcache: RefCell<FnvHashMap<creader_cache_key, Ty<'tcx>>>,
+ pub rcache: RefCell<FnvHashMap<CReaderCacheKey, Ty<'tcx>>>,
pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, TypeContents>>,
pub ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo<'tcx>>>>>>,
pub lang_items: middle::lang_items::LanguageItems,
/// A mapping of fake provided method def_ids to the default implementation
pub provided_method_sources: RefCell<DefIdMap<ast::DefId>>,
- pub struct_fields: RefCell<DefIdMap<Rc<Vec<field_ty>>>>,
+ pub struct_fields: RefCell<DefIdMap<Rc<Vec<FieldTy>>>>,
/// Maps from def-id of a type or region parameter to its
/// (inferred) variance.
TySlice(Ty<'tcx>),
/// A raw pointer. Written as `*mut T` or `*const T`
- TyRawPtr(mt<'tcx>),
+ TyRawPtr(TypeAndMut<'tcx>),
/// A reference; a pointer with an associated lifetime. Written as
/// `&a mut T` or `&'a T`.
- TyRef(&'tcx Region, mt<'tcx>),
+ TyRef(&'tcx Region, TypeAndMut<'tcx>),
/// If the def-id is Some(_), then this is the type of a specific
/// fn item. Otherwise, if None(_), it a fn pointer type.
}
#[derive(Clone, Copy, Debug)]
-pub enum terr_vstore_kind {
- terr_vec,
- terr_str,
- terr_fn,
- terr_trait
-}
-
-#[derive(Clone, Copy, Debug)]
-pub struct expected_found<T> {
+pub struct ExpectedFound<T> {
pub expected: T,
pub found: T
}
// Data structures used in type unification
#[derive(Clone, Copy, Debug)]
-pub enum type_err<'tcx> {
- terr_mismatch,
- terr_unsafety_mismatch(expected_found<ast::Unsafety>),
- terr_abi_mismatch(expected_found<abi::Abi>),
- terr_mutability,
- terr_box_mutability,
- terr_ptr_mutability,
- terr_ref_mutability,
- terr_vec_mutability,
- terr_tuple_size(expected_found<usize>),
- terr_fixed_array_size(expected_found<usize>),
- terr_ty_param_size(expected_found<usize>),
- terr_arg_count,
- terr_regions_does_not_outlive(Region, Region),
- terr_regions_not_same(Region, Region),
- terr_regions_no_overlap(Region, Region),
- terr_regions_insufficiently_polymorphic(BoundRegion, Region),
- terr_regions_overly_polymorphic(BoundRegion, Region),
- terr_sorts(expected_found<Ty<'tcx>>),
- terr_integer_as_char,
- terr_int_mismatch(expected_found<IntVarValue>),
- terr_float_mismatch(expected_found<ast::FloatTy>),
- terr_traits(expected_found<ast::DefId>),
- terr_builtin_bounds(expected_found<BuiltinBounds>),
- terr_variadic_mismatch(expected_found<bool>),
- terr_cyclic_ty,
- terr_convergence_mismatch(expected_found<bool>),
- terr_projection_name_mismatched(expected_found<ast::Name>),
- terr_projection_bounds_length(expected_found<usize>),
+pub enum TypeError<'tcx> {
+ Mismatch,
+ UnsafetyMismatch(ExpectedFound<ast::Unsafety>),
+ AbiMismatch(ExpectedFound<abi::Abi>),
+ Mutability,
+ BoxMutability,
+ PtrMutability,
+ RefMutability,
+ VecMutability,
+ TupleSize(ExpectedFound<usize>),
+ FixedArraySize(ExpectedFound<usize>),
+ TyParamSize(ExpectedFound<usize>),
+ ArgCount,
+ RegionsDoesNotOutlive(Region, Region),
+ RegionsNotSame(Region, Region),
+ RegionsNoOverlap(Region, Region),
+ RegionsInsufficientlyPolymorphic(BoundRegion, Region),
+ RegionsOverlyPolymorphic(BoundRegion, Region),
+ Sorts(ExpectedFound<Ty<'tcx>>),
+ IntegerAsChar,
+ IntMismatch(ExpectedFound<IntVarValue>),
+ FloatMismatch(ExpectedFound<ast::FloatTy>),
+ Traits(ExpectedFound<ast::DefId>),
+ BuiltinBoundsMismatch(ExpectedFound<BuiltinBounds>),
+ VariadicMismatch(ExpectedFound<bool>),
+ CyclicTy,
+ ConvergenceMismatch(ExpectedFound<bool>),
+ ProjectionNameMismatched(ExpectedFound<ast::Name>),
+ ProjectionBoundsLength(ExpectedFound<usize>),
}
/// Bounds suitable for an existentially quantified type parameter
self.mk_ty(TyBox(ty))
}
- pub fn mk_ptr(&self, tm: mt<'tcx>) -> Ty<'tcx> {
+ pub fn mk_ptr(&self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
self.mk_ty(TyRawPtr(tm))
}
- pub fn mk_ref(&self, r: &'tcx Region, tm: mt<'tcx>) -> Ty<'tcx> {
+ pub fn mk_ref(&self, r: &'tcx Region, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
self.mk_ty(TyRef(r, tm))
}
pub fn mk_mut_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ref(r, mt {ty: ty, mutbl: ast::MutMutable})
+ self.mk_ref(r, TypeAndMut {ty: ty, mutbl: ast::MutMutable})
}
pub fn mk_imm_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ref(r, mt {ty: ty, mutbl: ast::MutImmutable})
+ self.mk_ref(r, TypeAndMut {ty: ty, mutbl: ast::MutImmutable})
}
pub fn mk_mut_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ptr(mt {ty: ty, mutbl: ast::MutMutable})
+ self.mk_ptr(TypeAndMut {ty: ty, mutbl: ast::MutMutable})
}
pub fn mk_imm_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ptr(mt {ty: ty, mutbl: ast::MutImmutable})
+ self.mk_ptr(TypeAndMut {ty: ty, mutbl: ast::MutImmutable})
}
pub fn mk_nil_ptr(&self) -> Ty<'tcx> {
}
fn tc_mt<'tcx>(cx: &ctxt<'tcx>,
- mt: mt<'tcx>,
+ mt: TypeAndMut<'tcx>,
cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
{
let mc = TC::ReachesMutable.when(mt.mutbl == MutMutable);
// Fast-path for primitive types
let result = match self.sty {
TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
- TyRawPtr(..) | TyBareFn(..) | TyRef(_, mt {
+ TyRawPtr(..) | TyBareFn(..) | TyRef(_, TypeAndMut {
mutbl: ast::MutImmutable, ..
}) => Some(false),
- TyStr | TyBox(..) | TyRef(_, mt {
+ TyStr | TyBox(..) | TyRef(_, TypeAndMut {
mutbl: ast::MutMutable, ..
}) => Some(true),
//
// The parameter `explicit` indicates if this is an *explicit* dereference.
// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
- pub fn builtin_deref(&self, explicit: bool) -> Option<mt<'tcx>> {
+ pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
match self.sty {
TyBox(ty) => {
- Some(mt {
+ Some(TypeAndMut {
ty: ty,
mutbl: ast::MutImmutable,
})
match autoref {
None => self,
Some(AutoPtr(r, m)) => {
- cx.mk_ref(r, mt { ty: self, mutbl: m })
+ cx.mk_ref(r, TypeAndMut { ty: self, mutbl: m })
}
Some(AutoUnsafe(m)) => {
- cx.mk_ptr(mt { ty: self, mutbl: m })
+ cx.mk_ptr(TypeAndMut { ty: self, mutbl: m })
}
}
}
fn sort_string(&self, cx: &ctxt) -> String {
+
match self.sty {
TyBool | TyChar | TyInt(_) |
TyUint(_) | TyFloat(_) | TyStr => self.to_string(),
/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
/// afterwards to present additional details, particularly when it comes to lifetime-related
/// errors.
-impl<'tcx> fmt::Display for type_err<'tcx> {
+impl<'tcx> fmt::Display for TypeError<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ use self::TypeError::*;
+
match *self {
- terr_cyclic_ty => write!(f, "cyclic type of infinite size"),
- terr_mismatch => write!(f, "types differ"),
- terr_unsafety_mismatch(values) => {
+ CyclicTy => write!(f, "cyclic type of infinite size"),
+ Mismatch => write!(f, "types differ"),
+ UnsafetyMismatch(values) => {
write!(f, "expected {} fn, found {} fn",
values.expected,
values.found)
}
- terr_abi_mismatch(values) => {
+ AbiMismatch(values) => {
write!(f, "expected {} fn, found {} fn",
values.expected,
values.found)
}
- terr_mutability => write!(f, "values differ in mutability"),
- terr_box_mutability => {
+ Mutability => write!(f, "values differ in mutability"),
+ BoxMutability => {
write!(f, "boxed values differ in mutability")
}
- terr_vec_mutability => write!(f, "vectors differ in mutability"),
- terr_ptr_mutability => write!(f, "pointers differ in mutability"),
- terr_ref_mutability => write!(f, "references differ in mutability"),
- terr_ty_param_size(values) => {
+ VecMutability => write!(f, "vectors differ in mutability"),
+ PtrMutability => write!(f, "pointers differ in mutability"),
+ RefMutability => write!(f, "references differ in mutability"),
+ TyParamSize(values) => {
write!(f, "expected a type with {} type params, \
found one with {} type params",
values.expected,
values.found)
}
- terr_fixed_array_size(values) => {
+ FixedArraySize(values) => {
write!(f, "expected an array with a fixed size of {} elements, \
found one with {} elements",
values.expected,
values.found)
}
- terr_tuple_size(values) => {
+ TupleSize(values) => {
write!(f, "expected a tuple with {} elements, \
found one with {} elements",
values.expected,
values.found)
}
- terr_arg_count => {
+ ArgCount => {
write!(f, "incorrect number of function parameters")
}
- terr_regions_does_not_outlive(..) => {
+ RegionsDoesNotOutlive(..) => {
write!(f, "lifetime mismatch")
}
- terr_regions_not_same(..) => {
+ RegionsNotSame(..) => {
write!(f, "lifetimes are not the same")
}
- terr_regions_no_overlap(..) => {
+ RegionsNoOverlap(..) => {
write!(f, "lifetimes do not intersect")
}
- terr_regions_insufficiently_polymorphic(br, _) => {
+ RegionsInsufficientlyPolymorphic(br, _) => {
write!(f, "expected bound lifetime parameter {}, \
found concrete lifetime", br)
}
- terr_regions_overly_polymorphic(br, _) => {
+ RegionsOverlyPolymorphic(br, _) => {
write!(f, "expected concrete lifetime, \
found bound lifetime parameter {}", br)
}
- terr_sorts(values) => tls::with(|tcx| {
+ Sorts(values) => tls::with(|tcx| {
// A naive approach to making sure that we're not reporting silly errors such as:
// (expected closure, found closure).
let expected_str = values.expected.sort_string(tcx);
write!(f, "expected {}, found {}", expected_str, found_str)
}
}),
- terr_traits(values) => tls::with(|tcx| {
+ Traits(values) => tls::with(|tcx| {
write!(f, "expected trait `{}`, found trait `{}`",
tcx.item_path_str(values.expected),
tcx.item_path_str(values.found))
}),
- terr_builtin_bounds(values) => {
+ BuiltinBoundsMismatch(values) => {
if values.expected.is_empty() {
write!(f, "expected no bounds, found `{}`",
values.found)
values.found)
}
}
- terr_integer_as_char => {
+ IntegerAsChar => {
write!(f, "expected an integral type, found `char`")
}
- terr_int_mismatch(ref values) => {
+ IntMismatch(ref values) => {
write!(f, "expected `{:?}`, found `{:?}`",
values.expected,
values.found)
}
- terr_float_mismatch(ref values) => {
+ FloatMismatch(ref values) => {
write!(f, "expected `{:?}`, found `{:?}`",
values.expected,
values.found)
}
- terr_variadic_mismatch(ref values) => {
+ VariadicMismatch(ref values) => {
write!(f, "expected {} fn, found {} function",
if values.expected { "variadic" } else { "non-variadic" },
if values.found { "variadic" } else { "non-variadic" })
}
- terr_convergence_mismatch(ref values) => {
+ ConvergenceMismatch(ref values) => {
write!(f, "expected {} fn, found {} function",
if values.expected { "converging" } else { "diverging" },
if values.found { "converging" } else { "diverging" })
}
- terr_projection_name_mismatched(ref values) => {
+ ProjectionNameMismatched(ref values) => {
write!(f, "expected {}, found {}",
values.expected,
values.found)
}
- terr_projection_bounds_length(ref values) => {
+ ProjectionBoundsLength(ref values) => {
write!(f, "expected {} associated type bindings, found {}",
values.expected,
values.found)
}
}
- pub fn field_idx_strict(&self, name: ast::Name, fields: &[field])
+ pub fn field_idx_strict(&self, name: ast::Name, fields: &[Field<'tcx>])
-> usize {
let mut i = 0;
for f in fields { if f.name == name { return i; } i += 1; }
.collect::<Vec<String>>()));
}
- pub fn note_and_explain_type_err(&self, err: &type_err<'tcx>, sp: Span) {
+ pub fn note_and_explain_type_err(&self, err: &TypeError<'tcx>, sp: Span) {
+ use self::TypeError::*;
+
match *err {
- terr_regions_does_not_outlive(subregion, superregion) => {
+ RegionsDoesNotOutlive(subregion, superregion) => {
self.note_and_explain_region("", subregion, "...");
self.note_and_explain_region("...does not necessarily outlive ",
superregion, "");
}
- terr_regions_not_same(region1, region2) => {
+ RegionsNotSame(region1, region2) => {
self.note_and_explain_region("", region1, "...");
self.note_and_explain_region("...is not the same lifetime as ",
region2, "");
}
- terr_regions_no_overlap(region1, region2) => {
+ RegionsNoOverlap(region1, region2) => {
self.note_and_explain_region("", region1, "...");
self.note_and_explain_region("...does not overlap ",
region2, "");
}
- terr_regions_insufficiently_polymorphic(_, conc_region) => {
+ RegionsInsufficientlyPolymorphic(_, conc_region) => {
self.note_and_explain_region("concrete lifetime that was found is ",
conc_region, "");
}
- terr_regions_overly_polymorphic(_, ty::ReInfer(ty::ReVar(_))) => {
+ RegionsOverlyPolymorphic(_, ty::ReInfer(ty::ReVar(_))) => {
// don't bother to print out the message below for
// inference variables, it's not very illuminating.
}
- terr_regions_overly_polymorphic(_, conc_region) => {
+ RegionsOverlyPolymorphic(_, conc_region) => {
self.note_and_explain_region("expected concrete lifetime is ",
conc_region, "");
}
- terr_sorts(values) => {
+ Sorts(values) => {
let expected_str = values.expected.sort_string(self);
let found_str = values.found.sort_string(self);
if expected_str == found_str && expected_str == "closure" {
// Look up the list of field names and IDs for a given struct.
// Panics if the id is not bound to a struct.
- pub fn lookup_struct_fields(&self, did: ast::DefId) -> Vec<field_ty> {
+ pub fn lookup_struct_fields(&self, did: ast::DefId) -> Vec<FieldTy> {
if did.krate == ast::LOCAL_CRATE {
let struct_fields = self.struct_fields.borrow();
match struct_fields.get(&did) {
// Returns a list of fields corresponding to the struct's items. trans uses
// this. Takes a list of substs with which to instantiate field types.
pub fn struct_fields(&self, did: ast::DefId, substs: &Substs<'tcx>)
- -> Vec<field<'tcx>> {
+ -> Vec<Field<'tcx>> {
self.lookup_struct_fields(did).iter().map(|f| {
- field {
+ Field {
name: f.name,
- mt: mt {
+ mt: TypeAndMut {
ty: self.lookup_field_type(did, f.id, substs),
mutbl: MutImmutable
}
}
UpvarCapture::ByRef(borrow) => {
tcx.mk_ref(tcx.mk_region(borrow.region),
- ty::mt {
+ ty::TypeAndMut {
ty: freevar_ty,
mutbl: borrow.kind.to_mutbl_lossy(),
})
h.as_str().hash(state);
did.node.hash(state);
};
- let mt = |state: &mut SipHasher, mt: mt| {
+ let mt = |state: &mut SipHasher, mt: TypeAndMut| {
mt.mutbl.hash(state);
};
let fn_sig = |state: &mut SipHasher, sig: &Binder<FnSig<'tcx>>| {
}
}
-impl<'tcx> HasTypeFlags for field<'tcx> {
+impl<'tcx> HasTypeFlags for Field<'tcx> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.mt.ty.has_type_flags(flags)
}
}
}
-impl<'tcx> fmt::Debug for field<'tcx> {
+impl<'tcx> fmt::Debug for Field<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "field({},{})", self.name, self.mt)
}
super_fold_ty(self, t)
}
- fn fold_mt(&mut self, t: &ty::mt<'tcx>) -> ty::mt<'tcx> {
+ fn fold_mt(&mut self, t: &ty::TypeAndMut<'tcx>) -> ty::TypeAndMut<'tcx> {
super_fold_mt(self, t)
}
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::mt<'tcx> {
- fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::mt<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for ty::TypeAndMut<'tcx> {
+ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TypeAndMut<'tcx> {
folder.fold_mt(self)
}
}
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::field<'tcx> {
- fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::field<'tcx> {
- ty::field {
+impl<'tcx> TypeFoldable<'tcx> for ty::Field<'tcx> {
+ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Field<'tcx> {
+ ty::Field {
name: self.name,
mt: self.mt.fold_with(folder),
}
}
pub fn super_fold_mt<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
- mt: &ty::mt<'tcx>)
- -> ty::mt<'tcx> {
- ty::mt {ty: mt.ty.fold_with(this),
+ mt: &ty::TypeAndMut<'tcx>)
+ -> ty::TypeAndMut<'tcx> {
+ ty::TypeAndMut {ty: mt.ty.fold_with(this),
mutbl: mt.mutbl}
}
(&ty::TyInfer(_), _) |
(_, &ty::TyInfer(_)) => {
- Err(ty::terr_sorts(ty_relate::expected_found(self, &a, &b)))
+ Err(ty::TypeError::Sorts(ty_relate::expected_found(self, &a, &b)))
}
(&ty::TyError, _) | (_, &ty::TyError) => {
//! type equality, etc.
use middle::subst::{ErasedRegions, NonerasedRegions, ParamSpace, Substs};
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, TypeError};
use middle::ty_fold::TypeFoldable;
use std::rc::Rc;
use syntax::abi;
use syntax::ast;
-pub type RelateResult<'tcx, T> = Result<T, ty::type_err<'tcx>>;
+pub type RelateResult<'tcx, T> = Result<T, ty::TypeError<'tcx>>;
#[derive(Clone, Debug)]
pub enum Cause {
///////////////////////////////////////////////////////////////////////////
// Relate impls
-impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::mt<'tcx> {
+impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::TypeAndMut<'tcx> {
fn relate<R>(relation: &mut R,
- a: &ty::mt<'tcx>,
- b: &ty::mt<'tcx>)
- -> RelateResult<'tcx, ty::mt<'tcx>>
+ a: &ty::TypeAndMut<'tcx>,
+ b: &ty::TypeAndMut<'tcx>)
+ -> RelateResult<'tcx, ty::TypeAndMut<'tcx>>
where R: TypeRelation<'a,'tcx>
{
debug!("{}.mts({:?}, {:?})",
a,
b);
if a.mutbl != b.mutbl {
- Err(ty::terr_mutability)
+ Err(TypeError::Mutability)
} else {
let mutbl = a.mutbl;
let variance = match mutbl {
ast::MutMutable => ty::Invariant,
};
let ty = try!(relation.relate_with_variance(variance, &a.ty, &b.ty));
- Ok(ty::mt {ty: ty, mutbl: mutbl})
+ Ok(ty::TypeAndMut {ty: ty, mutbl: mutbl})
}
}
}
where R: TypeRelation<'a,'tcx>
{
if a_tys.len() != b_tys.len() {
- return Err(ty::terr_ty_param_size(expected_found(relation,
+ return Err(TypeError::TyParamSize(expected_found(relation,
&a_tys.len(),
&b_tys.len())));
}
where R: TypeRelation<'a,'tcx>
{
if a.variadic != b.variadic {
- return Err(ty::terr_variadic_mismatch(
+ return Err(TypeError::VariadicMismatch(
expected_found(relation, &a.variadic, &b.variadic)));
}
(ty::FnDiverging, ty::FnDiverging) =>
Ok(ty::FnDiverging),
(a, b) =>
- Err(ty::terr_convergence_mismatch(
+ Err(TypeError::ConvergenceMismatch(
expected_found(relation, &(a != ty::FnDiverging), &(b != ty::FnDiverging)))),
});
where R: TypeRelation<'a,'tcx>
{
if a_args.len() != b_args.len() {
- return Err(ty::terr_arg_count);
+ return Err(TypeError::ArgCount);
}
a_args.iter().zip(b_args)
where R: TypeRelation<'a,'tcx>
{
if a != b {
- Err(ty::terr_unsafety_mismatch(expected_found(relation, a, b)))
+ Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b)))
} else {
Ok(*a)
}
if a == b {
Ok(*a)
} else {
- Err(ty::terr_abi_mismatch(expected_found(relation, a, b)))
+ Err(TypeError::AbiMismatch(expected_found(relation, a, b)))
}
}
}
where R: TypeRelation<'a,'tcx>
{
if a.item_name != b.item_name {
- Err(ty::terr_projection_name_mismatched(
+ Err(TypeError::ProjectionNameMismatched(
expected_found(relation, &a.item_name, &b.item_name)))
} else {
let trait_ref = try!(relation.relate(&a.trait_ref, &b.trait_ref));
// so we can just iterate through the lists pairwise, so long as they are the
// same length.
if a.len() != b.len() {
- Err(ty::terr_projection_bounds_length(expected_found(relation, &a.len(), &b.len())))
+ Err(TypeError::ProjectionBoundsLength(expected_found(relation, &a.len(), &b.len())))
} else {
a.iter().zip(b)
.map(|(a, b)| relation.relate(a, b))
// Two sets of builtin bounds are only relatable if they are
// precisely the same (but see the coercion code).
if a != b {
- Err(ty::terr_builtin_bounds(expected_found(relation, a, b)))
+ Err(TypeError::BuiltinBoundsMismatch(expected_found(relation, a, b)))
} else {
Ok(*a)
}
{
// Different traits cannot be related
if a.def_id != b.def_id {
- Err(ty::terr_traits(expected_found(relation, &a.def_id, &b.def_id)))
+ Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
} else {
let substs = try!(relate_item_substs(relation, a.def_id, a.substs, b.substs));
Ok(ty::TraitRef { def_id: a.def_id, substs: relation.tcx().mk_substs(substs) })
if sz_a == sz_b {
Ok(tcx.mk_array(t, sz_a))
} else {
- Err(ty::terr_fixed_array_size(expected_found(relation, &sz_a, &sz_b)))
+ Err(TypeError::FixedArraySize(expected_found(relation, &sz_a, &sz_b)))
}
}
.collect::<Result<_, _>>());
Ok(tcx.mk_tup(ts))
} else if !(as_.is_empty() || bs.is_empty()) {
- Err(ty::terr_tuple_size(
+ Err(TypeError::TupleSize(
expected_found(relation, &as_.len(), &bs.len())))
} else {
- Err(ty::terr_sorts(expected_found(relation, &a, &b)))
+ Err(TypeError::Sorts(expected_found(relation, &a, &b)))
}
}
_ =>
{
- Err(ty::terr_sorts(expected_found(relation, &a, &b)))
+ Err(TypeError::Sorts(expected_found(relation, &a, &b)))
}
}
}
pub fn expected_found<'a,'tcx:'a,R,T>(relation: &mut R,
a: &T,
b: &T)
- -> ty::expected_found<T>
+ -> ty::ExpectedFound<T>
where R: TypeRelation<'a,'tcx>, T: Clone
{
expected_found_bool(relation.a_is_expected(), a, b)
pub fn expected_found_bool<T>(a_is_expected: bool,
a: &T,
b: &T)
- -> ty::expected_found<T>
+ -> ty::ExpectedFound<T>
where T: Clone
{
let a = a.clone();
let b = b.clone();
if a_is_expected {
- ty::expected_found {expected: a, found: b}
+ ty::ExpectedFound {expected: a, found: b}
} else {
- ty::expected_found {expected: b, found: a}
+ ty::ExpectedFound {expected: b, found: a}
}
}
use middle::ty::{TyParam, TyRawPtr, TyRef, TyTuple};
use middle::ty::TyClosure;
use middle::ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
-use middle::ty::{self, mt, Ty, HasTypeFlags};
+use middle::ty::{self, TypeAndMut, Ty, HasTypeFlags};
use middle::ty_fold::{self, TypeFoldable};
use std::fmt;
}
}
-impl<'tcx> fmt::Display for ty::mt<'tcx> {
+impl<'tcx> fmt::Display for ty::TypeAndMut<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}{}",
if self.mutbl == ast::MutMutable { "mut " } else { "" },
--- /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.
+
+use target::Target;
+
+pub fn target() -> Target {
+ let mut base = super::freebsd_base::opts();
+ base.cpu = "pentium4".to_string();
+ base.pre_link_args.push("-m32".to_string());
+ base.morestack = false;
+
+ Target {
+ data_layout: "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string(),
+ llvm_target: "i686-unknown-freebsd".to_string(),
+ target_endian: "little".to_string(),
+ target_pointer_width: "32".to_string(),
+ arch: "x86".to_string(),
+ target_os: "freebsd".to_string(),
+ target_env: "".to_string(),
+ options: base,
+ }
+}
arm_linux_androideabi,
aarch64_linux_android,
+ i686_unknown_freebsd,
x86_64_unknown_freebsd,
i686_unknown_dragonfly,
let module_path = match view_path.node {
ViewPathSimple(_, ref full_path) => {
full_path.segments
- .init()
+ .split_last().unwrap().1
.iter().map(|ident| ident.identifier.name)
.collect()
}
continue;
}
};
- let module_path = module_path.init();
+ let module_path = module_path.split_last().unwrap().1;
(module_path.to_vec(), name)
}
};
#![feature(rc_weak)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
-#![feature(slice_extras)]
+#![feature(slice_splits)]
#![feature(staged_api)]
#[macro_use] extern crate log;
segments: &[ast::PathSegment],
namespace: Namespace)
-> Option<(Def, LastPrivate)> {
- let module_path = segments.init().iter()
+ let module_path = segments.split_last().unwrap().1.iter()
.map(|ps| ps.identifier.name)
.collect::<Vec<_>>();
segments: &[ast::PathSegment],
namespace: Namespace)
-> Option<(Def, LastPrivate)> {
- let module_path = segments.init().iter()
+ let module_path = segments.split_last().unwrap().1.iter()
.map(|ps| ps.identifier.name)
.collect::<Vec<_>>();
mut path: DiscrField) -> Option<DiscrField> {
match ty.sty {
// Fat &T/&mut T/Box<T> i.e. T is [T], str, or Trait
- ty::TyRef(_, ty::mt { ty, .. }) | ty::TyBox(ty) if !type_is_sized(tcx, ty) => {
+ ty::TyRef(_, ty::TypeAndMut { ty, .. }) | ty::TyBox(ty) if !type_is_sized(tcx, ty) => {
path.push(FAT_PTR_ADDR);
Some(path)
},
assert_eq!(nonzero_fields.len(), 1);
let nonzero_field = tcx.lookup_field_type(did, nonzero_fields[0].id, substs);
match nonzero_field.sty {
- ty::TyRawPtr(ty::mt { ty, .. }) if !type_is_sized(tcx, ty) => {
+ ty::TyRawPtr(ty::TypeAndMut { ty, .. }) if !type_is_sized(tcx, ty) => {
path.push_all(&[0, FAT_PTR_ADDR]);
Some(path)
},
// We can also mark the return value as `dereferenceable` in certain cases
match ret_ty.sty {
// These are not really pointers but pairs, (pointer, len)
- ty::TyRef(_, ty::mt { ty: inner, .. })
+ ty::TyRef(_, ty::TypeAndMut { ty: inner, .. })
| ty::TyBox(inner) if common::type_is_sized(ccx.tcx(), inner) => {
let llret_sz = machine::llsize_of_real(ccx, type_of::type_of(ccx, inner));
attrs.ret(llvm::DereferenceableAttribute(llret_sz));
pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
match ty.sty {
- ty::TyRawPtr(ty::mt{ty, ..}) |
- ty::TyRef(_, ty::mt{ty, ..}) |
+ ty::TyRawPtr(ty::TypeAndMut{ty, ..}) |
+ ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
ty::TyBox(ty) => {
!type_is_sized(cx, ty)
}
let len = unsafe { llvm::LLVMConstIntGetZExtValue(len) as u64 };
let len = match bt.sty {
- ty::TyBox(ty) | ty::TyRef(_, ty::mt{ty, ..}) => match ty.sty {
+ ty::TyBox(ty) | ty::TyRef(_, ty::TypeAndMut{ty, ..}) => match ty.sty {
ty::TyStr => {
assert!(len > 0);
len - 1
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
unique_type_id.push_str(&inner_type_id[..]);
},
- ty::TyRawPtr(ty::mt { ty: inner_type, mutbl } ) => {
+ ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
unique_type_id.push('*');
if mutbl == ast::MutMutable {
unique_type_id.push_str("mut");
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
unique_type_id.push_str(&inner_type_id[..]);
},
- ty::TyRef(_, ty::mt { ty: inner_type, mutbl }) => {
+ ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
unique_type_id.push('&');
if mutbl == ast::MutMutable {
unique_type_id.push_str("mut");
unique_type_id: UniqueTypeId,
span: Span)
-> MetadataCreationResult {
- let data_ptr_type = cx.tcx().mk_ptr(ty::mt {
+ let data_ptr_type = cx.tcx().mk_ptr(ty::TypeAndMut {
ty: element_type,
mutbl: ast::MutImmutable
});
trait_pointer_metadata(cx, t, None, unique_type_id),
false)
}
- ty::TyBox(ty) | ty::TyRawPtr(ty::mt{ty, ..}) | ty::TyRef(_, ty::mt{ty, ..}) => {
+ ty::TyBox(ty) |
+ ty::TyRawPtr(ty::TypeAndMut{ty, ..}) |
+ ty::TyRef(_, ty::TypeAndMut{ty, ..}) => {
match ty.sty {
ty::TySlice(typ) => {
vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)
// Creates MemberDescriptions for the fields of a struct
struct StructMemberDescriptionFactory<'tcx> {
- fields: Vec<ty::field<'tcx>>,
+ fields: Vec<ty::Field<'tcx>>,
is_simd: bool,
span: Span,
}
push_debuginfo_type_name(cx, inner_type, true, output);
output.push('>');
},
- ty::TyRawPtr(ty::mt { ty: inner_type, mutbl } ) => {
+ ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
output.push('*');
match mutbl {
ast::MutImmutable => output.push_str("const "),
push_debuginfo_type_name(cx, inner_type, true, output);
},
- ty::TyRef(_, ty::mt { ty: inner_type, mutbl }) => {
+ ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
output.push('&');
if mutbl == ast::MutMutable {
output.push_str("mut ");
match (&source.ty.sty, &target.ty.sty) {
(&ty::TyBox(a), &ty::TyBox(b)) |
- (&ty::TyRef(_, ty::mt { ty: a, .. }), &ty::TyRef(_, ty::mt { ty: b, .. })) |
- (&ty::TyRef(_, ty::mt { ty: a, .. }), &ty::TyRawPtr(ty::mt { ty: b, .. })) |
- (&ty::TyRawPtr(ty::mt { ty: a, .. }), &ty::TyRawPtr(ty::mt { ty: b, .. })) => {
+ (&ty::TyRef(_, ty::TypeAndMut { ty: a, .. }),
+ &ty::TyRef(_, ty::TypeAndMut { ty: b, .. })) |
+ (&ty::TyRef(_, ty::TypeAndMut { ty: a, .. }),
+ &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) |
+ (&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }),
+ &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => {
let (inner_source, inner_target) = (a, b);
let (base, old_info) = if !type_is_sized(bcx.tcx(), inner_source) {
base: &ast::Expr,
get_idx: F)
-> DatumBlock<'blk, 'tcx, Expr> where
- F: FnOnce(&'blk ty::ctxt<'tcx>, &[ty::field<'tcx>]) -> usize,
+ F: FnOnce(&'blk ty::ctxt<'tcx>, &[ty::Field<'tcx>]) -> usize,
{
let mut bcx = bcx;
let _icx = push_ctxt("trans_rec_field");
node_id_opt: Option<ast::NodeId>,
op: F)
-> R where
- F: FnOnce(ty::Disr, &[ty::field<'tcx>]) -> R,
+ F: FnOnce(ty::Disr, &[ty::Field<'tcx>]) -> R,
{
match ty.sty {
ty::TyStruct(did, substs) => {
ty::TyTuple(ref v) => {
let fields: Vec<_> = v.iter().enumerate().map(|(i, &f)| {
- ty::field {
+ ty::Field {
name: token::intern(&i.to_string()),
- mt: ty::mt {
+ mt: ty::TypeAndMut {
ty: f,
mutbl: ast::MutImmutable
}
}
match (t_in.builtin_deref(true), t_out.builtin_deref(true)) {
- (Some(ty::mt{ ty: t_in, .. }), Some(ty::mt{ ty: t_out, .. })) => {
+ (Some(ty::TypeAndMut{ ty: t_in, .. }), Some(ty::TypeAndMut{ ty: t_out, .. })) => {
t_in == t_out
}
_ => {
}
}
- ty::TyRawPtr(ty::mt { ty: content_ty, .. }) |
- ty::TyRef(_, ty::mt { ty: content_ty, .. }) => {
+ ty::TyRawPtr(ty::TypeAndMut { ty: content_ty, .. }) |
+ ty::TyRef(_, ty::TypeAndMut { ty: content_ty, .. }) => {
if type_is_sized(bcx.tcx(), content_ty) {
let ptr = datum.to_llscalarish(bcx);
}
// Only used for pattern matching.
- ty::TyBox(ty) | ty::TyRef(_, ty::mt{ty, ..}) => {
+ ty::TyBox(ty) | ty::TyRef(_, ty::TypeAndMut{ty, ..}) => {
let inner = if type_is_sized(bcx.tcx(), ty) {
Load(bcx, llval)
} else {
ty::TyUint(t) => Type::uint_from_ty(cx, t),
ty::TyFloat(t) => Type::float_from_ty(cx, t),
- ty::TyBox(ty) | ty::TyRef(_, ty::mt{ty, ..}) | ty::TyRawPtr(ty::mt{ty, ..}) => {
+ ty::TyBox(ty) |
+ ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
+ ty::TyRawPtr(ty::TypeAndMut{ty, ..}) => {
if type_is_sized(cx.tcx(), ty) {
Type::i8p(cx)
} else {
adt::incomplete_type_of(cx, &*repr, "closure")
}
- ty::TyBox(ty) | ty::TyRef(_, ty::mt{ty, ..}) | ty::TyRawPtr(ty::mt{ty, ..}) => {
+ ty::TyBox(ty) |
+ ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
+ ty::TyRawPtr(ty::TypeAndMut{ty, ..}) => {
if !type_is_sized(cx.tcx(), ty) {
if let ty::TyStr = ty.sty {
// This means we get a nicer name in the output (str is always
base_segments.last().unwrap(),
&mut projection_bounds);
- check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS);
+ check_path_args(tcx, base_segments.split_last().unwrap().1, NO_TPS | NO_REGIONS);
trait_ref_to_object_type(this,
rscope,
span,
&[])
}
def::DefTy(did, _) | def::DefStruct(did) => {
- check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS);
+ check_path_args(tcx, base_segments.split_last().unwrap().1, NO_TPS | NO_REGIONS);
ast_path_to_ty(this,
rscope,
span,
}
}
ast::TyPtr(ref mt) => {
- tcx.mk_ptr(ty::mt {
+ tcx.mk_ptr(ty::TypeAndMut {
ty: ast_ty_to_ty(this, rscope, &*mt.ty),
mutbl: mt.mutbl
})
rscope,
ty::ObjectLifetimeDefault::Specific(r));
let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
- tcx.mk_ref(tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
+ tcx.mk_ref(tcx.mk_region(r), ty::TypeAndMut {ty: t, mutbl: mt.mutbl})
}
ast::TyTup(ref fields) => {
let flds = fields.iter()
ty::ByReferenceExplicitSelfCategory(region, mutability) => {
(Some(this.tcx().mk_ref(
this.tcx().mk_region(region),
- ty::mt {
+ ty::TypeAndMut {
ty: self_info.untransformed_self_ty,
mutbl: mutability
})),
// then `x` is assigned a value of type `&M T` where M is the mutability
// and T is the expected type.
let region_var = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
- let mt = ty::mt { ty: expected, mutbl: mutbl };
+ let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
let region_ty = tcx.mk_ref(tcx.mk_region(region_var), mt);
// `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
ast::PatRegion(ref inner, mutbl) => {
let inner_ty = fcx.infcx().next_ty_var();
- let mt = ty::mt { ty: inner_ty, mutbl: mutbl };
+ let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
let rptr_ty = tcx.mk_ref(tcx.mk_region(region), mt);
}),
_ => {
let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
- tcx.mk_ref(tcx.mk_region(region), ty::mt {
+ tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
ty: tcx.mk_slice(inner_ty),
mutbl: expected_ty.builtin_deref(true).map(|mt| mt.mutbl)
.unwrap_or(ast::MutImmutable)
let mutbl = expected_ty.builtin_deref(true)
.map_or(ast::MutImmutable, |mt| mt.mutbl);
- let slice_ty = tcx.mk_ref(tcx.mk_region(region), ty::mt {
+ let slice_ty = tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
ty: tcx.mk_slice(inner_ty),
mutbl: mutbl
});
pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
span: Span,
fields: &'tcx [Spanned<ast::FieldPat>],
- struct_fields: &[ty::field<'tcx>],
+ struct_fields: &[ty::Field<'tcx>],
struct_id: ast::DefId,
etc: bool) {
let tcx = pcx.fcx.ccx.tcx;
fn check_ptr_ptr_cast<'a>(&self,
fcx: &FnCtxt<'a, 'tcx>,
- m_expr: &'tcx ty::mt<'tcx>,
- m_cast: &'tcx ty::mt<'tcx>)
+ m_expr: &'tcx ty::TypeAndMut<'tcx>,
+ m_cast: &'tcx ty::TypeAndMut<'tcx>)
-> Result<CastKind, CastError>
{
debug!("check_ptr_ptr_cast m_expr={:?} m_cast={:?}",
fn check_fptr_ptr_cast<'a>(&self,
fcx: &FnCtxt<'a, 'tcx>,
- m_cast: &'tcx ty::mt<'tcx>)
+ m_cast: &'tcx ty::TypeAndMut<'tcx>)
-> Result<CastKind, CastError>
{
// fptr-ptr cast. must be to sized ptr
fn check_ptr_addr_cast<'a>(&self,
fcx: &FnCtxt<'a, 'tcx>,
- m_expr: &'tcx ty::mt<'tcx>)
+ m_expr: &'tcx ty::TypeAndMut<'tcx>)
-> Result<CastKind, CastError>
{
// ptr-addr cast. must be from sized ptr
fn check_ref_cast<'a>(&self,
fcx: &FnCtxt<'a, 'tcx>,
- m_expr: &'tcx ty::mt<'tcx>,
- m_cast: &'tcx ty::mt<'tcx>)
+ m_expr: &'tcx ty::TypeAndMut<'tcx>,
+ m_cast: &'tcx ty::TypeAndMut<'tcx>)
-> Result<CastKind, CastError>
{
// array-ptr-cast.
fn check_addr_ptr_cast<'a>(&self,
fcx: &FnCtxt<'a, 'tcx>,
- m_cast: &'tcx ty::mt<'tcx>)
+ m_cast: &'tcx ty::TypeAndMut<'tcx>)
-> Result<CastKind, CastError>
{
// ptr-addr cast. pointer must be thin.
use middle::traits::{self, ObligationCause};
use middle::traits::{predicate_for_trait_def, report_selection_error};
use middle::ty::{AutoDerefRef, AdjustDerefRef};
-use middle::ty::{self, mt, Ty};
+use middle::ty::{self, TypeAndMut, Ty, TypeError};
use middle::ty_relate::RelateResult;
use util::common::indent;
return None;
}
let ty = self.tcx().mk_ref(r_borrow,
- mt {ty: inner_ty, mutbl: mutbl_b});
+ TypeAndMut {ty: inner_ty, mutbl: mutbl_b});
if let Err(err) = self.subtype(ty, b) {
if first_error.is_none() {
first_error = Some(err);
(u, cu)
} else {
debug!("Missing Unsize or CoerceUnsized traits");
- return Err(ty::terr_mismatch);
+ return Err(TypeError::Mismatch);
};
// Note, we want to avoid unnecessary unsizing. We don't want to coerce to
// Uncertain or unimplemented.
Ok(None) | Err(traits::Unimplemented) => {
debug!("coerce_unsized: early return - can't prove obligation");
- return Err(ty::terr_mismatch);
+ return Err(TypeError::Mismatch);
}
// Object safety violations or miscellaneous.
};
// Check that the types which they point at are compatible.
- let a_unsafe = self.tcx().mk_ptr(ty::mt{ mutbl: mutbl_b, ty: mt_a.ty });
+ let a_unsafe = self.tcx().mk_ptr(ty::TypeAndMut{ mutbl: mutbl_b, ty: mt_a.ty });
try!(self.subtype(a_unsafe, b));
try!(coerce_mutbls(mt_a.mutbl, mutbl_b));
(ast::MutMutable, ast::MutMutable) |
(ast::MutImmutable, ast::MutImmutable) |
(ast::MutMutable, ast::MutImmutable) => Ok(None),
- (ast::MutImmutable, ast::MutMutable) => Err(ty::terr_mutability)
+ (ast::MutImmutable, ast::MutMutable) => Err(TypeError::Mutability)
}
}
ty_a: Ty<'tcx>,
ty_b: Ty<'tcx>,
handle_err: F) where
- F: FnOnce(Span, Ty<'tcx>, Ty<'tcx>, &ty::type_err<'tcx>),
+ F: FnOnce(Span, Ty<'tcx>, Ty<'tcx>, &ty::TypeError<'tcx>),
{
// n.b.: order of actual, expected is reversed
match infer::mk_subty(fcx.infcx(), b_is_expected, infer::Misc(sp),
};
match sig.0.inputs[0].sty {
- ty::TyRef(_, ty::mt {
+ ty::TyRef(_, ty::TypeAndMut {
ty: _,
mutbl: ast::MutMutable,
}) => {}
// Trait method is fn(&self) or fn(&mut self), need an
// autoref. Pull the region etc out of the type of first argument.
match transformed_self_ty.sty {
- ty::TyRef(region, ty::mt { mutbl, ty: _ }) => {
+ ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ }) => {
fcx.write_adjustment(self_expr.id,
ty::AdjustDerefRef(ty::AutoDerefRef {
autoderefs: autoderefs,
let lang_def_id = self.tcx().lang_items.slice_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
- ty::TyRawPtr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => {
+ ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: ast::MutImmutable }) => {
let lang_def_id = self.tcx().lang_items.const_ptr_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
- ty::TyRawPtr(ty::mt { ty: _, mutbl: ast::MutMutable }) => {
+ ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: ast::MutMutable }) => {
let lang_def_id = self.tcx().lang_items.mut_ptr_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
// Search through mutabilities in order to find one where pick works:
[ast::MutImmutable, ast::MutMutable].iter().filter_map(|&m| {
- let autoref_ty = tcx.mk_ref(region, ty::mt {
+ let autoref_ty = tcx.mk_ref(region, ty::TypeAndMut {
ty: step.self_ty,
mutbl: m
});
format!("cast to unsized type: `{}` as `{}`", actual, tstr)
}, t_expr, None);
match t_expr.sty {
- ty::TyRef(_, ty::mt { mutbl: mt, .. }) => {
+ ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => {
let mtstr = match mt {
ast::MutMutable => "mut ",
ast::MutImmutable => ""
origin: infer::TypeOrigin,
sub: Ty<'tcx>,
sup: Ty<'tcx>)
- -> Result<(), ty::type_err<'tcx>> {
+ -> Result<(), ty::TypeError<'tcx>> {
infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
}
origin: infer::TypeOrigin,
sub: Ty<'tcx>,
sup: Ty<'tcx>)
- -> Result<(), ty::type_err<'tcx>> {
+ -> Result<(), ty::TypeError<'tcx>> {
infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
}
sp: Span,
mk_msg: M,
actual_ty: Ty<'tcx>,
- err: Option<&ty::type_err<'tcx>>) where
+ err: Option<&ty::TypeError<'tcx>>) where
M: FnOnce(String) -> String,
{
self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
sp: Span,
e: Ty<'tcx>,
a: Ty<'tcx>,
- err: &ty::type_err<'tcx>) {
+ err: &ty::TypeError<'tcx>) {
self.infcx().report_mismatched_types(sp, e, a, err)
}
pub fn lookup_field_ty(&self,
span: Span,
class_id: ast::DefId,
- items: &[ty::field_ty],
+ items: &[ty::FieldTy],
fieldname: ast::Name,
substs: &subst::Substs<'tcx>)
-> Option<Ty<'tcx>>
pub fn lookup_tup_field_ty(&self,
span: Span,
class_id: ast::DefId,
- items: &[ty::field_ty],
+ items: &[ty::FieldTy],
idx: usize,
substs: &subst::Substs<'tcx>)
-> Option<Ty<'tcx>>
base_expr: Option<&ast::Expr>,
base_ty: Ty<'tcx>,
lvalue_pref: LvaluePreference)
- -> Option<ty::mt<'tcx>>
+ -> Option<ty::TypeAndMut<'tcx>>
{
// Try DerefMut first, if preferred.
let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
method_call: Option<MethodCall>,
method: Option<MethodCallee<'tcx>>)
- -> Option<ty::mt<'tcx>>
+ -> Option<ty::TypeAndMut<'tcx>>
{
match method {
Some(method) => {
class_id: ast::DefId,
node_id: ast::NodeId,
substitutions: &'tcx subst::Substs<'tcx>,
- field_types: &[ty::field_ty],
+ field_types: &[ty::FieldTy],
ast_fields: &'tcx [ast::Field],
check_completeness: bool,
enum_id_opt: Option<ast::DefId>) {
hint,
lvalue_pref);
- let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
+ let tm = ty::TypeAndMut { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
let oprnd_t = if tm.ty.references_error() {
tcx.types.err
} else {
Some((opt_self_ty, &path.segments, path_res.base_def))
} else {
let mut def = path_res.base_def;
- let ty_segments = path.segments.init();
+ let ty_segments = path.segments.split_last().unwrap().1;
let base_ty_end = path.segments.len() - path_res.depth;
let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, span,
PathParamMode::Optional,
"offset" | "arith_offset" => {
(1,
vec!(
- tcx.mk_ptr(ty::mt {
+ tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0),
mutbl: ast::MutImmutable
}),
ccx.tcx.types.isize
),
- tcx.mk_ptr(ty::mt {
+ tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0),
mutbl: ast::MutImmutable
}))
"copy" | "copy_nonoverlapping" => {
(1,
vec!(
- tcx.mk_ptr(ty::mt {
+ tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0),
mutbl: ast::MutImmutable
}),
- tcx.mk_ptr(ty::mt {
+ tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0),
mutbl: ast::MutMutable
}),
"volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
(1,
vec!(
- tcx.mk_ptr(ty::mt {
+ tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0),
mutbl: ast::MutMutable
}),
- tcx.mk_ptr(ty::mt {
+ tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0),
mutbl: ast::MutImmutable
}),
"write_bytes" | "volatile_set_memory" => {
(1,
vec!(
- tcx.mk_ptr(ty::mt {
+ tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0),
mutbl: ast::MutMutable
}),
}
// For DST, all intermediate types must be sized.
- if !variant.fields.is_empty() {
- for field in variant.fields.init() {
+ if let Some((_, fields)) = variant.fields.split_last() {
+ for field in fields {
fcx.register_builtin_bound(
field.ty,
ty::BoundSized,
reason: reason }
}
- fn report_error(&self, e: infer::fixup_err) {
+ fn report_error(&self, e: infer::FixupError) {
self.writeback_errors.set(true);
if !self.tcx.sess.has_errors() {
match self.reason {
let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env), true);
- let check_mutbl = |mt_a: ty::mt<'tcx>, mt_b: ty::mt<'tcx>,
+ let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>,
mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| {
if (mt_a.mutbl, mt_b.mutbl) == (ast::MutImmutable, ast::MutMutable) {
infcx.report_mismatched_types(span, mk_ptr(mt_b.ty),
- target, &ty::terr_mutability);
+ target, &ty::TypeError::Mutability);
}
(mt_a.ty, mt_b.ty, unsize_trait, None)
};
"[T]",
item.span);
}
- ty::TyRawPtr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => {
+ ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: ast::MutImmutable }) => {
self.check_primitive_impl(def_id,
self.tcx.lang_items.const_ptr_impl(),
"const_ptr",
"*const T",
item.span);
}
- ty::TyRawPtr(ty::mt { ty: _, mutbl: ast::MutMutable }) => {
+ ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: ast::MutMutable }) => {
self.check_primitive_impl(def_id,
self.tcx.lang_items.mut_ptr_impl(),
"mut_ptr",
struct_predicates: &ty::GenericPredicates<'tcx>,
v: &ast::StructField,
origin: ast::DefId)
- -> ty::field_ty
+ -> ty::FieldTy
{
let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &*v.node.ty);
write_ty_to_tcx(ccx.tcx, v.node.id, tt);
match v.node.kind {
ast::NamedField(ident, visibility) => {
- ty::field_ty {
+ ty::FieldTy {
name: ident.name,
id: local_def(v.node.id),
vis: visibility,
}
}
ast::UnnamedField(visibility) => {
- ty::field_ty {
+ ty::FieldTy {
name: special_idents::unnamed_field.name,
id: local_def(v.node.id),
vis: visibility,
#![feature(ref_slice)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
-#![feature(slice_extras)]
+#![feature(slice_splits)]
#![feature(staged_api)]
#![feature(vec_push_all)]
#![feature(cell_extras)]
/// appearing in a context with ambient variance `variance`
fn add_constraints_from_mt(&mut self,
generics: &ty::Generics<'tcx>,
- mt: &ty::mt<'tcx>,
+ mt: &ty::TypeAndMut<'tcx>,
variance: VarianceTermPtr<'a>) {
match mt.mutbl {
ast::MutMutable => {
}
}
-impl Clean<Item> for ty::field_ty {
+impl Clean<Item> for ty::FieldTy {
fn clean(&self, cx: &DocContext) -> Item {
use syntax::parse::token::special_idents::unnamed_field;
use rustc::metadata::csearch;
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
- placeholder="Click or press 'S' to search, '?' for more options..."
+ placeholder="Click or press ‘S’ to search, ‘?’ for more options…"
type="search">
</div>
</form>
<div id="help" class="hidden">
<div class="shortcuts">
- <h1>Keyboard shortcuts</h1>
+ <h1>Keyboard Shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
</dl>
</div>
<div class="infos">
- <h1>Search tricks</h1>
+ <h1>Search Tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
#help {
background: #e9e9e9;
- border-radius: 4px;
box-shadow: 0 0 6px rgba(0,0,0,.2);
position: absolute;
top: 300px;
#help dt {
float: left;
- border-radius: 3px;
+ border-radius: 4px;
border: 1px solid #bfbfbf;
background: #fff;
width: 23px;
highlightSourceLines(null);
$(window).on('hashchange', highlightSourceLines);
- // Helper function for Keyboard events,
- // Get's the char from the keypress event
+ // Gets the human-readable string for the virtual-key code of the
+ // given KeyboardEvent, ev.
//
- // This method is used because e.wich === x is not
- // compatible with non-english keyboard layouts
+ // This function is meant as a polyfill for KeyboardEvent#key,
+ // since it is not supported in Trident. We also test for
+ // KeyboardEvent#keyCode because the handleShortcut handler is
+ // also registered for the keydown event, because Blink doesn't fire
+ // keypress on hitting the Escape key.
//
- // Note: event.type must be keypress !
- function getChar(event) {
- if (event.which == null) {
- return String.fromCharCode(event.keyCode) // IE
- } else if (event.which!=0 && event.charCode!=0) {
- return String.fromCharCode(event.which) // the rest
- } else {
- return null // special key
- }
+ // So I guess you could say things are getting pretty interoperable.
+ function getVirtualKey(ev) {
+ if ("key" in ev && typeof ev.key != "undefined")
+ return ev.key;
+
+ var c = ev.charCode || ev.keyCode;
+ if (c == 27)
+ return "Escape";
+ return String.fromCharCode(c);
}
- $(document).on('keypress', function handleKeyboardShortcut(e) {
- if (document.activeElement.tagName === 'INPUT') {
+ function handleShortcut(ev) {
+ if (document.activeElement.tagName == "INPUT")
return;
- }
- if (getChar(e) === '?') {
- if (e.shiftKey && $('#help').hasClass('hidden')) {
- e.preventDefault();
- $('#help').removeClass('hidden');
+ switch (getVirtualKey(ev)) {
+ case "Escape":
+ if (!$("#help").hasClass("hidden")) {
+ ev.preventDefault();
+ $("#help").addClass("hidden");
+ } else if (!$("#search").hasClass("hidden")) {
+ ev.preventDefault();
+ $("#search").addClass("hidden");
+ $("#main").removeClass("hidden");
}
- } else if (getChar(e) === 's' || getChar(e) === 'S') {
- e.preventDefault();
- $('.search-input').focus();
- }
- }).on('keydown', function(e) {
- // The escape key event has to be captured with the keydown event.
- // Because keypressed has no keycode for the escape key
- // (and other special keys in general)...
- if (document.activeElement.tagName === 'INPUT') {
- return;
- }
-
- if (e.keyCode === 27) { // escape key
- if (!$('#help').hasClass('hidden')) {
- e.preventDefault();
- $('#help').addClass('hidden');
- } else if (!$('#search').hasClass('hidden')) {
- e.preventDefault();
- $('#search').addClass('hidden');
- $('#main').removeClass('hidden');
+ break;
+
+ case "s":
+ case "S":
+ ev.preventDefault();
+ $(".search-input").focus();
+ break;
+
+ case "?":
+ if (ev.shiftKey && $("#help").hasClass("hidden")) {
+ ev.preventDefault();
+ $("#help").removeClass("hidden");
}
+ break;
}
- }).on('click', function(e) {
- if (!$(e.target).closest('#help').length) {
- $('#help').addClass('hidden');
+ }
+
+ $(document).on("keypress", handleShortcut);
+ $(document).on("keydown", handleShortcut);
+ $(document).on("click", function(ev) {
+ if (!$(ev.target).closest("#help").length) {
+ $("#help").addClass("hidden");
}
});
-
$('.version-selector').on('change', function() {
var i, match,
url = document.location.href,
document.location.href = url;
});
+
/**
* A function to compute the Levenshtein distance between two strings
* Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
return;
}
- var elements = document.querySelectorAll('pre.rust');
+ var featureRegexp = new RegExp('^\s*#!\\[feature\\(\.*?\\)\\]');
+ var elements = document.querySelectorAll('pre.rust-example-rendered');
Array.prototype.forEach.call(elements, function(el) {
el.onmouseover = function(e) {
a.setAttribute('class', 'test-arrow');
var code = el.previousElementSibling.textContent;
+
+ var channel = '';
+ if (featureRegexp.test(code)) {
+ channel = '&version=nightly';
+ }
+
a.setAttribute('href', window.playgroundUrl + '?code=' +
- encodeURIComponent(code));
+ encodeURIComponent(code) + channel);
a.setAttribute('target', '_blank');
el.appendChild(a);
#![feature(path_relative_from)]
#![feature(rustc_private)]
#![feature(set_stdio)]
-#![feature(slice_extras)]
#![feature(slice_patterns)]
#![feature(staged_api)]
#![feature(subslice_offset)]
}
pub fn main_args(args: &[String]) -> isize {
- let matches = match getopts::getopts(args.tail(), &opts()) {
+ let matches = match getopts::getopts(&args[1..], &opts()) {
Ok(m) => m,
Err(err) => {
println!("{}", err);
if !lines.is_empty() {
let mut unindented = vec![ lines[0].trim().to_string() ];
- unindented.push_all(&lines.tail().iter().map(|&line| {
+ unindented.push_all(&lines[1..].iter().map(|&line| {
if line.chars().all(|c| c.is_whitespace()) {
line.to_string()
} else {
// except according to those terms.
//! A fixed-size array is denoted `[T; N]` for the element type `T` and
-//! the compile time constant size `N`. The size should be zero or positive.
+//! the compile time constant size `N`. The size must be zero or positive.
//!
//! Arrays values are created either with an explicit expression that lists
//! each element: `[x, y, z]` or a repeat expression: `[x; N]`. The repeat
//!
//! [slice]: primitive.slice.html
//!
-//! ## Examples
+//! Rust does not currently support generics over the size of an array type.
+//!
+//! # Examples
//!
//! ```
//! let mut array: [i32; 3] = [0; 3];
//!
//! ```
//!
-//! Rust does not currently support generics over the size of an array type.
-//!
#![doc(primitive = "array")]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use ascii;
use borrow::{Cow, ToOwned, Borrow};
use boxed::Box;
use clone::Clone;
use convert::{Into, From};
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use error::Error;
-use fmt;
+use fmt::{self, Write};
use io;
use iter::Iterator;
use libc;
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for CString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Debug::fmt(&String::from_utf8_lossy(self.as_bytes()), f)
+ fmt::Debug::fmt(&**self, f)
+ }
+}
+
+#[stable(feature = "cstr_debug", since = "1.3.0")]
+impl fmt::Debug for CStr {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(f, "\""));
+ for byte in self.to_bytes().iter().flat_map(|&b| ascii::escape_default(b)) {
+ try!(f.write_char(byte as char));
+ }
+ write!(f, "\"")
}
}
#[test]
fn formatted() {
- let s = CString::new(&b"12"[..]).unwrap();
- assert_eq!(format!("{:?}", s), "\"12\"");
+ let s = CString::new(&b"abc\x01\x02\n\xE2\x80\xA6\xFF"[..]).unwrap();
+ assert_eq!(format!("{:?}", s), r#""abc\x01\x02\n\xe2\x80\xa6\xff""#);
}
#[test]
/// will be extended to `size` and have all of the intermediate data filled
/// in with 0s.
///
+ /// # Errors
+ ///
+ /// This function will return an error if the file is not opened for writing.
+ ///
/// # Examples
///
/// ```no_run
/// use std::fs::File;
///
/// # fn foo() -> std::io::Result<()> {
- /// let mut f = try!(File::open("foo.txt"));
- /// try!(f.set_len(0));
+ /// let mut f = try!(File::create("foo.txt"));
+ /// try!(f.set_len(10));
/// # Ok(())
/// # }
/// ```
use io::{self, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom};
use ptr;
-/// Wraps a `Read` and buffers input from it.
+/// The `BufReader` struct adds buffering to any reader.
///
/// It can be excessively inefficient to work directly with a `Read` instance.
/// For example, every call to `read` on `TcpStream` results in a system call.
///
/// # Examples
///
-/// ```no_run
+/// ```
/// use std::io::prelude::*;
/// use std::io::BufReader;
/// use std::fs::File;
impl<R: Read> BufReader<R> {
/// Creates a new `BufReader` with a default buffer capacity.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::io::BufReader;
+ /// use std::fs::File;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut f = try!(File::open("log.txt"));
+ /// let mut reader = BufReader::new(f);
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: R) -> BufReader<R> {
BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
}
/// Creates a new `BufReader` with the specified buffer capacity.
+ ///
+ /// # Examples
+ ///
+ /// Creating a buffer with ten bytes of capacity:
+ ///
+ /// ```
+ /// use std::io::BufReader;
+ /// use std::fs::File;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut f = try!(File::open("log.txt"));
+ /// let mut reader = BufReader::with_capacity(10, f);
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
BufReader {
}
/// Gets a reference to the underlying reader.
+ ///
+ /// It is inadvisable to directly read from the underlying reader.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::io::BufReader;
+ /// use std::fs::File;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut f1 = try!(File::open("log.txt"));
+ /// let mut reader = BufReader::new(f1);
+ ///
+ /// let f2 = reader.get_ref();
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &R { &self.inner }
/// Gets a mutable reference to the underlying reader.
///
- /// # Warning
- ///
/// It is inadvisable to directly read from the underlying reader.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::io::BufReader;
+ /// use std::fs::File;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut f1 = try!(File::open("log.txt"));
+ /// let mut reader = BufReader::new(f1);
+ ///
+ /// let f2 = reader.get_mut();
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
/// Unwraps this `BufReader`, returning the underlying reader.
///
/// Note that any leftover data in the internal buffer is lost.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::io::BufReader;
+ /// use std::fs::File;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut f1 = try!(File::open("log.txt"));
+ /// let mut reader = BufReader::new(f1);
+ ///
+ /// let f2 = reader.into_inner();
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> R { self.inner }
}
use result;
use sys;
-/// A type for results generated by I/O related functions where the `Err` type
-/// is hard-wired to `io::Error`.
+/// A specialized [`Result`][result] type for I/O operations.
+///
+/// [result]: ../result/enum.Result.html
+///
+/// This type is broadly used across `std::io` for any operation which may
+/// produce an error.
///
/// This typedef is generally used to avoid writing out `io::Error` directly and
-/// is otherwise a direct mapping to `std::result::Result`.
+/// is otherwise a direct mapping to `Result`.
+///
+/// While usual Rust style is to import types directly, aliases of `Result`
+/// often are not, to make it easier to distinguish between them. `Result` is
+/// generally assumed to be `std::result::Result`, and so users of this alias
+/// will generally use `io::Result` instead of shadowing the prelude's import
+/// of `std::result::Result`.
+///
+/// # Examples
+///
+/// A convenience function that bubbles an `io::Result` to its caller:
+///
+/// ```
+/// use std::io;
+///
+/// fn get_string() -> io::Result<String> {
+/// let mut buffer = String::new();
+///
+/// try!(io::stdin().read_line(&mut buffer));
+///
+/// Ok(buffer)
+/// }
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub type Result<T> = result::Result<T, Error>;
//! # #![allow(unused_imports)]
//! use std::io::prelude::*;
//! ```
-//!
-//! This module contains reexports of many core I/O traits such as `Read`,
-//! `Write` and `BufRead`. Structures and functions are not
-//! contained in this module.
#![stable(feature = "rust1", since = "1.0.0")]
inner: MutexGuard<'a, BufReader<Maybe<StdinRaw>>>,
}
-/// Creates a new handle to the global standard input stream of this process.
+/// Constructs a new handle to the standard input of the current process.
///
-/// The handle returned refers to a globally shared buffer between all threads.
-/// Access is synchronized and can be explicitly controlled with the `lock()`
-/// method.
+/// Each handle returned is a reference to a shared global buffer whose access
+/// is synchronized via a mutex. If you need more explicit control over
+/// locking, see the [lock() method][lock].
+///
+/// [lock]: struct.Stdin.html#method.lock
+///
+/// # Examples
+///
+/// Using implicit synchronization:
+///
+/// ```
+/// use std::io::{self, Read};
+///
+/// # fn foo() -> io::Result<String> {
+/// let mut buffer = String::new();
+/// try!(io::stdin().read_to_string(&mut buffer));
+/// # Ok(buffer)
+/// # }
+/// ```
+///
+/// Using explicit synchronization:
///
-/// The `Read` trait is implemented for the returned value but the `BufRead`
-/// trait is not due to the global nature of the standard input stream. The
-/// locked version, `StdinLock`, implements both `Read` and `BufRead`, however.
+/// ```
+/// use std::io::{self, Read};
+///
+/// # fn foo() -> io::Result<String> {
+/// let mut buffer = String::new();
+/// let stdin = io::stdin();
+/// let mut handle = stdin.lock();
+///
+/// try!(handle.read_to_string(&mut buffer));
+/// # Ok(buffer)
+/// # }
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdin() -> Stdin {
static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new(stdin_init);
inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>,
}
-/// Constructs a new reference to the standard output of the current process.
+/// Constructs a new handle to the standard output of the current process.
///
/// Each handle returned is a reference to a shared global buffer whose access
-/// is synchronized via a mutex. Explicit control over synchronization is
-/// provided via the `lock` method.
+/// is synchronized via a mutex. If you need more explicit control over
+/// locking, see the [lock() method][lock].
+///
+/// [lock]: struct.Stdout.html#method.lock
+///
+/// # Examples
+///
+/// Using implicit synchronization:
+///
+/// ```
+/// use std::io::{self, Write};
+///
+/// # fn foo() -> io::Result<()> {
+/// try!(io::stdout().write(b"hello world"));
///
-/// The returned handle implements the `Write` trait.
+/// # Ok(())
+/// # }
+/// ```
+///
+/// Using explicit synchronization:
+///
+/// ```
+/// use std::io::{self, Write};
+///
+/// # fn foo() -> io::Result<()> {
+/// let stdout = io::stdout();
+/// let mut handle = stdout.lock();
+///
+/// try!(handle.write(b"hello world"));
+///
+/// # Ok(())
+/// # }
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdout() -> Stdout {
static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>
inner: ReentrantMutexGuard<'a, RefCell<Maybe<StderrRaw>>>,
}
-/// Constructs a new reference to the standard error stream of a process.
+/// Constructs a new handle to the standard error of the current process.
+///
+/// This handle is not buffered.
+///
+/// # Examples
+///
+/// Using implicit synchronization:
+///
+/// ```
+/// use std::io::{self, Write};
+///
+/// # fn foo() -> io::Result<()> {
+/// try!(io::stderr().write(b"hello world"));
+///
+/// # Ok(())
+/// # }
+/// ```
+///
+/// Using explicit synchronization:
+///
+/// ```
+/// use std::io::{self, Write};
+///
+/// # fn foo() -> io::Result<()> {
+/// let stderr = io::stderr();
+/// let mut handle = stderr.lock();
///
-/// Each returned handle is synchronized amongst all other handles created from
-/// this function. No handles are buffered, however.
+/// try!(handle.write(b"hello world"));
///
-/// The returned handle implements the `Write` trait.
+/// # Ok(())
+/// # }
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stderr() -> Stderr {
static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new(stderr_init);
/// This function will return an error immediately if any call to `read` or
/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
/// handled by this function and the underlying operation is retried.
+///
+/// # Examples
+///
+/// ```
+/// use std::io;
+///
+/// # fn foo() -> io::Result<()> {
+/// let mut reader: &[u8] = b"hello";
+/// let mut writer: Vec<u8> = vec![];
+///
+/// try!(io::copy(&mut reader, &mut writer));
+///
+/// assert_eq!(reader, &writer[..]);
+/// # Ok(())
+/// # }
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: Read, W: Write>(reader: &mut R, writer: &mut W) -> io::Result<u64> {
let mut buf = [0; super::DEFAULT_BUF_SIZE];
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty { _priv: () }
-/// Creates an instance of an empty reader.
+/// Constructs a new handle to an empty reader.
///
/// All reads from the returned reader will return `Ok(0)`.
+///
+/// # Examples
+///
+/// A slightly sad example of not reading anything into a buffer:
+///
+/// ```
+/// use std::io;
+/// use std::io::Read;
+///
+/// # fn foo() -> io::Result<String> {
+/// let mut buffer = String::new();
+/// try!(io::empty().read_to_string(&mut buffer));
+/// # Ok(buffer)
+/// # }
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn empty() -> Empty { Empty { _priv: () } }
asm!("movl $$0x48+90*4, %eax
movl $0, %gs:(%eax)" :: "r"(limit) : "eax" : "volatile")
}
- #[cfg(all(target_arch = "x86",
- any(target_os = "linux", target_os = "freebsd")))]
+ #[cfg(all(target_arch = "x86", target_os = "linux"))]
#[inline(always)]
unsafe fn target_record_sp_limit(limit: usize) {
asm!("movl $0, %gs:48" :: "r"(limit) :: "volatile")
// aarch64 - FIXME(AARCH64): missing...
// powerpc - FIXME(POWERPC): missing...
// arm-ios - iOS segmented stack is disabled for now, see related notes
- // openbsd - segmented stack is disabled
+ // openbsd/bitrig/netbsd - no segmented stacks.
+ // x86-freebsd - no segmented stacks.
#[cfg(any(target_arch = "aarch64",
target_arch = "powerpc",
all(target_arch = "arm", target_os = "ios"),
+ all(target_arch = "x86", target_os = "freebsd"),
target_os = "bitrig",
target_os = "netbsd",
target_os = "openbsd"))]
movl %gs:(%eax), $0" : "=r"(limit) :: "eax" : "volatile");
return limit;
}
- #[cfg(all(target_arch = "x86",
- any(target_os = "linux", target_os = "freebsd")))]
+ #[cfg(all(target_arch = "x86", target_os = "linux"))]
#[inline(always)]
unsafe fn target_get_sp_limit() -> usize {
let limit;
// aarch64 - FIXME(AARCH64): missing...
// powerpc - FIXME(POWERPC): missing...
- // arm-ios - iOS doesn't support segmented stacks yet.
- // openbsd - OpenBSD doesn't support segmented stacks.
+ // arm-ios - no segmented stacks.
+ // openbsd/bitrig/netbsd - no segmented stacks.
+ // x86-freebsd - no segmented stacks..
//
// This function might be called by runtime though
// so it is unsafe to unreachable, let's return a fixed constant.
#[cfg(any(target_arch = "aarch64",
target_arch = "powerpc",
all(target_arch = "arm", target_os = "ios"),
+ all(target_arch = "x86", target_os = "freebsd"),
target_os = "bitrig",
target_os = "netbsd",
target_os = "openbsd"))]
readlink(&p).ok()
}
- #[cfg(not(target_os = "linux"))]
+ #[cfg(target_os = "macos")]
+ fn get_path(fd: c_int) -> Option<PathBuf> {
+ let mut buf = vec![0;libc::PATH_MAX as usize];
+ let n = unsafe { libc::fcntl(fd, libc::F_GETPATH, buf.as_ptr()) };
+ if n == -1 {
+ return None;
+ }
+ let l = buf.iter().position(|&c| c == 0).unwrap();
+ buf.truncate(l as usize);
+ Some(PathBuf::from(OsString::from_vec(buf)))
+ }
+
+ #[cfg(not(any(target_os = "linux", target_os = "macos")))]
fn get_path(_fd: c_int) -> Option<PathBuf> {
// FIXME(#24570): implement this for other Unix platforms
None
}
- #[cfg(target_os = "linux")]
+ #[cfg(any(target_os = "linux", target_os = "macos"))]
fn get_mode(fd: c_int) -> Option<(bool, bool)> {
let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) };
if mode == -1 {
}
}
- #[cfg(not(target_os = "linux"))]
+ #[cfg(not(any(target_os = "linux", target_os = "macos")))]
fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
// FIXME(#24570): implement this for other Unix platforms
None
pub const ERROR_NO_MORE_FILES: libc::DWORD = 18;
pub const TOKEN_READ: libc::DWORD = 0x20008;
pub const FILE_FLAG_OPEN_REPARSE_POINT: libc::DWORD = 0x00200000;
+pub const FILE_FLAG_BACKUP_SEMANTICS: libc::DWORD = 0x02000000;
pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;
pub const FSCTL_GET_REPARSE_POINT: libc::DWORD = 0x900a8;
pub const IO_REPARSE_TAG_SYMLINK: libc::DWORD = 0xa000000c;
+pub const IO_REPARSE_TAG_MOUNT_POINT: libc::DWORD = 0xa0000003;
+pub const FSCTL_SET_REPARSE_POINT: libc::DWORD = 0x900a4;
+pub const FSCTL_DELETE_REPARSE_POINT: libc::DWORD = 0x900ac;
pub const SYMBOLIC_LINK_FLAG_DIRECTORY: libc::DWORD = 0x1;
pub const PROGRESS_STOP: libc::DWORD = 2;
pub const PROGRESS_QUIET: libc::DWORD = 3;
+pub const TOKEN_ADJUST_PRIVILEGES: libc::DWORD = 0x0020;
+pub const SE_PRIVILEGE_ENABLED: libc::DWORD = 2;
+
#[repr(C)]
#[cfg(target_arch = "x86")]
pub struct WSADATA {
};
pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: 0 as *mut _ };
+#[repr(C)]
+pub struct LUID {
+ pub LowPart: libc::DWORD,
+ pub HighPart: libc::c_long,
+}
+
+pub type PLUID = *mut LUID;
+
+#[repr(C)]
+pub struct TOKEN_PRIVILEGES {
+ pub PrivilegeCount: libc::DWORD,
+ pub Privileges: [LUID_AND_ATTRIBUTES; 1],
+}
+
+pub type PTOKEN_PRIVILEGES = *mut TOKEN_PRIVILEGES;
+
+#[repr(C)]
+pub struct LUID_AND_ATTRIBUTES {
+ pub Luid: LUID,
+ pub Attributes: libc::DWORD,
+}
+
+#[repr(C)]
+pub struct REPARSE_MOUNTPOINT_DATA_BUFFER {
+ pub ReparseTag: libc::DWORD,
+ pub ReparseDataLength: libc::DWORD,
+ pub Reserved: libc::WORD,
+ pub ReparseTargetLength: libc::WORD,
+ pub ReparseTargetMaximumLength: libc::WORD,
+ pub Reserved1: libc::WORD,
+ pub ReparseTarget: libc::WCHAR,
+}
+
+
#[link(name = "ws2_32")]
#[link(name = "userenv")]
extern "system" {
lpData: libc::LPVOID,
pbCancel: LPBOOL,
dwCopyFlags: libc::DWORD) -> libc::BOOL;
+ pub fn LookupPrivilegeValueW(lpSystemName: libc::LPCWSTR,
+ lpName: libc::LPCWSTR,
+ lpLuid: PLUID) -> libc::BOOL;
+ pub fn AdjustTokenPrivileges(TokenHandle: libc::HANDLE,
+ DisableAllPrivileges: libc::BOOL,
+ NewState: PTOKEN_PRIVILEGES,
+ BufferLength: libc::DWORD,
+ PreviousState: PTOKEN_PRIVILEGES,
+ ReturnLength: *mut libc::DWORD) -> libc::BOOL;
}
// Functions that aren't available on Windows XP, but we still use them and just
pub struct FileAttr {
data: c::WIN32_FILE_ATTRIBUTE_DATA,
- is_symlink: bool,
+ reparse_tag: libc::DWORD,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum FileType {
- Dir, File, Symlink, ReparsePoint
+ Dir, File, Symlink, ReparsePoint, MountPoint,
}
pub struct ReadDir {
pub fn file_type(&self) -> io::Result<FileType> {
Ok(FileType::new(self.data.dwFileAttributes,
- self.data.dwReserved0 == c::IO_REPARSE_TAG_SYMLINK))
+ /* reparse_tag = */ self.data.dwReserved0))
}
pub fn metadata(&self) -> io::Result<FileAttr> {
nFileSizeHigh: self.data.nFileSizeHigh,
nFileSizeLow: self.data.nFileSizeLow,
},
- is_symlink: self.data.dwReserved0 == c::IO_REPARSE_TAG_SYMLINK,
+ reparse_tag: self.data.dwReserved0,
})
}
}
}
impl File {
- fn open_reparse_point(path: &Path) -> io::Result<File> {
+ fn open_reparse_point(path: &Path, write: bool) -> io::Result<File> {
let mut opts = OpenOptions::new();
- opts.read(true);
- opts.flags_and_attributes(c::FILE_FLAG_OPEN_REPARSE_POINT);
+ opts.read(!write);
+ opts.write(write);
+ opts.flags_and_attributes(c::FILE_FLAG_OPEN_REPARSE_POINT |
+ c::FILE_FLAG_BACKUP_SEMANTICS);
File::open(path, &opts)
}
nFileSizeHigh: info.nFileSizeHigh,
nFileSizeLow: info.nFileSizeLow,
},
- is_symlink: false,
+ reparse_tag: 0,
};
if attr.is_reparse_point() {
- attr.is_symlink = self.is_symlink();
+ let mut b = [0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ if let Ok((_, buf)) = self.reparse_point(&mut b) {
+ attr.reparse_tag = buf.ReparseTag;
+ }
}
Ok(attr)
}
pub fn handle(&self) -> &Handle { &self.handle }
- fn is_symlink(&self) -> bool {
- self.readlink().is_ok()
- }
-
- fn readlink(&self) -> io::Result<PathBuf> {
- let mut space = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
- let mut bytes = 0;
-
+ fn reparse_point<'a>(&self,
+ space: &'a mut [u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE])
+ -> io::Result<(libc::DWORD, &'a c::REPARSE_DATA_BUFFER)> {
unsafe {
+ let mut bytes = 0;
try!(cvt({
c::DeviceIoControl(self.handle.raw(),
c::FSCTL_GET_REPARSE_POINT,
&mut bytes,
0 as *mut _)
}));
- let buf: *const c::REPARSE_DATA_BUFFER = space.as_ptr() as *const _;
- if (*buf).ReparseTag != c::IO_REPARSE_TAG_SYMLINK {
- return Err(io::Error::new(io::ErrorKind::Other, "not a symlink"))
- }
+ Ok((bytes, &*(space.as_ptr() as *const c::REPARSE_DATA_BUFFER)))
+ }
+ }
+
+ fn readlink(&self) -> io::Result<PathBuf> {
+ let mut space = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ let (_bytes, buf) = try!(self.reparse_point(&mut space));
+ if buf.ReparseTag != c::IO_REPARSE_TAG_SYMLINK {
+ return Err(io::Error::new(io::ErrorKind::Other, "not a symlink"))
+ }
+
+ unsafe {
let info: *const c::SYMBOLIC_LINK_REPARSE_BUFFER =
- &(*buf).rest as *const _ as *const _;
+ &buf.rest as *const _ as *const _;
let path_buffer = &(*info).PathBuffer as *const _ as *const u16;
let subst_off = (*info).SubstituteNameOffset / 2;
let subst_ptr = path_buffer.offset(subst_off as isize);
pub fn attrs(&self) -> u32 { self.data.dwFileAttributes as u32 }
pub fn file_type(&self) -> FileType {
- FileType::new(self.data.dwFileAttributes, self.is_symlink)
+ FileType::new(self.data.dwFileAttributes, self.reparse_tag)
}
pub fn created(&self) -> u64 { self.to_u64(&self.data.ftCreationTime) }
}
impl FileType {
- fn new(attrs: libc::DWORD, is_symlink: bool) -> FileType {
+ fn new(attrs: libc::DWORD, reparse_tag: libc::DWORD) -> FileType {
if attrs & libc::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
- if is_symlink {
- FileType::Symlink
- } else {
- FileType::ReparsePoint
+ match reparse_tag {
+ c::IO_REPARSE_TAG_SYMLINK => FileType::Symlink,
+ c::IO_REPARSE_TAG_MOUNT_POINT => FileType::MountPoint,
+ _ => FileType::ReparsePoint,
}
} else if attrs & c::FILE_ATTRIBUTE_DIRECTORY != 0 {
FileType::Dir
pub fn is_dir(&self) -> bool { *self == FileType::Dir }
pub fn is_file(&self) -> bool { *self == FileType::File }
- pub fn is_symlink(&self) -> bool { *self == FileType::Symlink }
+ pub fn is_symlink(&self) -> bool {
+ *self == FileType::Symlink || *self == FileType::MountPoint
+ }
}
impl DirBuilder {
}
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
- let file = try!(File::open_reparse_point(p));
+ let file = try!(File::open_reparse_point(p, false));
file.readlink()
}
pub fn stat(p: &Path) -> io::Result<FileAttr> {
let attr = try!(lstat(p));
- if attr.data.dwFileAttributes & libc::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
- let opts = OpenOptions::new();
+
+ // If this is a reparse point, then we need to reopen the file to get the
+ // actual destination. We also pass the FILE_FLAG_BACKUP_SEMANTICS flag to
+ // ensure that we can open directories (this path may be a directory
+ // junction). Once the file is opened we ask the opened handle what its
+ // metadata information is.
+ if attr.is_reparse_point() {
+ let mut opts = OpenOptions::new();
+ opts.flags_and_attributes(c::FILE_FLAG_BACKUP_SEMANTICS);
let file = try!(File::open(p, &opts));
file.file_attr()
} else {
c::GetFileExInfoStandard,
&mut attr.data as *mut _ as *mut _)));
if attr.is_reparse_point() {
- attr.is_symlink = File::open_reparse_point(p).map(|f| {
- f.is_symlink()
- }).unwrap_or(false);
+ attr.reparse_tag = File::open_reparse_point(p, false).and_then(|f| {
+ let mut b = [0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ f.reparse_point(&mut b).map(|(_, b)| b.ReparseTag)
+ }).unwrap_or(0);
}
Ok(attr)
}
}));
Ok(size as u64)
}
+
+#[test]
+fn directory_junctions_are_directories() {
+ use ffi::OsStr;
+ use env;
+ use rand::{self, StdRng, Rng};
+
+ macro_rules! t {
+ ($e:expr) => (match $e {
+ Ok(e) => e,
+ Err(e) => panic!("{} failed with: {}", stringify!($e), e),
+ })
+ }
+
+ let d = DirBuilder::new();
+ let p = env::temp_dir();
+ let mut r = rand::thread_rng();
+ let ret = p.join(&format!("rust-{}", r.next_u32()));
+ let foo = ret.join("foo");
+ let bar = ret.join("bar");
+ t!(d.mkdir(&ret));
+ t!(d.mkdir(&foo));
+ t!(d.mkdir(&bar));
+
+ t!(create_junction(&bar, &foo));
+ let metadata = stat(&bar);
+ t!(delete_junction(&bar));
+
+ t!(rmdir(&foo));
+ t!(rmdir(&bar));
+ t!(rmdir(&ret));
+
+ let metadata = t!(metadata);
+ assert!(metadata.file_type().is_dir());
+
+ // Creating a directory junction on windows involves dealing with reparse
+ // points and the DeviceIoControl function, and this code is a skeleton of
+ // what can be found here:
+ //
+ // http://www.flexhex.com/docs/articles/hard-links.phtml
+ fn create_junction(src: &Path, dst: &Path) -> io::Result<()> {
+ let f = try!(opendir(src, true));
+ let h = f.handle().raw();
+
+ unsafe {
+ let mut data = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ let mut db = data.as_mut_ptr()
+ as *mut c::REPARSE_MOUNTPOINT_DATA_BUFFER;
+ let mut buf = &mut (*db).ReparseTarget as *mut _;
+ let mut i = 0;
+ let v = br"\??\";
+ let v = v.iter().map(|x| *x as u16);
+ for c in v.chain(dst.as_os_str().encode_wide()) {
+ *buf.offset(i) = c;
+ i += 1;
+ }
+ *buf.offset(i) = 0;
+ i += 1;
+ (*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT;
+ (*db).ReparseTargetMaximumLength = (i * 2) as libc::WORD;
+ (*db).ReparseTargetLength = ((i - 1) * 2) as libc::WORD;
+ (*db).ReparseDataLength =
+ (*db).ReparseTargetLength as libc::DWORD + 12;
+
+ let mut ret = 0;
+ cvt(c::DeviceIoControl(h as *mut _,
+ c::FSCTL_SET_REPARSE_POINT,
+ data.as_ptr() as *mut _,
+ (*db).ReparseDataLength + 8,
+ 0 as *mut _, 0,
+ &mut ret,
+ 0 as *mut _)).map(|_| ())
+ }
+ }
+
+ fn opendir(p: &Path, write: bool) -> io::Result<File> {
+ unsafe {
+ let mut token = 0 as *mut _;
+ let mut tp: c::TOKEN_PRIVILEGES = mem::zeroed();
+ try!(cvt(c::OpenProcessToken(c::GetCurrentProcess(),
+ c::TOKEN_ADJUST_PRIVILEGES,
+ &mut token)));
+ let name: &OsStr = if write {
+ "SeRestorePrivilege".as_ref()
+ } else {
+ "SeBackupPrivilege".as_ref()
+ };
+ let name = name.encode_wide().chain(Some(0)).collect::<Vec<_>>();
+ try!(cvt(c::LookupPrivilegeValueW(0 as *const _,
+ name.as_ptr(),
+ &mut tp.Privileges[0].Luid)));
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Attributes = c::SE_PRIVILEGE_ENABLED;
+ let size = mem::size_of::<c::TOKEN_PRIVILEGES>() as libc::DWORD;
+ try!(cvt(c::AdjustTokenPrivileges(token, libc::FALSE, &mut tp, size,
+ 0 as *mut _, 0 as *mut _)));
+ try!(cvt(libc::CloseHandle(token)));
+
+ File::open_reparse_point(p, write)
+ }
+ }
+
+ fn delete_junction(p: &Path) -> io::Result<()> {
+ unsafe {
+ let f = try!(opendir(p, true));
+ let h = f.handle().raw();
+ let mut data = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ let mut db = data.as_mut_ptr()
+ as *mut c::REPARSE_MOUNTPOINT_DATA_BUFFER;
+ (*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT;
+ let mut bytes = 0;
+ cvt(c::DeviceIoControl(h as *mut _,
+ c::FSCTL_DELETE_REPARSE_POINT,
+ data.as_ptr() as *mut _,
+ (*db).ReparseDataLength + 8,
+ 0 as *mut _, 0,
+ &mut bytes,
+ 0 as *mut _)).map(|_| ())
+ }
+ }
+}
#![feature(rt)]
#![feature(rustc_private)]
#![feature(set_stdio)]
-#![feature(slice_extras)]
#![feature(staged_api)]
extern crate getopts;
// Parses command line arguments into test options
pub fn parse_opts(args: &[String]) -> Option<OptRes> {
- let args_ = args.tail();
+ let args_ = &args[1..];
let matches =
match getopts::getopts(args_, &optgroups()) {
Ok(m) => m,
-Subproject commit 0da191a30ba385215c5eb1dc97c2b5f076f93b07
+Subproject commit c37d3747da75c280237dc2d6b925078e69555499