CFG_LDPATH_armv7-unknown-linux-gnueabihf :=
CFG_RUN_armv7-unknown-linux-gnueabihf=$(2)
CFG_RUN_TARG_armv7-unknown-linux-gnueabihf=$(call CFG_RUN_armv7-unknown-linux-gnueabihf,,$(2))
-RUSTC_FLAGS_armv7-unknown-linux-gnueabihf := -C target-feature=+v7,+vfp2,+neon
+RUSTC_FLAGS_armv7-unknown-linux-gnueabihf :=
RUSTC_CROSS_FLAGS_armv7-unknown-linux-gnueabihf :=
CFG_GNU_TRIPLE_armv7-unknown-linux-gnueabihf := armv7-unknown-linux-gnueabihf
# except according to those terms.
import re
+import os
license_re = re.compile(
u"""(#|//) Copyright .* The Rust Project Developers. See the COPYRIGHT
]
def check_license(name, contents):
+ name = os.path.normpath(name)
# Whitelist check
- if any(name.endswith(e) for e in exceptions):
+ if any(name.endswith(os.path.normpath(e)) for e in exceptions):
return True
# Xfail check
'src/liblibc',
}
- if any(d in dirpath for d in skippable_dirs):
+ dirpath = os.path.normpath(dirpath)
+ if any(os.path.normpath(d) in dirpath for d in skippable_dirs):
continue
file_names = [os.path.join(dirpath, f) for f in filenames
{
/// Borrowed data.
#[stable(feature = "rust1", since = "1.0.0")]
- Borrowed(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a B),
+ Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B),
/// Owned data.
#[stable(feature = "rust1", since = "1.0.0")]
Owned(
- #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] <B as ToOwned>::Owned
+ #[stable(feature = "rust1", since = "1.0.0")] <B as ToOwned>::Owned
),
}
/// A vacant Entry
#[stable(feature = "rust1", since = "1.0.0")]
Vacant(
- #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] VacantEntry<'a, K, V>
+ #[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>
),
/// An occupied Entry
#[stable(feature = "rust1", since = "1.0.0")]
Occupied(
- #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] OccupiedEntry<'a, K, V>
+ #[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>
),
}
/// platforms this is a `*mut *mut T` which is filled in by the compiler and
/// on MSVC it's `*mut [usize; 2]`. For more information see the compiler's
/// source as well as std's catch implementation.
- #[cfg(not(stage0))]
pub fn try(f: fn(*mut u8), data: *mut u8, local_ptr: *mut u8) -> i32;
- #[cfg(stage0)]
- pub fn try(f: fn(*mut u8), data: *mut u8) -> *mut u8;
}
None,
/// Some value `T`
#[stable(feature = "rust1", since = "1.0.0")]
- Some(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] T)
+ Some(#[stable(feature = "rust1", since = "1.0.0")] T)
}
/////////////////////////////////////////////////////////////////////////////
pub enum Result<T, E> {
/// Contains the success value
#[stable(feature = "rust1", since = "1.0.0")]
- Ok(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] T),
+ Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
/// Contains the error value
#[stable(feature = "rust1", since = "1.0.0")]
- Err(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] E)
+ Err(#[stable(feature = "rust1", since = "1.0.0")] E)
}
/////////////////////////////////////////////////////////////////////////////
target_vendor: "unknown".to_string(),
options: TargetOptions {
- features: "+v7,+vfp2,+neon".to_string(),
+ features: "+v7,+vfp3,+neon".to_string(),
cpu: "cortex-a8".to_string(),
.. base
}
let extra_words = self.data.len() - num_words;
self.data.extend((0..extra_words).map(|_| 0));
}
+
+ /// Iterates over indexes of set bits in a sorted order
+ pub fn iter<'a>(&'a self) -> BitVectorIter<'a> {
+ BitVectorIter {
+ iter: self.data.iter(),
+ current: 0,
+ idx: 0
+ }
+ }
+}
+
+pub struct BitVectorIter<'a> {
+ iter: ::std::slice::Iter<'a, u64>,
+ current: u64,
+ idx: usize
+}
+
+impl<'a> Iterator for BitVectorIter<'a> {
+ type Item = usize;
+ fn next(&mut self) -> Option<usize> {
+ while self.current == 0 {
+ self.current = if let Some(&i) = self.iter.next() {
+ if i == 0 {
+ self.idx += 64;
+ continue;
+ } else {
+ self.idx = u64s(self.idx) * 64;
+ i
+ }
+ } else {
+ return None;
+ }
+ }
+ let offset = self.current.trailing_zeros() as usize;
+ self.current >>= offset;
+ self.current >>= 1; // shift otherwise overflows for 0b1000_0000_…_0000
+ self.idx += offset + 1;
+ return Some(self.idx - 1);
+ }
}
/// A "bit matrix" is basically a square matrix of booleans
(word, mask)
}
+#[test]
+fn bitvec_iter_works() {
+ let mut bitvec = BitVector::new(100);
+ bitvec.insert(1);
+ bitvec.insert(10);
+ bitvec.insert(19);
+ bitvec.insert(62);
+ bitvec.insert(63);
+ bitvec.insert(64);
+ bitvec.insert(65);
+ bitvec.insert(66);
+ bitvec.insert(99);
+ assert_eq!(bitvec.iter().collect::<Vec<_>>(), [1, 10, 19, 62, 63, 64, 65, 66, 99]);
+}
+
+#[test]
+fn bitvec_iter_works_2() {
+ let mut bitvec = BitVector::new(300);
+ bitvec.insert(1);
+ bitvec.insert(10);
+ bitvec.insert(19);
+ bitvec.insert(62);
+ bitvec.insert(66);
+ bitvec.insert(99);
+ bitvec.insert(299);
+ assert_eq!(bitvec.iter().collect::<Vec<_>>(), [1, 10, 19, 62, 66, 99, 299]);
+
+}
+
+#[test]
+fn bitvec_iter_works_3() {
+ let mut bitvec = BitVector::new(319);
+ bitvec.insert(0);
+ bitvec.insert(127);
+ bitvec.insert(191);
+ bitvec.insert(255);
+ bitvec.insert(319);
+ assert_eq!(bitvec.iter().collect::<Vec<_>>(), [0, 127, 191, 255, 319]);
+}
+
#[test]
fn union_two_vecs() {
let mut vec1 = BitVector::new(65);
pub mod erase_regions;
pub mod no_landing_pads;
pub mod type_check;
-mod util;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use rustc_data_structures::bitvec::BitVector;
use rustc::middle::const_eval::ConstVal;
use rustc::middle::infer;
use rustc::mir::repr::*;
-use transform::util;
use rustc::mir::transform::MirPass;
pub struct SimplifyCfg;
}
fn remove_dead_blocks(&self, mir: &mut Mir) {
- let mut seen = vec![false; mir.basic_blocks.len()];
-
+ let mut seen = BitVector::new(mir.basic_blocks.len());
// These blocks are always required.
- seen[START_BLOCK.index()] = true;
- seen[END_BLOCK.index()] = true;
+ seen.insert(START_BLOCK.index());
+ seen.insert(END_BLOCK.index());
- let mut worklist = vec![START_BLOCK];
+ let mut worklist = Vec::with_capacity(4);
+ worklist.push(START_BLOCK);
while let Some(bb) = worklist.pop() {
for succ in mir.basic_block_data(bb).terminator().successors().iter() {
- if !seen[succ.index()] {
- seen[succ.index()] = true;
+ if seen.insert(succ.index()) {
worklist.push(*succ);
}
}
}
-
- util::retain_basic_blocks(mir, &seen);
+ retain_basic_blocks(mir, &seen);
}
fn remove_goto_chains(&self, mir: &mut Mir) -> bool {
for bb in mir.all_basic_blocks() {
let basic_block = mir.basic_block_data_mut(bb);
let mut terminator = basic_block.terminator_mut();
-
*terminator = match *terminator {
Terminator::If { ref targets, .. } if targets.0 == targets.1 => {
changed = true;
Terminator::Goto { target: targets.0 }
}
+
Terminator::If { ref targets, cond: Operand::Constant(Constant {
literal: Literal::Value {
value: ConstVal::Bool(cond)
Terminator::Goto { target: targets.1 }
}
}
+
Terminator::SwitchInt { ref targets, .. } if targets.len() == 1 => {
Terminator::Goto { target: targets[0] }
}
mir.basic_blocks.shrink_to_fit();
}
}
+
+/// Mass removal of basic blocks to keep the ID-remapping cheap.
+fn retain_basic_blocks(mir: &mut Mir, keep: &BitVector) {
+ let num_blocks = mir.basic_blocks.len();
+
+ let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
+ let mut used_blocks = 0;
+ for alive_index in keep.iter() {
+ replacements[alive_index] = BasicBlock::new(used_blocks);
+ if alive_index != used_blocks {
+ // Swap the next alive block data with the current available slot. Since alive_index is
+ // non-decreasing this is a valid operation.
+ mir.basic_blocks.swap(alive_index, used_blocks);
+ }
+ used_blocks += 1;
+ }
+ mir.basic_blocks.truncate(used_blocks);
+
+ for bb in mir.all_basic_blocks() {
+ for target in mir.basic_block_data_mut(bb).terminator_mut().successors_mut() {
+ *target = replacements[target.index()];
+ }
+ }
+}
+++ /dev/null
-// Copyright 2015 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 rustc::mir::repr::*;
-
-/// Update basic block ids in all terminators using the given replacements,
-/// useful e.g. after removal of several basic blocks to update all terminators
-/// in a single pass
-pub fn update_basic_block_ids(mir: &mut Mir, replacements: &[BasicBlock]) {
- for bb in mir.all_basic_blocks() {
- for target in mir.basic_block_data_mut(bb).terminator_mut().successors_mut() {
- *target = replacements[target.index()];
- }
- }
-}
-
-/// Mass removal of basic blocks to keep the ID-remapping cheap.
-pub fn retain_basic_blocks(mir: &mut Mir, keep: &[bool]) {
- let num_blocks = mir.basic_blocks.len();
-
- // Check that we have a usage flag for every block
- assert_eq!(num_blocks, keep.len());
-
- let first_dead = match keep.iter().position(|&k| !k) {
- None => return,
- Some(first_dead) => first_dead,
- };
-
- // `replacements` maps the old block ids to the new ones
- let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
-
- let mut dead = 0;
- for i in first_dead..num_blocks {
- if keep[i] {
- replacements[i] = BasicBlock::new(i - dead);
- mir.basic_blocks.swap(i, i - dead);
- } else {
- dead += 1;
- }
- }
- mir.basic_blocks.truncate(num_blocks - dead);
-
- update_basic_block_ids(mir, &replacements);
-}
use externalfiles::ExternalHtml;
-use serialize::json::{self, ToJson};
+use serialize::json::{ToJson, Json, as_json};
use syntax::{abi, ast};
use syntax::feature_gate::UnstableFeatures;
use rustc::middle::cstore::LOCAL_CRATE;
path: String,
desc: String,
parent: Option<DefId>,
+ parent_idx: Option<usize>,
search_type: Option<IndexItemFunctionType>,
}
+impl ToJson for IndexItem {
+ fn to_json(&self) -> Json {
+ assert_eq!(self.parent.is_some(), self.parent_idx.is_some());
+
+ let mut data = Vec::with_capacity(6);
+ data.push((self.ty as usize).to_json());
+ data.push(self.name.to_json());
+ data.push(self.path.to_json());
+ data.push(self.desc.to_json());
+ data.push(self.parent_idx.to_json());
+ data.push(self.search_type.to_json());
+
+ Json::Array(data)
+ }
+}
+
/// A type used for the search index.
struct Type {
name: Option<String>,
}
-impl fmt::Display for Type {
- /// Formats type as {name: $name}.
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- // Wrapping struct fmt should never call us when self.name is None,
- // but just to be safe we write `null` in that case.
+impl ToJson for Type {
+ fn to_json(&self) -> Json {
match self.name {
- Some(ref n) => write!(f, "{{\"name\":\"{}\"}}", n),
- None => write!(f, "null")
+ Some(ref name) => {
+ let mut data = BTreeMap::new();
+ data.insert("name".to_owned(), name.to_json());
+ Json::Object(data)
+ },
+ None => Json::Null
}
}
}
output: Option<Type>
}
-impl fmt::Display for IndexItemFunctionType {
- /// Formats a full fn type as a JSON {inputs: [Type], outputs: Type/null}.
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+impl ToJson for IndexItemFunctionType {
+ fn to_json(&self) -> Json {
// If we couldn't figure out a type, just write `null`.
- if self.inputs.iter().any(|ref i| i.name.is_none()) ||
- (self.output.is_some() && self.output.as_ref().unwrap().name.is_none()) {
- return write!(f, "null")
+ if self.inputs.iter().chain(self.output.iter()).any(|ref i| i.name.is_none()) {
+ Json::Null
+ } else {
+ let mut data = BTreeMap::new();
+ data.insert("inputs".to_owned(), self.inputs.to_json());
+ data.insert("output".to_owned(), self.output.to_json());
+ Json::Object(data)
}
-
- let inputs: Vec<String> = self.inputs.iter().map(|ref t| {
- format!("{}", t)
- }).collect();
- try!(write!(f, "{{\"inputs\":[{}],\"output\":", inputs.join(",")));
-
- match self.output {
- Some(ref t) => try!(write!(f, "{}", t)),
- None => try!(write!(f, "null"))
- };
-
- Ok(try!(write!(f, "}}")))
}
}
cx.krate(krate)
}
+/// Build the search index from the collected metadata
fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
- // Build the search index from the collected metadata
let mut nodeid_to_pathid = HashMap::new();
- let mut pathid_to_nodeid = Vec::new();
- {
- let Cache { ref mut search_index,
- ref orphan_methods,
- ref mut paths, .. } = *cache;
-
- // Attach all orphan methods to the type's definition if the type
- // has since been learned.
- for &(did, ref item) in orphan_methods {
- match paths.get(&did) {
- Some(&(ref fqp, _)) => {
- // Needed to determine `self` type.
- let parent_basename = Some(fqp[fqp.len() - 1].clone());
- search_index.push(IndexItem {
- ty: shortty(item),
- name: item.name.clone().unwrap(),
- path: fqp[..fqp.len() - 1].join("::"),
- desc: Escape(&shorter(item.doc_value())).to_string(),
- parent: Some(did),
- search_type: get_index_search_type(&item, parent_basename),
- });
- },
- None => {}
- }
- }
-
- // Reduce `NodeId` in paths into smaller sequential numbers,
- // and prune the paths that do not appear in the index.
- for item in search_index.iter() {
- match item.parent {
- Some(nodeid) => {
- if !nodeid_to_pathid.contains_key(&nodeid) {
- let pathid = pathid_to_nodeid.len();
- nodeid_to_pathid.insert(nodeid, pathid);
- pathid_to_nodeid.push(nodeid);
- }
- }
- None => {}
- }
+ let mut crate_items = Vec::with_capacity(cache.search_index.len());
+ let mut crate_paths = Vec::<Json>::new();
+
+ let Cache { ref mut search_index,
+ ref orphan_methods,
+ ref mut paths, .. } = *cache;
+
+ // Attach all orphan methods to the type's definition if the type
+ // has since been learned.
+ for &(did, ref item) in orphan_methods {
+ match paths.get(&did) {
+ Some(&(ref fqp, _)) => {
+ // Needed to determine `self` type.
+ let parent_basename = Some(fqp[fqp.len() - 1].clone());
+ search_index.push(IndexItem {
+ ty: shortty(item),
+ name: item.name.clone().unwrap(),
+ path: fqp[..fqp.len() - 1].join("::"),
+ desc: Escape(&shorter(item.doc_value())).to_string(),
+ parent: Some(did),
+ parent_idx: None,
+ search_type: get_index_search_type(&item, parent_basename),
+ });
+ },
+ None => {}
}
- assert_eq!(nodeid_to_pathid.len(), pathid_to_nodeid.len());
}
- // Collect the index into a string
- let mut w = io::Cursor::new(Vec::new());
- write!(&mut w, r#"searchIndex['{}'] = {{"items":["#, krate.name).unwrap();
+ // Reduce `NodeId` in paths into smaller sequential numbers,
+ // and prune the paths that do not appear in the index.
+ let mut lastpath = String::new();
+ let mut lastpathid = 0usize;
- let mut lastpath = "".to_string();
- for (i, item) in cache.search_index.iter().enumerate() {
- // Omit the path if it is same to that of the prior item.
- let path;
- if lastpath == item.path {
- path = "";
- } else {
- lastpath = item.path.to_string();
- path = &item.path;
- };
+ for item in search_index {
+ item.parent_idx = item.parent.map(|nodeid| {
+ if nodeid_to_pathid.contains_key(&nodeid) {
+ *nodeid_to_pathid.get(&nodeid).unwrap()
+ } else {
+ let pathid = lastpathid;
+ nodeid_to_pathid.insert(nodeid, pathid);
+ lastpathid += 1;
- if i > 0 {
- write!(&mut w, ",").unwrap();
- }
- write!(&mut w, r#"[{},"{}","{}",{}"#,
- item.ty as usize, item.name, path,
- item.desc.to_json().to_string()).unwrap();
- match item.parent {
- Some(nodeid) => {
- let pathid = *nodeid_to_pathid.get(&nodeid).unwrap();
- write!(&mut w, ",{}", pathid).unwrap();
+ let &(ref fqp, short) = paths.get(&nodeid).unwrap();
+ crate_paths.push(((short as usize), fqp.last().unwrap().clone()).to_json());
+ pathid
}
- None => write!(&mut w, ",null").unwrap()
- }
- match item.search_type {
- Some(ref t) => write!(&mut w, ",{}", t).unwrap(),
- None => write!(&mut w, ",null").unwrap()
- }
- write!(&mut w, "]").unwrap();
- }
-
- write!(&mut w, r#"],"paths":["#).unwrap();
+ });
- for (i, &did) in pathid_to_nodeid.iter().enumerate() {
- let &(ref fqp, short) = cache.paths.get(&did).unwrap();
- if i > 0 {
- write!(&mut w, ",").unwrap();
+ // Omit the parent path if it is same to that of the prior item.
+ if lastpath == item.path {
+ item.path.clear();
+ } else {
+ lastpath = item.path.clone();
}
- write!(&mut w, r#"[{},"{}"]"#,
- short as usize, *fqp.last().unwrap()).unwrap();
+ crate_items.push(item.to_json());
}
- write!(&mut w, "]}};").unwrap();
+ let crate_doc = krate.module.as_ref().map(|module| {
+ Escape(&shorter(module.doc_value())).to_string()
+ }).unwrap_or(String::new());
- String::from_utf8(w.into_inner()).unwrap()
+ let mut crate_data = BTreeMap::new();
+ crate_data.insert("doc".to_owned(), Json::String(crate_doc));
+ crate_data.insert("items".to_owned(), Json::Array(crate_items));
+ crate_data.insert("paths".to_owned(), Json::Array(crate_paths));
+
+ // Collect the index into a string
+ format!("searchIndex[{}] = {};",
+ as_json(&krate.name),
+ Json::Object(crate_data))
}
fn write_shared(cx: &Context,
if !line.starts_with(key) {
continue
}
- if line.starts_with(&format!("{}['{}']", key, krate)) {
+ if line.starts_with(&format!(r#"{}["{}"]"#, key, krate)) {
continue
}
ret.push(line.to_string());
path: path.join("::").to_string(),
desc: Escape(&shorter(item.doc_value())).to_string(),
parent: parent,
+ parent_idx: None,
search_type: get_index_search_type(&item, parent_basename),
});
}
let js_dst = this.dst.join("sidebar-items.js");
let mut js_out = BufWriter::new(try_err!(File::create(&js_dst), &js_dst));
try_err!(write!(&mut js_out, "initSidebarItems({});",
- json::as_json(&items)), &js_dst);
+ as_json(&items)), &js_dst);
}
for item in m.items {
displayPath = "";
href = rootPath + item.path.replace(/::/g, '/') +
'/' + type + '.' + name + '.html';
+ } else if (type === "externcrate") {
+ displayPath = "";
+ href = rootPath + name + '/index.html';
} else if (item.parent !== undefined) {
var myparent = item.parent;
var anchor = '#' + type + '.' + name;
for (var crate in rawSearchIndex) {
if (!rawSearchIndex.hasOwnProperty(crate)) { continue; }
+ searchWords.push(crate);
+ searchIndex.push({
+ crate: crate,
+ ty: 1, // == ExternCrate
+ name: crate,
+ path: "",
+ desc: rawSearchIndex[crate].doc,
+ type: null,
+ });
+
// an array of [(Number) item type,
// (String) name,
// (String) full path or empty string for previous path,
}
.content a.primitive { color: #39a7bf; }
-.content span.mod, .content a.mod, block a.current.mod { color: #4d76ae; }
+.content span.externcrate, span.mod, .content a.mod, block a.current.mod { color: #4d76ae; }
.content span.fn, .content a.fn, .block a.current.fn,
.content span.method, .content a.method, .block a.current.method,
.content span.tymethod, .content a.tymethod, .block a.current.tymethod,
/// An occupied Entry.
#[stable(feature = "rust1", since = "1.0.0")]
Occupied(
- #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] OccupiedEntry<'a, K, V>
+ #[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>
),
/// A vacant Entry.
#[stable(feature = "rust1", since = "1.0.0")]
Vacant(
- #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] VacantEntry<'a, K, V>
+ #[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>
),
}
/// valid unicode data. The found data is returned as a payload of this
/// variant.
#[stable(feature = "env", since = "1.0.0")]
- NotUnicode(#[cfg_attr(not(stage0), stable(feature = "env", since = "1.0.0"))] OsString),
+ NotUnicode(#[stable(feature = "env", since = "1.0.0")] OsString),
}
#[stable(feature = "env", since = "1.0.0")]
mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
}
+ /// Creates a C string wrapper from a byte slice.
+ ///
+ /// This function will cast the provided `bytes` to a `CStr` wrapper after
+ /// ensuring that it is null terminated and does not contain any interior
+ /// nul bytes.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #![feature(cstr_from_bytes)]
+ /// use std::ffi::CStr;
+ ///
+ /// # fn main() {
+ /// let cstr = CStr::from_bytes_with_nul(b"hello\0");
+ /// assert!(cstr.is_some());
+ /// # }
+ /// ```
+ #[unstable(feature = "cstr_from_bytes", reason = "recently added", issue = "31190")]
+ pub fn from_bytes_with_nul(bytes: &[u8]) -> Option<&CStr> {
+ if bytes.is_empty() || memchr::memchr(0, &bytes) != Some(bytes.len() - 1) {
+ None
+ } else {
+ Some(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
+ }
+ }
+
+ /// Unsafely creates a C string wrapper from a byte slice.
+ ///
+ /// This function will cast the provided `bytes` to a `CStr` wrapper without
+ /// performing any sanity checks. The provided slice must be null terminated
+ /// and not contain any interior nul bytes.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #![feature(cstr_from_bytes)]
+ /// use std::ffi::{CStr, CString};
+ ///
+ /// # fn main() {
+ /// unsafe {
+ /// let cstring = CString::new("hello").unwrap();
+ /// let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
+ /// assert_eq!(cstr, &*cstring);
+ /// }
+ /// # }
+ /// ```
+ #[unstable(feature = "cstr_from_bytes", reason = "recently added", issue = "31190")]
+ pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
+ mem::transmute(bytes)
+ }
+
/// Returns the inner pointer to this C string.
///
/// The returned pointer will be valid for as long as `self` is and points
assert_eq!(cstr_hash, cstring_hash);
}
+
+ #[test]
+ fn from_bytes_with_nul() {
+ let data = b"123\0";
+ let cstr = CStr::from_bytes_with_nul(data);
+ assert_eq!(cstr.map(CStr::to_bytes), Some(&b"123"[..]));
+ assert_eq!(cstr.map(CStr::to_bytes_with_nul), Some(&b"123\0"[..]));
+
+ unsafe {
+ let cstr_unchecked = CStr::from_bytes_with_nul_unchecked(data);
+ assert_eq!(cstr, Some(cstr_unchecked));
+ }
+ }
+
+ #[test]
+ fn from_bytes_with_nul_unterminated() {
+ let data = b"123";
+ let cstr = CStr::from_bytes_with_nul(data);
+ assert!(cstr.is_none());
+ }
+
+ #[test]
+ fn from_bytes_with_nul_interior() {
+ let data = b"1\023\0";
+ let cstr = CStr::from_bytes_with_nul(data);
+ assert!(cstr.is_none());
+ }
}
fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
}
+macro_rules! impl_cmp {
+ ($lhs:ty, $rhs: ty) => {
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
+ impl<'a, 'b> PartialEq<$rhs> for $lhs {
+ #[inline]
+ fn eq(&self, other: &$rhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
+ }
+
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
+ impl<'a, 'b> PartialEq<$lhs> for $rhs {
+ #[inline]
+ fn eq(&self, other: &$lhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
+ }
+
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
+ impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+ #[inline]
+ fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
+ <OsStr as PartialOrd>::partial_cmp(self, other)
+ }
+ }
+
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
+ impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+ #[inline]
+ fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
+ <OsStr as PartialOrd>::partial_cmp(self, other)
+ }
+ }
+ }
+}
+
+impl_cmp!(OsString, OsStr);
+impl_cmp!(OsString, &'a OsStr);
+impl_cmp!(Cow<'a, OsStr>, OsStr);
+impl_cmp!(Cow<'a, OsStr>, &'b OsStr);
+impl_cmp!(Cow<'a, OsStr>, OsString);
+
#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for OsStr {
#[inline]
pub enum SeekFrom {
/// Set the offset to the provided number of bytes.
#[stable(feature = "rust1", since = "1.0.0")]
- Start(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] u64),
+ Start(#[stable(feature = "rust1", since = "1.0.0")] u64),
/// Set the offset to the size of this object plus the specified number of
/// bytes.
/// It is possible to seek beyond the end of an object, but it's an error to
/// seek before byte 0.
#[stable(feature = "rust1", since = "1.0.0")]
- End(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] i64),
+ End(#[stable(feature = "rust1", since = "1.0.0")] i64),
/// Set the offset to the current position plus the specified number of
/// bytes.
/// It is possible to seek beyond the end of an object, but it's an error to
/// seek before byte 0.
#[stable(feature = "rust1", since = "1.0.0")]
- Current(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] i64),
+ Current(#[stable(feature = "rust1", since = "1.0.0")] i64),
}
fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
pub enum SocketAddr {
/// An IPv4 socket address which is a (ip, port) combination.
#[stable(feature = "rust1", since = "1.0.0")]
- V4(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] SocketAddrV4),
+ V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4),
/// An IPv6 socket address
#[stable(feature = "rust1", since = "1.0.0")]
- V6(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] SocketAddrV6),
+ V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6),
}
/// An IPv4 socket address which is a (ip, port) combination.
pub enum IpAddr {
/// Representation of an IPv4 address.
#[stable(feature = "ip_addr", since = "1.7.0")]
- V4(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.7.0"))] Ipv4Addr),
+ V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
/// Representation of an IPv6 address.
#[stable(feature = "ip_addr", since = "1.7.0")]
- V6(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.7.0"))] Ipv6Addr),
+ V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
}
/// Representation of an IPv4 address.
pub enum Prefix<'a> {
/// Prefix `\\?\`, together with the given component immediately following it.
#[stable(feature = "rust1", since = "1.0.0")]
- Verbatim(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr),
+ Verbatim(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
/// Prefix `\\?\UNC\`, with the "server" and "share" components following it.
#[stable(feature = "rust1", since = "1.0.0")]
VerbatimUNC(
- #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr,
- #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr,
+ #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
+ #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
),
/// Prefix like `\\?\C:\`, for the given drive letter
#[stable(feature = "rust1", since = "1.0.0")]
- VerbatimDisk(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] u8),
+ VerbatimDisk(#[stable(feature = "rust1", since = "1.0.0")] u8),
/// Prefix `\\.\`, together with the given component immediately following it.
#[stable(feature = "rust1", since = "1.0.0")]
- DeviceNS(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr),
+ DeviceNS(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
/// Prefix `\\server\share`, with the given "server" and "share" components.
#[stable(feature = "rust1", since = "1.0.0")]
UNC(
- #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr,
- #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr,
+ #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
+ #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
),
/// Prefix `C:` for the given disk drive.
#[stable(feature = "rust1", since = "1.0.0")]
- Disk(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] u8),
+ Disk(#[stable(feature = "rust1", since = "1.0.0")] u8),
}
impl<'a> Prefix<'a> {
/// Does not occur on Unix.
#[stable(feature = "rust1", since = "1.0.0")]
Prefix(
- #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] PrefixComponent<'a>
+ #[stable(feature = "rust1", since = "1.0.0")] PrefixComponent<'a>
),
/// The root directory component, appears after any prefix and before anything else
/// A normal component, i.e. `a` and `b` in `a/b`
#[stable(feature = "rust1", since = "1.0.0")]
- Normal(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr),
+ Normal(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
}
impl<'a> Component<'a> {
}
}
+#[stable(feature = "cow_os_str_as_ref_path", since = "1.8.0")]
+impl<'a> AsRef<Path> for Cow<'a, OsStr> {
+ fn as_ref(&self) -> &Path {
+ Path::new(self)
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for OsString {
fn as_ref(&self) -> &Path {
fn into_iter(self) -> Iter<'a> { self.iter() }
}
-macro_rules! impl_eq {
+macro_rules! impl_cmp {
($lhs:ty, $rhs: ty) => {
#[stable(feature = "partialeq_path", since = "1.6.0")]
impl<'a, 'b> PartialEq<$rhs> for $lhs {
fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self, other) }
}
+ #[stable(feature = "cmp_path", since = "1.8.0")]
+ impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+ #[inline]
+ fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
+ <Path as PartialOrd>::partial_cmp(self, other)
+ }
+ }
+
+ #[stable(feature = "cmp_path", since = "1.8.0")]
+ impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+ #[inline]
+ fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
+ <Path as PartialOrd>::partial_cmp(self, other)
+ }
+ }
+ }
+}
+
+impl_cmp!(PathBuf, Path);
+impl_cmp!(PathBuf, &'a Path);
+impl_cmp!(Cow<'a, Path>, Path);
+impl_cmp!(Cow<'a, Path>, &'b Path);
+impl_cmp!(Cow<'a, Path>, PathBuf);
+
+macro_rules! impl_cmp_os_str {
+ ($lhs:ty, $rhs: ty) => {
+ #[stable(feature = "cmp_path", since = "1.8.0")]
+ impl<'a, 'b> PartialEq<$rhs> for $lhs {
+ #[inline]
+ fn eq(&self, other: &$rhs) -> bool { <Path as PartialEq>::eq(self, other.as_ref()) }
+ }
+
+ #[stable(feature = "cmp_path", since = "1.8.0")]
+ impl<'a, 'b> PartialEq<$lhs> for $rhs {
+ #[inline]
+ fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self.as_ref(), other) }
+ }
+
+ #[stable(feature = "cmp_path", since = "1.8.0")]
+ impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+ #[inline]
+ fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
+ <Path as PartialOrd>::partial_cmp(self, other.as_ref())
+ }
+ }
+
+ #[stable(feature = "cmp_path", since = "1.8.0")]
+ impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+ #[inline]
+ fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
+ <Path as PartialOrd>::partial_cmp(self.as_ref(), other)
+ }
+ }
}
}
-impl_eq!(PathBuf, Path);
-impl_eq!(PathBuf, &'a Path);
-impl_eq!(Cow<'a, Path>, Path);
-impl_eq!(Cow<'a, Path>, &'b Path);
-impl_eq!(Cow<'a, Path>, PathBuf);
+impl_cmp_os_str!(PathBuf, OsStr);
+impl_cmp_os_str!(PathBuf, &'a OsStr);
+impl_cmp_os_str!(PathBuf, Cow<'a, OsStr>);
+impl_cmp_os_str!(PathBuf, OsString);
+impl_cmp_os_str!(Path, OsStr);
+impl_cmp_os_str!(Path, &'a OsStr);
+impl_cmp_os_str!(Path, Cow<'a, OsStr>);
+impl_cmp_os_str!(Path, OsString);
+impl_cmp_os_str!(&'a Path, OsStr);
+impl_cmp_os_str!(&'a Path, Cow<'b, OsStr>);
+impl_cmp_os_str!(&'a Path, OsString);
+impl_cmp_os_str!(Cow<'a, Path>, OsStr);
+impl_cmp_os_str!(Cow<'a, Path>, &'b OsStr);
+impl_cmp_os_str!(Cow<'a, Path>, OsString);
#[stable(since = "1.7.0", feature = "strip_prefix")]
impl fmt::Display for StripPrefixError {
/// this is not a buffered channel, then there is no receiver available to
/// acquire the data.
#[stable(feature = "rust1", since = "1.0.0")]
- Full(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] T),
+ Full(#[stable(feature = "rust1", since = "1.0.0")] T),
/// This channel's receiving half has disconnected, so the data could not be
/// sent. The data is returned back to the callee in this case.
#[stable(feature = "rust1", since = "1.0.0")]
- Disconnected(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] T),
+ Disconnected(#[stable(feature = "rust1", since = "1.0.0")] T),
}
enum Flavor<T> {
/// The lock could not be acquired because another thread failed while holding
/// the lock.
#[stable(feature = "rust1", since = "1.0.0")]
- Poisoned(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] PoisonError<T>),
+ Poisoned(#[stable(feature = "rust1", since = "1.0.0")] PoisonError<T>),
/// The lock could not be acquired at this time because the operation would
/// otherwise block.
#[stable(feature = "rust1", since = "1.0.0")]
}
}
-#[cfg(not(stage0))]
pub fn payload() -> *mut u8 {
0 as *mut u8
}
}
}
-#[cfg(not(stage0))]
unsafe fn inner_try(f: fn(*mut u8), data: *mut u8)
-> Result<(), Box<Any + Send>> {
PANIC_COUNT.with(|s| {
})
}
-#[cfg(stage0)]
-unsafe fn inner_try(f: fn(*mut u8), data: *mut u8)
- -> Result<(), Box<Any + Send>> {
- PANIC_COUNT.with(|s| {
- let prev = s.get();
- s.set(0);
- let ep = intrinsics::try(f, data);
- s.set(prev);
- if ep.is_null() {
- Ok(())
- } else {
- Err(imp::cleanup(ep))
- }
- })
-}
-
/// Determines whether the current thread is unwinding because of panic.
pub fn panicking() -> bool {
PANIC_COUNT.with(|s| s.get() != 0)
pub use self::imp::*;
-#[cfg(stage0)]
-mod imp {
- use prelude::v1::*;
- use any::Any;
-
- pub unsafe fn panic(_data: Box<Any + Send + 'static>) -> ! {
- rtabort!("cannot unwind SEH in stage0")
- }
-
- pub unsafe fn cleanup(_ptr: *mut u8) -> Box<Any + Send + 'static> {
- rtabort!("can't cleanup SEH in stage0")
- }
-
- #[lang = "msvc_try_filter"]
- #[linkage = "external"]
- unsafe extern fn __rust_try_filter() -> i32 {
- 0
- }
-
- #[lang = "eh_unwind_resume"]
- #[unwind]
- unsafe extern fn rust_eh_unwind_resume(_ptr: *mut u8) -> ! {
- rtabort!("can't resume unwind SEH in stage0")
- }
- #[lang = "eh_personality_catch"]
- unsafe extern fn rust_eh_personality_catch() {}
-}
-
-#[cfg(not(stage0))]
mod imp {
use prelude::v1::*;
rtabort!("could not unwind stack");
}
-#[cfg(not(stage0))]
pub fn payload() -> *mut u8 {
0 as *mut u8
}
//! copy of that function in my mingw install (maybe it was broken?). Instead,
//! this takes the route of using StackWalk64 in order to walk the stack.
-#![allow(dead_code, deprecated)]
+#![allow(deprecated)] // dynamic_lib
use io::prelude::*;
#[path = "printing/gnu.rs"]
mod printing;
-type SymFromAddrFn =
- extern "system" fn(c::HANDLE, u64, *mut u64,
- *mut c::SYMBOL_INFO) -> c::BOOL;
-type SymGetLineFromAddr64Fn =
- extern "system" fn(c::HANDLE, u64, *mut u32,
- *mut c::IMAGEHLP_LINE64) -> c::BOOL;
type SymInitializeFn =
extern "system" fn(c::HANDLE, *mut c_void,
c::BOOL) -> c::BOOL;
//! C definitions used by libnative that don't belong in liblibc
-#![allow(bad_style, overflowing_literals, dead_code, deprecated, unused_imports)]
+#![allow(bad_style)]
+#![cfg_attr(test, allow(dead_code))]
use os::raw::{c_int, c_uint, c_ulong, c_long, c_longlong, c_ushort};
-use os::raw::{c_char, c_short, c_ulonglong};
+use os::raw::{c_char, c_ulonglong};
use libc::{wchar_t, size_t, c_void};
use ptr;
#[repr(simd)]
#[repr(C)]
+#[cfg(target_arch = "x86_64")]
struct u64x2(u64, u64);
-pub use self::GET_FILEEX_INFO_LEVELS::*;
pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
pub use self::EXCEPTION_DISPOSITION::*;
pub type LPWCH = *mut WCHAR;
pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
pub type LPWSADATA = *mut WSADATA;
-pub type LPWSANETWORKEVENTS = *mut WSANETWORKEVENTS;
pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN;
pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
pub type LPWSTR = *mut WCHAR;
pub const FILE_ATTRIBUTE_READONLY: DWORD = 0x1;
pub const FILE_ATTRIBUTE_DIRECTORY: DWORD = 0x10;
-pub const FILE_ATTRIBUTE_NORMAL: DWORD = 0x80;
pub const FILE_ATTRIBUTE_REPARSE_POINT: DWORD = 0x400;
+
pub const FILE_SHARE_DELETE: DWORD = 0x4;
pub const FILE_SHARE_READ: DWORD = 0x1;
pub const FILE_SHARE_WRITE: DWORD = 0x2;
+
pub const CREATE_ALWAYS: DWORD = 2;
pub const CREATE_NEW: DWORD = 1;
pub const OPEN_ALWAYS: DWORD = 4;
pub const OPEN_EXISTING: DWORD = 3;
pub const TRUNCATE_EXISTING: DWORD = 5;
-pub const FILE_READ_DATA: DWORD = 0x00000001;
pub const FILE_WRITE_DATA: DWORD = 0x00000002;
pub const FILE_APPEND_DATA: DWORD = 0x00000004;
-pub const FILE_READ_EA: DWORD = 0x00000008;
pub const FILE_WRITE_EA: DWORD = 0x00000010;
-pub const FILE_EXECUTE: DWORD = 0x00000020;
-pub const FILE_READ_ATTRIBUTES: DWORD = 0x00000080;
pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100;
-
-pub const DELETE: DWORD = 0x00008000;
pub const READ_CONTROL: DWORD = 0x00020000;
-pub const WRITE_DAC: DWORD = 0x00040000;
-pub const WRITE_OWNER: DWORD = 0x00080000;
pub const SYNCHRONIZE: DWORD = 0x00100000;
-
pub const GENERIC_READ: DWORD = 0x80000000;
pub const GENERIC_WRITE: DWORD = 0x40000000;
-pub const GENERIC_EXECUTE: DWORD = 0x20000000;
-pub const GENERIC_ALL: DWORD = 0x10000000;
-
-pub const STANDARD_RIGHTS_READ: DWORD = READ_CONTROL;
pub const STANDARD_RIGHTS_WRITE: DWORD = READ_CONTROL;
-pub const STANDARD_RIGHTS_EXECUTE: DWORD = READ_CONTROL;
-pub const FILE_GENERIC_READ: DWORD = STANDARD_RIGHTS_READ | FILE_READ_DATA |
- FILE_READ_ATTRIBUTES |
- FILE_READ_EA |
- SYNCHRONIZE;
pub const FILE_GENERIC_WRITE: DWORD = STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA |
FILE_WRITE_ATTRIBUTES |
FILE_WRITE_EA |
FILE_APPEND_DATA |
SYNCHRONIZE;
-pub const SECURITY_ANONYMOUS: DWORD = 0 << 16;
-pub const SECURITY_IDENTIFICATION: DWORD = 1 << 16;
-pub const SECURITY_IMPERSONATION: DWORD = 2 << 16;
-pub const SECURITY_DELEGATION: DWORD = 3 << 16;
-pub const SECURITY_CONTEXT_TRACKING: DWORD = 0x00040000;
-pub const SECURITY_EFFECTIVE_ONLY: DWORD = 0x00080000;
+pub const FILE_FLAG_OPEN_REPARSE_POINT: DWORD = 0x00200000;
+pub const FILE_FLAG_BACKUP_SEMANTICS: DWORD = 0x02000000;
pub const SECURITY_SQOS_PRESENT: DWORD = 0x00100000;
#[repr(C)]
fn clone(&self) -> Self { *self }
}
-pub const FIONBIO: c_long = 0x8004667e;
-pub const FD_SETSIZE: usize = 64;
-pub const MSG_DONTWAIT: c_int = 0;
-pub const ENABLE_ECHO_INPUT: DWORD = 0x4;
-pub const ENABLE_EXTENDED_FLAGS: DWORD = 0x80;
-pub const ENABLE_INSERT_MODE: DWORD = 0x20;
-pub const ENABLE_LINE_INPUT: DWORD = 0x2;
-pub const ENABLE_PROCESSED_INPUT: DWORD = 0x1;
-pub const ENABLE_QUICK_EDIT_MODE: DWORD = 0x40;
-
-pub const FD_ACCEPT: c_long = 0x08;
-pub const FD_MAX_EVENTS: usize = 10;
-
-pub const WSA_INVALID_EVENT: WSAEVENT = 0 as WSAEVENT;
-pub const WSA_INFINITE: DWORD = INFINITE;
-pub const WSA_WAIT_TIMEOUT: DWORD = WAIT_TIMEOUT;
-pub const WSA_WAIT_EVENT_0: DWORD = WAIT_OBJECT_0;
-pub const WSA_WAIT_FAILED: DWORD = WAIT_FAILED;
pub const WSA_FLAG_OVERLAPPED: DWORD = 0x01;
-pub const WSA_FLAG_NO_HANDLE_INHERIT: DWORD = 0x80;
pub const WSADESCRIPTION_LEN: usize = 256;
pub const WSASYS_STATUS_LEN: usize = 128;
pub const WSAPROTOCOL_LEN: DWORD = 255;
pub const INVALID_SOCKET: SOCKET = !0;
-pub const WSAEINTR: c_int = 10004;
-pub const WSAEBADF: c_int = 10009;
pub const WSAEACCES: c_int = 10013;
-pub const WSAEFAULT: c_int = 10014;
pub const WSAEINVAL: c_int = 10022;
-pub const WSAEMFILE: c_int = 10024;
pub const WSAEWOULDBLOCK: c_int = 10035;
-pub const WSAEINPROGRESS: c_int = 10036;
-pub const WSAEALREADY: c_int = 10037;
-pub const WSAENOTSOCK: c_int = 10038;
-pub const WSAEDESTADDRREQ: c_int = 10039;
-pub const WSAEMSGSIZE: c_int = 10040;
-pub const WSAEPROTOTYPE: c_int = 10041;
-pub const WSAENOPROTOOPT: c_int = 10042;
-pub const WSAEPROTONOSUPPORT: c_int = 10043;
-pub const WSAESOCKTNOSUPPORT: c_int = 10044;
-pub const WSAEOPNOTSUPP: c_int = 10045;
-pub const WSAEPFNOSUPPORT: c_int = 10046;
-pub const WSAEAFNOSUPPORT: c_int = 10047;
pub const WSAEADDRINUSE: c_int = 10048;
pub const WSAEADDRNOTAVAIL: c_int = 10049;
-pub const WSAENETDOWN: c_int = 10050;
-pub const WSAENETUNREACH: c_int = 10051;
-pub const WSAENETRESET: c_int = 10052;
pub const WSAECONNABORTED: c_int = 10053;
pub const WSAECONNRESET: c_int = 10054;
-pub const WSAENOBUFS: c_int = 10055;
-pub const WSAEISCONN: c_int = 10056;
pub const WSAENOTCONN: c_int = 10057;
pub const WSAESHUTDOWN: c_int = 10058;
-pub const WSAETOOMANYREFS: c_int = 10059;
pub const WSAETIMEDOUT: c_int = 10060;
pub const WSAECONNREFUSED: c_int = 10061;
-pub const WSAELOOP: c_int = 10062;
-pub const WSAENAMETOOLONG: c_int = 10063;
-pub const WSAEHOSTDOWN: c_int = 10064;
-pub const WSAEHOSTUNREACH: c_int = 10065;
-pub const WSAENOTEMPTY: c_int = 10066;
-pub const WSAEPROCLIM: c_int = 10067;
-pub const WSAEUSERS: c_int = 10068;
-pub const WSAEDQUOT: c_int = 10069;
-pub const WSAESTALE: c_int = 10070;
-pub const WSAEREMOTE: c_int = 10071;
-pub const WSASYSNOTREADY: c_int = 10091;
-pub const WSAVERNOTSUPPORTED: c_int = 10092;
-pub const WSANOTINITIALISED: c_int = 10093;
-pub const WSAEDISCON: c_int = 10101;
-pub const WSAENOMORE: c_int = 10102;
-pub const WSAECANCELLED: c_int = 10103;
-pub const WSAEINVALIDPROCTABLE: c_int = 10104;
+
pub const NI_MAXHOST: DWORD = 1025;
pub const MAX_PROTOCOL_CHAIN: DWORD = 7;
pub const TOKEN_READ: DWORD = 0x20008;
-pub const FILE_FLAG_OPEN_REPARSE_POINT: DWORD = 0x00200000;
-pub const FILE_FLAG_BACKUP_SEMANTICS: DWORD = 0x02000000;
pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;
pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8;
pub const IO_REPARSE_TAG_SYMLINK: DWORD = 0xa000000c;
pub const IO_REPARSE_TAG_MOUNT_POINT: DWORD = 0xa0000003;
pub const SYMLINK_FLAG_RELATIVE: DWORD = 0x00000001;
pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4;
-pub const FSCTL_DELETE_REPARSE_POINT: DWORD = 0x900ac;
pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1;
pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;
pub const PROGRESS_CONTINUE: DWORD = 0;
-pub const PROGRESS_CANCEL: DWORD = 1;
-pub const PROGRESS_STOP: DWORD = 2;
-pub const PROGRESS_QUIET: DWORD = 3;
-
-pub const TOKEN_ADJUST_PRIVILEGES: DWORD = 0x0020;
-pub const SE_PRIVILEGE_ENABLED: DWORD = 2;
-
-pub const ERROR_SUCCESS: DWORD = 0;
-pub const ERROR_INVALID_FUNCTION: DWORD = 1;
pub const ERROR_FILE_NOT_FOUND: DWORD = 2;
pub const ERROR_PATH_NOT_FOUND: DWORD = 3;
pub const ERROR_ACCESS_DENIED: DWORD = 5;
pub const ERROR_INVALID_HANDLE: DWORD = 6;
pub const ERROR_NO_MORE_FILES: DWORD = 18;
pub const ERROR_BROKEN_PIPE: DWORD = 109;
-pub const ERROR_DISK_FULL: DWORD = 112;
pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120;
pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122;
-pub const ERROR_INVALID_NAME: DWORD = 123;
pub const ERROR_ALREADY_EXISTS: DWORD = 183;
-pub const ERROR_PIPE_BUSY: DWORD = 231;
pub const ERROR_NO_DATA: DWORD = 232;
-pub const ERROR_INVALID_ADDRESS: DWORD = 487;
-pub const ERROR_PIPE_CONNECTED: DWORD = 535;
-pub const ERROR_ILLEGAL_CHARACTER: DWORD = 582;
pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203;
-pub const ERROR_NOTHING_TO_TERMINATE: DWORD = 758;
pub const ERROR_OPERATION_ABORTED: DWORD = 995;
-pub const ERROR_IO_PENDING: DWORD = 997;
-pub const ERROR_FILE_INVALID: DWORD = 1006;
-pub const ERROR_NOT_FOUND: DWORD = 1168;
pub const ERROR_TIMEOUT: DWORD = 0x5B4;
pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE;
};
pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: ptr::null_mut() };
-pub const STILL_ACTIVE: DWORD = 259;
-
pub const DETACHED_PROCESS: DWORD = 0x00000008;
pub const CREATE_NEW_PROCESS_GROUP: DWORD = 0x00000200;
pub const CREATE_UNICODE_ENVIRONMENT: DWORD = 0x00000400;
pub const FILE_CURRENT: DWORD = 1;
pub const FILE_END: DWORD = 2;
-pub const WAIT_ABANDONED: DWORD = 0x00000080;
pub const WAIT_OBJECT_0: DWORD = 0x00000000;
-pub const WAIT_TIMEOUT: DWORD = 0x00000102;
-pub const WAIT_FAILED: DWORD = !0;
+#[cfg(target_env = "msvc")]
pub const MAX_SYM_NAME: usize = 2000;
+#[cfg(target_arch = "x86")]
pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c;
-pub const IMAGE_FILE_MACHINE_IA64: DWORD = 0x0200;
+#[cfg(target_arch = "x86_64")]
pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
pub const PROV_RSA_FULL: DWORD = 1;
pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
pub const EXCEPTION_NONCONTINUABLE: DWORD = 0x1; // Noncontinuable exception
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
pub const EXCEPTION_UNWINDING: DWORD = 0x2; // Unwind is in progress
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
pub const EXCEPTION_EXIT_UNWIND: DWORD = 0x4; // Exit unwind is in progress
-pub const EXCEPTION_STACK_INVALID: DWORD = 0x8; // Stack out of limits or unaligned
-pub const EXCEPTION_NESTED_CALL: DWORD = 0x10; // Nested exception handler call
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
pub const EXCEPTION_TARGET_UNWIND: DWORD = 0x20; // Target unwind in progress
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
pub const EXCEPTION_COLLIDED_UNWIND: DWORD = 0x40; // Collided exception handler call
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
pub const EXCEPTION_UNWIND: DWORD = EXCEPTION_UNWINDING |
EXCEPTION_EXIT_UNWIND |
EXCEPTION_TARGET_UNWIND |
pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1],
}
-#[repr(C)]
-pub struct WSANETWORKEVENTS {
- pub lNetworkEvents: c_long,
- pub iErrorCode: [c_int; FD_MAX_EVENTS],
-}
-
pub type WSAEVENT = HANDLE;
#[repr(C)]
pub szProtocol: [u16; (WSAPROTOCOL_LEN as usize) + 1],
}
-#[repr(C)]
-pub struct fd_set {
- fd_count: c_uint,
- fd_array: [SOCKET; FD_SETSIZE],
-}
-
-pub fn fd_set(set: &mut fd_set, s: SOCKET) {
- set.fd_array[set.fd_count as usize] = s;
- set.fd_count += 1;
-}
-
-pub type SHORT = c_short;
-
-#[repr(C)]
-pub struct COORD {
- pub X: SHORT,
- pub Y: SHORT,
-}
-
-#[repr(C)]
-pub struct SMALL_RECT {
- pub Left: SHORT,
- pub Top: SHORT,
- pub Right: SHORT,
- pub Bottom: SHORT,
-}
-
-#[repr(C)]
-pub struct CONSOLE_SCREEN_BUFFER_INFO {
- pub dwSize: COORD,
- pub dwCursorPosition: COORD,
- pub wAttributes: WORD,
- pub srWindow: SMALL_RECT,
- pub dwMaximumWindowSize: COORD,
-}
-pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO;
-
#[repr(C)]
#[derive(Copy, Clone)]
pub struct WIN32_FILE_ATTRIBUTE_DATA {
}
#[repr(C)]
-pub enum GET_FILEEX_INFO_LEVELS {
- GetFileExInfoStandard,
- GetFileExMaxInfoLevel
-}
-
-#[repr(C)]
+#[allow(dead_code)] // we only use some variants
pub enum FILE_INFO_BY_HANDLE_CLASS {
FileBasicInfo = 0,
FileStandardInfo = 1,
SpinCount: ULONG_PTR
}
-#[repr(C)]
-pub struct LUID {
- pub LowPart: DWORD,
- pub HighPart: c_long,
-}
-
-pub type PLUID = *mut LUID;
-
-#[repr(C)]
-pub struct TOKEN_PRIVILEGES {
- pub PrivilegeCount: 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: DWORD,
-}
-
#[repr(C)]
pub struct REPARSE_MOUNTPOINT_DATA_BUFFER {
pub ReparseTag: DWORD,
}
#[repr(C)]
+#[cfg(target_env = "msvc")]
pub struct SYMBOL_INFO {
pub SizeOfStruct: c_ulong,
pub TypeIndex: c_ulong,
}
#[repr(C)]
+#[cfg(target_env = "msvc")]
pub struct IMAGEHLP_LINE64 {
pub SizeOfStruct: u32,
pub Key: *const c_void,
}
#[repr(C)]
+#[allow(dead_code)] // we only use some variants
pub enum ADDRESS_MODE {
AddrMode1616,
AddrMode1632,
pub s6_addr: [u8; 16],
}
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
pub enum UNWIND_HISTORY_TABLE {}
#[repr(C)]
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
pub struct RUNTIME_FUNCTION {
pub BeginAddress: DWORD,
pub EndAddress: DWORD,
}
#[repr(C)]
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
pub struct DISPATCHER_CONTEXT {
pub ControlPc: LPVOID,
pub ImageBase: LPVOID,
#[repr(C)]
#[derive(Copy, Clone)]
+#[allow(dead_code)] // we only use some variants
pub enum EXCEPTION_DISPOSITION {
ExceptionContinueExecution,
ExceptionContinueSearch,
pub fn GetConsoleMode(hConsoleHandle: HANDLE,
lpMode: LPDWORD) -> BOOL;
- pub fn GetFileAttributesExW(lpFileName: LPCWSTR,
- fInfoLevelId: GET_FILEEX_INFO_LEVELS,
- lpFileInformation: LPVOID) -> BOOL;
pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
pub fn SetFileAttributesW(lpFileName: LPCWSTR,
dwFileAttributes: DWORD) -> BOOL;
lpData: LPVOID,
pbCancel: LPBOOL,
dwCopyFlags: DWORD) -> BOOL;
- pub fn LookupPrivilegeValueW(lpSystemName: LPCWSTR,
- lpName: LPCWSTR,
- lpLuid: PLUID) -> BOOL;
- pub fn AdjustTokenPrivileges(TokenHandle: HANDLE,
- DisableAllPrivileges: BOOL,
- NewState: PTOKEN_PRIVILEGES,
- BufferLength: DWORD,
- PreviousState: PTOKEN_PRIVILEGES,
- ReturnLength: *mut DWORD) -> BOOL;
pub fn AddVectoredExceptionHandler(FirstHandler: ULONG,
VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
-> LPVOID;
pub fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
#[unwind]
+ #[cfg(any(target_arch = "x86_64", target_env = "msvc"))]
pub fn RaiseException(dwExceptionCode: DWORD,
dwExceptionFlags: DWORD,
nNumberOfArguments: DWORD,
lpArguments: *const ULONG_PTR);
+ #[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
pub fn RtlUnwindEx(TargetFrame: LPVOID,
TargetIp: LPVOID,
ExceptionRecord: *const EXCEPTION_RECORD,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use cmp;
use io::ErrorKind;
use io;
use mem;
use ptr;
use sys::c;
use sys::cvt;
+use u32;
/// An owned container for `HANDLE` object, closing them on Drop.
///
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
let mut read = 0;
+ // ReadFile takes a DWORD (u32) for the length so it only supports
+ // reading u32::MAX bytes at a time.
+ let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
let res = cvt(unsafe {
- c::ReadFile(self.0, buf.as_ptr() as c::LPVOID,
- buf.len() as c::DWORD, &mut read,
- ptr::null_mut())
+ c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
+ len, &mut read, ptr::null_mut())
});
match res {
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
let mut amt = 0;
+ // WriteFile takes a DWORD (u32) for the length so it only supports
+ // writing u32::MAX bytes at a time.
+ let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
try!(cvt(unsafe {
c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
- buf.len() as c::DWORD, &mut amt,
- ptr::null_mut())
+ len, &mut amt, ptr::null_mut())
}));
Ok(amt as usize)
}
use io;
use libc::{c_ulong, c_int, c_char, c_void};
use mem;
-use super::{SymFromAddrFn, SymGetLineFromAddr64Fn};
use sys::c;
use sys_common::backtrace::{output, output_fileline};
+type SymFromAddrFn =
+ extern "system" fn(c::HANDLE, u64, *mut u64,
+ *mut c::SYMBOL_INFO) -> c::BOOL;
+type SymGetLineFromAddr64Fn =
+ extern "system" fn(c::HANDLE, u64, *mut u32,
+ *mut c::IMAGEHLP_LINE64) -> c::BOOL;
+
pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary,
process: c::HANDLE) -> io::Result<()> {
let SymFromAddr = sym!(dbghelp, "SymFromAddr", SymFromAddrFn);
#[link_section = ".CRT$XLB"]
#[linkage = "external"]
-#[allow(warnings)]
+#[allow(dead_code, unused_variables)]
pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD,
c::LPVOID) =
on_tls_callback;
-#[allow(warnings)]
+#[allow(dead_code, unused_variables)]
unsafe extern "system" fn on_tls_callback(h: c::LPVOID,
dwReason: c::DWORD,
pv: c::LPVOID) {
use deriving::generic::*;
use deriving::generic::ty::*;
-use syntax::ast::{MetaItem, Expr};
+use syntax::ast::{MetaItem, Expr, VariantData};
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, Annotatable};
use syntax::ext::build::AstBuilder;
cx.expr_call_global(field.span, fn_path.clone(), args)
};
+ let vdata;
match *substr.fields {
- Struct(ref af) => {
+ Struct(vdata_, ref af) => {
ctor_path = cx.path(trait_span, vec![substr.type_ident]);
all_fields = af;
+ vdata = vdata_;
}
EnumMatching(_, variant, ref af) => {
ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]);
all_fields = af;
+ vdata = &variant.node.data;
},
EnumNonMatchingCollapsed (..) => {
cx.span_bug(trait_span,
}
}
- if !all_fields.is_empty() && all_fields[0].name.is_none() {
- // enum-like
- let subcalls = all_fields.iter().map(subcall).collect();
- let path = cx.expr_path(ctor_path);
- cx.expr_call(trait_span, path, subcalls)
- } else {
- // struct-like
- let fields = all_fields.iter().map(|field| {
- let ident = match field.name {
- Some(i) => i,
- None => {
- cx.span_bug(trait_span,
- &format!("unnamed field in normal struct in \
- `derive({})`", name))
- }
- };
- cx.field_imm(field.span, ident, subcall(field))
- }).collect::<Vec<_>>();
+ match *vdata {
+ VariantData::Struct(..) => {
+ let fields = all_fields.iter().map(|field| {
+ let ident = match field.name {
+ Some(i) => i,
+ None => {
+ cx.span_bug(trait_span,
+ &format!("unnamed field in normal struct in \
+ `derive({})`", name))
+ }
+ };
+ cx.field_imm(field.span, ident, subcall(field))
+ }).collect::<Vec<_>>();
- if fields.is_empty() {
- // no fields, so construct like `None`
- cx.expr_path(ctor_path)
- } else {
cx.expr_struct(trait_span, ctor_path, fields)
}
+ VariantData::Tuple(..) => {
+ let subcalls = all_fields.iter().map(subcall).collect();
+ let path = cx.expr_path(ctor_path);
+ cx.expr_call(trait_span, path, subcalls)
+ }
+ VariantData::Unit(..) => {
+ cx.expr_path(ctor_path)
+ }
}
}
// build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build()
// or fmt.debug_tuple(<name>).field(&<fieldval>)....build()
// based on the "shape".
- let ident = match *substr.fields {
- Struct(_) => substr.type_ident,
- EnumMatching(_, v, _) => v.node.name,
+ let (ident, is_struct) = match *substr.fields {
+ Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
+ EnumMatching(_, v, _) => (v.node.name, v.node.data.is_struct()),
EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => {
cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
}
let fmt = substr.nonself_args[0].clone();
let stmts = match *substr.fields {
- Struct(ref fields) | EnumMatching(_, _, ref fields) => {
+ Struct(_, ref fields) | EnumMatching(_, _, ref fields) => {
let mut stmts = vec![];
- if fields.is_empty() || fields[0].name.is_none() {
+ if !is_struct {
// tuple struct/"normal" variant
let expr = cx.expr_method_call(span,
fmt,
let encode = cx.ident_of("encode");
return match *substr.fields {
- Struct(ref fields) => {
+ Struct(_, ref fields) => {
let emit_struct_field = cx.ident_of("emit_struct_field");
let mut stmts = Vec::new();
for (i, &FieldInfo {
/// A summary of the possible sets of fields.
pub enum SubstructureFields<'a> {
- Struct(Vec<FieldInfo<'a>>),
+ Struct(&'a ast::VariantData, Vec<FieldInfo<'a>>),
/// Matching variants of the enum: variant index, ast::Variant,
/// fields: the field name is only non-`None` in the case of a struct
/// variant.
type_ident,
self_args,
nonself_args,
- &Struct(fields));
+ &Struct(struct_def, fields));
// make a series of nested matches, to destructure the
// structs. This is actually right-to-left, but it shouldn't
fields in generic `derive`"),
// named fields
(_, false) => Named(named_idents),
- // tuple structs (includes empty structs)
- (_, _) => Unnamed(just_spans)
+ // empty structs
+ _ if struct_def.is_struct() => Named(named_idents),
+ _ => Unnamed(just_spans),
}
}
P<Expr>,
&'a [ast::Attribute])>) {
if struct_def.fields().is_empty() {
- return (cx.pat_enum(self.span, struct_path, vec![]), vec![]);
+ if struct_def.is_struct() {
+ return (cx.pat_struct(self.span, struct_path, vec![]), vec![]);
+ } else {
+ return (cx.pat_enum(self.span, struct_path, vec![]), vec![]);
+ }
}
let mut paths = Vec::new();
// struct_type is definitely not Unknown, since struct_def.fields
// must be nonempty to reach here
- let pattern = if struct_type == Record {
+ let pattern = if struct_def.is_struct() {
let field_pats = subpats.into_iter().zip(&ident_expr)
.map(|(pat, &(_, id, _, _))| {
// id is guaranteed to be Some
F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>,
{
match *substructure.fields {
- EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
+ EnumMatching(_, _, ref all_fields) | Struct(_, ref all_fields) => {
if use_foldl {
all_fields.iter().fold(base, |old, field| {
f(cx,
F: FnOnce(&mut ExtCtxt, Span, Vec<P<Expr>>) -> P<Expr>,
{
match *substructure.fields {
- EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
+ EnumMatching(_, _, ref all_fields) | Struct(_, ref all_fields) => {
// call self_n.method(other_1_n, other_2_n, ...)
let called = all_fields.iter().map(|field| {
cx.expr_method_call(field.span,
let mut stmts = Vec::new();
let fields = match *substr.fields {
- Struct(ref fs) => fs,
+ Struct(_, ref fs) => fs,
EnumMatching(index, variant, ref fs) => {
// Determine the discriminant. We will feed this value to the byte
// iteration function.
+S 2016-02-17 4d3eebf
+ linux-i386 5f194aa7628c0703f0fd48adc4ec7f3cc64b98c7
+ linux-x86_64 d29b7607d13d64078b6324aec82926fb493f59ba
+ macos-i386 4c8e42dd649e247f3576bf9dfa273327b4907f9c
+ macos-x86_64 411a41363f922d1d93fa62ff2fedf5c35e9cccb2
+ winnt-i386 0c336d794a65f8e285c121866c7d59aa2dd0d1e1
+ winnt-x86_64 27e75b1bf99770b3564bcebd7f3230be01135a92
+ openbsd-x86_64 ac957c6b84de2bd67f01df085d9ea515f96e22f3
+
S 2015-12-18 3391630
bitrig-x86_64 6476e1562df02389b55553b4c88b1f4fd121cd40
freebsd-i386 7e624c50494402e1feb14c743d659fbd71b448f5
fn totalsum_substructure(cx: &mut ExtCtxt, trait_span: Span,
substr: &Substructure) -> P<ast::Expr> {
let fields = match *substr.fields {
- Struct(ref fs) | EnumMatching(_, _, ref fs) => fs,
+ Struct(_, ref fs) | EnumMatching(_, _, ref fs) => fs,
_ => cx.span_bug(trait_span, "impossible substructure")
};
--- /dev/null
+// Copyright 2015 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.
+
+// `#[derive(Trait)]` works for empty structs/variants with braces
+
+#![feature(braced_empty_structs)]
+#![feature(rustc_private)]
+
+extern crate serialize as rustc_serialize;
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
+ Default, Debug, RustcEncodable, RustcDecodable)]
+struct S {}
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
+ Debug, RustcEncodable, RustcDecodable)]
+enum E {
+ V {},
+ U,
+}
+
+fn main() {
+ let s = S {};
+ let s1 = s;
+ let s2 = s.clone();
+ assert_eq!(s, s1);
+ assert_eq!(s, s2);
+ assert!(!(s < s1));
+ assert_eq!(format!("{:?}", s), "S");
+
+ let e = E::V {};
+ let e1 = e;
+ let e2 = e.clone();
+ assert_eq!(e, e1);
+ assert_eq!(e, e2);
+ assert!(!(e < e1));
+ assert_eq!(format!("{:?}", e), "V");
+}