From df2c3a288a1f0218fe1abe34aa7b2287a39aa8f8 Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Thu, 22 Jan 2015 15:45:47 +0100 Subject: [PATCH 01/36] copyright: update paths and entries valgrind files moved and modpath.iss deleted. Both entries updated in COPYRIGHT file. Signed-off-by: Luca Bruno --- COPYRIGHT | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index da8ac7b3adde7..d4ad98e6e8799 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -23,12 +23,12 @@ The following third party packages are included, and carry their own copyright notices and license terms: * Two header files that are part of the Valgrind - package. These files are found at src/rt/vg/valgrind.h and - src/rt/vg/memcheck.h, within this distribution. These files + package. These files are found at src/rt/valgrind/valgrind.h and + src/rt/valgrind/memcheck.h, within this distribution. These files are redistributed under the following terms, as noted in them: - for src/rt/vg/valgrind.h: + for src/rt/valgrind/valgrind.h: This file is part of Valgrind, a dynamic binary instrumentation framework. @@ -74,7 +74,7 @@ their own copyright notices and license terms: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - for src/rt/vg/memcheck.h: + for src/rt/valgrind/memcheck.h: This file is part of MemCheck, a heavyweight Valgrind tool for detecting memory errors. @@ -120,18 +120,6 @@ their own copyright notices and license terms: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* The auxiliary file src/etc/pkg/modpath.iss contains a - library routine compiled, by Inno Setup, into the Windows - installer binary. This file is licensed under the LGPL, - version 3, but, in our legal interpretation, this does not - affect the aggregate "collected work" license of the Rust - distribution (MIT/ASL2) nor any other components of it. We - believe that the terms governing distribution of the - binary Windows installer built from modpath.iss are - therefore LGPL, but not the terms governing distribution - of any of the files installed by such an installer (such - as the Rust compiler or runtime libraries themselves). - * The src/rt/miniz.c file, carrying an implementation of RFC1950/RFC1951 DEFLATE, by Rich Geldreich . All uses of this file are From cf535a3b8fa63fb1e7539fa06e087c1886d48c0a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 30 Jan 2015 09:48:23 -0800 Subject: [PATCH 02/36] rustc: Use --extern to always override Previously if --extern was specified it would not override crates in the standard distribution, leading to issues like #21771. This commit alters the behavior such that if --extern is passed then it will always override any other choice of crates and no previous match will be used (unless it is the same path as --extern). Closes #21771 --- src/librustc/metadata/creader.rs | 1 + .../extern-overrides-distribution/Makefile | 5 +++++ .../extern-overrides-distribution/libc.rs | 13 +++++++++++++ .../extern-overrides-distribution/main.rs | 16 ++++++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 src/test/run-make/extern-overrides-distribution/Makefile create mode 100644 src/test/run-make/extern-overrides-distribution/libc.rs create mode 100644 src/test/run-make/extern-overrides-distribution/main.rs diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 7b71120ba64a6..16141b171ffa8 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -330,6 +330,7 @@ impl<'a> CrateReader<'a> { if found { ret = Some(cnum); } + return } // Alright, so we've gotten this far which means that `data` has the diff --git a/src/test/run-make/extern-overrides-distribution/Makefile b/src/test/run-make/extern-overrides-distribution/Makefile new file mode 100644 index 0000000000000..110db9f068dae --- /dev/null +++ b/src/test/run-make/extern-overrides-distribution/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) libc.rs + $(RUSTC) main.rs --extern libc=$(TMPDIR)/liblibc.rlib diff --git a/src/test/run-make/extern-overrides-distribution/libc.rs b/src/test/run-make/extern-overrides-distribution/libc.rs new file mode 100644 index 0000000000000..a489d834a9236 --- /dev/null +++ b/src/test/run-make/extern-overrides-distribution/libc.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] + +pub fn foo() {} diff --git a/src/test/run-make/extern-overrides-distribution/main.rs b/src/test/run-make/extern-overrides-distribution/main.rs new file mode 100644 index 0000000000000..92b353c892ae7 --- /dev/null +++ b/src/test/run-make/extern-overrides-distribution/main.rs @@ -0,0 +1,16 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate libc; + +fn main() { + libc::foo(); +} + From 682f867bbfff97e3aef55bdf228d279e45f25cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Fri, 30 Jan 2015 17:14:17 +0100 Subject: [PATCH 03/36] Add missing calls to llvm.lifetime.end intrinsics These missing calls lead to miscompilations with more recent LLVM versions. --- src/librustc_trans/trans/base.rs | 6 +++++- src/librustc_trans/trans/datum.rs | 4 ++++ src/librustc_trans/trans/intrinsic.rs | 9 +++++++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 1195b9f084b0f..5e7ea67fd84e5 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2007,7 +2007,11 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let bcx = match dest { expr::SaveIn(_) => bcx, expr::Ignore => { - glue::drop_ty(bcx, llresult, result_ty, debug_loc) + let bcx = glue::drop_ty(bcx, llresult, result_ty, debug_loc); + if !type_is_zero_size(ccx, result_ty) { + call_lifetime_end(bcx, llresult); + } + bcx } }; diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index dd4ef97b88da6..39d17f45ffa08 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -199,6 +199,9 @@ impl KindOps for Rvalue { -> Block<'blk, 'tcx> { // No cleanup is scheduled for an rvalue, so we don't have // to do anything after a move to cancel or duplicate it. + if self.is_by_ref() { + call_lifetime_end(bcx, _val); + } bcx } @@ -320,6 +323,7 @@ impl<'tcx> Datum<'tcx, Rvalue> { ByValue => DatumBlock::new(bcx, self), ByRef => { let llval = load_ty(bcx, self.val, self.ty); + call_lifetime_end(bcx, self.val); DatumBlock::new(bcx, Datum::new(llval, self.ty, Rvalue::new(ByValue))) } } diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 9bee2c5bbc61c..35e9179185515 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -243,7 +243,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, dest }; - fcx.pop_custom_cleanup_scope(cleanup_scope); + fcx.scopes.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean(); + fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope); return match dest { expr::SaveIn(d) => Result::new(bcx, d), @@ -268,7 +269,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, false, RustIntrinsic); - fcx.pop_custom_cleanup_scope(cleanup_scope); + fcx.scopes.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean(); let call_debug_location = DebugLoc::At(call_info.id, call_info.span); @@ -276,9 +277,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, if name.get() == "abort" { let llfn = ccx.get_intrinsic(&("llvm.trap")); Call(bcx, llfn, &[], None, call_debug_location); + fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope); Unreachable(bcx); return Result::new(bcx, C_undef(Type::nil(ccx).ptr_to())); } else if name.get() == "unreachable" { + fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope); Unreachable(bcx); return Result::new(bcx, C_nil(ccx)); } @@ -765,6 +768,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, expr::SaveIn(_) => {} } + fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope); + Result::new(bcx, llresult) } From 0832364946654a576383bdc49245fb22445bf069 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 30 Jan 2015 18:02:36 -0800 Subject: [PATCH 04/36] std: Stabilize Atomic{Isize,Usize} methods These methods were intended to be stable as of #16258 but the tags have since been lost in various refactorings. This commit re-adds the `#[stable]` attributes to each of these functions. --- src/libcore/atomic.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index cf2854be016e1..0f3823eb7a5b0 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -415,6 +415,7 @@ impl AtomicIsize { /// let atomic_forty_two = AtomicIsize::new(42); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(v: isize) -> AtomicIsize { AtomicIsize {v: UnsafeCell::new(v)} } @@ -437,6 +438,7 @@ impl AtomicIsize { /// let value = some_isize.load(Ordering::Relaxed); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn load(&self, order: Ordering) -> isize { unsafe { atomic_load(self.v.get(), order) } } @@ -459,6 +461,7 @@ impl AtomicIsize { /// /// Panics if `order` is `Acquire` or `AcqRel`. #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, val: isize, order: Ordering) { unsafe { atomic_store(self.v.get(), val, order); } } @@ -477,6 +480,7 @@ impl AtomicIsize { /// let value = some_isize.swap(10, Ordering::Relaxed); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(&self, val: isize, order: Ordering) -> isize { unsafe { atomic_swap(self.v.get(), val, order) } } @@ -498,6 +502,7 @@ impl AtomicIsize { /// let value = some_isize.compare_and_swap(5, 10, Ordering::Relaxed); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn compare_and_swap(&self, old: isize, new: isize, order: Ordering) -> isize { unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) } } @@ -514,6 +519,7 @@ impl AtomicIsize { /// assert_eq!(10, foo.load(Ordering::SeqCst)); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn fetch_add(&self, val: isize, order: Ordering) -> isize { unsafe { atomic_add(self.v.get(), val, order) } } @@ -530,6 +536,7 @@ impl AtomicIsize { /// assert_eq!(-10, foo.load(Ordering::SeqCst)); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn fetch_sub(&self, val: isize, order: Ordering) -> isize { unsafe { atomic_sub(self.v.get(), val, order) } } @@ -545,6 +552,7 @@ impl AtomicIsize { /// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst)); /// assert_eq!(0b100001, foo.load(Ordering::SeqCst)); #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn fetch_and(&self, val: isize, order: Ordering) -> isize { unsafe { atomic_and(self.v.get(), val, order) } } @@ -560,6 +568,7 @@ impl AtomicIsize { /// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst)); /// assert_eq!(0b111111, foo.load(Ordering::SeqCst)); #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn fetch_or(&self, val: isize, order: Ordering) -> isize { unsafe { atomic_or(self.v.get(), val, order) } } @@ -575,6 +584,7 @@ impl AtomicIsize { /// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst)); /// assert_eq!(0b011110, foo.load(Ordering::SeqCst)); #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn fetch_xor(&self, val: isize, order: Ordering) -> isize { unsafe { atomic_xor(self.v.get(), val, order) } } @@ -592,6 +602,7 @@ impl AtomicUsize { /// let atomic_forty_two = AtomicUsize::new(42); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(v: usize) -> AtomicUsize { AtomicUsize { v: UnsafeCell::new(v) } } @@ -614,6 +625,7 @@ impl AtomicUsize { /// let value = some_usize.load(Ordering::Relaxed); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn load(&self, order: Ordering) -> usize { unsafe { atomic_load(self.v.get(), order) } } @@ -636,6 +648,7 @@ impl AtomicUsize { /// /// Panics if `order` is `Acquire` or `AcqRel`. #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, val: usize, order: Ordering) { unsafe { atomic_store(self.v.get(), val, order); } } @@ -654,6 +667,7 @@ impl AtomicUsize { /// let value = some_usize.swap(10, Ordering::Relaxed); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(&self, val: usize, order: Ordering) -> usize { unsafe { atomic_swap(self.v.get(), val, order) } } @@ -675,6 +689,7 @@ impl AtomicUsize { /// let value = some_usize.compare_and_swap(5, 10, Ordering::Relaxed); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn compare_and_swap(&self, old: usize, new: usize, order: Ordering) -> usize { unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) } } @@ -691,6 +706,7 @@ impl AtomicUsize { /// assert_eq!(10, foo.load(Ordering::SeqCst)); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn fetch_add(&self, val: usize, order: Ordering) -> usize { unsafe { atomic_add(self.v.get(), val, order) } } @@ -707,6 +723,7 @@ impl AtomicUsize { /// assert_eq!(0, foo.load(Ordering::SeqCst)); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn fetch_sub(&self, val: usize, order: Ordering) -> usize { unsafe { atomic_sub(self.v.get(), val, order) } } @@ -722,6 +739,7 @@ impl AtomicUsize { /// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst)); /// assert_eq!(0b100001, foo.load(Ordering::SeqCst)); #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn fetch_and(&self, val: usize, order: Ordering) -> usize { unsafe { atomic_and(self.v.get(), val, order) } } @@ -737,6 +755,7 @@ impl AtomicUsize { /// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst)); /// assert_eq!(0b111111, foo.load(Ordering::SeqCst)); #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn fetch_or(&self, val: usize, order: Ordering) -> usize { unsafe { atomic_or(self.v.get(), val, order) } } @@ -752,6 +771,7 @@ impl AtomicUsize { /// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst)); /// assert_eq!(0b011110, foo.load(Ordering::SeqCst)); #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn fetch_xor(&self, val: usize, order: Ordering) -> usize { unsafe { atomic_xor(self.v.get(), val, order) } } From f9f7ad74cf6a46b3aa78a6240ad1404e76594026 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 30 Jan 2015 22:27:36 -0800 Subject: [PATCH 05/36] rustc: Make unused_features lint warn by default When it was un*known*_features it was reasonably to by deny by default. cc #21798 --- src/librustc/lint/builtin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index ae537e557e7d0..41a4dd3657479 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -1984,7 +1984,7 @@ declare_lint! { declare_lint! { pub UNUSED_FEATURES, - Deny, + Warn, "unused or unknown features found in crate-level #[feature] directives" } From e9ade4826a60d907f5df03105db86a13d3dc8843 Mon Sep 17 00:00:00 2001 From: madmalik Date: Sat, 31 Jan 2015 12:27:57 +0100 Subject: [PATCH 06/36] updating the link to rustdoc http://doc.rust-lang.org/rustdoc.html states that its content was moved to http://doc.rust-lang.org/book/documentation.html --- src/doc/trpl/comments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/comments.md b/src/doc/trpl/comments.md index 3c211b007cf90..66670c7c631cd 100644 --- a/src/doc/trpl/comments.md +++ b/src/doc/trpl/comments.md @@ -43,5 +43,5 @@ When writing doc comments, adding sections for any arguments, return values, and providing some examples of usage is very, very helpful. Don't worry about the `&str`, we'll get to it soon. -You can use the [`rustdoc`](../rustdoc.html) tool to generate HTML documentation +You can use the [`rustdoc`](documentation.html) tool to generate HTML documentation from these doc comments. From 64ca751eb000c498374435da666ddd1c878c03ad Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 31 Jan 2015 19:42:13 +0200 Subject: [PATCH 07/36] Mention the type in the overflowing literal lint Fixes #21807 --- src/librustc/lint/builtin.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index e8e8d35fe072a..bdc0ea12e2819 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -227,7 +227,7 @@ impl LintPass for TypeLimits { if (negative && v > (min.abs() as u64)) || (!negative && v > (max.abs() as u64)) { cx.span_lint(OVERFLOWING_LITERALS, e.span, - "literal out of range for its type"); + &*format!("literal out of range for {:?}", t)); return; } } @@ -246,7 +246,7 @@ impl LintPass for TypeLimits { }; if lit_val < min || lit_val > max { cx.span_lint(OVERFLOWING_LITERALS, e.span, - "literal out of range for its type"); + &*format!("literal out of range for {:?}", t)); } }, ty::ty_float(t) => { @@ -263,7 +263,7 @@ impl LintPass for TypeLimits { }; if lit_val < min || lit_val > max { cx.span_lint(OVERFLOWING_LITERALS, e.span, - "literal out of range for its type"); + &*format!("literal out of range for {:?}", t)); } }, _ => () From afa526c5710e45c9fb010bcd0a40c2867b29496d Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 31 Jan 2015 20:16:31 +0200 Subject: [PATCH 08/36] Update tests for overflowing literals Changed in 64ca751 --- src/test/compile-fail/lint-type-limits.rs | 4 +- src/test/compile-fail/lint-type-overflow.rs | 41 +++++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/test/compile-fail/lint-type-limits.rs b/src/test/compile-fail/lint-type-limits.rs index 3eae12f234fe2..95d892010e726 100644 --- a/src/test/compile-fail/lint-type-limits.rs +++ b/src/test/compile-fail/lint-type-limits.rs @@ -26,7 +26,7 @@ fn bar() -> i8 { fn baz() -> bool { 128 > bar() //~ ERROR comparison is useless due to type limits - //~^ WARNING literal out of range for its type + //~^ WARNING literal out of range for i8 } fn bleh() { @@ -44,7 +44,7 @@ fn bleh() { fn qux() { let mut i = 1i8; while 200 != i { //~ ERROR comparison is useless due to type limits - //~^ WARNING literal out of range for its type + //~^ WARNING literal out of range for i8 i += 1; } } diff --git a/src/test/compile-fail/lint-type-overflow.rs b/src/test/compile-fail/lint-type-overflow.rs index 47dc93dae13e9..ed6a0bd37eb28 100644 --- a/src/test/compile-fail/lint-type-overflow.rs +++ b/src/test/compile-fail/lint-type-overflow.rs @@ -18,42 +18,43 @@ fn test(x: i8) { #[allow(unused_variables)] fn main() { let x1: u8 = 255; // should be OK - let x1: u8 = 256; //~ error: literal out of range for its type + let x1: u8 = 256; //~ error: literal out of range for u8 let x1 = 255_u8; // should be OK - let x1 = 256_u8; //~ error: literal out of range for its type + let x1 = 256_u8; //~ error: literal out of range for u8 let x2: i8 = -128; // should be OK - let x1: i8 = 128; //~ error: literal out of range for its type - let x2: i8 = --128; //~ error: literal out of range for its type + let x1: i8 = 128; //~ error: literal out of range for i8 + let x2: i8 = --128; //~ error: literal out of range for i8 - let x3: i8 = -129; //~ error: literal out of range for its type - let x3: i8 = -(129); //~ error: literal out of range for its type - let x3: i8 = -{129}; //~ error: literal out of range for its type + let x3: i8 = -129; //~ error: literal out of range for i8 + let x3: i8 = -(129); //~ error: literal out of range for i8 + let x3: i8 = -{129}; //~ error: literal out of range for i8 - test(1000); //~ error: literal out of range for its type + test(1000); //~ error: literal out of range for i8 - let x = 128_i8; //~ error: literal out of range for its type + let x = 128_i8; //~ error: literal out of range for i8 let x = 127_i8; let x = -128_i8; let x = -(128_i8); - let x = -129_i8; //~ error: literal out of range for its type + let x = -129_i8; //~ error: literal out of range for i8 let x: i32 = 2147483647; // should be OK let x = 2147483647_i32; // should be OK - let x: i32 = 2147483648; //~ error: literal out of range for its type - let x = 2147483648_i32; //~ error: literal out of range for its type + let x: i32 = 2147483648; //~ error: literal out of range for i32 + let x = 2147483648_i32; //~ error: literal out of range for i32 let x: i32 = -2147483648; // should be OK let x = -2147483648_i32; // should be OK - let x: i32 = -2147483649; //~ error: literal out of range for its type - let x = -2147483649_i32; //~ error: literal out of range for its type + let x: i32 = -2147483649; //~ error: literal out of range for i32 + let x = -2147483649_i32; //~ error: literal out of range for i32 + let x = 2147483648; //~ error: literal out of range for i32 - let x = 9223372036854775808_i64; //~ error: literal out of range for its type + let x = 9223372036854775808_i64; //~ error: literal out of range for i64 let x = -9223372036854775808_i64; // should be OK - let x = 18446744073709551615_i64; //~ error: literal out of range for its type + let x = 18446744073709551615_i64; //~ error: literal out of range for i64 - let x = -3.40282348e+38_f32; //~ error: literal out of range for its type - let x = 3.40282348e+38_f32; //~ error: literal out of range for its type - let x = -1.7976931348623159e+308_f64; //~ error: literal out of range for its type - let x = 1.7976931348623159e+308_f64; //~ error: literal out of range for its type + let x = -3.40282348e+38_f32; //~ error: literal out of range for f32 + let x = 3.40282348e+38_f32; //~ error: literal out of range for f32 + let x = -1.7976931348623159e+308_f64; //~ error: literal out of range for f64 + let x = 1.7976931348623159e+308_f64; //~ error: literal out of range for f64 } From 1935bbd91321b4ebb61b21a300f43234a0be6433 Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Sun, 1 Feb 2015 02:49:12 +0800 Subject: [PATCH 09/36] Make use of a binary operator's RHS type for LHS inference For "symmetric" binary operators, meaning the types of two side must be equal, if the type of LHS doesn't know yet but RHS does, use that as an hint to infer LHS' type. Closes #21634 --- src/librustc_typeck/check/mod.rs | 57 +++++++++++++++++++++++--------- src/libsyntax/ast_util.rs | 14 ++++++++ src/test/run-pass/issue-21634.rs | 22 ++++++++++++ 3 files changed, 77 insertions(+), 16 deletions(-) create mode 100644 src/test/run-pass/issue-21634.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9dcde1c2a0a50..a41f27cfea880 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2815,11 +2815,19 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, BinopAssignment => PreferMutLvalue, SimpleBinop => NoPreference }; - check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref); + check_expr_with_lvalue_pref(fcx, lhs, lvalue_pref); // Callee does bot / err checking - let lhs_t = structurally_resolved_type(fcx, lhs.span, - fcx.expr_ty(&*lhs)); + let lhs_t = + structurally_resolve_type_or_else(fcx, lhs.span, fcx.expr_ty(lhs), || { + if ast_util::is_symmetric_binop(op.node) { + // Try RHS first + check_expr(fcx, &**rhs); + fcx.expr_ty(&**rhs) + } else { + fcx.tcx().types.err + } + }); if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op.node) { // Shift is a special case: rhs must be uint, no matter what lhs is @@ -5071,28 +5079,45 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } -// Resolves `typ` by a single level if `typ` is a type variable. If no -// resolution is possible, then an error is reported. -pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - sp: Span, - ty: Ty<'tcx>) - -> Ty<'tcx> +fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, + sp: Span, + ty: Ty<'tcx>, + f: F) -> Ty<'tcx> + where F: Fn() -> Ty<'tcx> { let mut ty = fcx.resolve_type_vars_if_possible(ty); - // If not, error. if ty::type_is_ty_var(ty) { - fcx.type_error_message(sp, |_actual| { - "the type of this value must be known in this \ - context".to_string() - }, ty, None); - demand::suptype(fcx, sp, fcx.tcx().types.err, ty); - ty = fcx.tcx().types.err; + let alternative = f(); + + // If not, error. + if ty::type_is_ty_var(alternative) || ty::type_is_error(alternative) { + fcx.type_error_message(sp, |_actual| { + "the type of this value must be known in this context".to_string() + }, ty, None); + demand::suptype(fcx, sp, fcx.tcx().types.err, ty); + ty = fcx.tcx().types.err; + } else { + demand::suptype(fcx, sp, alternative, ty); + ty = alternative; + } } ty } +// Resolves `typ` by a single level if `typ` is a type variable. If no +// resolution is possible, then an error is reported. +pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + sp: Span, + ty: Ty<'tcx>) + -> Ty<'tcx> +{ + structurally_resolve_type_or_else(fcx, sp, ty, || { + fcx.tcx().types.err + }) +} + // Returns true if b contains a break that can exit from b pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool { // First: is there an unlabeled break immediately diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 7f1264ac9a1d3..5049b87d69452 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -102,6 +102,20 @@ pub fn is_by_value_binop(b: BinOp_) -> bool { } } +/// Returns `true` if the binary operator is symmetric in the sense that LHS +/// and RHS must have the same type. So the type of LHS can serve as an hint +/// for the type of RHS and vice versa. +pub fn is_symmetric_binop(b: BinOp_) -> bool { + match b { + BiAdd | BiSub | BiMul | BiDiv | BiRem | + BiBitXor | BiBitAnd | BiBitOr | + BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => { + true + } + _ => false + } +} + /// Returns `true` if the unary operator takes its argument by value pub fn is_by_value_unop(u: UnOp) -> bool { match u { diff --git a/src/test/run-pass/issue-21634.rs b/src/test/run-pass/issue-21634.rs new file mode 100644 index 0000000000000..e5a2790917ff0 --- /dev/null +++ b/src/test/run-pass/issue-21634.rs @@ -0,0 +1,22 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +fn main() { + if let Ok(x) = "3.1415".parse() { + assert_eq!(false, x <= 0.0); + } + if let Ok(x) = "3.1415".parse() { + assert_eq!(3.1415, x + 0.0); + } + if let Ok(mut x) = "3.1415".parse() { + assert_eq!(8.1415, { x += 5.0; x }); + } +} From 60fa1ff347588027c4a1786b978f386447c35016 Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Sun, 1 Feb 2015 02:57:26 +0800 Subject: [PATCH 10/36] Fix fallout --- .../associated-types-ICE-when-projecting-out-of-err.rs | 4 ++-- src/test/compile-fail/issue-2149.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index 183781e9e2417..b35d5131c781a 100644 --- a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -29,6 +29,6 @@ trait Add { fn ice(a: A) { let r = loop {}; - r = r + a; // here the type `r` is not yet inferred, hence `r+a` generates an error. - //~^ ERROR type of this value must be known + r = r + a; + //~^ ERROR binary operation `+` cannot be applied to type `A` } diff --git a/src/test/compile-fail/issue-2149.rs b/src/test/compile-fail/issue-2149.rs index 691660f897157..4852dfc9a02bc 100644 --- a/src/test/compile-fail/issue-2149.rs +++ b/src/test/compile-fail/issue-2149.rs @@ -16,7 +16,7 @@ impl vec_monad for Vec { fn bind(&self, mut f: F) where F: FnMut(A) -> Vec { let mut r = panic!(); for elt in self.iter() { r = r + f(*elt); } - //~^ ERROR the type of this value must be known + //~^ ERROR binary operation `+` cannot be applied to type `collections::vec::Vec` } } fn main() { From 7eaa589fe519298893899a8581d57667f9427a11 Mon Sep 17 00:00:00 2001 From: Dan Yang Date: Sat, 31 Jan 2015 12:16:14 -0800 Subject: [PATCH 11/36] fix use decl code example in reference --- src/doc/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 936c0aac79f16..089db3f359c0f 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1061,7 +1061,7 @@ mod foo { extern crate core; use foo::core::iter; // good: foo is at crate root -// use core::iter; // bad: native is not at the crate root +// use core::iter; // bad: core is not at the crate root use self::baz::foobaz; // good: self refers to module 'foo' use foo::bar::foobar; // good: foo is at crate root From cedc6753f2bb8aedf527245ba9874e85cf669ac2 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Sat, 31 Jan 2015 14:54:43 -0800 Subject: [PATCH 12/36] Fix end of TtDelimited span --- src/libsyntax/parse/mod.rs | 23 +++++++++++++++++++++++ src/libsyntax/parse/parser.rs | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index e7be876edbbec..6e368bfa803a6 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -755,6 +755,7 @@ mod test { use ast; use abi; use attr::{first_attr_value_str_by_name, AttrMetaMethods}; + use parse; use parse::parser::Parser; use parse::token::{str_to_ident}; use print::pprust::item_to_string; @@ -1214,4 +1215,26 @@ mod test { let doc = first_attr_value_str_by_name(item.attrs.as_slice(), "doc").unwrap(); assert_eq!(doc.get(), "/** doc comment\n * with CRLF */"); } + + #[test] + fn ttdelim_span() { + let sess = parse::new_parse_sess(); + let expr = parse::parse_expr_from_source_str("foo".to_string(), + "foo!( fn main() { body } )".to_string(), vec![], &sess); + + let tts = match expr.node { + ast::ExprMac(ref mac) => { + let ast::MacInvocTT(_, ref tts, _) = mac.node; + tts.clone() + } + _ => panic!("not a macro"), + }; + + let span = tts.iter().rev().next().unwrap().get_span(); + + match sess.span_diagnostic.cm.span_to_snippet(span) { + Some(s) => assert_eq!(&s[], "{ body }"), + None => panic!("could not get snippet"), + } + } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d99095eeba377..8e88f5a567985 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2735,7 +2735,7 @@ impl<'a> Parser<'a> { self.open_braces.pop().unwrap(); // Expand to cover the entire delimited token tree - let span = Span { hi: self.span.hi, ..pre_span }; + let span = Span { hi: close_span.hi, ..pre_span }; TtDelimited(span, Rc::new(Delimited { delim: delim, From b796c1d6141b0677b2d2401cf65215b5438901ef Mon Sep 17 00:00:00 2001 From: Nick Sarten Date: Sun, 1 Feb 2015 16:42:22 +1300 Subject: [PATCH 13/36] Updated unicode escape documentation to match current implementation. Unicode escapes were changed in [this RFC](https://github.com/rust-lang/rfcs/blob/28aeb3c391c9afd344f124d3a69bdc2a420638b2/text/0446-es6-unicode-escapes.md) to use the ES6 \u{00FFFF} syntax with a variable number of digits from 1-6, eliminating the need for two different syntaxes for unicode literals. --- src/doc/grammar.md | 3 +-- src/doc/reference.md | 16 ++++++---------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/doc/grammar.md b/src/doc/grammar.md index c2cbb3ae3fb2f..59a1c8f828b29 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -196,8 +196,7 @@ raw_string : '"' raw_string_body '"' | '#' raw_string '#' ; common_escape : '\x5c' | 'n' | 'r' | 't' | '0' | 'x' hex_digit 2 -unicode_escape : 'u' hex_digit 4 - | 'U' hex_digit 8 ; +unicode_escape : 'u' '{' hex_digit+ 6 '}'; hex_digit : 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' diff --git a/src/doc/reference.md b/src/doc/reference.md index 936c0aac79f16..156054871da5e 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -250,8 +250,7 @@ cases mentioned in [Number literals](#number-literals) below. ##### Unicode escapes | | Name | |---|------| -| `\u7FFF` | 16-bit character code (exactly 4 digits) | -| `\U7EEEFFFF` | 32-bit character code (exactly 8 digits) | +| `\u{7FFF}` | 24-bit Unicode character code (up to 6 digits) | ##### Numbers @@ -286,8 +285,8 @@ raw_string : '"' raw_string_body '"' | '#' raw_string '#' ; common_escape : '\x5c' | 'n' | 'r' | 't' | '0' | 'x' hex_digit 2 -unicode_escape : 'u' hex_digit 4 - | 'U' hex_digit 8 ; + +unicode_escape : 'u' '{' hex_digit+ 6 '}'; hex_digit : 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' @@ -320,12 +319,9 @@ following forms: * An _8-bit codepoint escape_ escape starts with `U+0078` (`x`) and is followed by exactly two _hex digits_. It denotes the Unicode codepoint equal to the provided hex value. -* A _16-bit codepoint escape_ starts with `U+0075` (`u`) and is followed - by exactly four _hex digits_. It denotes the Unicode codepoint equal to - the provided hex value. -* A _32-bit codepoint escape_ starts with `U+0055` (`U`) and is followed - by exactly eight _hex digits_. It denotes the Unicode codepoint equal to - the provided hex value. +* A _24-bit codepoint escape_ starts with `U+0075` (`u`) and is followed + by up to six _hex digits_ surrounded by braces `U+007B` (`{`) and `U+007D` + (`}`). It denotes the Unicode codepoint equal to the provided hex value. * A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072` (`r`), or `U+0074` (`t`), denoting the unicode values `U+000A` (LF), `U+000D` (CR) or `U+0009` (HT) respectively. From fcb30a0b67b1bd4acbc3422ff74fac5d031ae1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Thu, 29 Jan 2015 08:19:28 +0100 Subject: [PATCH 14/36] openbsd support --- configure | 4 + mk/cfg/x86_64-unknown-openbsd.mk | 26 + src/compiletest/util.rs | 3 +- src/doc/reference.md | 3 +- src/etc/local_stage0.sh | 4 +- src/etc/snapshot.py | 5 +- src/libbacktrace/configure | 2 +- src/liblibc/lib.rs | 710 +++++++++++++++++- src/librustc_back/arm.rs | 4 +- src/librustc_back/mips.rs | 4 +- src/librustc_back/mipsel.rs | 4 +- src/librustc_back/rpath.rs | 6 +- src/librustc_back/target/mod.rs | 4 + src/librustc_back/target/openbsd_base.rs | 28 + .../target/x86_64_unknown_openbsd.rs | 28 + src/librustc_back/x86.rs | 5 +- src/librustc_back/x86_64.rs | 7 +- src/librustdoc/flock.rs | 4 +- src/libstd/dynamic_lib.rs | 19 +- src/libstd/os.rs | 34 +- src/libstd/rt/args.rs | 5 +- src/libstd/rt/libunwind.rs | 2 +- src/libstd/rtdeps.rs | 4 +- src/libstd/sys/common/net.rs | 10 +- src/libstd/sys/common/stack.rs | 11 + src/libstd/sys/unix/backtrace.rs | 5 +- src/libstd/sys/unix/c.rs | 17 +- src/libstd/sys/unix/os.rs | 30 +- src/libstd/sys/unix/process.rs | 5 +- src/libstd/sys/unix/stack_overflow.rs | 23 +- src/libstd/sys/unix/sync.rs | 4 +- src/libstd/sys/unix/thread.rs | 50 +- src/libstd/sys/unix/thread_local.rs | 8 +- src/libstd/sys/unix/time.rs | 3 +- src/libstd/sys/unix/tty.rs | 6 +- src/libsyntax/abi.rs | 6 +- src/rt/rust_builtin.c | 54 +- src/test/run-make/tools.mk | 3 + src/test/run-pass/intrinsic-alignment.rs | 3 +- src/test/run-pass/lang-item-public.rs | 6 +- src/test/run-pass/rec-align-u64.rs | 3 +- src/test/run-pass/tcp-stress.rs | 3 +- src/test/run-pass/x86stdcall.rs | 3 +- 43 files changed, 1066 insertions(+), 102 deletions(-) create mode 100644 mk/cfg/x86_64-unknown-openbsd.mk create mode 100644 src/librustc_back/target/openbsd_base.rs create mode 100644 src/librustc_back/target/x86_64_unknown_openbsd.rs diff --git a/configure b/configure index 7b7eac8e73527..2127f2c656d03 100755 --- a/configure +++ b/configure @@ -374,6 +374,10 @@ case $CFG_OSTYPE in CFG_OSTYPE=unknown-dragonfly ;; + OpenBSD) + CFG_OSTYPE=unknown-openbsd + ;; + Darwin) CFG_OSTYPE=apple-darwin ;; diff --git a/mk/cfg/x86_64-unknown-openbsd.mk b/mk/cfg/x86_64-unknown-openbsd.mk new file mode 100644 index 0000000000000..582d75c3eaf09 --- /dev/null +++ b/mk/cfg/x86_64-unknown-openbsd.mk @@ -0,0 +1,26 @@ +# x86_64-pc-openbsd-elf configuration +CC_x86_64-unknown-openbsd=$(CC) +CXX_x86_64-unknown-openbsd=$(CXX) +CPP_x86_64-unknown-openbsd=$(CPP) +AR_x86_64-unknown-openbsd=$(AR) +CFG_LIB_NAME_x86_64-unknown-openbsd=lib$(1).so +CFG_STATIC_LIB_NAME_x86_64-unknown-openbsd=lib$(1).a +CFG_LIB_GLOB_x86_64-unknown-openbsd=lib$(1)-*.so +CFG_LIB_DSYM_GLOB_x86_64-unknown-openbsd=$(1)-*.dylib.dSYM +CFG_JEMALLOC_CFLAGS_x86_64-unknown-openbsd := -m64 -I/usr/include $(CFLAGS) +CFG_GCCISH_CFLAGS_x86_64-unknown-openbsd := -Wall -Werror -g -fPIC -m64 -I/usr/include $(CFLAGS) +CFG_GCCISH_LINK_FLAGS_x86_64-unknown-openbsd := -shared -fPIC -g -pthread -m64 +CFG_GCCISH_DEF_FLAG_x86_64-unknown-openbsd := -Wl,--export-dynamic,--dynamic-list= +CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-openbsd := -Wl,-whole-archive +CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-openbsd := -Wl,-no-whole-archive +CFG_DEF_SUFFIX_x86_64-unknown-openbsd := .bsd.def +CFG_LLC_FLAGS_x86_64-unknown-openbsd := +CFG_INSTALL_NAME_x86_64-unknown-openbsd = +CFG_EXE_SUFFIX_x86_64-unknown-openbsd := +CFG_WINDOWSY_x86_64-unknown-openbsd := +CFG_UNIXY_x86_64-unknown-openbsd := 1 +CFG_PATH_MUNGE_x86_64-unknown-openbsd := +CFG_LDPATH_x86_64-unknown-openbsd := +CFG_RUN_x86_64-unknown-openbsd=$(2) +CFG_RUN_TARG_x86_64-unknown-openbsd=$(call CFG_RUN_x86_64-unknown-openbsd,,$(2)) +CFG_GNU_TRIPLE_x86_64-unknown-openbsd := x86_64-unknown-openbsd diff --git a/src/compiletest/util.rs b/src/compiletest/util.rs index a116cc33690db..533ff9d2676f5 100644 --- a/src/compiletest/util.rs +++ b/src/compiletest/util.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -23,6 +23,7 @@ static OS_TABLE: &'static [(&'static str, &'static str)] = &[ ("linux", "linux"), ("freebsd", "freebsd"), ("dragonfly", "dragonfly"), + ("openbsd", "openbsd"), ]; pub fn get_os(triple: &str) -> &'static str { diff --git a/src/doc/reference.md b/src/doc/reference.md index 936c0aac79f16..51914ef859e9d 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2195,7 +2195,8 @@ The following configurations must be defined by the implementation: `"unix"` or `"windows"`. The value of this configuration option is defined as a configuration itself, like `unix` or `windows`. * `target_os = "..."`. Operating system of the target, examples include - `"win32"`, `"macos"`, `"linux"`, `"android"`, `"freebsd"` or `"dragonfly"`. + `"win32"`, `"macos"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"` or + `"openbsd"`. * `target_word_size = "..."`. Target word size in bits. This is set to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for 64-bit pointers. diff --git a/src/etc/local_stage0.sh b/src/etc/local_stage0.sh index 41dea2eeff4a1..b506aff94e720 100755 --- a/src/etc/local_stage0.sh +++ b/src/etc/local_stage0.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT # file at the top-level directory of this distribution and at # http://rust-lang.org/COPYRIGHT. # @@ -18,7 +18,7 @@ LIB_PREFIX=lib OS=`uname -s` case $OS in - ("Linux"|"FreeBSD"|"DragonFly") + ("Linux"|"FreeBSD"|"DragonFly"|"OpenBSD") BIN_SUF= LIB_SUF=.so ;; diff --git a/src/etc/snapshot.py b/src/etc/snapshot.py index 698c3a551e2a0..264af5f9854cc 100644 --- a/src/etc/snapshot.py +++ b/src/etc/snapshot.py @@ -1,4 +1,4 @@ -# Copyright 2011-2014 The Rust Project Developers. See the COPYRIGHT +# Copyright 2011-2015 The Rust Project Developers. See the COPYRIGHT # file at the top-level directory of this distribution and at # http://rust-lang.org/COPYRIGHT. # @@ -46,6 +46,7 @@ def scrub(b): "winnt": ["bin/rustc.exe"], "freebsd": ["bin/rustc"], "dragonfly": ["bin/rustc"], + "openbsd": ["bin/rustc"], } winnt_runtime_deps_32 = ["libgcc_s_dw2-1.dll", "libstdc++-6.dll"] @@ -100,6 +101,8 @@ def get_kernel(triple): return "freebsd" if os_name == "dragonfly": return "dragonfly" + if os_name == "openbsd": + return "openbsd" return "linux" diff --git a/src/libbacktrace/configure b/src/libbacktrace/configure index f4f9d058ec8e1..14a9fd4f45279 100755 --- a/src/libbacktrace/configure +++ b/src/libbacktrace/configure @@ -9332,7 +9332,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) + freebsd* | dragonfly* | openbsd*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index bd8537f53cd32..dcd4edb0c219c 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -280,7 +280,8 @@ pub use funcs::bsd43::{shutdown}; #[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] pub use consts::os::posix01::{CLOCK_REALTIME, CLOCK_MONOTONIC}; #[cfg(any(target_os = "linux", target_os = "android"))] @@ -290,7 +291,7 @@ pub use types::os::arch::extra::{sockaddr_ll}; #[cfg(any(target_os = "linux", target_os = "android"))] pub use consts::os::extra::{AF_PACKET}; -#[cfg(all(unix, not(target_os = "freebsd")))] +#[cfg(all(unix, not(any(target_os = "freebsd", target_os = "openbsd"))))] pub use consts::os::extra::{MAP_STACK}; #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] @@ -1326,6 +1327,233 @@ pub mod types { } } + #[cfg(target_os = "openbsd")] + pub mod os { + pub mod common { + pub mod posix01 { + use types::common::c95::{c_void}; + use types::os::arch::c95::{c_char, c_int, size_t, + time_t, suseconds_t, c_long}; + use types::os::arch::c99::{uintptr_t}; + + pub type pthread_t = uintptr_t; + + #[repr(C)] + #[derive(Copy)] pub struct glob_t { + pub gl_pathc: c_int, + pub __unused1: c_int, + pub gl_offs: c_int, + pub __unused2: c_int, + pub gl_pathv: *mut *mut c_char, + + pub __unused3: *mut c_void, + + pub __unused4: *mut c_void, + pub __unused5: *mut c_void, + pub __unused6: *mut c_void, + pub __unused7: *mut c_void, + pub __unused8: *mut c_void, + pub __unused9: *mut c_void, + } + + #[repr(C)] + #[derive(Copy)] pub struct timeval { + pub tv_sec: time_t, + pub tv_usec: suseconds_t, + } + + #[repr(C)] + #[derive(Copy)] pub struct timespec { + pub tv_sec: time_t, + pub tv_nsec: c_long, + } + + #[derive(Copy)] pub enum timezone {} + + pub type sighandler_t = size_t; + } + pub mod bsd44 { + use types::common::c95::{c_void}; + use types::os::arch::c95::{c_char, c_int, c_uint}; + + pub type socklen_t = u32; + pub type sa_family_t = u8; + pub type in_port_t = u16; + pub type in_addr_t = u32; + #[repr(C)] + #[derive(Copy)] pub struct sockaddr { + pub sa_len: u8, + pub sa_family: sa_family_t, + pub sa_data: [u8; 14], + } + #[repr(C)] + #[derive(Copy)] pub struct sockaddr_storage { + pub ss_len: u8, + pub ss_family: sa_family_t, + pub __ss_pad1: [u8; 6], + pub __ss_pad2: i64, + pub __ss_pad3: [u8; 240], + } + #[repr(C)] + #[derive(Copy)] pub struct sockaddr_in { + pub sin_len: u8, + pub sin_family: sa_family_t, + pub sin_port: in_port_t, + pub sin_addr: in_addr, + pub sin_zero: [u8; 8], + } + #[repr(C)] + #[derive(Copy)] pub struct in_addr { + pub s_addr: in_addr_t, + } + #[repr(C)] + #[derive(Copy)] pub struct sockaddr_in6 { + pub sin6_len: u8, + pub sin6_family: sa_family_t, + pub sin6_port: in_port_t, + pub sin6_flowinfo: u32, + pub sin6_addr: in6_addr, + pub sin6_scope_id: u32, + } + #[repr(C)] + #[derive(Copy)] pub struct in6_addr { + pub s6_addr: [u16; 8] + } + #[repr(C)] + #[derive(Copy)] pub struct ip_mreq { + pub imr_multiaddr: in_addr, + pub imr_interface: in_addr, + } + #[repr(C)] + #[derive(Copy)] pub struct ip6_mreq { + pub ipv6mr_multiaddr: in6_addr, + pub ipv6mr_interface: c_uint, + } + #[repr(C)] + #[derive(Copy)] pub struct addrinfo { + pub ai_flags: c_int, + pub ai_family: c_int, + pub ai_socktype: c_int, + pub ai_protocol: c_int, + pub ai_addrlen: socklen_t, + pub ai_addr: *mut sockaddr, + pub ai_canonname: *mut c_char, + pub ai_next: *mut addrinfo, + } + #[repr(C)] + #[derive(Copy)] pub struct sockaddr_un { + pub sun_len: u8, + pub sun_family: sa_family_t, + pub sun_path: [c_char; 104] + } + #[repr(C)] + #[derive(Copy)] pub struct ifaddrs { + pub ifa_next: *mut ifaddrs, + pub ifa_name: *mut c_char, + pub ifa_flags: c_uint, + pub ifa_addr: *mut sockaddr, + pub ifa_netmask: *mut sockaddr, + pub ifa_dstaddr: *mut sockaddr, + pub ifa_data: *mut c_void + } + + } + } + + #[cfg(target_arch = "x86_64")] + 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 = i64; + pub type c_ulong = u64; + pub type c_float = f32; + pub type c_double = f64; + pub type size_t = u64; + pub type ptrdiff_t = i64; + pub type clock_t = i64; + pub type time_t = i64; + pub type suseconds_t = i64; + pub type wchar_t = i32; + } + pub mod c99 { + pub type c_longlong = i64; + pub type c_ulonglong = u64; + pub type intptr_t = i64; + pub type uintptr_t = u64; + 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 = u64; + pub type pid_t = i32; + pub type uid_t = u32; + pub type gid_t = u32; + pub type useconds_t = u32; + pub type mode_t = u32; + pub type ssize_t = i64; + } + pub mod posix01 { + use types::common::c95::{c_void}; + use types::common::c99::{uint32_t, uint64_t}; + use types::os::arch::c95::{c_long, time_t}; + use types::os::arch::posix88::{dev_t, gid_t}; + use types::os::arch::posix88::{mode_t, off_t}; + use types::os::arch::posix88::{uid_t}; + + pub type nlink_t = u32; + pub type blksize_t = uint32_t; + pub type ino_t = uint64_t; + pub type blkcnt_t = i64; + pub type fflags_t = u32; // type not declared, but struct stat have u_int32_t + + #[repr(C)] + #[derive(Copy)] pub struct stat { + pub st_mode: mode_t, + pub st_dev: dev_t, + pub st_ino: ino_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_birthtime: time_t, + pub st_birthtime_nsec: c_long, + } + #[repr(C)] + #[derive(Copy)] 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_os = "windows")] pub mod os { pub mod common { @@ -3254,7 +3482,8 @@ pub mod consts { } } - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] + #[cfg(any(target_os = "freebsd", + target_os = "dragonfly"))] pub mod os { pub mod c95 { use types::os::arch::c95::{c_int, c_uint}; @@ -3524,6 +3753,9 @@ pub mod consts { #[cfg(target_os = "dragonfly")] pub const PTHREAD_STACK_MIN: size_t = 1024; + #[cfg(target_os = "openbsd")] + pub const PTHREAD_STACK_MIN: size_t = 2048; + pub const CLOCK_REALTIME: c_int = 0; pub const CLOCK_MONOTONIC: c_int = 4; } @@ -3663,7 +3895,7 @@ pub mod consts { } } - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(target_os = "openbsd")] pub mod os { pub mod c95 { use types::os::arch::c95::{c_int, c_uint}; @@ -3751,14 +3983,11 @@ pub mod consts { pub const MCL_CURRENT : c_int = 0x0001; pub const MCL_FUTURE : c_int = 0x0002; + pub const MS_SYNC : c_int = 0x0002; // changed pub const MS_ASYNC : c_int = 0x0001; - pub const MS_INVALIDATE : c_int = 0x0002; - pub const MS_SYNC : c_int = 0x0010; - - pub const MS_KILLPAGES : c_int = 0x0004; - pub const MS_DEACTIVATE : c_int = 0x0008; + pub const MS_INVALIDATE : c_int = 0x0004; // changed - pub const EPERM : c_int = 1; + pub const EPERM : c_int = 1; // not checked pub const ENOENT : c_int = 2; pub const ESRCH : c_int = 3; pub const EINTR : c_int = 4; @@ -3793,7 +4022,7 @@ pub mod consts { pub const EDOM : c_int = 33; pub const ERANGE : c_int = 34; pub const EAGAIN : c_int = 35; - pub const EWOULDBLOCK : c_int = EAGAIN; + pub const EWOULDBLOCK : c_int = 35; pub const EINPROGRESS : c_int = 36; pub const EALREADY : c_int = 37; pub const ENOTSOCK : c_int = 38; @@ -3803,7 +4032,7 @@ pub mod consts { pub const ENOPROTOOPT : c_int = 42; pub const EPROTONOSUPPORT : c_int = 43; pub const ESOCKTNOSUPPORT : c_int = 44; - pub const ENOTSUP : c_int = 45; + pub const EOPNOTSUPP : c_int = 45; pub const EPFNOSUPPORT : c_int = 46; pub const EAFNOSUPPORT : c_int = 47; pub const EADDRINUSE : c_int = 48; @@ -3840,28 +4069,424 @@ pub mod consts { pub const EFTYPE : c_int = 79; pub const EAUTH : c_int = 80; pub const ENEEDAUTH : c_int = 81; - pub const EPWROFF : c_int = 82; - pub const EDEVERR : c_int = 83; + pub const EIDRM : c_int = 82; + pub const ENOMSG : c_int = 83; pub const EOVERFLOW : c_int = 84; - pub const EBADEXEC : c_int = 85; - pub const EBADARCH : c_int = 86; - pub const ESHLIBVERS : c_int = 87; - pub const EBADMACHO : c_int = 88; - pub const ECANCELED : c_int = 89; - pub const EIDRM : c_int = 90; - pub const ENOMSG : c_int = 91; - pub const EILSEQ : c_int = 92; - pub const ENOATTR : c_int = 93; - pub const EBADMSG : c_int = 94; - pub const EMULTIHOP : c_int = 95; - pub const ENODATA : c_int = 96; - pub const ENOLINK : c_int = 97; - pub const ENOSR : c_int = 98; - pub const ENOSTR : c_int = 99; - pub const EPROTO : c_int = 100; - pub const ETIME : c_int = 101; - pub const EOPNOTSUPP : c_int = 102; - pub const ENOPOLICY : c_int = 103; + pub const ECANCELED : c_int = 85; + pub const EILSEQ : c_int = 86; + pub const ENOATTR : c_int = 87; + pub const EDOOFUS : c_int = 88; + pub const EBADMSG : c_int = 89; + pub const EMULTIHOP : c_int = 90; + pub const ENOLINK : c_int = 91; + pub const EPROTO : c_int = 92; + pub const ENOMEDIUM : c_int = 93; + pub const EUNUSED94 : c_int = 94; + pub const EUNUSED95 : c_int = 95; + pub const EUNUSED96 : c_int = 96; + pub const EUNUSED97 : c_int = 97; + pub const EUNUSED98 : c_int = 98; + pub const EASYNC : c_int = 99; + pub const ELAST : c_int = 99; + } + pub mod posix01 { + use types::os::arch::c95::{c_int, size_t}; + + pub const F_DUPFD : c_int = 0; + pub const F_GETFD : c_int = 1; + pub const F_SETFD : c_int = 2; + pub const F_GETFL : c_int = 3; + pub const F_SETFL : c_int = 4; + + pub const SIGTRAP : c_int = 5; + pub const SIGPIPE: c_int = 13; + pub const SIG_IGN: size_t = 1; + + pub const GLOB_APPEND : c_int = 0x0001; + pub const GLOB_DOOFFS : c_int = 0x0002; + pub const GLOB_ERR : c_int = 0x0004; + pub const GLOB_MARK : c_int = 0x0008; + pub const GLOB_NOCHECK : c_int = 0x0010; + pub const GLOB_NOSORT : c_int = 0x0020; + pub const GLOB_NOESCAPE : c_int = 0x1000; // changed + + pub const GLOB_NOSPACE : c_int = -1; + pub const GLOB_ABORTED : c_int = -2; + pub const GLOB_NOMATCH : c_int = -3; + + pub const POSIX_MADV_NORMAL : c_int = 0; + pub const POSIX_MADV_RANDOM : c_int = 1; + pub const POSIX_MADV_SEQUENTIAL : c_int = 2; + pub const POSIX_MADV_WILLNEED : c_int = 3; + pub const POSIX_MADV_DONTNEED : c_int = 4; + + pub const _SC_IOV_MAX : c_int = 51; // all changed... + pub const _SC_GETGR_R_SIZE_MAX : c_int = 100; + pub const _SC_GETPW_R_SIZE_MAX : c_int = 101; + pub const _SC_LOGIN_NAME_MAX : c_int = 102; + pub const _SC_MQ_PRIO_MAX : c_int = 59; + pub const _SC_THREAD_ATTR_STACKADDR : c_int = 77; + pub const _SC_THREAD_ATTR_STACKSIZE : c_int = 78; + pub const _SC_THREAD_DESTRUCTOR_ITERATIONS : c_int = 80; + pub const _SC_THREAD_KEYS_MAX : c_int = 81; + pub const _SC_THREAD_PRIO_INHERIT : c_int = 82; + pub const _SC_THREAD_PRIO_PROTECT : c_int = 83; + pub const _SC_THREAD_PRIORITY_SCHEDULING : c_int = 84; + pub const _SC_THREAD_PROCESS_SHARED : c_int = 85; + pub const _SC_THREAD_SAFE_FUNCTIONS : c_int = 103; + pub const _SC_THREAD_STACK_MIN : c_int = 89; + pub const _SC_THREAD_THREADS_MAX : c_int = 90; + pub const _SC_THREADS : c_int = 91; + pub const _SC_TTY_NAME_MAX : c_int = 107; + pub const _SC_ATEXIT_MAX : c_int = 46; + pub const _SC_XOPEN_CRYPT : c_int = 117; + pub const _SC_XOPEN_ENH_I18N : c_int = 118; + pub const _SC_XOPEN_LEGACY : c_int = 119; + pub const _SC_XOPEN_REALTIME : c_int = 120; + pub const _SC_XOPEN_REALTIME_THREADS : c_int = 121; + pub const _SC_XOPEN_SHM : c_int = 30; + pub const _SC_XOPEN_UNIX : c_int = 123; + pub const _SC_XOPEN_VERSION : c_int = 125; + //pub const _SC_XOPEN_XCU_VERSION : c_int = ; + + pub const PTHREAD_CREATE_JOINABLE: c_int = 0; + pub const PTHREAD_CREATE_DETACHED: c_int = 1; + pub const PTHREAD_STACK_MIN: size_t = 2048; + + pub const CLOCK_REALTIME: c_int = 0; + pub const CLOCK_MONOTONIC: c_int = 3; + } + pub mod posix08 { + } + pub mod bsd44 { + use types::os::arch::c95::c_int; + + pub const MADV_NORMAL : c_int = 0; + pub const MADV_RANDOM : c_int = 1; + pub const MADV_SEQUENTIAL : c_int = 2; + pub const MADV_WILLNEED : c_int = 3; + pub const MADV_DONTNEED : c_int = 4; + pub const MADV_FREE : c_int = 6; // changed + //pub const MADV_NOSYNC : c_int = ; + //pub const MADV_AUTOSYNC : c_int = ; + //pub const MADV_NOCORE : c_int = ; + //pub const MADV_CORE : c_int = ; + //pub const MADV_PROTECT : c_int = ; + + //pub const MINCORE_INCORE : c_int = ; + //pub const MINCORE_REFERENCED : c_int = ; + //pub const MINCORE_MODIFIED : c_int = ; + //pub const MINCORE_REFERENCED_OTHER : c_int = ; + //pub const MINCORE_MODIFIED_OTHER : c_int = ; + //pub const MINCORE_SUPER : c_int = ; + + pub const AF_INET: c_int = 2; + pub const AF_INET6: c_int = 24; // changed + pub const AF_UNIX: c_int = 1; + pub const SOCK_STREAM: c_int = 1; + pub const SOCK_DGRAM: c_int = 2; + pub const SOCK_RAW: c_int = 3; + pub const IPPROTO_TCP: c_int = 6; + pub const IPPROTO_IP: c_int = 0; + pub const IPPROTO_IPV6: c_int = 41; + pub const IP_MULTICAST_TTL: c_int = 10; + pub const IP_MULTICAST_LOOP: c_int = 11; + pub const IP_TTL: c_int = 4; + pub const IP_HDRINCL: c_int = 2; + pub const IP_ADD_MEMBERSHIP: c_int = 12; + pub const IP_DROP_MEMBERSHIP: c_int = 13; + pub const IPV6_ADD_MEMBERSHIP: c_int = 12; // don't exist, keep same as IP_ADD_MEMBERSHIP + pub const IPV6_DROP_MEMBERSHIP: c_int = 13; // don't exist, keep same as IP_DROP_MEMBERSHIP + + pub const TCP_NODELAY: c_int = 1; + //pub const TCP_KEEPIDLE: c_int = ; + pub const SOL_SOCKET: c_int = 0xffff; + pub const SO_KEEPALIVE: c_int = 0x0008; + pub const SO_BROADCAST: c_int = 0x0020; + pub const SO_REUSEADDR: c_int = 0x0004; + pub const SO_ERROR: c_int = 0x1007; + + pub const IFF_LOOPBACK: c_int = 0x8; + + pub const SHUT_RD: c_int = 0; + pub const SHUT_WR: c_int = 1; + pub const SHUT_RDWR: c_int = 2; + } + pub mod extra { + use types::os::arch::c95::c_int; + + pub const O_SYNC : c_int = 128; + pub const O_NONBLOCK : c_int = 4; + pub const CTL_KERN: c_int = 1; + pub const KERN_PROC: c_int = 66; + + pub const MAP_COPY : c_int = 0x0002; + pub const MAP_RENAME : c_int = 0x0000; // changed + pub const MAP_NORESERVE : c_int = 0x0000; // changed + pub const MAP_HASSEMAPHORE : c_int = 0x0000; // changed + //pub const MAP_STACK : c_int = ; + //pub const MAP_NOSYNC : c_int = ; + //pub const MAP_NOCORE : c_int = ; + + pub const IPPROTO_RAW : c_int = 255; + } + pub mod sysconf { + use types::os::arch::c95::c_int; + + pub const _SC_ARG_MAX : c_int = 1; + pub const _SC_CHILD_MAX : c_int = 2; + pub const _SC_CLK_TCK : c_int = 3; + pub const _SC_NGROUPS_MAX : c_int = 4; + pub const _SC_OPEN_MAX : c_int = 5; + pub const _SC_JOB_CONTROL : c_int = 6; + pub const _SC_SAVED_IDS : c_int = 7; + pub const _SC_VERSION : c_int = 8; + pub const _SC_BC_BASE_MAX : c_int = 9; + pub const _SC_BC_DIM_MAX : c_int = 10; + pub const _SC_BC_SCALE_MAX : c_int = 11; + pub const _SC_BC_STRING_MAX : c_int = 12; + pub const _SC_COLL_WEIGHTS_MAX : c_int = 13; + pub const _SC_EXPR_NEST_MAX : c_int = 14; + pub const _SC_LINE_MAX : c_int = 15; + pub const _SC_RE_DUP_MAX : c_int = 16; + pub const _SC_2_VERSION : c_int = 17; + pub const _SC_2_C_BIND : c_int = 18; + pub const _SC_2_C_DEV : c_int = 19; + pub const _SC_2_CHAR_TERM : c_int = 20; + pub const _SC_2_FORT_DEV : c_int = 21; + pub const _SC_2_FORT_RUN : c_int = 22; + pub const _SC_2_LOCALEDEF : c_int = 23; + pub const _SC_2_SW_DEV : c_int = 24; + pub const _SC_2_UPE : c_int = 25; + pub const _SC_STREAM_MAX : c_int = 26; + pub const _SC_TZNAME_MAX : c_int = 27; + pub const _SC_ASYNCHRONOUS_IO : c_int = 45; // changed... + pub const _SC_MAPPED_FILES : c_int = 53; + pub const _SC_MEMLOCK : c_int = 54; + pub const _SC_MEMLOCK_RANGE : c_int = 55; + pub const _SC_MEMORY_PROTECTION : c_int = 56; + pub const _SC_MESSAGE_PASSING : c_int = 57; + pub const _SC_PRIORITIZED_IO : c_int = 60; + pub const _SC_PRIORITY_SCHEDULING : c_int = 61; + pub const _SC_REALTIME_SIGNALS : c_int = 64; + pub const _SC_SEMAPHORES : c_int = 67; + pub const _SC_FSYNC : c_int = 29; + pub const _SC_SHARED_MEMORY_OBJECTS : c_int = 68; + pub const _SC_SYNCHRONIZED_IO : c_int = 75; + pub const _SC_TIMERS : c_int = 94; // ...changed + pub const _SC_AIO_LISTIO_MAX : c_int = 42; + pub const _SC_AIO_MAX : c_int = 43; + pub const _SC_AIO_PRIO_DELTA_MAX : c_int = 44; + pub const _SC_DELAYTIMER_MAX : c_int = 50; // changed... + pub const _SC_MQ_OPEN_MAX : c_int = 58; + pub const _SC_PAGESIZE : c_int = 28; + pub const _SC_RTSIG_MAX : c_int = 66; + pub const _SC_SEM_NSEMS_MAX : c_int = 31; + pub const _SC_SEM_VALUE_MAX : c_int = 32; + pub const _SC_SIGQUEUE_MAX : c_int = 70; + pub const _SC_TIMER_MAX : c_int = 93; + } + } + + #[cfg(any(target_os = "macos", target_os = "ios"))] + pub mod os { + pub mod c95 { + use types::os::arch::c95::{c_int, c_uint}; + + pub const EXIT_FAILURE : c_int = 1; + pub const EXIT_SUCCESS : c_int = 0; + pub const RAND_MAX : c_int = 2147483647; + pub const EOF : c_int = -1; + pub const SEEK_SET : c_int = 0; + pub const SEEK_CUR : c_int = 1; + pub const SEEK_END : c_int = 2; + pub const _IOFBF : c_int = 0; + pub const _IONBF : c_int = 2; + pub const _IOLBF : c_int = 1; + pub const BUFSIZ : c_uint = 1024_u32; + pub const FOPEN_MAX : c_uint = 20_u32; + pub const FILENAME_MAX : c_uint = 1024_u32; + pub const L_tmpnam : c_uint = 1024_u32; + pub const TMP_MAX : c_uint = 308915776_u32; + } + pub mod c99 { + } + pub mod posix88 { + use types::common::c95::c_void; + use types::os::arch::c95::c_int; + use types::os::arch::posix88::mode_t; + + pub const O_RDONLY : c_int = 0; + pub const O_WRONLY : c_int = 1; + pub const O_RDWR : c_int = 2; + pub const O_APPEND : c_int = 8; + pub const O_CREAT : c_int = 512; + pub const O_EXCL : c_int = 2048; + pub const O_TRUNC : c_int = 1024; + pub const S_IFIFO : mode_t = 4096; + pub const S_IFCHR : mode_t = 8192; + pub const S_IFBLK : mode_t = 24576; + pub const S_IFDIR : mode_t = 16384; + pub const S_IFREG : mode_t = 32768; + pub const S_IFLNK : mode_t = 40960; + pub const S_IFMT : mode_t = 61440; + pub const S_IEXEC : mode_t = 64; + pub const S_IWRITE : mode_t = 128; + pub const S_IREAD : mode_t = 256; + pub const S_IRWXU : mode_t = 448; + pub const S_IXUSR : mode_t = 64; + pub const S_IWUSR : mode_t = 128; + pub const S_IRUSR : mode_t = 256; + pub const F_OK : c_int = 0; + pub const R_OK : c_int = 4; + pub const W_OK : c_int = 2; + pub const X_OK : c_int = 1; + pub const STDIN_FILENO : c_int = 0; + pub const STDOUT_FILENO : c_int = 1; + pub const STDERR_FILENO : c_int = 2; + pub const F_LOCK : c_int = 1; + pub const F_TEST : c_int = 3; + pub const F_TLOCK : c_int = 2; + pub const F_ULOCK : c_int = 0; + pub const SIGHUP : c_int = 1; + pub const SIGINT : c_int = 2; + pub const SIGQUIT : c_int = 3; + pub const SIGILL : c_int = 4; + pub const SIGABRT : c_int = 6; + pub const SIGFPE : c_int = 8; + pub const SIGKILL : c_int = 9; + pub const SIGSEGV : c_int = 11; + pub const SIGPIPE : c_int = 13; + pub const SIGALRM : c_int = 14; + pub const SIGTERM : c_int = 15; + + pub const PROT_NONE : c_int = 0; + pub const PROT_READ : c_int = 1; + pub const PROT_WRITE : c_int = 2; + pub const PROT_EXEC : c_int = 4; + + pub const MAP_FILE : c_int = 0x0000; + pub const MAP_SHARED : c_int = 0x0001; + pub const MAP_PRIVATE : c_int = 0x0002; + pub const MAP_FIXED : c_int = 0x0010; + pub const MAP_ANON : c_int = 0x1000; + + pub const MAP_FAILED : *mut c_void = -1 as *mut c_void; + + pub const MCL_CURRENT : c_int = 0x0001; + pub const MCL_FUTURE : c_int = 0x0002; + + pub const MS_ASYNC : c_int = 0x0001; + pub const MS_INVALIDATE : c_int = 0x0002; + pub const MS_SYNC : c_int = 0x0010; + + pub const MS_KILLPAGES : c_int = 0x0004; + pub const MS_DEACTIVATE : c_int = 0x0008; + + pub const EPERM : c_int = 1; + pub const ENOENT : c_int = 2; + pub const ESRCH : c_int = 3; + pub const EINTR : c_int = 4; + pub const EIO : c_int = 5; + pub const ENXIO : c_int = 6; + pub const E2BIG : c_int = 7; + pub const ENOEXEC : c_int = 8; + pub const EBADF : c_int = 9; + pub const ECHILD : c_int = 10; + pub const EDEADLK : c_int = 11; + pub const ENOMEM : c_int = 12; + pub const EACCES : c_int = 13; + pub const EFAULT : c_int = 14; + pub const ENOTBLK : c_int = 15; + pub const EBUSY : c_int = 16; + pub const EEXIST : c_int = 17; + pub const EXDEV : c_int = 18; + pub const ENODEV : c_int = 19; + pub const ENOTDIR : c_int = 20; + pub const EISDIR : c_int = 21; + pub const EINVAL : c_int = 22; + pub const ENFILE : c_int = 23; + pub const EMFILE : c_int = 24; + pub const ENOTTY : c_int = 25; + pub const ETXTBSY : c_int = 26; + pub const EFBIG : c_int = 27; + pub const ENOSPC : c_int = 28; + pub const ESPIPE : c_int = 29; + pub const EROFS : c_int = 30; + pub const EMLINK : c_int = 31; + pub const EPIPE : c_int = 32; + pub const EDOM : c_int = 33; + pub const ERANGE : c_int = 34; + pub const EAGAIN : c_int = 35; + pub const EWOULDBLOCK : c_int = EAGAIN; + pub const EINPROGRESS : c_int = 36; + pub const EALREADY : c_int = 37; + pub const ENOTSOCK : c_int = 38; + pub const EDESTADDRREQ : c_int = 39; + pub const EMSGSIZE : c_int = 40; + pub const EPROTOTYPE : c_int = 41; + pub const ENOPROTOOPT : c_int = 42; + pub const EPROTONOSUPPORT : c_int = 43; + pub const ESOCKTNOSUPPORT : c_int = 44; + pub const ENOTSUP : c_int = 45; + pub const EPFNOSUPPORT : c_int = 46; + pub const EAFNOSUPPORT : c_int = 47; + pub const EADDRINUSE : c_int = 48; + pub const EADDRNOTAVAIL : c_int = 49; + pub const ENETDOWN : c_int = 50; + pub const ENETUNREACH : c_int = 51; + pub const ENETRESET : c_int = 52; + pub const ECONNABORTED : c_int = 53; + pub const ECONNRESET : c_int = 54; + pub const ENOBUFS : c_int = 55; + pub const EISCONN : c_int = 56; + pub const ENOTCONN : c_int = 57; + pub const ESHUTDOWN : c_int = 58; + pub const ETOOMANYREFS : c_int = 59; + pub const ETIMEDOUT : c_int = 60; + pub const ECONNREFUSED : c_int = 61; + pub const ELOOP : c_int = 62; + pub const ENAMETOOLONG : c_int = 63; + pub const EHOSTDOWN : c_int = 64; + pub const EHOSTUNREACH : c_int = 65; + pub const ENOTEMPTY : c_int = 66; + pub const EPROCLIM : c_int = 67; + pub const EUSERS : c_int = 68; + pub const EDQUOT : c_int = 69; + pub const ESTALE : c_int = 70; + pub const EREMOTE : c_int = 71; + pub const EBADRPC : c_int = 72; + pub const ERPCMISMATCH : c_int = 73; + pub const EPROGUNAVAIL : c_int = 74; + pub const EPROGMISMATCH : c_int = 75; + pub const EPROCUNAVAIL : c_int = 76; + pub const ENOLCK : c_int = 77; + pub const ENOSYS : c_int = 78; + pub const EFTYPE : c_int = 79; + pub const EAUTH : c_int = 80; + pub const ENEEDAUTH : c_int = 81; + pub const EPWROFF : c_int = 82; + pub const EDEVERR : c_int = 83; + pub const EOVERFLOW : c_int = 84; + pub const EBADEXEC : c_int = 85; + pub const EBADARCH : c_int = 86; + pub const ESHLIBVERS : c_int = 87; + pub const EBADMACHO : c_int = 88; + pub const ECANCELED : c_int = 89; + pub const EIDRM : c_int = 90; + pub const ENOMSG : c_int = 91; + pub const EILSEQ : c_int = 92; + pub const ENOATTR : c_int = 93; + pub const EBADMSG : c_int = 94; + pub const EMULTIHOP : c_int = 95; + pub const ENODATA : c_int = 96; + pub const ENOLINK : c_int = 97; + pub const ENOSR : c_int = 98; + pub const ENOSTR : c_int = 99; + pub const EPROTO : c_int = 100; + pub const ETIME : c_int = 101; + pub const EOPNOTSUPP : c_int = 102; + pub const ENOPOLICY : c_int = 103; pub const ENOTRECOVERABLE : c_int = 104; pub const EOWNERDEAD : c_int = 105; pub const EQFULL : c_int = 106; @@ -4380,7 +5005,8 @@ pub mod funcs { target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] pub mod posix88 { pub mod stat_ { use types::os::arch::c95::{c_char, c_int}; @@ -4394,6 +5020,7 @@ pub mod funcs { #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", + target_os = "openbsd", target_os = "android", target_os = "ios"))] pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; @@ -4408,6 +5035,7 @@ pub mod funcs { #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", + target_os = "openbsd", target_os = "android", target_os = "ios"))] pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; @@ -4600,7 +5228,8 @@ pub mod funcs { target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] pub mod posix01 { pub mod stat_ { use types::os::arch::c95::{c_char, c_int}; @@ -4610,6 +5239,7 @@ pub mod funcs { #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", + target_os = "openbsd", target_os = "android", target_os = "ios"))] pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int; @@ -4717,7 +5347,8 @@ pub mod funcs { target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] pub mod posix08 { pub mod unistd { } @@ -4803,7 +5434,8 @@ pub mod funcs { #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] pub mod bsd44 { use types::common::c95::{c_void}; use types::os::arch::c95::{c_char, c_uchar, c_int, c_uint, c_ulong, size_t}; @@ -4866,7 +5498,9 @@ pub mod funcs { } } - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] + #[cfg(any(target_os = "freebsd", + target_os = "dragonfly", + target_os = "openbsd"))] pub mod extra { } diff --git a/src/librustc_back/arm.rs b/src/librustc_back/arm.rs index 7e28cd699a1a6..a4417b49f1c41 100644 --- a/src/librustc_back/arm.rs +++ b/src/librustc_back/arm.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -61,7 +61,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs -a:0:64-n32".to_string() } - abi::OsFreebsd | abi::OsDragonfly => { + abi::OsFreebsd | abi::OsDragonfly | abi::OsOpenbsd => { "e-p:32:32:32\ -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\ -f32:32:32-f64:64:64\ diff --git a/src/librustc_back/mips.rs b/src/librustc_back/mips.rs index bc7732157cefe..cb44fe117f546 100644 --- a/src/librustc_back/mips.rs +++ b/src/librustc_back/mips.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -56,7 +56,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs -a:0:64-n32".to_string() } - abi::OsFreebsd | abi::OsDragonfly => { + abi::OsFreebsd | abi::OsDragonfly | abi::OsOpenbsd => { "E-p:32:32:32\ -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\ -f32:32:32-f64:64:64\ diff --git a/src/librustc_back/mipsel.rs b/src/librustc_back/mipsel.rs index 3eea0a0dba405..7ee357fb1eaf3 100644 --- a/src/librustc_back/mipsel.rs +++ b/src/librustc_back/mipsel.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -56,7 +56,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs -a:0:64-n32".to_string() } - abi::OsFreebsd | abi::OsDragonfly => { + abi::OsFreebsd | abi::OsDragonfly | abi::OsOpenbsd => { "e-p:32:32:32\ -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\ -f32:32:32-f64:64:64\ diff --git a/src/librustc_back/rpath.rs b/src/librustc_back/rpath.rs index 47b909df5e8da..0c18f1bdf7764 100644 --- a/src/librustc_back/rpath.rs +++ b/src/librustc_back/rpath.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -214,7 +214,9 @@ mod test { } #[test] - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] + #[cfg(any(target_os = "freebsd", + target_os = "dragonfly", + target_os = "openbsd"))] fn test_rpath_relative() { let config = &mut RPathConfig { used_crates: Vec::new(), diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 16adccfba575e..1e787a3583868 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -56,6 +56,7 @@ mod apple_base; mod apple_ios_base; mod freebsd_base; mod dragonfly_base; +mod openbsd_base; mod armv7_apple_ios; mod armv7s_apple_ios; @@ -80,6 +81,7 @@ mod x86_64_pc_windows_gnu; mod x86_64_unknown_freebsd; mod x86_64_unknown_dragonfly; mod x86_64_unknown_linux_gnu; +mod x86_64_unknown_openbsd; /// Everything `rustc` knows about how to compile for a specific target. /// @@ -352,6 +354,8 @@ impl Target { i686_unknown_dragonfly, x86_64_unknown_dragonfly, + x86_64_unknown_openbsd, + x86_64_apple_darwin, i686_apple_darwin, diff --git a/src/librustc_back/target/openbsd_base.rs b/src/librustc_back/target/openbsd_base.rs new file mode 100644 index 0000000000000..42220a87bd414 --- /dev/null +++ b/src/librustc_back/target/openbsd_base.rs @@ -0,0 +1,28 @@ +// Copyright 2014-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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::TargetOptions; +use std::default::Default; + +pub fn opts() -> TargetOptions { + TargetOptions { + linker: "cc".to_string(), + dynamic_linking: true, + executables: true, + morestack: false, + linker_is_gnu: true, + has_rpath: true, + pre_link_args: vec!( + ), + position_independent_executables: true, + .. Default::default() + } +} + diff --git a/src/librustc_back/target/x86_64_unknown_openbsd.rs b/src/librustc_back/target/x86_64_unknown_openbsd.rs new file mode 100644 index 0000000000000..d2667dcd1dd9e --- /dev/null +++ b/src/librustc_back/target/x86_64_unknown_openbsd.rs @@ -0,0 +1,28 @@ +// Copyright 2014-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 or the MIT license +// , 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::openbsd_base::opts(); + base.pre_link_args.push("-m64".to_string()); + + Target { + data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\ + f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\ + s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(), + llvm_target: "x86_64-unknown-openbsd".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + arch: "x86_64".to_string(), + target_os: "openbsd".to_string(), + options: base, + } +} diff --git a/src/librustc_back/x86.rs b/src/librustc_back/x86.rs index 52c07165900a9..9d1b7347d0651 100644 --- a/src/librustc_back/x86.rs +++ b/src/librustc_back/x86.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -51,6 +51,9 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) abi::OsDragonfly => { "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string() } + abi::OsOpenbsd => { + "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string() + } }, diff --git a/src/librustc_back/x86_64.rs b/src/librustc_back/x86_64.rs index cbb288a533d6a..2f13bb3158119 100644 --- a/src/librustc_back/x86_64.rs +++ b/src/librustc_back/x86_64.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -57,6 +57,11 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\ s0:64:64-f80:128:128-n8:16:32:64-S128".to_string() } + abi::OsOpenbsd => { + "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\ + f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\ + s0:64:64-f80:128:128-n8:16:32:64-S128".to_string() + } }, diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index ede71d1935453..a7cf5eb89187f 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -64,7 +64,7 @@ mod imp { pub const F_SETLKW: libc::c_int = 13; } - #[cfg(target_os = "dragonfly")] + #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] mod os { use libc; diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index f35f63143ef82..458b0a46e8b2f 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -1,4 +1,4 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -173,7 +173,8 @@ mod test { #[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] fn test_errors_do_not_crash() { // Open /dev/null as a library to get an error, and make sure // that only causes an error, and not a crash. @@ -190,7 +191,8 @@ mod test { target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] mod dl { use prelude::v1::*; @@ -254,6 +256,7 @@ mod dl { dlclose(handle as *mut libc::c_void); () } + #[cfg(not(target_os = "openbsd"))] #[link_name = "dl"] extern { fn dlopen(filename: *const libc::c_char, @@ -263,6 +266,16 @@ mod dl { symbol: *const libc::c_char) -> *mut libc::c_void; fn dlclose(handle: *mut libc::c_void) -> libc::c_int; } + + #[cfg(target_os = "openbsd")] + extern { + fn dlopen(filename: *const libc::c_char, + flag: libc::c_int) -> *mut libc::c_void; + fn dlerror() -> *mut libc::c_char; + fn dlsym(handle: *mut libc::c_void, + symbol: *const libc::c_char) -> *mut libc::c_void; + fn dlclose(handle: *mut libc::c_void) -> libc::c_int; + } } #[cfg(target_os = "windows")] diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 600ca60349ae2..0da9e860145e9 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -693,7 +693,8 @@ fn real_args_as_bytes() -> Vec> { #[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] fn real_args_as_bytes() -> Vec> { use rt; rt::args::clone().unwrap_or_else(|| vec![]) @@ -1326,6 +1327,37 @@ pub mod consts { pub const EXE_EXTENSION: &'static str = ""; } +#[cfg(target_os = "openbsd")] +pub mod consts { + pub use os::arch_consts::ARCH; + + pub const FAMILY: &'static str = "unix"; + + /// A string describing the specific operating system in use: in this + /// case, `openbsd`. + pub const SYSNAME: &'static str = "openbsd"; + + /// Specifies the filename prefix used for shared libraries on this + /// platform: in this case, `lib`. + pub const DLL_PREFIX: &'static str = "lib"; + + /// Specifies the filename suffix used for shared libraries on this + /// platform: in this case, `.so`. + pub const DLL_SUFFIX: &'static str = ".so"; + + /// Specifies the file extension used for shared libraries on this + /// platform that goes after the dot: in this case, `so`. + pub const DLL_EXTENSION: &'static str = "so"; + + /// Specifies the filename suffix used for executable binaries on this + /// platform: in this case, the empty string. + pub const EXE_SUFFIX: &'static str = ""; + + /// Specifies the file extension, if any, used for executable binaries + /// on this platform: in this case, the empty string. + pub const EXE_EXTENSION: &'static str = ""; +} + #[cfg(target_os = "android")] pub mod consts { pub use os::arch_consts::ARCH; diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index b63f2e2d73a03..b3bed4af96248 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -42,7 +42,8 @@ pub fn clone() -> Option>> { imp::clone() } #[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] mod imp { use prelude::v1::*; diff --git a/src/libstd/rt/libunwind.rs b/src/libstd/rt/libunwind.rs index dd9923307d6f0..43e3a43f56d36 100644 --- a/src/libstd/rt/libunwind.rs +++ b/src/libstd/rt/libunwind.rs @@ -101,7 +101,7 @@ pub type _Unwind_Exception_Cleanup_Fn = #[link(name = "gcc_s")] extern {} -#[cfg(target_os = "android")] +#[cfg(any(target_os = "android", target_os = "openbsd"))] #[link(name = "gcc")] extern {} diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs index 06b6816248709..1392bc815c4f9 100644 --- a/src/libstd/rtdeps.rs +++ b/src/libstd/rtdeps.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -39,7 +39,7 @@ extern {} #[link(name = "pthread")] extern {} -#[cfg(target_os = "dragonfly")] +#[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] #[link(name = "pthread")] extern {} diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 51b6e0a1c1e12..c826522e5d1cf 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -1,4 +1,4 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -694,10 +694,16 @@ impl TcpStream { setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, seconds as libc::c_int) } + #[cfg(target_os = "openbsd")] + fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> { + setsockopt(self.fd(), libc::IPPROTO_TCP, libc::SO_KEEPALIVE, + seconds as libc::c_int) + } #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly")))] + target_os = "dragonfly", + target_os = "openbsd")))] fn set_tcp_keepalive(&mut self, _seconds: uint) -> IoResult<()> { Ok(()) } diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs index 88bb9395cf122..cd5458a2109c6 100644 --- a/src/libstd/sys/common/stack.rs +++ b/src/libstd/sys/common/stack.rs @@ -241,6 +241,11 @@ pub unsafe fn record_sp_limit(limit: uint) { #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)] unsafe fn target_record_sp_limit(_: uint) { } + + #[cfg(target_os = "openbsd")] #[inline(always)] + unsafe fn target_record_sp_limit(_: uint) { + // segmented stack is disabled + } } /// The counterpart of the function above, this function will fetch the current @@ -345,4 +350,10 @@ pub unsafe fn get_sp_limit() -> uint { unsafe fn target_get_sp_limit() -> uint { 1024 } + + #[cfg(target_os = "openbsd")] #[inline(always)] + unsafe fn target_get_sp_limit() -> uint { + // segmented stack is disabled + 1024 + } } diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index e310b8f6d90b3..f32d59fe3c3aa 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -318,7 +318,8 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { static mut LAST_FILENAME: [libc::c_char; 256] = [0; 256]; if !STATE.is_null() { return STATE } let selfname = if cfg!(target_os = "freebsd") || - cfg!(target_os = "dragonfly") { + cfg!(target_os = "dragonfly") || + cfg!(target_os = "openbsd") { os::self_exe_name() } else { None diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs index 9016d1a2c99ca..4fd7218d25659 100644 --- a/src/libstd/sys/unix/c.rs +++ b/src/libstd/sys/unix/c.rs @@ -23,7 +23,8 @@ use libc; #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] pub const FIONBIO: libc::c_ulong = 0x8004667e; #[cfg(any(all(target_os = "linux", any(target_arch = "x86", @@ -41,7 +42,8 @@ pub const FIONBIO: libc::c_ulong = 0x667e; #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] pub const FIOCLEX: libc::c_ulong = 0x20006601; #[cfg(any(all(target_os = "linux", any(target_arch = "x86", @@ -59,7 +61,8 @@ pub const FIOCLEX: libc::c_ulong = 0x6601; #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] pub const MSG_DONTWAIT: libc::c_int = 0x80; #[cfg(any(target_os = "linux", target_os = "android"))] pub const MSG_DONTWAIT: libc::c_int = 0x40; @@ -111,6 +114,7 @@ mod select { #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "dragonfly", + target_os = "openbsd", target_os = "linux"))] mod select { use uint; @@ -235,7 +239,8 @@ mod signal { #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] mod signal { use libc; @@ -248,7 +253,9 @@ mod signal { pub const SA_SIGINFO: libc::c_int = 0x0040; pub const SIGCHLD: libc::c_int = 20; - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(any(target_os = "macos", + target_os = "ios", + target_os = "openbsd"))] pub type sigset_t = u32; #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] #[repr(C)] diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index dd343baa7c9c3..dd39501a7cbdf 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -50,6 +50,16 @@ pub fn errno() -> int { } } + #[cfg(target_os = "openbsd")] + fn errno_location() -> *const c_int { + extern { + fn __errno() -> *const c_int; + } + unsafe { + __errno() + } + } + #[cfg(any(target_os = "linux", target_os = "android"))] fn errno_location() -> *const c_int { extern { @@ -71,7 +81,8 @@ pub fn error_string(errno: i32) -> String { target_os = "ios", target_os = "android", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int { extern { @@ -204,6 +215,21 @@ pub fn load_self() -> Option> { } } +#[cfg(target_os = "openbsd")] +pub fn load_self() -> Option> { + extern { + fn __load_self() -> *const c_char; + } + unsafe { + let v = __load_self(); + if v.is_null() { + None + } else { + Some(ffi::c_str_to_bytes(&v).to_vec()) + } + } +} + #[cfg(any(target_os = "linux", target_os = "android"))] pub fn load_self() -> Option> { use old_io; diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index b004a47f8a349..20a934445ee0a 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -604,7 +604,8 @@ fn translate_status(status: c_int) -> ProcessExit { #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] mod imp { pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 } pub fn WEXITSTATUS(status: i32) -> i32 { status >> 8 } diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index a526f3393f2d3..3512fa36eb3b7 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -32,7 +32,9 @@ impl Drop for Handler { } } -#[cfg(any(target_os = "linux", target_os = "macos"))] +#[cfg(any(target_os = "linux", + target_os = "macos", + target_os = "openbsd"))] mod imp { use core::prelude::*; use sys_common::stack; @@ -203,7 +205,7 @@ mod imp { } - #[cfg(target_os = "macos")] + #[cfg(any(target_os = "macos", target_os = "openbsd"))] mod signal { use libc; use super::sighandler_t; @@ -212,7 +214,10 @@ mod imp { pub const SA_SIGINFO: libc::c_int = 0x0040; pub const SIGBUS: libc::c_int = 10; + #[cfg(target_os = "macos")] pub const SIGSTKSZ: libc::size_t = 131072; + #[cfg(target_os = "openbsd")] + pub const SIGSTKSZ: libc::size_t = 40960; pub const SIG_DFL: sighandler_t = 0 as sighandler_t; @@ -220,6 +225,7 @@ mod imp { // This structure has more fields, but we're not all that interested in // them. + #[cfg(target_os = "macos")] #[repr(C)] pub struct siginfo { pub si_signo: libc::c_int, @@ -231,6 +237,16 @@ mod imp { pub si_addr: *mut libc::c_void } + #[cfg(target_os = "openbsd")] + #[repr(C)] + pub struct siginfo { + pub si_signo: libc::c_int, + pub si_code: libc::c_int, + pub si_errno: libc::c_int, + // union + pub si_addr: *mut libc::c_void, + } + #[repr(C)] pub struct sigaltstack { pub ss_sp: *mut libc::c_void, @@ -260,7 +276,8 @@ mod imp { } #[cfg(not(any(target_os = "linux", - target_os = "macos")))] + target_os = "macos", + target_os = "openbsd")))] mod imp { use libc; diff --git a/src/libstd/sys/unix/sync.rs b/src/libstd/sys/unix/sync.rs index c1e3fc88794eb..bc93513af63d4 100644 --- a/src/libstd/sys/unix/sync.rs +++ b/src/libstd/sys/unix/sync.rs @@ -44,7 +44,9 @@ extern { pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> libc::c_int; } -#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] +#[cfg(any(target_os = "freebsd", + target_os = "dragonfly", + target_os = "openbsd"))] mod os { use libc; diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 26a450b8599df..433c37a97f396 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -31,7 +31,9 @@ pub extern fn thread_start(main: *mut libc::c_void) -> rust_thread_return { return start_thread(main); } -#[cfg(all(not(target_os = "linux"), not(target_os = "macos")))] +#[cfg(all(not(target_os = "linux"), + not(target_os = "macos"), + not(target_os = "openbsd")))] pub mod guard { pub unsafe fn current() -> uint { 0 @@ -45,10 +47,15 @@ pub mod guard { } } -#[cfg(any(target_os = "linux", target_os = "macos"))] + +#[cfg(any(target_os = "linux", + target_os = "macos", + target_os = "openbsd"))] pub mod guard { use super::*; - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "linux", + target_os = "android", + target_os = "openbsd"))] use mem; #[cfg(any(target_os = "linux", target_os = "android"))] use ptr; @@ -64,7 +71,7 @@ pub mod guard { static mut PAGE_SIZE: uint = 0; static mut GUARD_PAGE: uint = 0; - #[cfg(target_os = "macos")] + #[cfg(any(target_os = "macos", target_os = "openbsd"))] unsafe fn get_stack_start() -> *mut libc::c_void { current() as *mut libc::c_void } @@ -141,6 +148,23 @@ pub mod guard { pthread_get_stacksize_np(pthread_self())) as uint } + #[cfg(target_os = "openbsd")] + pub unsafe fn current() -> uint { + let mut current_stack: stack_t = mem::zeroed(); + if pthread_stackseg_np(pthread_self(), &mut current_stack) != 0 { + panic!("failed to get current stack: pthread_stackseg_np") + } + + if pthread_main_np() == 1 { + // main thread + current_stack.ss_sp as uint - current_stack.ss_size as uint + 3 * PAGE_SIZE as uint + + } else { + // new thread + current_stack.ss_sp as uint - current_stack.ss_size as uint + } + } + #[cfg(any(target_os = "linux", target_os = "android"))] pub unsafe fn current() -> uint { let mut attr: libc::pthread_attr_t = mem::zeroed(); @@ -304,6 +328,22 @@ extern { fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int; } +#[cfg(target_os = "openbsd")] +extern { + pub fn pthread_self() -> libc::pthread_t; + pub fn pthread_stackseg_np(thread: libc::pthread_t, + sinfo: *mut stack_t) -> libc::c_uint; + pub fn pthread_main_np() -> libc::c_uint; +} + +#[cfg(target_os = "openbsd")] +#[repr(C)] +pub struct stack_t { + pub ss_sp: *mut libc::c_void, + pub ss_size: libc::size_t, + pub ss_flags: libc::c_int, +} + extern { fn pthread_create(native: *mut libc::pthread_t, attr: *const libc::pthread_attr_t, diff --git a/src/libstd/sys/unix/thread_local.rs b/src/libstd/sys/unix/thread_local.rs index ea1e9c261fecf..62d9a33c83d7a 100644 --- a/src/libstd/sys/unix/thread_local.rs +++ b/src/libstd/sys/unix/thread_local.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -42,13 +42,15 @@ pub unsafe fn destroy(key: Key) { type pthread_key_t = ::libc::c_ulong; #[cfg(any(target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] type pthread_key_t = ::libc::c_int; #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly")))] + target_os = "dragonfly", + target_os = "openbsd")))] type pthread_key_t = ::libc::c_uint; extern { diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index cc1e23fbca98a..bddf7b075df96 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -80,7 +80,8 @@ mod inner { } // Apparently android provides this in some other library? - #[cfg(not(target_os = "android"))] + // OpenBSD provide it via libc + #[cfg(not(any(target_os = "android", target_os = "openbsd")))] #[link(name = "rt")] extern {} diff --git a/src/libstd/sys/unix/tty.rs b/src/libstd/sys/unix/tty.rs index d414f70152da4..3a79047445cdd 100644 --- a/src/libstd/sys/unix/tty.rs +++ b/src/libstd/sys/unix/tty.rs @@ -21,7 +21,8 @@ pub struct TTY { } #[cfg(any(target_os = "macos", - target_os = "freebsd"))] + target_os = "freebsd", + target_os = "openbsd"))] const TIOCGWINSZ: c_ulong = 0x40087468; #[cfg(any(target_os = "linux", target_os = "android"))] @@ -53,7 +54,8 @@ impl TTY { #[cfg(any(target_os = "linux", target_os = "android", target_os = "macos", - target_os = "freebsd"))] + target_os = "freebsd", + target_os = "openbsd"))] pub fn get_winsize(&mut self) -> IoResult<(int, int)> { unsafe { #[repr(C)] diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 2325b3778c757..de3fa1135b161 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -24,6 +24,7 @@ pub enum Os { OsFreebsd, OsiOS, OsDragonfly, + OsOpenbsd, } #[derive(PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)] @@ -134,7 +135,8 @@ impl fmt::Display for Os { OsiOS => "ios".fmt(f), OsAndroid => "android".fmt(f), OsFreebsd => "freebsd".fmt(f), - OsDragonfly => "dragonfly".fmt(f) + OsDragonfly => "dragonfly".fmt(f), + OsOpenbsd => "openbsd".fmt(f), } } } diff --git a/src/rt/rust_builtin.c b/src/rt/rust_builtin.c index 03cd3fd6b88ea..372ff0f21472f 100644 --- a/src/rt/rust_builtin.c +++ b/src/rt/rust_builtin.c @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -47,7 +47,7 @@ extern char **environ; #endif #endif -#if defined(__FreeBSD__) || defined(__linux__) || defined(__ANDROID__) || defined(__DragonFly__) +#if defined(__FreeBSD__) || defined(__linux__) || defined(__ANDROID__) || defined(__DragonFly__) || defined(__OpenBSD__) extern char **environ; #endif @@ -199,6 +199,56 @@ rust_unset_sigprocmask() { int *__dfly_error(void) { return __error(); } #endif +#if defined(__OpenBSD__) +#include +#include +#include + +const char * __load_self() { + static char *self = NULL; + + if (self == NULL) { + int mib[4]; + char **argv = NULL; + size_t argv_len; + + /* initialize mib */ + mib[0] = CTL_KERN; + mib[1] = KERN_PROC_ARGS; + mib[2] = getpid(); + mib[3] = KERN_PROC_ARGV; + + /* request KERN_PROC_ARGV size */ + argv_len = 0; + if (sysctl(mib, 4, NULL, &argv_len, NULL, 0) == -1) + return (NULL); + + /* allocate size */ + if ((argv = malloc(argv_len)) == NULL) + return (NULL); + + /* request KERN_PROC_ARGV */ + if (sysctl(mib, 4, argv, &argv_len, NULL, 0) == -1) { + free(argv); + return (NULL); + } + + /* get realpath if possible */ + if ((argv[0] != NULL) && ((*argv[0] == '.') || (*argv[0] == '/') + || (strstr(argv[0], "/") != NULL))) + + self = realpath(argv[0], NULL); + else + self = NULL; + + /* cleanup */ + free(argv); + } + + return (self); +} +#endif + // // Local Variables: // mode: C++ diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk index 1c791f0690ca5..accb2f7faa719 100644 --- a/src/test/run-make/tools.mk +++ b/src/test/run-make/tools.mk @@ -59,11 +59,14 @@ ifeq ($(shell uname),Darwin) else ifeq ($(shell uname),FreeBSD) EXTRACFLAGS := -lm -lpthread -lgcc_s +ifeq ($(shell uname),OpenBSD) + EXTRACFLAGS := -lm -lpthread else EXTRACFLAGS := -lm -lrt -ldl -lpthread endif endif endif +endif REMOVE_DYLIBS = rm $(TMPDIR)/$(call DYLIB_GLOB,$(1)) REMOVE_RLIBS = rm $(TMPDIR)/$(call RLIB_GLOB,$(1)) diff --git a/src/test/run-pass/intrinsic-alignment.rs b/src/test/run-pass/intrinsic-alignment.rs index da07e9594c0e6..07f021e48d7e7 100644 --- a/src/test/run-pass/intrinsic-alignment.rs +++ b/src/test/run-pass/intrinsic-alignment.rs @@ -20,7 +20,8 @@ mod rusti { #[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] mod m { #[main] #[cfg(target_arch = "x86")] diff --git a/src/test/run-pass/lang-item-public.rs b/src/test/run-pass/lang-item-public.rs index f94f648275932..2d70fa0c81989 100644 --- a/src/test/run-pass/lang-item-public.rs +++ b/src/test/run-pass/lang-item-public.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -37,6 +37,10 @@ extern {} #[link(name = "c")] extern {} +#[cfg(target_os = "openbsd")] +#[link(name = "c")] +extern {} + #[cfg(target_os = "macos")] #[link(name = "System")] extern {} diff --git a/src/test/run-pass/rec-align-u64.rs b/src/test/run-pass/rec-align-u64.rs index eaf76ef5714a8..5330490e54f55 100644 --- a/src/test/run-pass/rec-align-u64.rs +++ b/src/test/run-pass/rec-align-u64.rs @@ -39,7 +39,8 @@ struct Outer { #[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] mod m { #[cfg(target_arch = "x86")] pub mod m { diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs index f5f013d171171..e0527c35871b0 100644 --- a/src/test/run-pass/tcp-stress.rs +++ b/src/test/run-pass/tcp-stress.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,6 +10,7 @@ // ignore-linux see joyent/libuv#1189 // ignore-android needs extra network permissions +// ignore-openbsd system ulimit (Too many open files) // exec-env:RUST_LOG=debug #[macro_use] diff --git a/src/test/run-pass/x86stdcall.rs b/src/test/run-pass/x86stdcall.rs index 15d18525d0aa7..75a8f6019b898 100644 --- a/src/test/run-pass/x86stdcall.rs +++ b/src/test/run-pass/x86stdcall.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -34,5 +34,6 @@ pub fn main() { target_os = "linux", target_os = "freebsd", target_os = "dragonfly", + target_os = "openbsd", target_os = "android"))] pub fn main() { } From 3096784a3b1dd7d20bc67f19d4ccd61ae497a7de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Thu, 29 Jan 2015 18:02:32 +0100 Subject: [PATCH 15/36] openbsd: break lines too long --- src/liblibc/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index dcd4edb0c219c..470f4bed5d85d 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -4195,8 +4195,10 @@ pub mod consts { pub const IP_HDRINCL: c_int = 2; pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; - pub const IPV6_ADD_MEMBERSHIP: c_int = 12; // don't exist, keep same as IP_ADD_MEMBERSHIP - pub const IPV6_DROP_MEMBERSHIP: c_int = 13; // don't exist, keep same as IP_DROP_MEMBERSHIP + // don't exist, keep same as IP_ADD_MEMBERSHIP + pub const IPV6_ADD_MEMBERSHIP: c_int = 12; + // don't exist, keep same as IP_DROP_MEMBERSHIP + pub const IPV6_DROP_MEMBERSHIP: c_int = 13; pub const TCP_NODELAY: c_int = 1; //pub const TCP_KEEPIDLE: c_int = ; From 568a451a90a14b101ed357235a5055de2940f16b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Fri, 30 Jan 2015 08:15:28 +0100 Subject: [PATCH 16/36] openbsd: incoporate remarks - consolidate target_record_sp_limit and target_get_sp_limit functions for aarch64, powerpc, arm-ios and openbsd as there are all without segmented stacks (no need to duplicate functions). - rename __load_self function to rust_load_self - use a mutex inner load_self() as underline implementation is not thread-safe --- src/libstd/sys/common/stack.rs | 54 +++++++++++----------------------- src/libstd/sys/unix/os.rs | 11 +++++-- src/rt/rust_builtin.c | 2 +- 3 files changed, 27 insertions(+), 40 deletions(-) diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs index cd5458a2109c6..8dd2f154fa8e3 100644 --- a/src/libstd/sys/common/stack.rs +++ b/src/libstd/sys/common/stack.rs @@ -227,24 +227,14 @@ pub unsafe fn record_sp_limit(limit: uint) { } // aarch64 - FIXME(AARCH64): missing... - #[cfg(target_arch = "aarch64")] - unsafe fn target_record_sp_limit(_: uint) { - } - // powerpc - FIXME(POWERPC): missing... - #[cfg(target_arch = "powerpc")] - unsafe fn target_record_sp_limit(_: uint) { - } - - - // iOS segmented stack is disabled for now, see related notes - #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)] - unsafe fn target_record_sp_limit(_: uint) { - } - - #[cfg(target_os = "openbsd")] #[inline(always)] + // arm-ios - iOS segmented stack is disabled for now, see related notes + // openbsd - segmented stack is disabled + #[cfg(any(target_arch = "aarch64", + target_arch = "powerpc", + all(target_arch = "arm", target_os = "ios"), + target_os = "openbsd"))] unsafe fn target_record_sp_limit(_: uint) { - // segmented stack is disabled } } @@ -332,28 +322,18 @@ pub unsafe fn get_sp_limit() -> uint { } // aarch64 - FIXME(AARCH64): missing... - #[cfg(target_arch = "aarch64")] - unsafe fn target_get_sp_limit() -> uint { - 1024 - } - - // powepc - FIXME(POWERPC): missing... - #[cfg(target_arch = "powerpc")] - unsafe fn target_get_sp_limit() -> uint { - 1024 - } - - // iOS doesn't support segmented stacks yet. This function might - // be called by runtime though so it is unsafe to mark it as - // unreachable, let's return a fixed constant. - #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)] - unsafe fn target_get_sp_limit() -> uint { - 1024 - } - - #[cfg(target_os = "openbsd")] #[inline(always)] + // powerpc - FIXME(POWERPC): missing... + // arm-ios - iOS doesn't support segmented stacks yet. + // openbsd - OpenBSD doesn't support 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"), + target_os = "openbsd"))] + #[inline(always)] unsafe fn target_get_sp_limit() -> uint { - // segmented stack is disabled 1024 } } diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index dd39501a7cbdf..9faa4a038ba23 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -217,11 +217,18 @@ pub fn load_self() -> Option> { #[cfg(target_os = "openbsd")] pub fn load_self() -> Option> { + use sync::{StaticMutex, MUTEX_INIT}; + + static LOCK: StaticMutex = MUTEX_INIT; + extern { - fn __load_self() -> *const c_char; + fn rust_load_self() -> *const c_char; } + + let _guard = LOCK.lock(); + unsafe { - let v = __load_self(); + let v = rust_load_self(); if v.is_null() { None } else { diff --git a/src/rt/rust_builtin.c b/src/rt/rust_builtin.c index 372ff0f21472f..382cbf0d5d129 100644 --- a/src/rt/rust_builtin.c +++ b/src/rt/rust_builtin.c @@ -204,7 +204,7 @@ int *__dfly_error(void) { return __error(); } #include #include -const char * __load_self() { +const char * rust_load_self() { static char *self = NULL; if (self == NULL) { From 34305784601e046f9eb8e107e88bf609f352afc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Fri, 30 Jan 2015 11:46:30 +0100 Subject: [PATCH 17/36] openbsd: remove unused openbsd code This code is in a block (libc::consts::os) that openbsd don't include This one is for freebsd and dragonfly. There is another block for openbsd below. Remove the unneed declaration. --- src/liblibc/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 470f4bed5d85d..75867eb38be65 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -3753,9 +3753,6 @@ pub mod consts { #[cfg(target_os = "dragonfly")] pub const PTHREAD_STACK_MIN: size_t = 1024; - #[cfg(target_os = "openbsd")] - pub const PTHREAD_STACK_MIN: size_t = 2048; - pub const CLOCK_REALTIME: c_int = 0; pub const CLOCK_MONOTONIC: c_int = 4; } From fdb5d77d0921f70d4c7b6b1ace15b5d481a6b732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Fri, 30 Jan 2015 14:28:13 +0100 Subject: [PATCH 18/36] openbsd: remove specific block and cleanup linkage - the specific block for dl* function isn't need for openbsd if libdl isn't marked to be linked here. remove them. - remove the linkage for libdl: it should already specified in `rtdeps.rs`. the code of `dynamic_lib.rs` include libdl for: - linux (already defined in rtdeps.rs) - android (already defined in rtdeps.rs) - macos (not needed for macos) - ios (probably the same as macos) - freebsd (libdl is a stub) - dragonfly (libdl is a stub) --- src/libstd/dynamic_lib.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index 458b0a46e8b2f..c4017627e2867 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -256,18 +256,6 @@ mod dl { dlclose(handle as *mut libc::c_void); () } - #[cfg(not(target_os = "openbsd"))] - #[link_name = "dl"] - extern { - fn dlopen(filename: *const libc::c_char, - flag: libc::c_int) -> *mut libc::c_void; - fn dlerror() -> *mut libc::c_char; - fn dlsym(handle: *mut libc::c_void, - symbol: *const libc::c_char) -> *mut libc::c_void; - fn dlclose(handle: *mut libc::c_void) -> libc::c_int; - } - - #[cfg(target_os = "openbsd")] extern { fn dlopen(filename: *const libc::c_char, flag: libc::c_int) -> *mut libc::c_void; From f6414b0187bfc6e5b563a17c85a9f790d6257551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sun, 1 Feb 2015 14:58:57 +0100 Subject: [PATCH 19/36] openbsd: rebase to master - incoporate changes introduced by #21678 --- src/libstd/sys/unix/thread.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 433c37a97f396..6f030ee91fe2d 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -248,7 +248,9 @@ pub unsafe fn set_name(name: &str) { } } -#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] +#[cfg(any(target_os = "freebsd", + target_os = "dragonfly", + target_os = "openbsd"))] pub unsafe fn set_name(name: &str) { // pthread_set_name_np() since almost forever on all BSDs let cname = CString::from_slice(name.as_bytes()); @@ -314,7 +316,9 @@ extern { stacksize: *mut libc::size_t) -> libc::c_int; } -#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] +#[cfg(any(target_os = "freebsd", + target_os = "dragonfly", + target_os = "openbsd"))] extern { pub fn pthread_self() -> libc::pthread_t; fn pthread_set_name_np(tid: libc::pthread_t, name: *const libc::c_char); @@ -330,7 +334,6 @@ extern { #[cfg(target_os = "openbsd")] extern { - pub fn pthread_self() -> libc::pthread_t; pub fn pthread_stackseg_np(thread: libc::pthread_t, sinfo: *mut stack_t) -> libc::c_uint; pub fn pthread_main_np() -> libc::c_uint; From 602e508db0fd3566ef59a6a4833b68c3a55ddc79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Fri, 30 Jan 2015 19:25:07 +0100 Subject: [PATCH 20/36] Update LLVM to rust-llvm-2015-01-30 --- src/librustc_llvm/lib.rs | 96 +++++---- src/librustc_trans/trans/common.rs | 4 - src/librustc_trans/trans/debuginfo.rs | 77 +++---- src/llvm | 2 +- src/rustllvm/ExecutionEngineWrapper.cpp | 21 +- src/rustllvm/RustWrapper.cpp | 269 +++++++++++++++--------- src/rustllvm/llvm-auto-clean-trigger | 2 +- 7 files changed, 268 insertions(+), 203 deletions(-) diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 5ce916f536047..eb7dae66538fb 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -64,8 +64,9 @@ use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char}; use libc::{c_longlong, c_ulonglong, c_void}; use debuginfo::{DIBuilderRef, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType, - DIBasicType, DIDerivedType, DICompositeType, - DIVariable, DIGlobalVariable, DIArray, DISubrange}; + DIBasicType, DIDerivedType, DICompositeType, DIScope, + DIVariable, DIGlobalVariable, DIArray, DISubrange, + DITemplateTypeParameter, DIEnumerator, DINameSpace}; pub mod archive_ro; pub mod diagnostic; @@ -443,6 +444,9 @@ pub type TypeRef = *mut Type_opaque; pub enum Value_opaque {} pub type ValueRef = *mut Value_opaque; #[allow(missing_copy_implementations)] +pub enum Metadata_opaque {} +pub type MetadataRef = *mut Metadata_opaque; +#[allow(missing_copy_implementations)] pub enum BasicBlock_opaque {} pub type BasicBlockRef = *mut BasicBlock_opaque; #[allow(missing_copy_implementations)] @@ -502,18 +506,19 @@ pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_v pub mod debuginfo { pub use self::DIDescriptorFlags::*; - use super::{ValueRef}; + use super::{MetadataRef}; #[allow(missing_copy_implementations)] pub enum DIBuilder_opaque {} pub type DIBuilderRef = *mut DIBuilder_opaque; - pub type DIDescriptor = ValueRef; + pub type DIDescriptor = MetadataRef; pub type DIScope = DIDescriptor; pub type DILocation = DIDescriptor; pub type DIFile = DIScope; pub type DILexicalBlock = DIScope; pub type DISubprogram = DIScope; + pub type DINameSpace = DIScope; pub type DIType = DIDescriptor; pub type DIBasicType = DIType; pub type DIDerivedType = DIType; @@ -522,6 +527,8 @@ pub mod debuginfo { pub type DIGlobalVariable = DIDescriptor; pub type DIArray = DIDescriptor; pub type DISubrange = DIDescriptor; + pub type DIEnumerator = DIDescriptor; + pub type DITemplateTypeParameter = DIDescriptor; #[derive(Copy)] pub enum DIDescriptorFlags { @@ -1779,8 +1786,8 @@ extern { Flags: c_uint, isOptimized: bool, Fn: ValueRef, - TParam: ValueRef, - Decl: ValueRef) + TParam: DIArray, + Decl: DIDescriptor) -> DISubprogram; pub fn LLVMDIBuilderCreateBasicType(Builder: DIBuilderRef, @@ -1808,7 +1815,7 @@ extern { DerivedFrom: DIType, Elements: DIArray, RunTimeLang: c_uint, - VTableHolder: ValueRef, + VTableHolder: DIType, UniqueId: *const c_char) -> DICompositeType; @@ -1825,14 +1832,14 @@ extern { -> DIDerivedType; pub fn LLVMDIBuilderCreateLexicalBlock(Builder: DIBuilderRef, - Scope: DIDescriptor, + Scope: DIScope, File: DIFile, Line: c_uint, Col: c_uint) -> DILexicalBlock; pub fn LLVMDIBuilderCreateStaticVariable(Builder: DIBuilderRef, - Context: DIDescriptor, + Context: DIScope, Name: *const c_char, LinkageName: *const c_char, File: DIFile, @@ -1840,10 +1847,10 @@ extern { Ty: DIType, isLocalToUnit: bool, Val: ValueRef, - Decl: ValueRef) + Decl: DIDescriptor) -> DIGlobalVariable; - pub fn LLVMDIBuilderCreateLocalVariable(Builder: DIBuilderRef, + pub fn LLVMDIBuilderCreateVariable(Builder: DIBuilderRef, Tag: c_uint, Scope: DIDescriptor, Name: *const c_char, @@ -1852,6 +1859,8 @@ extern { Ty: DIType, AlwaysPreserve: bool, Flags: c_uint, + AddrOps: *const i64, + AddrOpsCount: c_uint, ArgNo: c_uint) -> DIVariable; @@ -1882,79 +1891,80 @@ extern { pub fn LLVMDIBuilderInsertDeclareAtEnd(Builder: DIBuilderRef, Val: ValueRef, VarInfo: DIVariable, + AddrOps: *const i64, + AddrOpsCount: c_uint, InsertAtEnd: BasicBlockRef) -> ValueRef; pub fn LLVMDIBuilderInsertDeclareBefore(Builder: DIBuilderRef, Val: ValueRef, VarInfo: DIVariable, + AddrOps: *const i64, + AddrOpsCount: c_uint, InsertBefore: ValueRef) -> ValueRef; pub fn LLVMDIBuilderCreateEnumerator(Builder: DIBuilderRef, Name: *const c_char, Val: c_ulonglong) - -> ValueRef; + -> DIEnumerator; pub fn LLVMDIBuilderCreateEnumerationType(Builder: DIBuilderRef, - Scope: ValueRef, + Scope: DIScope, Name: *const c_char, - File: ValueRef, + File: DIFile, LineNumber: c_uint, SizeInBits: c_ulonglong, AlignInBits: c_ulonglong, - Elements: ValueRef, - ClassType: ValueRef) - -> ValueRef; + Elements: DIArray, + ClassType: DIType) + -> DIType; pub fn LLVMDIBuilderCreateUnionType(Builder: DIBuilderRef, - Scope: ValueRef, + Scope: DIScope, Name: *const c_char, - File: ValueRef, + File: DIFile, LineNumber: c_uint, SizeInBits: c_ulonglong, AlignInBits: c_ulonglong, Flags: c_uint, - Elements: ValueRef, + Elements: DIArray, RunTimeLang: c_uint, UniqueId: *const c_char) - -> ValueRef; + -> DIType; pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool); pub fn LLVMDIBuilderCreateTemplateTypeParameter(Builder: DIBuilderRef, - Scope: ValueRef, + Scope: DIScope, Name: *const c_char, - Ty: ValueRef, - File: ValueRef, + Ty: DIType, + File: DIFile, LineNo: c_uint, ColumnNo: c_uint) - -> ValueRef; - - pub fn LLVMDIBuilderCreateOpDeref(IntType: TypeRef) -> ValueRef; + -> DITemplateTypeParameter; - pub fn LLVMDIBuilderCreateOpPlus(IntType: TypeRef) -> ValueRef; + pub fn LLVMDIBuilderCreateOpDeref() -> i64; - pub fn LLVMDIBuilderCreateComplexVariable(Builder: DIBuilderRef, - Tag: c_uint, - Scope: ValueRef, - Name: *const c_char, - File: ValueRef, - LineNo: c_uint, - Ty: ValueRef, - AddrOps: *const ValueRef, - AddrOpsCount: c_uint, - ArgNo: c_uint) - -> ValueRef; + pub fn LLVMDIBuilderCreateOpPlus() -> i64; pub fn LLVMDIBuilderCreateNameSpace(Builder: DIBuilderRef, - Scope: ValueRef, + Scope: DIScope, Name: *const c_char, - File: ValueRef, + File: DIFile, LineNo: c_uint) - -> ValueRef; + -> DINameSpace; + + pub fn LLVMDIBuilderCreateDebugLocation(Context: ContextRef, + Line: c_uint, + Column: c_uint, + Scope: DIScope, + InlinedAt: MetadataRef) + -> ValueRef; - pub fn LLVMDICompositeTypeSetTypeArray(CompositeType: ValueRef, TypeArray: ValueRef); + pub fn LLVMDICompositeTypeSetTypeArray(Builder: DIBuilderRef, + CompositeType: DIType, + TypeArray: DIArray); pub fn LLVMWriteTypeToString(Type: TypeRef, s: RustStringRef); pub fn LLVMWriteValueToString(value_ref: ValueRef, s: RustStringRef); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 7d4e6aed876a5..1aac612299d03 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -780,10 +780,6 @@ pub fn C_i32(ccx: &CrateContext, i: i32) -> ValueRef { C_integral(Type::i32(ccx), i as u64, true) } -pub fn C_i64(ccx: &CrateContext, i: i64) -> ValueRef { - C_integral(Type::i64(ccx), i as u64, true) -} - pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef { C_integral(Type::i64(ccx), i, false) } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index ce9af3162a089..7edac00257869 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -197,7 +197,7 @@ use metadata::csearch; use middle::subst::{self, Substs}; use trans::{self, adt, machine, type_of}; use trans::common::{self, NodeIdAndSpan, CrateContext, FunctionContext, Block, - C_bytes, C_i32, C_i64, NormalizingClosureTyper}; + C_bytes, NormalizingClosureTyper}; use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef}; use trans::monomorphize; use trans::type_::Type; @@ -702,7 +702,7 @@ enum VariableAccess<'a> { DirectVariable { alloca: ValueRef }, // The llptr given is an alloca containing the start of some pointer chain // leading to the variable's content. - IndirectVariable { alloca: ValueRef, address_operations: &'a [ValueRef] } + IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] } } enum VariableKind { @@ -928,10 +928,10 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, env_index); let address_operations = unsafe { - [llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref()), - llvm::LLVMDIBuilderCreateOpPlus(Type::i64(cx).to_ref()), - C_i64(cx, byte_offset_of_var_in_env as i64), - llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())] + [llvm::LLVMDIBuilderCreateOpDeref(), + llvm::LLVMDIBuilderCreateOpPlus(), + byte_offset_of_var_in_env as i64, + llvm::LLVMDIBuilderCreateOpDeref()] }; let address_op_count = if captured_by_ref { @@ -969,7 +969,7 @@ pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let scope_metadata = scope_metadata(bcx.fcx, binding.id, binding.span); let aops = unsafe { - [llvm::LLVMDIBuilderCreateOpDeref(bcx.ccx().int_type().to_ref())] + [llvm::LLVMDIBuilderCreateOpDeref()] }; // Regardless of the actual type (`T`) we're always passed the stack slot (alloca) // for the binding. For ByRef bindings that's a `T*` but for ByMove bindings we @@ -1699,11 +1699,11 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }; let name = CString::from_slice(name.get().as_bytes()); - let (var_alloca, var_metadata) = match variable_access { - DirectVariable { alloca } => ( - alloca, - unsafe { - llvm::LLVMDIBuilderCreateLocalVariable( + match (variable_access, [].as_slice()) { + (DirectVariable { alloca }, address_operations) | + (IndirectVariable {alloca, address_operations}, _) => { + let metadata = unsafe { + llvm::LLVMDIBuilderCreateVariable( DIB(cx), dwarf_tag, scope_metadata, @@ -1713,38 +1713,25 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, type_metadata, cx.sess().opts.optimize != config::No, 0, - argument_index) - } - ), - IndirectVariable { alloca, address_operations } => ( - alloca, - unsafe { - llvm::LLVMDIBuilderCreateComplexVariable( - DIB(cx), - dwarf_tag, - scope_metadata, - name.as_ptr(), - file_metadata, - loc.line as c_uint, - type_metadata, address_operations.as_ptr(), address_operations.len() as c_uint, argument_index) - } - ) - }; - - set_debug_location(cx, InternalDebugLocation::new(scope_metadata, + }; + set_debug_location(cx, InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize())); - unsafe { - let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd( - DIB(cx), - var_alloca, - var_metadata, - bcx.llbb); + unsafe { + let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd( + DIB(cx), + alloca, + metadata, + address_operations.as_ptr(), + address_operations.len() as c_uint, + bcx.llbb); - llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr); + llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr); + } + } } match variable_kind { @@ -2716,7 +2703,7 @@ fn set_members_of_composite_type(cx: &CrateContext, unsafe { let type_array = create_DIArray(DIB(cx), &member_metadata[]); - llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array); + llvm::LLVMDICompositeTypeSetTypeArray(DIB(cx), composite_type_metadata, type_array); } } @@ -3150,12 +3137,14 @@ fn set_debug_location(cx: &CrateContext, debug_location: InternalDebugLocation) // Always set the column to zero like Clang and GCC let col = UNKNOWN_COLUMN_NUMBER; debug!("setting debug location to {} {}", line, col); - let elements = [C_i32(cx, line as i32), C_i32(cx, col as i32), - scope, ptr::null_mut()]; + unsafe { - metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext, - elements.as_ptr(), - elements.len() as c_uint); + metadata_node = llvm::LLVMDIBuilderCreateDebugLocation( + debug_context(cx).llcontext, + line as c_uint, + col as c_uint, + scope, + ptr::null_mut()); } } UnknownLocation => { diff --git a/src/llvm b/src/llvm index b820135911e17..2d54c4f559b1a 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit b820135911e17c7a46b901db56baa48e5155bf46 +Subproject commit 2d54c4f559b1acbfe1867950c3a25bfb2f76b693 diff --git a/src/rustllvm/ExecutionEngineWrapper.cpp b/src/rustllvm/ExecutionEngineWrapper.cpp index d37cf9d12a5e0..8ca81ab3d68ea 100644 --- a/src/rustllvm/ExecutionEngineWrapper.cpp +++ b/src/rustllvm/ExecutionEngineWrapper.cpp @@ -82,21 +82,24 @@ extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine( InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser(); - std::unique_ptr m(unwrap(mod)); - RustJITMemoryManager *mm = unwrap(mref); - std::string error_str; TargetOptions options; options.JITEmitDebugInfo = true; options.NoFramePointerElim = true; - ExecutionEngine *ee = EngineBuilder(std::move(m)) - .setEngineKind(EngineKind::JIT) - .setErrorStr(&error_str) - .setMCJITMemoryManager(mm) - .setTargetOptions(options) - .create(); + ExecutionEngine *ee = + #if LLVM_VERSION_MINOR <= 5 + EngineBuilder(unwrap(mod)) + .setMCJITMemoryManager(unwrap(mref)) + #else + EngineBuilder(std::unique_ptr(unwrap(mod))) + .setMCJITMemoryManager(std::unique_ptr(unwrap(mref))) + #endif + .setEngineKind(EngineKind::JIT) + .setErrorStr(&error_str) + .setTargetOptions(options) + .create(); if (!ee) LLVMRustSetLastError(error_str.c_str()); diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 728ff1461fc2b..aaf6d8df29cad 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -228,8 +228,22 @@ extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty, typedef DIBuilder* DIBuilderRef; +#if LLVM_VERSION_MINOR >= 6 +typedef struct LLVMOpaqueMetadata *LLVMMetadataRef; + +namespace llvm { +DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef) + +inline Metadata **unwrap(LLVMMetadataRef *Vals) { + return reinterpret_cast(Vals); +} +} +#else +typedef LLVMValueRef LLVMMetadataRef; +#endif + template -DIT unwrapDI(LLVMValueRef ref) { +DIT unwrapDI(LLVMMetadataRef ref) { return DIT(ref ? unwrap(ref) : NULL); } @@ -257,7 +271,7 @@ extern "C" void LLVMDIBuilderFinalize(DIBuilderRef Builder) { Builder->finalize(); } -extern "C" LLVMValueRef LLVMDIBuilderCreateCompileUnit( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateCompileUnit( DIBuilderRef Builder, unsigned Lang, const char* File, @@ -277,17 +291,17 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateCompileUnit( SplitName)); } -extern "C" LLVMValueRef LLVMDIBuilderCreateFile( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateFile( DIBuilderRef Builder, const char* Filename, const char* Directory) { return wrap(Builder->createFile(Filename, Directory)); } -extern "C" LLVMValueRef LLVMDIBuilderCreateSubroutineType( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType( DIBuilderRef Builder, - LLVMValueRef File, - LLVMValueRef ParameterTypes) { + LLVMMetadataRef File, + LLVMMetadataRef ParameterTypes) { return wrap(Builder->createSubroutineType( unwrapDI(File), #if LLVM_VERSION_MINOR >= 6 @@ -297,22 +311,22 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateSubroutineType( #endif } -extern "C" LLVMValueRef LLVMDIBuilderCreateFunction( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction( DIBuilderRef Builder, - LLVMValueRef Scope, + LLVMMetadataRef Scope, const char* Name, const char* LinkageName, - LLVMValueRef File, + LLVMMetadataRef File, unsigned LineNo, - LLVMValueRef Ty, + LLVMMetadataRef Ty, bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, unsigned Flags, bool isOptimized, LLVMValueRef Fn, - LLVMValueRef TParam, - LLVMValueRef Decl) { + LLVMMetadataRef TParam, + LLVMMetadataRef Decl) { return wrap(Builder->createFunction( unwrapDI(Scope), Name, LinkageName, unwrapDI(File), LineNo, @@ -323,7 +337,7 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateFunction( unwrapDI(Decl))); } -extern "C" LLVMValueRef LLVMDIBuilderCreateBasicType( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType( DIBuilderRef Builder, const char* Name, uint64_t SizeInBits, @@ -334,9 +348,9 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateBasicType( AlignInBits, Encoding)); } -extern "C" LLVMValueRef LLVMDIBuilderCreatePointerType( +extern "C" LLVMMetadataRef LLVMDIBuilderCreatePointerType( DIBuilderRef Builder, - LLVMValueRef PointeeTy, + LLVMMetadataRef PointeeTy, uint64_t SizeInBits, uint64_t AlignInBits, const char* Name) { @@ -344,19 +358,19 @@ extern "C" LLVMValueRef LLVMDIBuilderCreatePointerType( unwrapDI(PointeeTy), SizeInBits, AlignInBits, Name)); } -extern "C" LLVMValueRef LLVMDIBuilderCreateStructType( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType( DIBuilderRef Builder, - LLVMValueRef Scope, + LLVMMetadataRef Scope, const char* Name, - LLVMValueRef File, + LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, - LLVMValueRef DerivedFrom, - LLVMValueRef Elements, + LLVMMetadataRef DerivedFrom, + LLVMMetadataRef Elements, unsigned RunTimeLang, - LLVMValueRef VTableHolder, + LLVMMetadataRef VTableHolder, const char *UniqueId) { return wrap(Builder->createStructType( unwrapDI(Scope), @@ -376,17 +390,17 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateStructType( )); } -extern "C" LLVMValueRef LLVMDIBuilderCreateMemberType( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateMemberType( DIBuilderRef Builder, - LLVMValueRef Scope, + LLVMMetadataRef Scope, const char* Name, - LLVMValueRef File, + LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, - LLVMValueRef Ty) { + LLVMMetadataRef Ty) { return wrap(Builder->createMemberType( unwrapDI(Scope), Name, unwrapDI(File), LineNo, @@ -394,10 +408,10 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateMemberType( unwrapDI(Ty))); } -extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock( DIBuilderRef Builder, - LLVMValueRef Scope, - LLVMValueRef File, + LLVMMetadataRef Scope, + LLVMMetadataRef File, unsigned Line, unsigned Col) { return wrap(Builder->createLexicalBlock( @@ -409,17 +423,17 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock( )); } -extern "C" LLVMValueRef LLVMDIBuilderCreateStaticVariable( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable( DIBuilderRef Builder, - LLVMValueRef Context, + LLVMMetadataRef Context, const char* Name, const char* LinkageName, - LLVMValueRef File, + LLVMMetadataRef File, unsigned LineNo, - LLVMValueRef Ty, + LLVMMetadataRef Ty, bool isLocalToUnit, LLVMValueRef Val, - LLVMValueRef Decl = NULL) { + LLVMMetadataRef Decl = NULL) { #if LLVM_VERSION_MINOR == 6 return wrap(Builder->createGlobalVariable(unwrapDI(Context), #else @@ -431,21 +445,42 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateStaticVariable( LineNo, unwrapDI(Ty), isLocalToUnit, - unwrap(Val), + cast(unwrap(Val)), unwrapDI(Decl))); } -extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable( DIBuilderRef Builder, unsigned Tag, - LLVMValueRef Scope, + LLVMMetadataRef Scope, const char* Name, - LLVMValueRef File, + LLVMMetadataRef File, unsigned LineNo, - LLVMValueRef Ty, + LLVMMetadataRef Ty, bool AlwaysPreserve, unsigned Flags, + int64_t* AddrOps, + unsigned AddrOpsCount, unsigned ArgNo) { +#if LLVM_VERSION_MINOR < 6 + if (AddrOpsCount > 0) { + SmallVector addr_ops; + llvm::Type *Int64Ty = Type::getInt64Ty(VMContext); + for (int i = 0; i < AddrOpsCount; ++i) + addr_ops.push_back(ConstantInt::get(Int64Ty, AddrOps[i])); + + return wrap(Builder->createComplexVariable( + Tag, + unwrapDI(Scope), + Name, + unwrapDI(File), + LineNo, + unwrapDI(Ty), + addr_ops, + ArgNo + )); + } +#endif return wrap(Builder->createLocalVariable(Tag, unwrapDI(Scope), Name, unwrapDI(File), @@ -453,66 +488,94 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable( unwrapDI(Ty), AlwaysPreserve, Flags, ArgNo)); } -extern "C" LLVMValueRef LLVMDIBuilderCreateArrayType( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType( DIBuilderRef Builder, uint64_t Size, uint64_t AlignInBits, - LLVMValueRef Ty, - LLVMValueRef Subscripts) { + LLVMMetadataRef Ty, + LLVMMetadataRef Subscripts) { return wrap(Builder->createArrayType(Size, AlignInBits, unwrapDI(Ty), unwrapDI(Subscripts))); } -extern "C" LLVMValueRef LLVMDIBuilderCreateVectorType( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType( DIBuilderRef Builder, uint64_t Size, uint64_t AlignInBits, - LLVMValueRef Ty, - LLVMValueRef Subscripts) { + LLVMMetadataRef Ty, + LLVMMetadataRef Subscripts) { return wrap(Builder->createVectorType(Size, AlignInBits, unwrapDI(Ty), unwrapDI(Subscripts))); } -extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateSubrange( +extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange( DIBuilderRef Builder, int64_t Lo, int64_t Count) { return wrap(Builder->getOrCreateSubrange(Lo, Count)); } -extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateArray( +extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray( DIBuilderRef Builder, - LLVMValueRef* Ptr, + LLVMMetadataRef* Ptr, unsigned Count) { return wrap(Builder->getOrCreateArray( - ArrayRef(reinterpret_cast(Ptr), Count))); + ArrayRef(unwrap(Ptr), Count))); } extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( DIBuilderRef Builder, LLVMValueRef Val, - LLVMValueRef VarInfo, + LLVMMetadataRef VarInfo, + int64_t* AddrOps, + unsigned AddrOpsCount, LLVMBasicBlockRef InsertAtEnd) { +#if LLVM_VERSION_MINOR >= 6 + DIExpression Expr; + if (AddrOpsCount == 0) { + Expr = Builder->createExpression(); + } else { + llvm::ArrayRef addr_ops(AddrOps, AddrOpsCount); + Expr = Builder->createExpression(addr_ops); + } +#endif return wrap(Builder->insertDeclare( unwrap(Val), unwrapDI(VarInfo), +#if LLVM_VERSION_MINOR >= 6 + Expr, +#endif unwrap(InsertAtEnd))); } extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore( DIBuilderRef Builder, LLVMValueRef Val, - LLVMValueRef VarInfo, + LLVMMetadataRef VarInfo, + int64_t* AddrOps, + unsigned AddrOpsCount, LLVMValueRef InsertBefore) { +#if LLVM_VERSION_MINOR >= 6 + DIExpression Expr; + if (AddrOpsCount == 0) { + Expr = Builder->createExpression(); + } else { + llvm::ArrayRef addr_ops(AddrOps, AddrOpsCount); + Expr = Builder->createExpression(addr_ops); + } +#endif return wrap(Builder->insertDeclare( unwrap(Val), unwrapDI(VarInfo), +#if LLVM_VERSION_MINOR >= 6 + Expr, +#endif unwrap(InsertBefore))); } -extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerator( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerator( DIBuilderRef Builder, const char* Name, uint64_t Val) @@ -520,16 +583,16 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerator( return wrap(Builder->createEnumerator(Name, Val)); } -extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerationType( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerationType( DIBuilderRef Builder, - LLVMValueRef Scope, + LLVMMetadataRef Scope, const char* Name, - LLVMValueRef File, + LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, - LLVMValueRef Elements, - LLVMValueRef ClassType) + LLVMMetadataRef Elements, + LLVMMetadataRef ClassType) { return wrap(Builder->createEnumerationType( unwrapDI(Scope), @@ -542,16 +605,16 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerationType( unwrapDI(ClassType))); } -extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType( DIBuilderRef Builder, - LLVMValueRef Scope, + LLVMMetadataRef Scope, const char* Name, - LLVMValueRef File, + LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, - LLVMValueRef Elements, + LLVMMetadataRef Elements, unsigned RunTimeLang, const char* UniqueId) { @@ -577,12 +640,12 @@ extern "C" void LLVMSetUnnamedAddr(LLVMValueRef Value, LLVMBool Unnamed) { } #endif -extern "C" LLVMValueRef LLVMDIBuilderCreateTemplateTypeParameter( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter( DIBuilderRef Builder, - LLVMValueRef Scope, + LLVMMetadataRef Scope, const char* Name, - LLVMValueRef Ty, - LLVMValueRef File, + LLVMMetadataRef Ty, + LLVMMetadataRef File, unsigned LineNo, unsigned ColumnNo) { @@ -595,47 +658,21 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateTemplateTypeParameter( ColumnNo)); } -extern "C" LLVMValueRef LLVMDIBuilderCreateOpDeref(LLVMTypeRef IntTy) +extern "C" int64_t LLVMDIBuilderCreateOpDeref() { - return LLVMConstInt(IntTy, DIBuilder::OpDeref, true); + return dwarf::DW_OP_deref; } -extern "C" LLVMValueRef LLVMDIBuilderCreateOpPlus(LLVMTypeRef IntTy) +extern "C" int64_t LLVMDIBuilderCreateOpPlus() { - return LLVMConstInt(IntTy, DIBuilder::OpPlus, true); + return dwarf::DW_OP_plus; } -extern "C" LLVMValueRef LLVMDIBuilderCreateComplexVariable( +extern "C" LLVMMetadataRef LLVMDIBuilderCreateNameSpace( DIBuilderRef Builder, - unsigned Tag, - LLVMValueRef Scope, - const char *Name, - LLVMValueRef File, - unsigned LineNo, - LLVMValueRef Ty, - LLVMValueRef* AddrOps, - unsigned AddrOpsCount, - unsigned ArgNo) -{ - llvm::ArrayRef addr_ops((llvm::Value**)AddrOps, AddrOpsCount); - - return wrap(Builder->createComplexVariable( - Tag, - unwrapDI(Scope), - Name, - unwrapDI(File), - LineNo, - unwrapDI(Ty), - addr_ops, - ArgNo - )); -} - -extern "C" LLVMValueRef LLVMDIBuilderCreateNameSpace( - DIBuilderRef Builder, - LLVMValueRef Scope, + LLVMMetadataRef Scope, const char* Name, - LLVMValueRef File, + LLVMMetadataRef File, unsigned LineNo) { return wrap(Builder->createNameSpace( @@ -646,16 +683,39 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateNameSpace( } extern "C" void LLVMDICompositeTypeSetTypeArray( - LLVMValueRef CompositeType, - LLVMValueRef TypeArray) + DIBuilderRef Builder, + LLVMMetadataRef CompositeType, + LLVMMetadataRef TypeArray) { #if LLVM_VERSION_MINOR >= 6 - unwrapDI(CompositeType).setArrays(unwrapDI(TypeArray)); + DICompositeType tmp = unwrapDI(CompositeType); + Builder->replaceArrays(tmp, unwrapDI(TypeArray)); #else unwrapDI(CompositeType).setTypeArray(unwrapDI(TypeArray)); #endif } +extern "C" LLVMValueRef LLVMDIBuilderCreateDebugLocation( + LLVMContextRef Context, + unsigned Line, + unsigned Column, + LLVMMetadataRef Scope, + LLVMMetadataRef InlinedAt) { + + LLVMContext& context = *unwrap(Context); + + DebugLoc debug_loc = DebugLoc::get(Line, + Column, + unwrapDI(Scope), + unwrapDI(InlinedAt)); + +#if LLVM_VERSION_MINOR >= 6 + return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode(context))); +#else + return wrap(debug_loc.getAsMDNode(context)); +#endif +} + extern "C" void LLVMWriteTypeToString(LLVMTypeRef Type, RustStringRef str) { raw_rust_string_ostream os(str); unwrap(Type)->print(os); @@ -690,7 +750,14 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) { } std::string Err; + +#if LLVM_VERSION_MINOR >= 6 + raw_string_ostream Stream(Err); + DiagnosticPrinterRawOStream DP(Stream); + if (Linker::LinkModules(Dst, *Src, [&](const DiagnosticInfo &DI) { DI.print(DP); })) { +#else if (Linker::LinkModules(Dst, *Src, Linker::DestroySource, &Err)) { +#endif LLVMRustSetLastError(Err.c_str()); return false; } @@ -772,7 +839,7 @@ extern "C" const char* #if LLVM_VERSION_MINOR >= 6 LLVMRustArchiveReadSection(OwningBinary *ob, char *name, size_t *size) { - std::unique_ptr &ar = ob->getBinary(); + Archive *ar = ob->getBinary(); #else LLVMRustArchiveReadSection(Archive *ar, char *name, size_t *size) { #endif diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index 9dd66ac0a3059..e159e9729b635 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2015-01-18 +2015-01-30 From 70ed3a48dfa301c5bb56de3e0a7c25214539b83c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 27 Jan 2015 12:20:58 -0800 Subject: [PATCH 21/36] std: Add a new `env` module This is an implementation of [RFC 578][rfc] which adds a new `std::env` module to replace most of the functionality in the current `std::os` module. More details can be found in the RFC itself, but as a summary the following methods have all been deprecated: [rfc]: https://github.com/rust-lang/rfcs/pull/578 * `os::args_as_bytes` => `env::args` * `os::args` => `env::args` * `os::consts` => `env::consts` * `os::dll_filename` => no replacement, use `env::consts` directly * `os::page_size` => `env::page_size` * `os::make_absolute` => use `env::current_dir` + `join` instead * `os::getcwd` => `env::current_dir` * `os::change_dir` => `env::set_current_dir` * `os::homedir` => `env::home_dir` * `os::tmpdir` => `env::temp_dir` * `os::join_paths` => `env::join_paths` * `os::split_paths` => `env::split_paths` * `os::self_exe_name` => `env::current_exe` * `os::self_exe_path` => use `env::current_exe` + `pop` * `os::set_exit_status` => `env::set_exit_status` * `os::get_exit_status` => `env::get_exit_status` * `os::env` => `env::vars` * `os::env_as_bytes` => `env::vars` * `os::getenv` => `env::var` or `env::var_string` * `os::getenv_as_bytes` => `env::var` * `os::setenv` => `env::set_var` * `os::unsetenv` => `env::remove_var` Many function signatures have also been tweaked for various purposes, but the main changes were: * `Vec`-returning APIs now all return iterators instead * All APIs are now centered around `OsString` instead of `Vec` or `String`. There is currently on convenience API, `env::var_string`, which can be used to get the value of an environment variable as a unicode `String`. All old APIs are `#[deprecated]` in-place and will remain for some time to allow for migrations. The semantics of the APIs have been tweaked slightly with regard to dealing with invalid unicode (panic instead of replacement). The new `std::env` module is all contained within the `env` feature, so crates must add the following to access the new APIs: #![feature(env)] [breaking-change] --- src/compiletest/compiletest.rs | 11 +- src/compiletest/runtest.rs | 6 +- src/etc/make-win-dist.py | 1 + src/liblog/lib.rs | 10 +- src/librustc/lib.rs | 2 +- src/librustc/metadata/filesearch.rs | 10 +- .../middle/infer/region_inference/graphviz.rs | 6 +- src/librustc/plugin/load.rs | 4 +- src/librustc/session/mod.rs | 6 +- src/librustc_back/archive.rs | 6 +- src/librustc_back/fs.rs | 4 +- src/librustc_back/lib.rs | 1 + src/librustc_back/rpath.rs | 11 +- src/librustc_back/target/mod.rs | 9 +- src/librustc_driver/driver.rs | 23 +- src/librustc_driver/lib.rs | 13 +- src/librustc_trans/lib.rs | 2 +- src/librustc_trans/save/mod.rs | 8 +- src/librustdoc/lib.rs | 7 +- src/librustdoc/test.rs | 6 +- src/libstd/dynamic_lib.rs | 20 +- src/libstd/env.rs | 833 ++++++++++++++++++ src/libstd/ffi/mod.rs | 7 +- src/libstd/ffi/os_str.rs | 86 +- src/libstd/lib.rs | 1 + src/libstd/old_io/process.rs | 1 + src/libstd/old_io/tempfile.rs | 12 +- src/libstd/old_io/test.rs | 6 +- src/libstd/os.rs | 247 +++--- src/libstd/rt/backtrace.rs | 4 +- src/libstd/rt/mod.rs | 4 +- src/libstd/rt/util.rs | 9 +- src/libstd/sys/common/mutex.rs | 7 - src/libstd/sys/common/rwlock.rs | 7 - src/libstd/sys/unix/backtrace.rs | 4 +- src/libstd/sys/unix/c.rs | 53 ++ src/libstd/sys/unix/mod.rs | 4 +- src/libstd/sys/unix/os.rs | 440 ++++++--- src/libstd/sys/unix/process.rs | 14 +- src/libstd/sys/windows/backtrace.rs | 34 +- src/libstd/sys/windows/c.rs | 190 +++- src/libstd/sys/windows/fs.rs | 20 +- src/libstd/sys/windows/handle.rs | 31 + src/libstd/sys/windows/mod.rs | 111 ++- src/libstd/sys/windows/mutex.rs | 2 - src/libstd/sys/windows/os.rs | 453 +++++----- src/libstd/sys/windows/pipe.rs | 18 +- src/libstd/sys/windows/process.rs | 24 +- src/libstd/sys/windows/rwlock.rs | 3 - src/libstd/sys/windows/stack_overflow.rs | 10 +- src/libstd/sys/windows/sync.rs | 2 +- src/libstd/sys/windows/tcp.rs | 9 +- src/libstd/sys/windows/thread.rs | 2 - src/libstd/sys/windows/thread_local.rs | 1 + src/libstd/sys/windows/timer.rs | 2 - src/libstd/sys/windows/tty.rs | 5 +- src/libsyntax/ext/env.rs | 14 +- src/libsyntax/lib.rs | 2 +- src/libterm/lib.rs | 3 +- src/libterm/terminfo/mod.rs | 10 +- src/libterm/terminfo/searcher.rs | 17 +- src/libtest/lib.rs | 12 +- src/test/bench/shootout-mandelbrot.rs | 7 +- src/test/compile-fail/liveness-unused.rs | 3 +- src/test/run-pass/env-home-dir.rs | 45 + src/test/run-pass/env-vars.rs | 22 + 66 files changed, 2175 insertions(+), 782 deletions(-) create mode 100644 src/libstd/env.rs create mode 100644 src/libstd/sys/windows/handle.rs create mode 100644 src/test/run-pass/env-home-dir.rs create mode 100644 src/test/run-pass/env-vars.rs diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index b73623223fd4e..7c0ee7be8a444 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -22,6 +22,7 @@ #![feature(std_misc)] #![feature(test)] #![feature(unicode)] +#![feature(env)] #![deny(warnings)] @@ -31,7 +32,7 @@ extern crate getopts; #[macro_use] extern crate log; -use std::os; +use std::env; use std::old_io; use std::old_io::fs; use std::thunk::Thunk; @@ -48,7 +49,7 @@ pub mod common; pub mod errors; pub fn main() { - let args = os::args(); + let args = env::args().map(|s| s.into_string().unwrap()).collect();; let config = parse_config(args); if config.valgrind_path.is_none() && config.force_valgrind { @@ -224,7 +225,7 @@ pub fn run_tests(config: &Config) { //arm-linux-androideabi debug-info test uses remote debugger //so, we test 1 task at once. // also trying to isolate problems with adb_run_wrapper.sh ilooping - os::setenv("RUST_TEST_TASKS","1"); + env::set_var("RUST_TEST_TASKS","1"); } match config.mode { @@ -232,7 +233,7 @@ pub fn run_tests(config: &Config) { // Some older versions of LLDB seem to have problems with multiple // instances running in parallel, so only run one test task at a // time. - os::setenv("RUST_TEST_TASKS", "1"); + env::set_var("RUST_TEST_TASKS", "1"); } _ => { /* proceed */ } } @@ -245,7 +246,7 @@ pub fn run_tests(config: &Config) { old_io::test::raise_fd_limit(); // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary - os::setenv("__COMPAT_LAYER", "RunAsInvoker"); + env::set_var("__COMPAT_LAYER", "RunAsInvoker"); let res = test::run_tests_console(&opts, tests.into_iter().collect()); match res { Ok(true) => {} diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 18cb3d1d5b006..5b0ea3b4854ed 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -31,7 +31,7 @@ use std::old_io::process::ProcessExit; use std::old_io::process; use std::old_io::timer; use std::old_io; -use std::os; +use std::env; use std::iter::repeat; use std::str; use std::string::String; @@ -1298,9 +1298,9 @@ fn make_lib_name(config: &Config, auxfile: &Path, testfile: &Path) -> Path { fn make_exe_name(config: &Config, testfile: &Path) -> Path { let mut f = output_base_name(config, testfile); - if !os::consts::EXE_SUFFIX.is_empty() { + if !env::consts::EXE_SUFFIX.is_empty() { let mut fname = f.filename().unwrap().to_vec(); - fname.extend(os::consts::EXE_SUFFIX.bytes()); + fname.extend(env::consts::EXE_SUFFIX.bytes()); f.set_filename(fname); } f diff --git a/src/etc/make-win-dist.py b/src/etc/make-win-dist.py index 13d0513502488..defda27acc9ec 100644 --- a/src/etc/make-win-dist.py +++ b/src/etc/make-win-dist.py @@ -87,6 +87,7 @@ def make_win_dist(rust_root, gcc_root, target_triple): "libsetupapi.a", "libshell32.a", "libuser32.a", + "libuserenv.a", "libuuid.a", "libwinhttp.a", "libwinmm.a", diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 81d8c60f8939b..34216518c21d2 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -173,15 +173,15 @@ #![feature(int_uint)] #![feature(core)] #![feature(io)] -#![feature(os)] #![feature(std_misc)] +#![feature(env)] use std::cell::RefCell; use std::fmt; use std::old_io::LineBufferedWriter; use std::old_io; use std::mem; -use std::os; +use std::env; use std::ptr; use std::rt; use std::slice; @@ -397,9 +397,9 @@ fn enabled(level: u32, /// This is not threadsafe at all, so initialization is performed through a /// `Once` primitive (and this function is called from that primitive). fn init() { - let (mut directives, filter) = match os::getenv("RUST_LOG") { - Some(spec) => directive::parse_logging_spec(&spec[]), - None => (Vec::new(), None), + let (mut directives, filter) = match env::var_string("RUST_LOG") { + Ok(spec) => directive::parse_logging_spec(&spec[]), + Err(..) => (Vec::new(), None), }; // Sort the provided directives by length of their name, this allows a diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 6ae861fcb0424..2f31a2c083f7f 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -32,7 +32,7 @@ #![feature(int_uint)] #![feature(io)] #![feature(libc)] -#![feature(os)] +#![feature(env)] #![feature(path)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index 26046cfb43d8a..45dd4b4dbacbd 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -13,9 +13,9 @@ pub use self::FileMatch::*; use std::collections::HashSet; +use std::env; use std::old_io::fs::PathExtensions; use std::old_io::fs; -use std::os; use util::fs as myfs; use session::search_paths::{SearchPaths, PathKind}; @@ -194,7 +194,7 @@ pub fn get_or_default_sysroot() -> Path { }) } - match canonicalize(os::self_exe_name()) { + match canonicalize(env::current_exe().ok()) { Some(mut p) => { p.pop(); p.pop(); p } None => panic!("can't determine value for sysroot") } @@ -207,7 +207,7 @@ static PATH_ENTRY_SEPARATOR: &'static str = ":"; /// Returns RUST_PATH as a string, without default paths added pub fn get_rust_path() -> Option { - os::getenv("RUST_PATH").map(|x| x.to_string()) + env::var_string("RUST_PATH").ok() } /// Returns the value of RUST_PATH, as a list @@ -224,7 +224,7 @@ pub fn rust_path() -> Vec { } None => Vec::new() }; - let mut cwd = os::getcwd().unwrap(); + let mut cwd = env::current_dir().unwrap(); // now add in default entries let cwd_dot_rust = cwd.join(".rust"); if !env_rust_path.contains(&cwd_dot_rust) { @@ -243,7 +243,7 @@ pub fn rust_path() -> Vec { } cwd.pop(); } - let h = os::homedir(); + let h = env::home_dir(); for h in h.iter() { let p = h.join(".rust"); if !env_rust_path.contains(&p) && p.exists() { diff --git a/src/librustc/middle/infer/region_inference/graphviz.rs b/src/librustc/middle/infer/region_inference/graphviz.rs index 460687629e7b5..87ea5436dab6b 100644 --- a/src/librustc/middle/infer/region_inference/graphviz.rs +++ b/src/librustc/middle/infer/region_inference/graphviz.rs @@ -27,7 +27,7 @@ use util::ppaux::Repr; use std::collections::hash_map::Entry::Vacant; use std::old_io::{self, File}; -use std::os; +use std::env; use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT}; use syntax::ast; @@ -59,13 +59,13 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a, } let requested_node : Option = - os::getenv("RUST_REGION_GRAPH_NODE").and_then(|s| s.parse().ok()); + env::var_string("RUST_REGION_GRAPH_NODE").ok().and_then(|s| s.parse().ok()); if requested_node.is_some() && requested_node != Some(subject_node) { return; } - let requested_output = os::getenv("RUST_REGION_GRAPH"); + let requested_output = env::var_string("RUST_REGION_GRAPH").ok(); debug!("requested_output: {:?} requested_node: {:?}", requested_output, requested_node); diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index c420d1f15b43b..c04bf755b1f6b 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -15,7 +15,7 @@ use metadata::creader::{CrateOrString, CrateReader}; use plugin::registry::Registry; use std::mem; -use std::os; +use std::env; use std::dynamic_lib::DynamicLibrary; use std::collections::HashSet; use syntax::ast; @@ -233,7 +233,7 @@ impl<'a> PluginLoader<'a> { path: Path, symbol: String) -> PluginRegistrarFun { // Make sure the path contains a / or the linker will search for it. - let path = os::make_absolute(&path).unwrap(); + let path = env::current_dir().unwrap().join(&path); let lib = match DynamicLibrary::open(Some(&path)) { Ok(lib) => lib, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index e62f3145e5a2e..a983f995d3f64 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -27,7 +27,7 @@ use syntax::{ast, codemap}; use rustc_back::target::Target; -use std::os; +use std::env; use std::cell::{Cell, RefCell}; pub mod config; @@ -347,7 +347,7 @@ pub fn build_session_(sopts: config::Options, if path.is_absolute() { path.clone() } else { - os::getcwd().unwrap().join(&path) + env::current_dir().unwrap().join(&path) } ); @@ -370,7 +370,7 @@ pub fn build_session_(sopts: config::Options, plugin_registrar_fn: Cell::new(None), default_sysroot: default_sysroot, local_crate_source_file: local_crate_source_file, - working_dir: os::getcwd().unwrap(), + working_dir: env::current_dir().unwrap(), lint_store: RefCell::new(lint::LintStore::new()), lints: RefCell::new(NodeMap()), crate_types: RefCell::new(Vec::new()), diff --git a/src/librustc_back/archive.rs b/src/librustc_back/archive.rs index ee8bc71668b35..f5483e666cfd4 100644 --- a/src/librustc_back/archive.rs +++ b/src/librustc_back/archive.rs @@ -14,7 +14,7 @@ use std::old_io::fs::PathExtensions; use std::old_io::process::{Command, ProcessOutput}; use std::old_io::{fs, TempDir}; use std::old_io; -use std::os; +use std::env; use std::str; use syntax::diagnostic::Handler as ErrorHandler; @@ -224,7 +224,7 @@ impl<'a> ArchiveBuilder<'a> { pub fn build(self) -> Archive<'a> { // Get an absolute path to the destination, so `ar` will work even // though we run it from `self.work_dir`. - let abs_dst = os::getcwd().unwrap().join(&self.archive.dst); + let abs_dst = env::current_dir().unwrap().join(&self.archive.dst); assert!(!abs_dst.is_relative()); let mut args = vec![&abs_dst]; let mut total_len = abs_dst.as_vec().len(); @@ -283,7 +283,7 @@ impl<'a> ArchiveBuilder<'a> { // First, extract the contents of the archive to a temporary directory. // We don't unpack directly into `self.work_dir` due to the possibility // of filename collisions. - let archive = os::make_absolute(archive).unwrap(); + let archive = env::current_dir().unwrap().join(archive); run_ar(self.archive.handler, &self.archive.maybe_ar_prog, "x", Some(loc.path()), &[&archive]); diff --git a/src/librustc_back/fs.rs b/src/librustc_back/fs.rs index 24f81b024789c..acf49d1ca46e3 100644 --- a/src/librustc_back/fs.rs +++ b/src/librustc_back/fs.rs @@ -10,13 +10,13 @@ use std::old_io; use std::old_io::fs; -use std::os; +use std::env; /// Returns an absolute path in the filesystem that `path` points to. The /// returned path does not contain any symlinks in its hierarchy. pub fn realpath(original: &Path) -> old_io::IoResult { static MAX_LINKS_FOLLOWED: uint = 256; - let original = os::make_absolute(original).unwrap(); + let original = try!(env::current_dir()).join(original); // Right now lstat on windows doesn't work quite well if cfg!(windows) { diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 2c6b5797f572b..54b3e8f208125 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -40,6 +40,7 @@ #![feature(path)] #![feature(rustc_private)] #![feature(staged_api)] +#![feature(env)] extern crate syntax; extern crate serialize; diff --git a/src/librustc_back/rpath.rs b/src/librustc_back/rpath.rs index 47b909df5e8da..b6a34b4beba71 100644 --- a/src/librustc_back/rpath.rs +++ b/src/librustc_back/rpath.rs @@ -10,7 +10,7 @@ use std::collections::HashSet; -use std::os; +use std::env; use std::old_io::IoError; use syntax::ast; @@ -105,8 +105,6 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path F: FnOnce() -> Path, G: FnMut(&Path) -> Result, { - use std::os; - // Mac doesn't appear to support $ORIGIN let prefix = if config.is_like_osx { "@loader_path" @@ -114,9 +112,10 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path "$ORIGIN" }; - let mut lib = (config.realpath)(&os::make_absolute(lib).unwrap()).unwrap(); + let cwd = env::current_dir().unwrap(); + let mut lib = (config.realpath)(&cwd.join(lib)).unwrap(); lib.pop(); - let mut output = (config.realpath)(&os::make_absolute(&config.out_filename).unwrap()).unwrap(); + let mut output = (config.realpath)(&cwd.join(&config.out_filename)).unwrap(); output.pop(); let relative = lib.path_relative_from(&output); let relative = relative.expect("could not create rpath relative to output"); @@ -131,7 +130,7 @@ fn get_install_prefix_rpath(config: RPathConfig) -> String where G: FnMut(&Path) -> Result, { let path = (config.get_install_prefix_lib_path)(); - let path = os::make_absolute(&path).unwrap(); + let path = env::current_dir().unwrap().join(&path); // FIXME (#9639): This needs to handle non-utf8 paths path.as_str().expect("non-utf8 component in rpath").to_string() } diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 16adccfba575e..eb7c23f95e2e1 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -301,7 +301,8 @@ impl Target { /// The error string could come from any of the APIs called, including filesystem access and /// JSON decoding. pub fn search(target: &str) -> Result { - use std::os; + use std::env; + use std::ffi::OsString; use std::old_io::File; use std::path::Path; use serialize::json; @@ -379,12 +380,12 @@ impl Target { Path::new(target) }; - let target_path = os::getenv("RUST_TARGET_PATH").unwrap_or(String::new()); + let target_path = env::var("RUST_TARGET_PATH") + .unwrap_or(OsString::from_str("")); - let paths = os::split_paths(&target_path[]); // FIXME 16351: add a sane default search path? - for dir in paths.iter() { + for dir in env::split_paths(&target_path) { let p = dir.join(path.clone()); if p.is_file() { return load_file(&p); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 9e00844b7eea2..4aa4193d51134 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -30,9 +30,10 @@ use rustc_privacy; use serialize::json; -use std::old_io; +use std::env; +use std::ffi::OsString; use std::old_io::fs; -use std::os; +use std::old_io; use syntax::ast; use syntax::ast_map; use syntax::attr; @@ -460,12 +461,12 @@ pub fn phase_2_configure_and_expand(sess: &Session, // dependent dlls. Note that this uses cfg!(windows) as opposed to // targ_cfg because syntax extensions are always loaded for the host // compiler, not for the target. - let mut _old_path = String::new(); + let mut _old_path = OsString::from_str(""); if cfg!(windows) { - _old_path = os::getenv("PATH").unwrap_or(_old_path); + _old_path = env::var("PATH").unwrap_or(_old_path); let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths(); - new_path.extend(os::split_paths(&_old_path[]).into_iter()); - os::setenv("PATH", os::join_paths(&new_path[]).unwrap()); + new_path.extend(env::split_paths(&_old_path)); + env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap()); } let cfg = syntax::ext::expand::ExpansionConfig { crate_name: crate_name.to_string(), @@ -478,7 +479,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, syntax_exts, krate); if cfg!(windows) { - os::setenv("PATH", _old_path); + env::set_var("PATH", &_old_path); } ret } @@ -734,10 +735,10 @@ pub fn phase_5_run_llvm_passes(sess: &Session, pub fn phase_6_link_output(sess: &Session, trans: &trans::CrateTranslation, outputs: &OutputFilenames) { - let old_path = os::getenv("PATH").unwrap_or_else(||String::new()); + let old_path = env::var("PATH").unwrap_or(OsString::from_str("")); let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(); - new_path.extend(os::split_paths(&old_path[]).into_iter()); - os::setenv("PATH", os::join_paths(&new_path[]).unwrap()); + new_path.extend(env::split_paths(&old_path)); + env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap()); time(sess.time_passes(), "linking", (), |_| link::link_binary(sess, @@ -745,7 +746,7 @@ pub fn phase_6_link_output(sess: &Session, outputs, &trans.link.crate_name[])); - os::setenv("PATH", old_path); + env::set_var("PATH", &old_path); } fn escape_dep_filename(filename: &str) -> String { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 2eada1ff174f1..6230f0b14a23b 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -26,6 +26,7 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(core)] +#![feature(env)] #![feature(int_uint)] #![feature(io)] #![feature(libc)] @@ -74,7 +75,7 @@ use rustc::util::common::time; use std::cmp::Ordering::Equal; use std::old_io; use std::iter::repeat; -use std::os; +use std::env; use std::sync::mpsc::channel; use std::thread; @@ -252,7 +253,7 @@ pub fn get_unstable_features_setting() -> UnstableFeatures { // subverting the unstable features lints let bootstrap_secret_key = option_env!("CFG_BOOTSTRAP_KEY"); // The matching key to the above, only known by the build system - let bootstrap_provided_key = os::getenv("RUSTC_BOOTSTRAP_KEY"); + let bootstrap_provided_key = env::var_string("RUSTC_BOOTSTRAP_KEY").ok(); match (disable_unstable_features, bootstrap_secret_key, bootstrap_provided_key) { (_, Some(ref s), Some(ref p)) if s == p => UnstableFeatures::Cheat, (true, _, _) => UnstableFeatures::Disallow, @@ -618,7 +619,7 @@ pub fn monitor(f: F) { // FIXME: Hacks on hacks. If the env is trying to override the stack size // then *don't* set it explicitly. - if os::getenv("RUST_MIN_STACK").is_none() { + if env::var("RUST_MIN_STACK").is_none() { cfg = cfg.stack_size(STACK_SIZE); } @@ -682,8 +683,8 @@ pub fn diagnostics_registry() -> diagnostics::registry::Registry { } pub fn main() { - let args = std::os::args(); - let result = run(args); - std::os::set_exit_status(result); + let args = env::args().map(|s| s.into_string().unwrap()); + let result = run(args.collect()); + std::env::set_exit_status(result as i32); } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index c46c2b7e6ddaf..11ffade6da6c6 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -32,8 +32,8 @@ #![feature(hash)] #![feature(int_uint)] #![feature(io)] +#![feature(env)] #![feature(libc)] -#![feature(os)] #![feature(path)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index fbeaae1d1dfa3..f429ab7599fef 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -34,7 +34,7 @@ use middle::ty::{self, Ty}; use std::cell::Cell; use std::old_io::{self, File, fs}; -use std::os; +use std::env; use syntax::ast_util::{self, PostExpansionMethod}; use syntax::ast::{self, NodeId, DefId}; @@ -1551,9 +1551,9 @@ pub fn process_crate(sess: &Session, info!("Dumping crate {}", cratename); // find a path to dump our data to - let mut root_path = match os::getenv("DXR_RUST_TEMP_FOLDER") { - Some(val) => Path::new(val), - None => match odir { + let mut root_path = match env::var_string("DXR_RUST_TEMP_FOLDER") { + Ok(val) => Path::new(val), + Err(..) => match odir { Some(val) => val.join("dxr"), None => Path::new("dxr-temp"), }, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 29e52d627cdfe..c9b50bdd3c1d2 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -21,6 +21,7 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(core)] +#![feature(env)] #![feature(hash)] #![feature(int_uint)] #![feature(io)] @@ -50,6 +51,7 @@ extern crate "serialize" as rustc_serialize; // used by deriving use std::cell::RefCell; use std::collections::HashMap; +use std::env; use std::old_io::File; use std::old_io; use std::rc::Rc; @@ -121,9 +123,10 @@ struct Output { pub fn main() { static STACK_SIZE: uint = 32000000; // 32MB let res = std::thread::Builder::new().stack_size(STACK_SIZE).scoped(move || { - main_args(std::os::args().as_slice()) + let s = env::args().map(|s| s.into_string().unwrap()); + main_args(&s.collect::>()) }).join(); - std::os::set_exit_status(res.ok().unwrap()); + env::set_exit_status(res.ok().unwrap() as i32); } pub fn opts() -> Vec { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 2f692fe99cda7..29abea009e547 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -13,7 +13,7 @@ use std::sync::mpsc::channel; use std::dynamic_lib::DynamicLibrary; use std::old_io::{Command, TempDir}; use std::old_io; -use std::os; +use std::env; use std::str; use std::thread::Thread; use std::thunk::Thunk; @@ -49,7 +49,7 @@ pub fn run(input: &str, let input = config::Input::File(input_path.clone()); let sessopts = config::Options { - maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()), + maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()), search_paths: libs.clone(), crate_types: vec!(config::CrateTypeDylib), externs: externs.clone(), @@ -119,7 +119,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths, let input = config::Input::Str(test.to_string()); let sessopts = config::Options { - maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()), + maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()), search_paths: libs, crate_types: vec!(config::CrateTypeExecutable), output_types: vec!(config::OutputTypeExe), diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index f35f63143ef82..46567aedbec4e 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -19,7 +19,7 @@ use prelude::v1::*; use ffi::CString; use mem; -use os; +use env; use str; #[allow(missing_copy_implementations)] @@ -68,8 +68,8 @@ impl DynamicLibrary { let mut search_path = DynamicLibrary::search_path(); search_path.insert(0, path.clone()); let newval = DynamicLibrary::create_path(search_path.as_slice()); - os::setenv(DynamicLibrary::envvar(), - str::from_utf8(newval.as_slice()).unwrap()); + env::set_var(DynamicLibrary::envvar(), + str::from_utf8(newval.as_slice()).unwrap()); } /// From a slice of paths, create a new vector which is suitable to be an @@ -102,18 +102,10 @@ impl DynamicLibrary { /// Returns the current search path for dynamic libraries being used by this /// process pub fn search_path() -> Vec { - let mut ret = Vec::new(); - match os::getenv_as_bytes(DynamicLibrary::envvar()) { - Some(env) => { - for portion in - env.as_slice() - .split(|a| *a == DynamicLibrary::separator()) { - ret.push(Path::new(portion)); - } - } - None => {} + match env::var(DynamicLibrary::envvar()) { + Some(var) => env::split_paths(&var).collect(), + None => Vec::new(), } - return ret; } /// Access the value at the symbol of the dynamic library diff --git a/src/libstd/env.rs b/src/libstd/env.rs new file mode 100644 index 0000000000000..5070f8c547ab0 --- /dev/null +++ b/src/libstd/env.rs @@ -0,0 +1,833 @@ +// Copyright 2012-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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Inspection and manipulation of the process's environment. +//! +//! This module contains methods to inspect various aspects such as +//! environment varibles, process arguments, the current directory, and various +//! other important directories. + +#![unstable(feature = "env", reason = "recently added via RFC 578")] + +use prelude::v1::*; + +use error::Error; +use ffi::{OsString, AsOsStr}; +use fmt; +use old_io::IoResult; +use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering}; +use sync::{StaticMutex, MUTEX_INIT}; +use sys::os as os_imp; + +/// Returns the current working directory as a `Path`. +/// +/// # Errors +/// +/// Returns an `Err` if the current working directory value is invalid. +/// Possible cases: +/// +/// * Current directory does not exist. +/// * There are insufficient permissions to access the current directory. +/// * The internal buffer is not large enough to hold the path. +/// +/// # Example +/// +/// ```rust +/// use std::env; +/// +/// // We assume that we are in a valid directory. +/// let p = env::current_dir().unwrap(); +/// println!("The current directory is {}", p.display()); +/// ``` +pub fn current_dir() -> IoResult { + os_imp::getcwd() +} + +/// Changes the current working directory to the specified path, returning +/// whether the change was completed successfully or not. +/// +/// # Example +/// +/// ```rust +/// use std::env; +/// use std::path::Path; +/// +/// let root = Path::new("/"); +/// assert!(env::set_current_dir(&root).is_ok()); +/// println!("Successfully changed working directory to {}!", root.display()); +/// ``` +pub fn set_current_dir(p: &Path) -> IoResult<()> { + os_imp::chdir(p) +} + +static ENV_LOCK: StaticMutex = MUTEX_INIT; + +/// An iterator over a snapshot of the environment variables of this process. +/// +/// This iterator is created through `std::env::vars()` and yields `(OsString, +/// OsString)` pairs. +pub struct Vars { inner: os_imp::Env } + +/// Returns an iterator of (variable, value) pairs, for all the environment +/// variables of the current process. +/// +/// The returned iterator contains a snapshot of the process's environment +/// variables at the time of this invocation, modifications to environment +/// variables afterwards will not be reflected in the returned iterator. +/// +/// # Example +/// +/// ```rust +/// use std::env; +/// +/// // We will iterate through the references to the element returned by +/// // env::vars(); +/// for (key, value) in env::vars() { +/// println!("{:?}: {:?}", key, value); +/// } +/// ``` +pub fn vars() -> Vars { + let _g = ENV_LOCK.lock(); + Vars { inner: os_imp::env() } +} + +impl Iterator for Vars { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { self.inner.next() } + fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } +} + +/// Fetches the environment variable `key` from the current process, returning +/// None if the variable isn't set. +/// +/// # Example +/// +/// ```rust +/// use std::env; +/// +/// let key = "HOME"; +/// match env::var(key) { +/// Some(val) => println!("{}: {:?}", key, val), +/// None => println!("{} is not defined in the environment.", key) +/// } +/// ``` +pub fn var(key: &K) -> Option where K: AsOsStr { + let _g = ENV_LOCK.lock(); + os_imp::getenv(key.as_os_str()) +} + +/// Fetches the environment variable `key` from the current process. +/// +/// The returned result is `Ok(s)` if the environment variable is present and is +/// valid unicode. If the environment variable is not present, or it is not +/// valid unicode, then `Err` will be returned. +/// +/// # Example +/// +/// ```rust +/// use std::env; +/// +/// let key = "HOME"; +/// match env::var_string(key) { +/// Ok(val) => println!("{}: {:?}", key, val), +/// Err(e) => println!("couldn't interpret {}: {}", key, e), +/// } +/// ``` +pub fn var_string(key: &K) -> Result where K: AsOsStr { + match var(key) { + Some(s) => s.into_string().map_err(VarError::NotUnicode), + None => Err(VarError::NotPresent) + } +} + +/// Possible errors from the `env::var` method. +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum VarError { + /// The specified environment variable was not present in the current + /// process's environment. + NotPresent, + + /// The specified environment variable was found, but it did not contain + /// valid unicode data. The found data is returned as a payload of this + /// variant. + NotUnicode(OsString), +} + +impl fmt::Display for VarError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + VarError::NotPresent => write!(f, "environment variable not found"), + VarError::NotUnicode(ref s) => { + write!(f, "environment variable was not valid unicode: {:?}", s) + } + } + } +} + +impl Error for VarError { + fn description(&self) -> &str { + match *self { + VarError::NotPresent => "environment variable not found", + VarError::NotUnicode(..) => "environment variable was not valid unicode", + } + } +} + +/// Sets the environment variable `k` to the value `v` for the currently running +/// process. +/// +/// # Example +/// +/// ```rust +/// use std::env; +/// +/// let key = "KEY"; +/// env::set_var(key, "VALUE"); +/// assert_eq!(env::var_string(key), Ok("VALUE".to_string())); +/// ``` +pub fn set_var(k: &K, v: &V) + where K: AsOsStr, V: AsOsStr +{ + let _g = ENV_LOCK.lock(); + os_imp::setenv(k.as_os_str(), v.as_os_str()) +} + +/// Remove a variable from the environment entirely. +pub fn remove_var(k: &K) where K: AsOsStr { + let _g = ENV_LOCK.lock(); + os_imp::unsetenv(k.as_os_str()) +} + +/// An iterator over `Path` instances for parsing an environment variable +/// according to platform-specific conventions. +/// +/// This structure is returned from `std::env::split_paths`. +pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> } + +/// Parses input according to platform conventions for the `PATH` +/// environment variable. +/// +/// Returns an iterator over the paths contained in `unparsed`. +/// +/// # Example +/// +/// ```rust +/// use std::env; +/// +/// let key = "PATH"; +/// match env::var(key) { +/// Some(paths) => { +/// for path in env::split_paths(&paths) { +/// println!("'{}'", path.display()); +/// } +/// } +/// None => println!("{} is not defined in the environment.", key) +/// } +/// ``` +pub fn split_paths(unparsed: &T) -> SplitPaths { + SplitPaths { inner: os_imp::split_paths(unparsed.as_os_str()) } +} + +impl<'a> Iterator for SplitPaths<'a> { + type Item = Path; + fn next(&mut self) -> Option { self.inner.next() } + fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } +} + +/// Error type returned from `std::env::join_paths` when paths fail to be +/// joined. +#[derive(Debug)] +pub struct JoinPathsError { + inner: os_imp::JoinPathsError +} + +/// Joins a collection of `Path`s appropriately for the `PATH` +/// environment variable. +/// +/// Returns an `OsString` on success. +/// +/// Returns an `Err` (containing an error message) if one of the input +/// `Path`s contains an invalid character for constructing the `PATH` +/// variable (a double quote on Windows or a colon on Unix). +/// +/// # Example +/// +/// ```rust +/// use std::env; +/// +/// if let Some(path) = env::var("PATH") { +/// let mut paths = env::split_paths(&path).collect::>(); +/// paths.push(Path::new("/home/xyz/bin")); +/// let new_path = env::join_paths(paths.iter()).unwrap(); +/// env::set_var("PATH", &new_path); +/// } +/// ``` +pub fn join_paths(paths: I) -> Result + where I: Iterator, T: AsOsStr +{ + os_imp::join_paths(paths).map_err(|e| { + JoinPathsError { inner: e } + }) +} + +impl fmt::Display for JoinPathsError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.inner.fmt(f) + } +} + +impl Error for JoinPathsError { + fn description(&self) -> &str { self.inner.description() } +} + +/// Optionally returns the path to the current user's home directory if known. +/// +/// # Unix +/// +/// Returns the value of the 'HOME' environment variable if it is set +/// and not equal to the empty string. +/// +/// # Windows +/// +/// Returns the value of the 'HOME' environment variable if it is +/// set and not equal to the empty string. Otherwise, returns the value of the +/// 'USERPROFILE' environment variable if it is set and not equal to the empty +/// string. +/// +/// # Example +/// +/// ```rust +/// use std::env; +/// +/// match env::home_dir() { +/// Some(ref p) => println!("{}", p.display()), +/// None => println!("Impossible to get your home dir!") +/// } +/// ``` +pub fn home_dir() -> Option { + os_imp::home_dir() +} + +/// Returns the path to a temporary directory. +/// +/// On Unix, returns the value of the 'TMPDIR' environment variable if it is +/// set, otherwise for non-Android it returns '/tmp'. If Android, since there +/// is no global temporary folder (it is usually allocated per-app), we return +/// '/data/local/tmp'. +/// +/// On Windows, returns the value of, in order, the 'TMP', 'TEMP', +/// 'USERPROFILE' environment variable if any are set and not the empty +/// string. Otherwise, tmpdir returns the path to the Windows directory. +pub fn temp_dir() -> Path { + os_imp::temp_dir() +} + +/// Optionally returns the filesystem path to the current executable which is +/// running but with the executable name. +/// +/// The path returned is not necessarily a "real path" to the executable as +/// there may be intermediate symlinks. +/// +/// # Errors +/// +/// Acquring the path to the current executable is a platform-specific operation +/// that can fail for a good number of reasons. Some errors can include, but not +/// be limited to filesystem operations failing or general syscall failures. +/// +/// # Examples +/// +/// ```rust +/// use std::env; +/// +/// match env::current_exe() { +/// Ok(exe_path) => println!("Path of this executable is: {}", +/// exe_path.display()), +/// Err(e) => println!("failed to get current exe path: {}", e), +/// }; +/// ``` +pub fn current_exe() -> IoResult { + os_imp::current_exe() +} + +static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT; + +/// Sets the process exit code +/// +/// Sets the exit code returned by the process if all supervised tasks +/// terminate successfully (without panicking). If the current root task panics +/// and is supervised by the scheduler then any user-specified exit status is +/// ignored and the process exits with the default panic status. +/// +/// Note that this is not synchronized against modifications of other threads. +pub fn set_exit_status(code: i32) { + EXIT_STATUS.store(code as isize, Ordering::SeqCst) +} + +/// Fetches the process's current exit code. This defaults to 0 and can change +/// by calling `set_exit_status`. +pub fn get_exit_status() -> i32 { + EXIT_STATUS.load(Ordering::SeqCst) as i32 +} + +/// An iterator over the arguments of a process, yielding an `OsString` value +/// for each argument. +/// +/// This structure is created through the `std::env::args` method. +pub struct Args { inner: os_imp::Args } + +/// Returns the arguments which this program was started with (normally passed +/// via the command line). +/// +/// The first element is traditionally the path to the executable, but it can be +/// set to arbitrary text, and it may not even exist, so this property should +/// not be relied upon for security purposes. +/// +/// # Example +/// +/// ```rust +/// use std::env; +/// +/// // Prints each argument on a separate line +/// for argument in env::args() { +/// println!("{:?}", argument); +/// } +/// ``` +pub fn args() -> Args { + Args { inner: os_imp::args() } +} + +impl Iterator for Args { + type Item = OsString; + fn next(&mut self) -> Option { self.inner.next() } + fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } +} + +/// Returns the page size of the current architecture in bytes. +pub fn page_size() -> usize { + os_imp::page_size() +} + +/// Constants associated with the current target +#[cfg(target_os = "linux")] +pub mod consts { + pub use super::arch_consts::ARCH; + + pub const FAMILY: &'static str = "unix"; + + /// A string describing the specific operating system in use: in this + /// case, `linux`. + pub const OS: &'static str = "linux"; + + /// Specifies the filename prefix used for shared libraries on this + /// platform: in this case, `lib`. + pub const DLL_PREFIX: &'static str = "lib"; + + /// Specifies the filename suffix used for shared libraries on this + /// platform: in this case, `.so`. + pub const DLL_SUFFIX: &'static str = ".so"; + + /// Specifies the file extension used for shared libraries on this + /// platform that goes after the dot: in this case, `so`. + pub const DLL_EXTENSION: &'static str = "so"; + + /// Specifies the filename suffix used for executable binaries on this + /// platform: in this case, the empty string. + pub const EXE_SUFFIX: &'static str = ""; + + /// Specifies the file extension, if any, used for executable binaries + /// on this platform: in this case, the empty string. + pub const EXE_EXTENSION: &'static str = ""; +} + +/// Constants associated with the current target +#[cfg(target_os = "macos")] +pub mod consts { + pub use super::arch_consts::ARCH; + + pub const FAMILY: &'static str = "unix"; + + /// A string describing the specific operating system in use: in this + /// case, `macos`. + pub const OS: &'static str = "macos"; + + /// Specifies the filename prefix used for shared libraries on this + /// platform: in this case, `lib`. + pub const DLL_PREFIX: &'static str = "lib"; + + /// Specifies the filename suffix used for shared libraries on this + /// platform: in this case, `.dylib`. + pub const DLL_SUFFIX: &'static str = ".dylib"; + + /// Specifies the file extension used for shared libraries on this + /// platform that goes after the dot: in this case, `dylib`. + pub const DLL_EXTENSION: &'static str = "dylib"; + + /// Specifies the filename suffix used for executable binaries on this + /// platform: in this case, the empty string. + pub const EXE_SUFFIX: &'static str = ""; + + /// Specifies the file extension, if any, used for executable binaries + /// on this platform: in this case, the empty string. + pub const EXE_EXTENSION: &'static str = ""; +} + +/// Constants associated with the current target +#[cfg(target_os = "ios")] +pub mod consts { + pub use super::arch_consts::ARCH; + + pub const FAMILY: &'static str = "unix"; + + /// A string describing the specific operating system in use: in this + /// case, `ios`. + pub const OS: &'static str = "ios"; + + /// Specifies the filename suffix used for executable binaries on this + /// platform: in this case, the empty string. + pub const EXE_SUFFIX: &'static str = ""; + + /// Specifies the file extension, if any, used for executable binaries + /// on this platform: in this case, the empty string. + pub const EXE_EXTENSION: &'static str = ""; +} + +/// Constants associated with the current target +#[cfg(target_os = "freebsd")] +pub mod consts { + pub use super::arch_consts::ARCH; + + pub const FAMILY: &'static str = "unix"; + + /// A string describing the specific operating system in use: in this + /// case, `freebsd`. + pub const OS: &'static str = "freebsd"; + + /// Specifies the filename prefix used for shared libraries on this + /// platform: in this case, `lib`. + pub const DLL_PREFIX: &'static str = "lib"; + + /// Specifies the filename suffix used for shared libraries on this + /// platform: in this case, `.so`. + pub const DLL_SUFFIX: &'static str = ".so"; + + /// Specifies the file extension used for shared libraries on this + /// platform that goes after the dot: in this case, `so`. + pub const DLL_EXTENSION: &'static str = "so"; + + /// Specifies the filename suffix used for executable binaries on this + /// platform: in this case, the empty string. + pub const EXE_SUFFIX: &'static str = ""; + + /// Specifies the file extension, if any, used for executable binaries + /// on this platform: in this case, the empty string. + pub const EXE_EXTENSION: &'static str = ""; +} + +/// Constants associated with the current target +#[cfg(target_os = "dragonfly")] +pub mod consts { + pub use super::arch_consts::ARCH; + + pub const FAMILY: &'static str = "unix"; + + /// A string describing the specific operating system in use: in this + /// case, `dragonfly`. + pub const OS: &'static str = "dragonfly"; + + /// Specifies the filename prefix used for shared libraries on this + /// platform: in this case, `lib`. + pub const DLL_PREFIX: &'static str = "lib"; + + /// Specifies the filename suffix used for shared libraries on this + /// platform: in this case, `.so`. + pub const DLL_SUFFIX: &'static str = ".so"; + + /// Specifies the file extension used for shared libraries on this + /// platform that goes after the dot: in this case, `so`. + pub const DLL_EXTENSION: &'static str = "so"; + + /// Specifies the filename suffix used for executable binaries on this + /// platform: in this case, the empty string. + pub const EXE_SUFFIX: &'static str = ""; + + /// Specifies the file extension, if any, used for executable binaries + /// on this platform: in this case, the empty string. + pub const EXE_EXTENSION: &'static str = ""; +} + +/// Constants associated with the current target +#[cfg(target_os = "android")] +pub mod consts { + pub use super::arch_consts::ARCH; + + pub const FAMILY: &'static str = "unix"; + + /// A string describing the specific operating system in use: in this + /// case, `android`. + pub const OS: &'static str = "android"; + + /// Specifies the filename prefix used for shared libraries on this + /// platform: in this case, `lib`. + pub const DLL_PREFIX: &'static str = "lib"; + + /// Specifies the filename suffix used for shared libraries on this + /// platform: in this case, `.so`. + pub const DLL_SUFFIX: &'static str = ".so"; + + /// Specifies the file extension used for shared libraries on this + /// platform that goes after the dot: in this case, `so`. + pub const DLL_EXTENSION: &'static str = "so"; + + /// Specifies the filename suffix used for executable binaries on this + /// platform: in this case, the empty string. + pub const EXE_SUFFIX: &'static str = ""; + + /// Specifies the file extension, if any, used for executable binaries + /// on this platform: in this case, the empty string. + pub const EXE_EXTENSION: &'static str = ""; +} + +/// Constants associated with the current target +#[cfg(target_os = "windows")] +pub mod consts { + pub use super::arch_consts::ARCH; + + pub const FAMILY: &'static str = "windows"; + + /// A string describing the specific operating system in use: in this + /// case, `windows`. + pub const OS: &'static str = "windows"; + + /// Specifies the filename prefix used for shared libraries on this + /// platform: in this case, the empty string. + pub const DLL_PREFIX: &'static str = ""; + + /// Specifies the filename suffix used for shared libraries on this + /// platform: in this case, `.dll`. + pub const DLL_SUFFIX: &'static str = ".dll"; + + /// Specifies the file extension used for shared libraries on this + /// platform that goes after the dot: in this case, `dll`. + pub const DLL_EXTENSION: &'static str = "dll"; + + /// Specifies the filename suffix used for executable binaries on this + /// platform: in this case, `.exe`. + pub const EXE_SUFFIX: &'static str = ".exe"; + + /// Specifies the file extension, if any, used for executable binaries + /// on this platform: in this case, `exe`. + pub const EXE_EXTENSION: &'static str = "exe"; +} + +#[cfg(target_arch = "x86")] +mod arch_consts { + pub const ARCH: &'static str = "x86"; +} + +#[cfg(target_arch = "x86_64")] +mod arch_consts { + pub const ARCH: &'static str = "x86_64"; +} + +#[cfg(target_arch = "arm")] +mod arch_consts { + pub const ARCH: &'static str = "arm"; +} + +#[cfg(target_arch = "aarch64")] +mod arch_consts { + pub const ARCH: &'static str = "aarch64"; +} + +#[cfg(target_arch = "mips")] +mod arch_consts { + pub const ARCH: &'static str = "mips"; +} + +#[cfg(target_arch = "mipsel")] +mod arch_consts { + pub const ARCH: &'static str = "mipsel"; +} + +#[cfg(target_arch = "powerpc")] +mod arch_consts { + pub const ARCH: &'static str = "powerpc"; +} + +#[cfg(test)] +mod tests { + use prelude::v1::*; + use super::*; + use iter::repeat; + use rand::{self, Rng}; + use ffi::{OsString, OsStr}; + + fn make_rand_name() -> OsString { + let mut rng = rand::thread_rng(); + let n = format!("TEST{}", rng.gen_ascii_chars().take(10) + .collect::()); + let n = OsString::from_string(n); + assert!(var(&n).is_none()); + n + } + + fn eq(a: Option, b: Option<&str>) { + assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::from_str).map(|s| &*s)); + } + + #[test] + fn test_set_var() { + let n = make_rand_name(); + set_var(&n, "VALUE"); + eq(var(&n), Some("VALUE")); + } + + #[test] + fn test_remove_var() { + let n = make_rand_name(); + set_var(&n, "VALUE"); + remove_var(&n); + eq(var(&n), None); + } + + #[test] + fn test_set_var_overwrite() { + let n = make_rand_name(); + set_var(&n, "1"); + set_var(&n, "2"); + eq(var(&n), Some("2")); + set_var(&n, ""); + eq(var(&n), Some("")); + } + + #[test] + fn test_var_big() { + let mut s = "".to_string(); + let mut i = 0; + while i < 100 { + s.push_str("aaaaaaaaaa"); + i += 1; + } + let n = make_rand_name(); + set_var(&n, s.as_slice()); + eq(var(&n), Some(s.as_slice())); + } + + #[test] + fn test_self_exe_path() { + let path = current_exe(); + assert!(path.is_ok()); + let path = path.unwrap(); + + // Hard to test this function + assert!(path.is_absolute()); + } + + #[test] + fn test_env_set_get_huge() { + let n = make_rand_name(); + let s = repeat("x").take(10000).collect::(); + set_var(&n, &s); + eq(var(&n), Some(s.as_slice())); + remove_var(&n); + eq(var(&n), None); + } + + #[test] + fn test_env_set_var() { + let n = make_rand_name(); + + let mut e = vars(); + set_var(&n, "VALUE"); + assert!(!e.any(|(k, v)| { + &*k == &*n && &*v == "VALUE" + })); + + assert!(vars().any(|(k, v)| { + &*k == &*n && &*v == "VALUE" + })); + } + + #[test] + fn test() { + assert!((!Path::new("test-path").is_absolute())); + + current_dir().unwrap(); + } + + #[test] + #[cfg(windows)] + fn split_paths_windows() { + fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { + split_paths(unparsed).collect::>() == + parsed.iter().map(|s| Path::new(*s)).collect::>() + } + + assert!(check_parse("", &mut [""])); + assert!(check_parse(r#""""#, &mut [""])); + assert!(check_parse(";;", &mut ["", "", ""])); + assert!(check_parse(r"c:\", &mut [r"c:\"])); + assert!(check_parse(r"c:\;", &mut [r"c:\", ""])); + assert!(check_parse(r"c:\;c:\Program Files\", + &mut [r"c:\", r"c:\Program Files\"])); + assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"])); + assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#, + &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"])); + } + + #[test] + #[cfg(unix)] + fn split_paths_unix() { + fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { + split_paths(unparsed).collect::>() == + parsed.iter().map(|s| Path::new(*s)).collect::>() + } + + assert!(check_parse("", &mut [""])); + assert!(check_parse("::", &mut ["", "", ""])); + assert!(check_parse("/", &mut ["/"])); + assert!(check_parse("/:", &mut ["/", ""])); + assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"])); + } + + #[test] + #[cfg(unix)] + fn join_paths_unix() { + fn test_eq(input: &[&str], output: &str) -> bool { + &*join_paths(input.iter().map(|s| *s)).unwrap() == + OsStr::from_str(output) + } + + assert!(test_eq(&[], "")); + assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"], + "/bin:/usr/bin:/usr/local/bin")); + assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""], + ":/bin:::/usr/bin:")); + assert!(join_paths(["/te:st"].iter().map(|s| *s)).is_err()); + } + + #[test] + #[cfg(windows)] + fn join_paths_windows() { + fn test_eq(input: &[&str], output: &str) -> bool { + &*join_paths(input.iter().map(|s| *s)).unwrap() == + OsStr::from_str(output) + } + + assert!(test_eq(&[], "")); + assert!(test_eq(&[r"c:\windows", r"c:\"], + r"c:\windows;c:\")); + assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""], + r";c:\windows;;;c:\;")); + assert!(test_eq(&[r"c:\te;st", r"c:\"], + r#""c:\te;st";c:\"#)); + assert!(join_paths([r#"c:\te"st"#].iter().map(|s| *s)).is_err()); + } + } diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 69ada28a4b4a4..76f925a23f174 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -20,7 +20,12 @@ pub use self::c_str::c_str_to_bytes_with_nul; pub use self::os_str::OsString; pub use self::os_str::OsStr; -pub use self::os_str::AsOsStr; mod c_str; mod os_str; + +/// Freely convertible to an `&OsStr` slice. +pub trait AsOsStr { + /// Convert to an `&OsStr` slice. + fn as_os_str(&self) -> &OsStr; +} diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 18e2aa8c098a7..57489e8623006 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -41,9 +41,11 @@ use string::{String, CowString}; use ops; use cmp; use hash::{Hash, Hasher, Writer}; +use path::{Path, GenericPath}; use sys::os_str::{Buf, Slice}; use sys_common::{AsInner, IntoInner, FromInner}; +use super::AsOsStr; /// Owned, mutable OS strings. #[derive(Clone)] @@ -69,6 +71,11 @@ impl OsString { OsString { inner: Buf::from_str(s) } } + /// Constructs a new empty `OsString`. + pub fn new() -> OsString { + OsString { inner: Buf::from_string(String::new()) } + } + /// Convert the `OsString` into a `String` if it contains valid Unicode data. /// /// On failure, ownership of the original `OsString` is returned. @@ -117,6 +124,62 @@ impl Debug for OsString { } } +impl PartialEq for OsString { + fn eq(&self, other: &OsString) -> bool { + &**self == &**other + } +} + +impl PartialEq for OsString { + fn eq(&self, other: &str) -> bool { + &**self == other + } +} + +impl PartialEq for str { + fn eq(&self, other: &OsString) -> bool { + &**other == self + } +} + +impl Eq for OsString {} + +impl PartialOrd for OsString { + #[inline] + fn partial_cmp(&self, other: &OsString) -> Option { + (&**self).partial_cmp(&**other) + } + #[inline] + fn lt(&self, other: &OsString) -> bool { &**self < &**other } + #[inline] + fn le(&self, other: &OsString) -> bool { &**self <= &**other } + #[inline] + fn gt(&self, other: &OsString) -> bool { &**self > &**other } + #[inline] + fn ge(&self, other: &OsString) -> bool { &**self >= &**other } +} + +impl PartialOrd for OsString { + #[inline] + fn partial_cmp(&self, other: &str) -> Option { + (&**self).partial_cmp(other) + } +} + +impl Ord for OsString { + #[inline] + fn cmp(&self, other: &OsString) -> cmp::Ordering { + (&**self).cmp(&**other) + } +} + +impl<'a, S: Hasher + Writer> Hash for OsString { + #[inline] + fn hash(&self, state: &mut S) { + (&**self).hash(state) + } +} + impl OsStr { /// Coerce directly from a `&str` slice to a `&OsStr` slice. pub fn from_str(s: &str) -> &OsStr { @@ -222,10 +285,10 @@ impl ToOwned for OsStr { fn to_owned(&self) -> OsString { self.to_os_string() } } -/// Freely convertible to an `&OsStr` slice. -pub trait AsOsStr { - /// Convert to an `&OsStr` slice. - fn as_os_str(&self) -> &OsStr; +impl<'a, T: AsOsStr + ?Sized> AsOsStr for &'a T { + fn as_os_str(&self) -> &OsStr { + (*self).as_os_str() + } } impl AsOsStr for OsStr { @@ -252,6 +315,21 @@ impl AsOsStr for String { } } +#[cfg(unix)] +impl AsOsStr for Path { + fn as_os_str(&self) -> &OsStr { + unsafe { mem::transmute(self.as_vec()) } + } +} + +#[cfg(windows)] +impl AsOsStr for Path { + fn as_os_str(&self) -> &OsStr { + // currently .as_str() is actually infallible on windows + OsStr::from_str(self.as_str().unwrap()) + } +} + impl FromInner for OsString { fn from_inner(buf: Buf) -> OsString { OsString { inner: buf } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 96aebb735ef12..487efb4332682 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -250,6 +250,7 @@ pub mod ffi; pub mod fmt; pub mod old_io; pub mod os; +pub mod env; pub mod path; pub mod rand; pub mod time; diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index f253f9799e9bd..81903d0a97e99 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -231,6 +231,7 @@ impl Command { self } // Get a mutable borrow of the environment variable map for this `Command`. + #[allow(deprecated)] fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap { match self.env { Some(ref mut map) => map, diff --git a/src/libstd/old_io/tempfile.rs b/src/libstd/old_io/tempfile.rs index 20cbde5db715a..83a42549424d6 100644 --- a/src/libstd/old_io/tempfile.rs +++ b/src/libstd/old_io/tempfile.rs @@ -10,13 +10,13 @@ //! Temporary files and directories +use env; +use iter::{IteratorExt}; use old_io::{fs, IoError, IoErrorKind, IoResult}; use old_io; -use iter::IteratorExt; use ops::Drop; -use option::Option; use option::Option::{None, Some}; -use os; +use option::Option; use path::{Path, GenericPath}; use rand::{Rng, thread_rng}; use result::Result::{Ok, Err}; @@ -97,8 +97,8 @@ impl TempDir { /// If no directory can be created, `Err` is returned. pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult { if !tmpdir.is_absolute() { - let abs_tmpdir = try!(os::make_absolute(tmpdir)); - return TempDir::new_in(&abs_tmpdir, prefix); + let cur_dir = try!(env::current_dir()); + return TempDir::new_in(&cur_dir.join(tmpdir), prefix); } let mut rng = thread_rng(); @@ -132,7 +132,7 @@ impl TempDir { /// /// If no directory can be created, `Err` is returned. pub fn new(prefix: &str) -> IoResult { - TempDir::new_in(&os::tmpdir(), prefix) + TempDir::new_in(&env::temp_dir(), prefix) } /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper. diff --git a/src/libstd/old_io/test.rs b/src/libstd/old_io/test.rs index f49e2397d4282..3f4e070e30d95 100644 --- a/src/libstd/old_io/test.rs +++ b/src/libstd/old_io/test.rs @@ -12,8 +12,8 @@ use prelude::v1::*; +use env; use libc; -use os; use std::old_io::net::ip::*; use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; @@ -41,7 +41,7 @@ fn next_test_unix_socket() -> String { pub fn next_test_unix() -> Path { let string = next_test_unix_socket(); if cfg!(unix) { - os::tmpdir().join(string) + env::temp_dir().join(string) } else { Path::new(format!("{}{}", r"\\.\pipe\", string)) } @@ -87,7 +87,7 @@ fn base_port() -> u16 { ]; // FIXME (#9639): This needs to handle non-utf8 paths - let path = os::getcwd().unwrap(); + let path = env::current_dir().unwrap(); let path_s = path.as_str().unwrap(); let mut final_base = base; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 600ca60349ae2..27e843d2383bf 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -34,29 +34,32 @@ use self::MemoryMapKind::*; use self::MapOption::*; use self::MapError::*; +use boxed::Box; use clone::Clone; +use env; use error::{FromError, Error}; +use ffi::{OsString, OsStr}; use fmt; -use old_io::{IoResult, IoError}; use iter::{Iterator, IteratorExt}; -use marker::{Copy, Send}; use libc::{c_void, c_int, c_char}; use libc; -use boxed::Box; +use marker::{Copy, Send}; +use old_io::{IoResult, IoError}; use ops::{Drop, FnOnce}; -use option::Option; use option::Option::{Some, None}; +use option::Option; use path::{Path, GenericPath, BytesContainer}; -use sys; -use sys::os as os_imp; use ptr::PtrExt; use ptr; -use result::Result; use result::Result::{Err, Ok}; +use result::Result; use slice::{AsSlice, SliceExt}; use str::{Str, StrExt}; +use str; use string::{String, ToString}; use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering}; +use sys::os as os_imp; +use sys; use vec::Vec; #[cfg(unix)] use ffi::{self, CString}; @@ -97,23 +100,10 @@ pub const TMPBUF_SZ : uint = 1000u; /// let current_working_directory = os::getcwd().unwrap(); /// println!("The current directory is {:?}", current_working_directory.display()); /// ``` +#[deprecated(since = "1.0.0", reason = "renamed to std::env::current_dir")] +#[unstable(feature = "os")] pub fn getcwd() -> IoResult { - sys::os::getcwd() -} - -/* -Accessing environment variables is not generally threadsafe. -Serialize access through a global lock. -*/ -fn with_env_lock(f: F) -> T where - F: FnOnce() -> T, -{ - use sync::{StaticMutex, MUTEX_INIT}; - - static LOCK: StaticMutex = MUTEX_INIT; - - let _guard = LOCK.lock(); - f() + env::current_dir() } /// Returns a vector of (variable, value) pairs, for all the environment @@ -132,37 +122,22 @@ fn with_env_lock(f: F) -> T where /// println!("'{}': '{}'", key, value ); /// } /// ``` +#[deprecated(since = "1.0.0", reason = "use env::vars instead")] +#[unstable(feature = "os")] pub fn env() -> Vec<(String,String)> { - env_as_bytes().into_iter().map(|(k,v)| { - let k = String::from_utf8_lossy(k.as_slice()).into_owned(); - let v = String::from_utf8_lossy(v.as_slice()).into_owned(); - (k,v) + env::vars().map(|(k, v)| { + (k.to_string_lossy().into_owned(), v.to_string_lossy().into_owned()) }).collect() } /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. -pub fn env_as_bytes() -> Vec<(Vec,Vec)> { - unsafe { - fn env_convert(input: Vec>) -> Vec<(Vec, Vec)> { - let mut pairs = Vec::new(); - for p in input.iter() { - let mut it = p.splitn(1, |b| *b == b'='); - let key = it.next().unwrap().to_vec(); - let default: &[u8] = &[]; - let val = it.next().unwrap_or(default).to_vec(); - pairs.push((key, val)); - } - pairs - } - with_env_lock(|| { - let unparsed_environ = sys::os::get_env_pairs(); - env_convert(unparsed_environ) - }) - } +#[deprecated(since = "1.0.0", reason = "use env::vars instead")] +#[unstable(feature = "os")] +pub fn env_as_bytes() -> Vec<(Vec, Vec)> { + env::vars().map(|(k, v)| (byteify(k), byteify(v))).collect() } -#[cfg(unix)] /// Fetches the environment variable `n` from the current process, returning /// None if the variable isn't set. /// @@ -184,52 +159,32 @@ pub fn env_as_bytes() -> Vec<(Vec,Vec)> { /// None => println!("{} is not defined in the environment.", key) /// } /// ``` +#[deprecated(since = "1.0.0", reason = "use env::var or env::var_string instead")] +#[unstable(feature = "os")] pub fn getenv(n: &str) -> Option { - getenv_as_bytes(n).map(|v| String::from_utf8_lossy(v.as_slice()).into_owned()) + env::var_string(n).ok() } -#[cfg(unix)] /// Fetches the environment variable `n` byte vector from the current process, /// returning None if the variable isn't set. /// /// # Panics /// /// Panics if `n` has any interior NULs. +#[deprecated(since = "1.0.0", reason = "use env::var instead")] +#[unstable(feature = "os")] pub fn getenv_as_bytes(n: &str) -> Option> { - unsafe { - with_env_lock(|| { - let s = CString::from_slice(n.as_bytes()); - let s = libc::getenv(s.as_ptr()) as *const _; - if s.is_null() { - None - } else { - Some(ffi::c_str_to_bytes(&s).to_vec()) - } - }) - } + env::var(n).map(byteify) } -#[cfg(windows)] -/// Fetches the environment variable `n` from the current process, returning -/// None if the variable isn't set. -pub fn getenv(n: &str) -> Option { - unsafe { - with_env_lock(|| { - use sys::os::fill_utf16_buf_and_decode; - let mut n: Vec = n.utf16_units().collect(); - n.push(0); - fill_utf16_buf_and_decode(|buf, sz| { - libc::GetEnvironmentVariableW(n.as_ptr(), buf, sz) - }) - }) - } +#[cfg(unix)] +fn byteify(s: OsString) -> Vec { + use os::unix::*; + s.into_vec() } - #[cfg(windows)] -/// Fetches the environment variable `n` byte vector from the current process, -/// returning None if the variable isn't set. -pub fn getenv_as_bytes(n: &str) -> Option> { - getenv(n).map(|s| s.into_bytes()) +fn byteify(s: OsString) -> Vec { + s.to_string_lossy().as_bytes().to_vec() } /// Sets the environment variable `n` to the value `v` for the currently running @@ -247,68 +202,30 @@ pub fn getenv_as_bytes(n: &str) -> Option> { /// None => println!("{} is not defined in the environment.", key) /// } /// ``` +#[deprecated(since = "1.0.0", reason = "renamed to env::set_var")] +#[unstable(feature = "os")] pub fn setenv(n: &str, v: T) { #[cfg(unix)] fn _setenv(n: &str, v: &[u8]) { - unsafe { - with_env_lock(|| { - let k = CString::from_slice(n.as_bytes()); - let v = CString::from_slice(v); - if libc::funcs::posix01::unistd::setenv(k.as_ptr(), - v.as_ptr(), 1) != 0 { - panic!(IoError::last_error()); - } - }) - } + use os::unix::*; + let v: OsString = OsStringExt::from_vec(v.to_vec()); + env::set_var(n, &v) } #[cfg(windows)] fn _setenv(n: &str, v: &[u8]) { - let mut n: Vec = n.utf16_units().collect(); - n.push(0); - let mut v: Vec = ::str::from_utf8(v).unwrap().utf16_units().collect(); - v.push(0); - - unsafe { - with_env_lock(|| { - if libc::SetEnvironmentVariableW(n.as_ptr(), v.as_ptr()) == 0 { - panic!(IoError::last_error()); - } - }) - } + let v = str::from_utf8(v).unwrap(); + env::set_var(n, v) } _setenv(n, v.container_as_bytes()) } /// Remove a variable from the environment entirely. +#[deprecated(since = "1.0.0", reason = "renamed to env::remove_var")] +#[unstable(feature = "os")] pub fn unsetenv(n: &str) { - #[cfg(unix)] - fn _unsetenv(n: &str) { - unsafe { - with_env_lock(|| { - let nbuf = CString::from_slice(n.as_bytes()); - if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 { - panic!(IoError::last_error()); - } - }) - } - } - - #[cfg(windows)] - fn _unsetenv(n: &str) { - let mut n: Vec = n.utf16_units().collect(); - n.push(0); - unsafe { - with_env_lock(|| { - if libc::SetEnvironmentVariableW(n.as_ptr(), ptr::null()) == 0 { - panic!(IoError::last_error()); - } - }) - } - } - - _unsetenv(n) + env::remove_var(n) } /// Parses input according to platform conventions for the `PATH` @@ -328,8 +245,12 @@ pub fn unsetenv(n: &str) { /// None => println!("{} is not defined in the environment.", key) /// } /// ``` +#[deprecated(since = "1.0.0", reason = "renamed to env::split_paths")] +#[unstable(feature = "os")] pub fn split_paths(unparsed: T) -> Vec { - sys::os::split_paths(unparsed.container_as_bytes()) + let b = unparsed.container_as_bytes(); + let s = str::from_utf8(b).unwrap(); + env::split_paths(s).collect() } /// Joins a collection of `Path`s appropriately for the `PATH` @@ -353,8 +274,14 @@ pub fn split_paths(unparsed: T) -> Vec { /// paths.push(Path::new("/home/xyz/bin")); /// os::setenv(key, os::join_paths(paths.as_slice()).unwrap()); /// ``` +#[deprecated(since = "1.0.0", reason = "renamed to env::join_paths")] +#[unstable(feature = "os")] pub fn join_paths(paths: &[T]) -> Result, &'static str> { - sys::os::join_paths(paths) + env::join_paths(paths.iter().map(|s| { + str::from_utf8(s.container_as_bytes()).unwrap() + })).map(|s| { + s.to_string_lossy().into_owned().into_bytes() + }).map_err(|_| "failed to join paths") } /// A low-level OS in-memory pipe. @@ -388,6 +315,8 @@ pub unsafe fn pipe() -> IoResult { /// Returns the proper dll filename for the given basename of a file /// as a String. #[cfg(not(target_os="ios"))] +#[deprecated(since = "1.0.0", reason = "this function will be removed, use the constants directly")] +#[unstable(feature = "os")] pub fn dll_filename(base: &str) -> String { format!("{}{}{}", consts::DLL_PREFIX, base, consts::DLL_SUFFIX) } @@ -405,8 +334,10 @@ pub fn dll_filename(base: &str) -> String { /// None => println!("Unable to get the path of this executable!") /// }; /// ``` +#[deprecated(since = "1.0.0", reason = "renamed to env::current_exe")] +#[unstable(feature = "os")] pub fn self_exe_name() -> Option { - sys::os::load_self().and_then(Path::new_opt) + env::current_exe().ok() } /// Optionally returns the filesystem path to the current executable which is @@ -424,8 +355,10 @@ pub fn self_exe_name() -> Option { /// None => println!("Impossible to fetch the path of this executable.") /// }; /// ``` +#[deprecated(since = "1.0.0", reason = "use env::current_exe + dir_path/pop")] +#[unstable(feature = "os")] pub fn self_exe_path() -> Option { - self_exe_name().map(|mut p| { p.pop(); p }) + env::current_exe().ok().map(|mut p| { p.pop(); p }) } /// Optionally returns the path to the current user's home directory if known. @@ -452,6 +385,9 @@ pub fn self_exe_path() -> Option { /// None => println!("Impossible to get your home dir!") /// } /// ``` +#[deprecated(since = "1.0.0", reason = "renamed to env::home_dir")] +#[allow(deprecated)] +#[unstable(feature = "os")] pub fn homedir() -> Option { #[inline] #[cfg(unix)] @@ -487,6 +423,9 @@ pub fn homedir() -> Option { /// On Windows, returns the value of, in order, the 'TMP', 'TEMP', /// 'USERPROFILE' environment variable if any are set and not the empty /// string. Otherwise, tmpdir returns the path to the Windows directory. +#[deprecated(since = "1.0.0", reason = "renamed to env::temp_dir")] +#[allow(deprecated)] +#[unstable(feature = "os")] pub fn tmpdir() -> Path { return lookup(); @@ -542,11 +481,13 @@ pub fn tmpdir() -> Path { // NB: this is here rather than in path because it is a form of environment // querying; what it does depends on the process working directory, not just // the input paths. +#[deprecated(since = "1.0.0", reason = "use env::current_dir + .join directly")] +#[unstable(feature = "os")] pub fn make_absolute(p: &Path) -> IoResult { if p.is_absolute() { Ok(p.clone()) } else { - getcwd().map(|mut cwd| { + env::current_dir().map(|mut cwd| { cwd.push(p); cwd }) @@ -565,6 +506,8 @@ pub fn make_absolute(p: &Path) -> IoResult { /// assert!(os::change_dir(&root).is_ok()); /// println!("Successfully changed working directory to {}!", root.display()); /// ``` +#[deprecated(since = "1.0.0", reason = "renamed to env::set_current_dir")] +#[unstable(feature = "os")] pub fn change_dir(p: &Path) -> IoResult<()> { return sys::os::chdir(p); } @@ -592,8 +535,6 @@ pub fn last_os_error() -> String { error_string(errno() as uint) } -static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT; - /// Sets the process exit code /// /// Sets the exit code returned by the process if all supervised tasks @@ -602,14 +543,18 @@ static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT; /// ignored and the process exits with the default panic status. /// /// Note that this is not synchronized against modifications of other threads. +#[deprecated(since = "1.0.0", reason = "renamed to env::set_exit_status")] +#[unstable(feature = "os")] pub fn set_exit_status(code: int) { - EXIT_STATUS.store(code, Ordering::SeqCst) + env::set_exit_status(code as i32) } /// Fetches the process's current exit code. This defaults to 0 and can change /// by calling `set_exit_status`. +#[deprecated(since = "1.0.0", reason = "renamed to env::get_exit_status")] +#[unstable(feature = "os")] pub fn get_exit_status() -> int { - EXIT_STATUS.load(Ordering::SeqCst) + env::get_exit_status() as isize } #[cfg(target_os = "macos")] @@ -726,7 +671,7 @@ fn real_args() -> Vec { // Push it onto the list. let ptr = ptr as *const u16; let buf = slice::from_raw_buf(&ptr, len); - let opt_s = String::from_utf16(sys::os::truncate_utf16_at_nul(buf)); + let opt_s = String::from_utf16(sys::truncate_utf16_at_nul(buf)); opt_s.ok().expect("CommandLineToArgvW returned invalid UTF-16") }).collect(); @@ -777,12 +722,16 @@ extern "system" { /// println!("{}", argument); /// } /// ``` +#[deprecated(since = "1.0.0", reason = "use env::args instead")] +#[unstable(feature = "os")] pub fn args() -> Vec { real_args() } /// Returns the arguments which this program was started with (normally passed /// via the command line) as byte vectors. +#[deprecated(since = "1.0.0", reason = "use env::args_raw instead")] +#[unstable(feature = "os")] pub fn args_as_bytes() -> Vec> { real_args_as_bytes() } @@ -790,11 +739,13 @@ pub fn args_as_bytes() -> Vec> { #[cfg(target_os = "macos")] extern { // These functions are in crt_externs.h. - pub fn _NSGetArgc() -> *mut c_int; - pub fn _NSGetArgv() -> *mut *mut *mut c_char; + fn _NSGetArgc() -> *mut c_int; + fn _NSGetArgv() -> *mut *mut *mut c_char; } /// Returns the page size of the current architecture in bytes. +#[deprecated(since = "1.0.0", reason = "renamed to env::page_size")] +#[unstable(feature = "os")] pub fn page_size() -> uint { sys::os::page_size() } @@ -970,7 +921,7 @@ impl MemoryMap { let mut fd = -1; let mut offset = 0; let mut custom_flags = false; - let len = round_up(min_len, page_size()); + let len = round_up(min_len, env::page_size()); for &o in options.iter() { match o { @@ -1020,7 +971,7 @@ impl MemoryMap { /// Granularity that the offset or address must be for `MapOffset` and /// `MapAddr` respectively. pub fn granularity() -> uint { - page_size() + env::page_size() } } @@ -1049,7 +1000,7 @@ impl MemoryMap { let mut executable = false; let mut handle: HANDLE = libc::INVALID_HANDLE_VALUE; let mut offset: uint = 0; - let len = round_up(min_len, page_size()); + let len = round_up(min_len, env::page_size()); for &o in options.iter() { match o { @@ -1184,6 +1135,8 @@ impl MemoryMap { } #[cfg(target_os = "linux")] +#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] +#[unstable(feature = "os")] pub mod consts { pub use os::arch_consts::ARCH; @@ -1215,6 +1168,8 @@ pub mod consts { } #[cfg(target_os = "macos")] +#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] +#[unstable(feature = "os")] pub mod consts { pub use os::arch_consts::ARCH; @@ -1246,6 +1201,8 @@ pub mod consts { } #[cfg(target_os = "ios")] +#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] +#[unstable(feature = "os")] pub mod consts { pub use os::arch_consts::ARCH; @@ -1265,6 +1222,8 @@ pub mod consts { } #[cfg(target_os = "freebsd")] +#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] +#[unstable(feature = "os")] pub mod consts { pub use os::arch_consts::ARCH; @@ -1296,6 +1255,8 @@ pub mod consts { } #[cfg(target_os = "dragonfly")] +#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] +#[unstable(feature = "os")] pub mod consts { pub use os::arch_consts::ARCH; @@ -1327,6 +1288,8 @@ pub mod consts { } #[cfg(target_os = "android")] +#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] +#[unstable(feature = "os")] pub mod consts { pub use os::arch_consts::ARCH; @@ -1358,6 +1321,8 @@ pub mod consts { } #[cfg(target_os = "windows")] +#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] +#[unstable(feature = "os")] pub mod consts { pub use os::arch_consts::ARCH; diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index f2d66e1a4d765..905cc06c4f007 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -14,7 +14,7 @@ use prelude::v1::*; -use os; +use env; use sync::atomic::{self, Ordering}; pub use sys::backtrace::write; @@ -29,7 +29,7 @@ pub fn log_enabled() -> bool { _ => {} } - let val = match os::getenv("RUST_BACKTRACE") { + let val = match env::var("RUST_BACKTRACE") { Some(..) => 2, None => 1, }; diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 7e19f1cac2c5b..00088d6d99a0a 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -65,7 +65,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int { use prelude::v1::*; use mem; - use os; + use env; use rt; use sys_common::thread_info::{self, NewThread}; use sys_common; @@ -131,7 +131,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int { if failed { rt::DEFAULT_ERROR_CODE } else { - os::get_exit_status() + env::get_exit_status() as isize } } diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index f5727a38b6997..86d21cf72782e 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -13,6 +13,7 @@ use prelude::v1::*; use cmp; +use env; use fmt; use intrinsics; use libc::{self, uintptr_t}; @@ -51,7 +52,7 @@ pub fn min_stack() -> uint { 0 => {} n => return n - 1, } - let amt = os::getenv("RUST_MIN_STACK").and_then(|s| s.parse().ok()); + let amt = env::var_string("RUST_MIN_STACK").ok().and_then(|s| s.parse().ok()); let amt = amt.unwrap_or(2 * 1024 * 1024); // 0 is our sentinel value, so ensure that we'll never see 0 after // initialization has run @@ -62,15 +63,15 @@ pub fn min_stack() -> uint { /// Get's the number of scheduler threads requested by the environment /// either `RUST_THREADS` or `num_cpus`. pub fn default_sched_threads() -> uint { - match os::getenv("RUST_THREADS") { - Some(nstr) => { + match env::var_string("RUST_THREADS") { + Ok(nstr) => { let opt_n: Option = nstr.parse().ok(); match opt_n { Some(n) if n > 0 => n, _ => panic!("`RUST_THREADS` is `{}`, should be a positive integer", nstr) } } - None => { + Err(..) => { if limit_thread_creation_due_to_osx_and_valgrind() { 1 } else { diff --git a/src/libstd/sys/common/mutex.rs b/src/libstd/sys/common/mutex.rs index 9aea0fb3b3172..0ca228267003d 100644 --- a/src/libstd/sys/common/mutex.rs +++ b/src/libstd/sys/common/mutex.rs @@ -24,13 +24,6 @@ unsafe impl Sync for Mutex {} pub const MUTEX_INIT: Mutex = Mutex(imp::MUTEX_INIT); impl Mutex { - /// Creates a newly initialized mutex. - /// - /// Behavior is undefined if the mutex is moved after the first method is - /// called on the mutex. - #[inline] - pub unsafe fn new() -> Mutex { Mutex(imp::Mutex::new()) } - /// Lock the mutex blocking the current thread until it is available. /// /// Behavior is undefined if the mutex has been moved between this and any diff --git a/src/libstd/sys/common/rwlock.rs b/src/libstd/sys/common/rwlock.rs index df016b9e293b7..fe374e1fd78a3 100644 --- a/src/libstd/sys/common/rwlock.rs +++ b/src/libstd/sys/common/rwlock.rs @@ -21,13 +21,6 @@ pub struct RWLock(imp::RWLock); pub const RWLOCK_INIT: RWLock = RWLock(imp::RWLOCK_INIT); impl RWLock { - /// Creates a new instance of an RWLock. - /// - /// Usage of an RWLock is undefined if it is moved after its first use (any - /// function calls below). - #[inline] - pub unsafe fn new() -> RWLock { RWLock(imp::RWLock::new()) } - /// Acquire shared access to the underlying lock, blocking the current /// thread to do so. /// diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index e310b8f6d90b3..51186feeaf4bc 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -240,7 +240,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { #[cfg(not(any(target_os = "macos", target_os = "ios")))] fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { - use os; + use env; use ptr; //////////////////////////////////////////////////////////////////////// @@ -319,7 +319,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { if !STATE.is_null() { return STATE } let selfname = if cfg!(target_os = "freebsd") || cfg!(target_os = "dragonfly") { - os::self_exe_name() + env::current_exe().ok() } else { None }; diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs index 9016d1a2c99ca..7a17e8b6f1e15 100644 --- a/src/libstd/sys/unix/c.rs +++ b/src/libstd/sys/unix/c.rs @@ -66,6 +66,53 @@ pub const MSG_DONTWAIT: libc::c_int = 0x40; pub const WNOHANG: libc::c_int = 1; +#[cfg(target_os = "linux")] +pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 70; +#[cfg(any(target_os = "macos", + target_os = "freebsd"))] +pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 71; +#[cfg(target_os = "android")] +pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 0x0048; + +#[repr(C)] +#[cfg(target_os = "linux")] +pub struct passwd { + pub pw_name: *mut libc::c_char, + pub pw_passwd: *mut libc::c_char, + pub pw_uid: libc::uid_t, + pub pw_gid: libc::gid_t, + pub pw_gecos: *mut libc::c_char, + pub pw_dir: *mut libc::c_char, + pub pw_shell: *mut libc::c_char, +} + +#[repr(C)] +#[cfg(any(target_os = "macos", + target_os = "freebsd"))] +pub struct passwd { + pub pw_name: *mut libc::c_char, + pub pw_passwd: *mut libc::c_char, + pub pw_uid: libc::uid_t, + pub pw_gid: libc::gid_t, + pub pw_change: libc::time_t, + pub pw_class: *mut libc::c_char, + pub pw_gecos: *mut libc::c_char, + pub pw_dir: *mut libc::c_char, + pub pw_shell: *mut libc::c_char, + pub pw_expire: libc::time_t, +} + +#[repr(C)] +#[cfg(target_os = "android")] +pub struct passwd { + pub pw_name: *mut libc::c_char, + pub pw_passwd: *mut libc::c_char, + pub pw_uid: libc::uid_t, + pub pw_gid: libc::gid_t, + pub pw_dir: *mut libc::c_char, + pub pw_shell: *mut libc::c_char, +} + extern { pub fn gettimeofday(timeval: *mut libc::timeval, tzp: *mut libc::c_void) -> libc::c_int; @@ -92,6 +139,12 @@ extern { pub fn sigaddset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int; pub fn sigdelset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int; pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int; + + pub fn getpwuid_r(uid: libc::uid_t, + pwd: *mut passwd, + buf: *mut libc::c_char, + buflen: libc::size_t, + result: *mut *mut passwd) -> libc::c_int; } #[cfg(any(target_os = "macos", target_os = "ios"))] diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index f2f2e7436bfb7..b03b9046966a0 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -141,7 +141,7 @@ pub fn retry (mut f: F) -> T where let one: T = Int::one(); loop { let n = f(); - if n == -one && os::errno() == libc::EINTR as int { } + if n == -one && os::errno() == libc::EINTR as i32 { } else { return n } } } @@ -155,7 +155,7 @@ pub fn ms_to_timeval(ms: u64) -> libc::timeval { pub fn wouldblock() -> bool { let err = os::errno(); - err == libc::EWOULDBLOCK as int || err == libc::EAGAIN as int + err == libc::EWOULDBLOCK as i32 || err == libc::EAGAIN as i32 } pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> { diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index dd343baa7c9c3..68818b07b7fef 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -11,93 +11,64 @@ //! Implementation of `std::os` functionality for unix systems use prelude::v1::*; +use os::unix::*; -use error::{FromError, Error}; -use ffi::{self, CString}; +use error::Error as StdError; +use ffi::{self, CString, OsString, OsStr, AsOsStr}; use fmt; -use old_io::{IoError, IoResult}; +use iter; use libc::{self, c_int, c_char, c_void}; -use os::TMPBUF_SZ; -use os; -use path::{BytesContainer}; +use mem; +use old_io::{IoResult, IoError, fs}; use ptr; +use slice; use str; +use sys::c; use sys::fs::FileDesc; +use vec; -const BUF_BYTES : uint = 2048u; +const BUF_BYTES: usize = 2048; +const TMPBUF_SZ: usize = 128; /// Returns the platform-specific value of errno -pub fn errno() -> int { +pub fn errno() -> i32 { #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))] - fn errno_location() -> *const c_int { - extern { - fn __error() -> *const c_int; - } - unsafe { - __error() - } + unsafe fn errno_location() -> *const c_int { + extern { fn __error() -> *const c_int; } + __error() } #[cfg(target_os = "dragonfly")] - fn errno_location() -> *const c_int { - extern { - fn __dfly_error() -> *const c_int; - } - unsafe { - __dfly_error() - } + unsafe fn errno_location() -> *const c_int { + extern { fn __dfly_error() -> *const c_int; } + __dfly_error() } #[cfg(any(target_os = "linux", target_os = "android"))] - fn errno_location() -> *const c_int { - extern { - fn __errno_location() -> *const c_int; - } - unsafe { - __errno_location() - } + unsafe fn errno_location() -> *const c_int { + extern { fn __errno_location() -> *const c_int; } + __errno_location() } unsafe { - (*errno_location()) as int + (*errno_location()) as i32 } } /// Get a detailed string description for the given error number pub fn error_string(errno: i32) -> String { - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "android", - target_os = "freebsd", - target_os = "dragonfly"))] - fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) - -> c_int { - extern { - fn strerror_r(errnum: c_int, buf: *mut c_char, - buflen: libc::size_t) -> c_int; - } - unsafe { - strerror_r(errnum, buf, buflen) - } - } - - // GNU libc provides a non-compliant version of strerror_r by default - // and requires macros to instead use the POSIX compliant variant. - // So we just use __xpg_strerror_r which is always POSIX compliant #[cfg(target_os = "linux")] - fn strerror_r(errnum: c_int, buf: *mut c_char, - buflen: libc::size_t) -> c_int { - extern { - fn __xpg_strerror_r(errnum: c_int, - buf: *mut c_char, - buflen: libc::size_t) - -> c_int; - } - unsafe { - __xpg_strerror_r(errnum, buf, buflen) - } + extern { + #[link_name = "__xpg_strerror_r"] + fn strerror_r(errnum: c_int, buf: *mut c_char, + buflen: libc::size_t) -> c_int; + } + #[cfg(not(target_os = "linux"))] + extern { + fn strerror_r(errnum: c_int, buf: *mut c_char, + buflen: libc::size_t) -> c_int; } let mut buf = [0 as c_char; TMPBUF_SZ]; @@ -113,15 +84,6 @@ pub fn error_string(errno: i32) -> String { } } -pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { - let mut fds = [0; 2]; - if libc::pipe(fds.as_mut_ptr()) == 0 { - Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true))) - } else { - Err(super::last_error()) - } -} - pub fn getcwd() -> IoResult { let mut buf = [0 as c_char; BUF_BYTES]; unsafe { @@ -133,43 +95,69 @@ pub fn getcwd() -> IoResult { } } -pub unsafe fn get_env_pairs() -> Vec> { - extern { - fn rust_env_pairs() -> *const *const c_char; - } - let mut environ = rust_env_pairs(); - if environ as uint == 0 { - panic!("os::env() failure getting env string from OS: {}", - os::last_os_error()); +pub fn chdir(p: &Path) -> IoResult<()> { + let p = CString::from_slice(p.as_vec()); + unsafe { + match libc::chdir(p.as_ptr()) == (0 as c_int) { + true => Ok(()), + false => Err(IoError::last_error()), + } } - let mut result = Vec::new(); - while *environ != ptr::null() { - let env_pair = ffi::c_str_to_bytes(&*environ).to_vec(); - result.push(env_pair); - environ = environ.offset(1); +} + +pub struct SplitPaths<'a> { + iter: iter::Map<&'a [u8], Path, + slice::Split<'a, u8, fn(&u8) -> bool>, + fn(&'a [u8]) -> Path>, +} + +pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> { + fn is_colon(b: &u8) -> bool { *b == b':' } + let unparsed = unparsed.as_byte_slice(); + SplitPaths { + iter: unparsed.split(is_colon as fn(&u8) -> bool) + .map(Path::new as fn(&'a [u8]) -> Path) } - result } -pub fn split_paths(unparsed: &[u8]) -> Vec { - unparsed.split(|b| *b == b':').map(Path::new).collect() +impl<'a> Iterator for SplitPaths<'a> { + type Item = Path; + fn next(&mut self) -> Option { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } -pub fn join_paths(paths: &[T]) -> Result, &'static str> { +#[derive(Debug)] +pub struct JoinPathsError; + +pub fn join_paths(paths: I) -> Result + where I: Iterator, T: AsOsStr +{ let mut joined = Vec::new(); let sep = b':'; - for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() { + for (i, path) in paths.enumerate() { + let path = path.as_os_str().as_byte_slice(); if i > 0 { joined.push(sep) } - if path.contains(&sep) { return Err("path segment contains separator `:`") } + if path.contains(&sep) { + return Err(JoinPathsError) + } joined.push_all(path); } + Ok(OsStringExt::from_vec(joined)) +} - Ok(joined) +impl fmt::Display for JoinPathsError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "path segment contains separator `:`".fmt(f) + } +} + +impl StdError for JoinPathsError { + fn description(&self) -> &str { "failed to join paths" } } #[cfg(target_os = "freebsd")] -pub fn load_self() -> Option> { +pub fn current_exe() -> IoResult { unsafe { use libc::funcs::bsd44::*; use libc::consts::os::extra::*; @@ -181,66 +169,276 @@ pub fn load_self() -> Option> { let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint, ptr::null_mut(), &mut sz, ptr::null_mut(), 0u as libc::size_t); - if err != 0 { return None; } - if sz == 0 { return None; } + if err != 0 { return Err(IoError::last_error()); } + if sz == 0 { return Err(IoError::last_error()); } let mut v: Vec = Vec::with_capacity(sz as uint); let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint, v.as_mut_ptr() as *mut libc::c_void, &mut sz, ptr::null_mut(), 0u as libc::size_t); - if err != 0 { return None; } - if sz == 0 { return None; } + if err != 0 { return Err(IoError::last_error()); } + if sz == 0 { return Err(IoError::last_error()); } v.set_len(sz as uint - 1); // chop off trailing NUL - Some(v) + Ok(Path::new(v)) } } #[cfg(target_os = "dragonfly")] -pub fn load_self() -> Option> { - use old_io; - - match old_io::fs::readlink(&Path::new("/proc/curproc/file")) { - Ok(path) => Some(path.into_vec()), - Err(..) => None - } +pub fn current_exe() -> IoResult { + fs::readlink(&Path::new("/proc/curproc/file")) } #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn load_self() -> Option> { - use old_io; - - match old_io::fs::readlink(&Path::new("/proc/self/exe")) { - Ok(path) => Some(path.into_vec()), - Err(..) => None - } +pub fn current_exe() -> IoResult { + fs::readlink(&Path::new("/proc/self/exe")) } #[cfg(any(target_os = "macos", target_os = "ios"))] -pub fn load_self() -> Option> { +pub fn current_exe() -> IoResult { unsafe { use libc::funcs::extra::_NSGetExecutablePath; let mut sz: u32 = 0; _NSGetExecutablePath(ptr::null_mut(), &mut sz); - if sz == 0 { return None; } + if sz == 0 { return Err(IoError::last_error()); } let mut v: Vec = Vec::with_capacity(sz as uint); let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz); - if err != 0 { return None; } + if err != 0 { return Err(IoError::last_error()); } v.set_len(sz as uint - 1); // chop off trailing NUL - Some(v) + Ok(Path::new(v)) } } -pub fn chdir(p: &Path) -> IoResult<()> { - let p = CString::from_slice(p.as_vec()); +pub struct Args { + iter: vec::IntoIter, + _dont_send_or_sync_me: *mut (), +} + +impl Iterator for Args { + type Item = OsString; + fn next(&mut self) -> Option { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +/// Returns the command line arguments +/// +/// Returns a list of the command line arguments. +#[cfg(target_os = "macos")] +pub fn args() -> Args { + extern { + // These functions are in crt_externs.h. + fn _NSGetArgc() -> *mut c_int; + fn _NSGetArgv() -> *mut *mut *mut c_char; + } + + let vec = unsafe { + let (argc, argv) = (*_NSGetArgc() as isize, + *_NSGetArgv() as *const *const c_char); + range(0, argc as isize).map(|i| { + let bytes = ffi::c_str_to_bytes(&*argv.offset(i)).to_vec(); + OsStringExt::from_vec(bytes) + }).collect::>() + }; + Args { + iter: vec.into_iter(), + _dont_send_or_sync_me: 0 as *mut (), + } +} + +// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs +// and use underscores in their names - they're most probably +// are considered private and therefore should be avoided +// Here is another way to get arguments using Objective C +// runtime +// +// In general it looks like: +// res = Vec::new() +// let args = [[NSProcessInfo processInfo] arguments] +// for i in range(0, [args count]) +// res.push([args objectAtIndex:i]) +// res +#[cfg(target_os = "ios")] +pub fn args() -> Args { + use iter::range; + use mem; + + #[link(name = "objc")] + extern { + fn sel_registerName(name: *const libc::c_uchar) -> Sel; + fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId; + fn objc_getClass(class_name: *const libc::c_uchar) -> NsId; + } + + #[link(name = "Foundation", kind = "framework")] + extern {} + + type Sel = *const libc::c_void; + type NsId = *const libc::c_void; + + let mut res = Vec::new(); + unsafe { - match libc::chdir(p.as_ptr()) == (0 as c_int) { - true => Ok(()), - false => Err(IoError::last_error()), + let processInfoSel = sel_registerName("processInfo\0".as_ptr()); + let argumentsSel = sel_registerName("arguments\0".as_ptr()); + let utf8Sel = sel_registerName("UTF8String\0".as_ptr()); + let countSel = sel_registerName("count\0".as_ptr()); + let objectAtSel = sel_registerName("objectAtIndex:\0".as_ptr()); + + let klass = objc_getClass("NSProcessInfo\0".as_ptr()); + let info = objc_msgSend(klass, processInfoSel); + let args = objc_msgSend(info, argumentsSel); + + let cnt: int = mem::transmute(objc_msgSend(args, countSel)); + for i in range(0, cnt) { + let tmp = objc_msgSend(args, objectAtSel, i); + let utf_c_str: *const libc::c_char = + mem::transmute(objc_msgSend(tmp, utf8Sel)); + let bytes = ffi::c_str_to_bytes(&utf_c_str).to_vec(); + res.push(OsString::from_vec(bytes)) + } + } + + Args { iter: res.into_iter(), _dont_send_or_sync_me: 0 as *mut _ } +} + +#[cfg(any(target_os = "linux", + target_os = "android", + target_os = "freebsd", + target_os = "dragonfly"))] +pub fn args() -> Args { + use rt; + let bytes = rt::args::clone().unwrap_or(Vec::new()); + let v: Vec = bytes.into_iter().map(|v| { + OsStringExt::from_vec(v) + }).collect(); + Args { iter: v.into_iter(), _dont_send_or_sync_me: 0 as *mut _ } +} + +pub struct Env { + iter: vec::IntoIter<(OsString, OsString)>, + _dont_send_or_sync_me: *mut (), +} + +impl Iterator for Env { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +#[cfg(target_os = "macos")] +pub unsafe fn environ() -> *mut *const *const c_char { + extern { fn _NSGetEnviron() -> *mut *const *const c_char; } + _NSGetEnviron() +} + +#[cfg(not(target_os = "macos"))] +pub unsafe fn environ() -> *mut *const *const c_char { + extern { static mut environ: *const *const c_char; } + &mut environ +} + +/// Returns a vector of (variable, value) byte-vector pairs for all the +/// environment variables of the current process. +pub fn env() -> Env { + return unsafe { + let mut environ = *environ(); + if environ as usize == 0 { + panic!("os::env() failure getting env string from OS: {}", + IoError::last_error()); + } + let mut result = Vec::new(); + while *environ != ptr::null() { + result.push(parse(ffi::c_str_to_bytes(&*environ))); + environ = environ.offset(1); + } + Env { iter: result.into_iter(), _dont_send_or_sync_me: 0 as *mut _ } + }; + + fn parse(input: &[u8]) -> (OsString, OsString) { + let mut it = input.splitn(1, |b| *b == b'='); + let key = it.next().unwrap().to_vec(); + let default: &[u8] = &[]; + let val = it.next().unwrap_or(default).to_vec(); + (OsStringExt::from_vec(key), OsStringExt::from_vec(val)) + } +} + +pub fn getenv(k: &OsStr) -> Option { + unsafe { + let s = CString::from_slice(k.as_byte_slice()); + let s = libc::getenv(s.as_ptr()) as *const _; + if s.is_null() { + None + } else { + Some(OsStringExt::from_vec(ffi::c_str_to_bytes(&s).to_vec())) + } + } +} + +pub fn setenv(k: &OsStr, v: &OsStr) { + unsafe { + let k = CString::from_slice(k.as_byte_slice()); + let v = CString::from_slice(v.as_byte_slice()); + if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 { + panic!("failed setenv: {}", IoError::last_error()); + } + } +} + +pub fn unsetenv(n: &OsStr) { + unsafe { + let nbuf = CString::from_slice(n.as_byte_slice()); + if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 { + panic!("failed unsetenv: {}", IoError::last_error()); } } } -pub fn page_size() -> uint { +pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { + let mut fds = [0; 2]; + if libc::pipe(fds.as_mut_ptr()) == 0 { + Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true))) + } else { + Err(IoError::last_error()) + } +} + +pub fn page_size() -> usize { unsafe { - libc::sysconf(libc::_SC_PAGESIZE) as uint + libc::sysconf(libc::_SC_PAGESIZE) as usize } } + +pub fn temp_dir() -> Path { + getenv("TMPDIR".as_os_str()).map(|p| Path::new(p.into_vec())).unwrap_or_else(|| { + if cfg!(target_os = "android") { + Path::new("/data/local/tmp") + } else { + Path::new("/tmp") + } + }) +} + +pub fn home_dir() -> Option { + getenv("HOME".as_os_str()).or_else(|| unsafe { + let mut amt = match libc::sysconf(c::_SC_GETPW_R_SIZE_MAX) { + n if n < 0 => 512 as usize, + n => n as usize, + }; + let me = libc::getuid(); + loop { + let mut buf = Vec::with_capacity(amt); + let mut passwd: c::passwd = mem::zeroed(); + let mut result = 0 as *mut _; + match c::getpwuid_r(me, &mut passwd, buf.as_mut_ptr(), + buf.capacity() as libc::size_t, + &mut result) { + 0 if !result.is_null() => {} + _ => return None + } + let ptr = passwd.pw_dir as *const _; + let bytes = ffi::c_str_to_bytes(&ptr).to_vec(); + return Some(OsStringExt::from_vec(bytes)) + } + }).map(|os| { + Path::new(os.into_vec()) + }) +} diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index b004a47f8a349..ae648d13959f9 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -72,18 +72,6 @@ impl Process { } } - #[cfg(target_os = "macos")] - unsafe fn set_environ(envp: *const c_void) { - extern { fn _NSGetEnviron() -> *mut *const c_void; } - - *_NSGetEnviron() = envp; - } - #[cfg(not(target_os = "macos"))] - unsafe fn set_environ(envp: *const c_void) { - extern { static mut environ: *const c_void; } - environ = envp; - } - unsafe fn set_cloexec(fd: c_int) { let ret = c::ioctl(fd, c::FIOCLEX); assert_eq!(ret, 0); @@ -269,7 +257,7 @@ impl Process { fail(&mut output); } if !envp.is_null() { - set_environ(envp); + *sys::os::environ() = envp as *const _; } let _ = execvp(*argv, argv as *mut _); fail(&mut output); diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index 1be1a412ffa9f..66712b9e3a1e6 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -7,29 +7,31 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -/// As always, windows has something very different than unix, we mainly want -/// to avoid having to depend too much on libunwind for windows. -/// -/// If you google around, you'll find a fair bit of references to built-in -/// functions to get backtraces on windows. It turns out that most of these are -/// in an external library called dbghelp. I was unable to find this library -/// via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent -/// of it. -/// -/// You'll also find that there's a function called CaptureStackBackTrace -/// mentioned frequently (which is also easy to use), but sadly I didn't have a -/// 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. + +//! As always, windows has something very different than unix, we mainly want +//! to avoid having to depend too much on libunwind for windows. +//! +//! If you google around, you'll find a fair bit of references to built-in +//! functions to get backtraces on windows. It turns out that most of these are +//! in an external library called dbghelp. I was unable to find this library +//! via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent +//! of it. +//! +//! You'll also find that there's a function called CaptureStackBackTrace +//! mentioned frequently (which is also easy to use), but sadly I didn't have a +//! 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)] use dynamic_lib::DynamicLibrary; use ffi; -use core::ops::Index; use intrinsics; use old_io::{IoResult, Writer}; use libc; use mem; use ops::Drop; -use option::Option::{Some, None}; +use option::Option::{Some}; use path::Path; use ptr; use result::Result::{Ok, Err}; @@ -296,7 +298,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> { // According to windows documentation, all dbghelp functions are // single-threaded. static LOCK: StaticMutex = MUTEX_INIT; - let _g = unsafe { LOCK.lock() }; + let _g = LOCK.lock(); // Open up dbghelp.dll, we don't link to it explicitly because it can't // always be found. Additionally, it's nice having fewer dependencies. diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index da3b7ee2f2fd5..0355565cf00f2 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -10,17 +10,21 @@ //! C definitions used by libnative that don't belong in liblibc -#![allow(overflowing_literals)] -#![allow(dead_code)] -#![allow(non_camel_case_types)] +#![allow(bad_style, dead_code, overflowing_literals)] use libc; -use prelude::v1::*; -pub const WSADESCRIPTION_LEN: uint = 256; -pub const WSASYS_STATUS_LEN: uint = 128; +pub use self::GET_FILEEX_INFO_LEVELS::*; +pub use self::FILE_INFO_BY_HANDLE_CLASS::*; +pub use libc::consts::os::extra::{ + FILE_ATTRIBUTE_READONLY, + FILE_ATTRIBUTE_DIRECTORY, +}; + +pub const WSADESCRIPTION_LEN: usize = 256; +pub const WSASYS_STATUS_LEN: usize = 128; pub const FIONBIO: libc::c_long = 0x8004667e; -pub const FD_SETSIZE: uint = 64; +pub const FD_SETSIZE: usize = 64; pub const MSG_DONTWAIT: libc::c_int = 0; pub const ERROR_ILLEGAL_CHARACTER: libc::c_int = 582; pub const ENABLE_ECHO_INPUT: libc::DWORD = 0x4; @@ -32,12 +36,15 @@ pub const ENABLE_QUICK_EDIT_MODE: libc::DWORD = 0x40; pub const WSA_INVALID_EVENT: WSAEVENT = 0 as WSAEVENT; pub const FD_ACCEPT: libc::c_long = 0x08; -pub const FD_MAX_EVENTS: uint = 10; +pub const FD_MAX_EVENTS: usize = 10; pub const WSA_INFINITE: libc::DWORD = libc::INFINITE; pub const WSA_WAIT_TIMEOUT: libc::DWORD = libc::consts::os::extra::WAIT_TIMEOUT; pub const WSA_WAIT_EVENT_0: libc::DWORD = libc::consts::os::extra::WAIT_OBJECT_0; pub const WSA_WAIT_FAILED: libc::DWORD = libc::consts::os::extra::WAIT_FAILED; +pub const ERROR_NO_MORE_FILES: libc::DWORD = 18; +pub const TOKEN_READ: libc::DWORD = 0x20008; + #[repr(C)] #[cfg(target_arch = "x86")] pub struct WSADATA { @@ -80,7 +87,7 @@ pub struct fd_set { } pub fn fd_set(set: &mut fd_set, s: libc::SOCKET) { - set.fd_array[set.fd_count as uint] = s; + set.fd_array[set.fd_count as usize] = s; set.fd_count += 1; } @@ -110,6 +117,69 @@ pub struct CONSOLE_SCREEN_BUFFER_INFO { } pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO; +#[repr(C)] +pub struct WIN32_FILE_ATTRIBUTE_DATA { + pub dwFileAttributes: libc::DWORD, + pub ftCreationTime: libc::FILETIME, + pub ftLastAccessTime: libc::FILETIME, + pub ftLastWriteTime: libc::FILETIME, + pub nFileSizeHigh: libc::DWORD, + pub nFileSizeLow: libc::DWORD, +} + +#[repr(C)] +pub struct BY_HANDLE_FILE_INFORMATION { + pub dwFileAttributes: libc::DWORD, + pub ftCreationTime: libc::FILETIME, + pub ftLastAccessTime: libc::FILETIME, + pub ftLastWriteTime: libc::FILETIME, + pub dwVolumeSerialNumber: libc::DWORD, + pub nFileSizeHigh: libc::DWORD, + pub nFileSizeLow: libc::DWORD, + pub nNumberOfLinks: libc::DWORD, + pub nFileIndexHigh: libc::DWORD, + pub nFileIndexLow: libc::DWORD, +} + +pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION; + +#[repr(C)] +pub enum GET_FILEEX_INFO_LEVELS { + GetFileExInfoStandard, + GetFileExMaxInfoLevel +} + +#[repr(C)] +pub enum FILE_INFO_BY_HANDLE_CLASS { + FileBasicInfo = 0, + FileStandardInfo = 1, + FileNameInfo = 2, + FileRenameInfo = 3, + FileDispositionInfo = 4, + FileAllocationInfo = 5, + FileEndOfFileInfo = 6, + FileStreamInfo = 7, + FileCompressionInfo = 8, + FileAttributeTagInfo = 9, + FileIdBothDirectoryInfo = 10, // 0xA + FileIdBothDirectoryRestartInfo = 11, // 0xB + FileIoPriorityHintInfo = 12, // 0xC + FileRemoteProtocolInfo = 13, // 0xD + FileFullDirectoryInfo = 14, // 0xE + FileFullDirectoryRestartInfo = 15, // 0xF + FileStorageInfo = 16, // 0x10 + FileAlignmentInfo = 17, // 0x11 + FileIdInfo = 18, // 0x12 + FileIdExtdDirectoryInfo = 19, // 0x13 + FileIdExtdDirectoryRestartInfo = 20, // 0x14 + MaximumFileInfoByHandlesClass +} + +#[repr(C)] +pub struct FILE_END_OF_FILE_INFO { + pub EndOfFile: libc::LARGE_INTEGER, +} + #[link(name = "ws2_32")] extern "system" { pub fn WSAStartup(wVersionRequested: libc::WORD, @@ -156,31 +226,29 @@ extern "system" { } pub mod compat { - use intrinsics::{atomic_store_relaxed, transmute}; - use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID}; use prelude::v1::*; + use ffi::CString; + use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID}; + use sync::atomic::{AtomicUsize, Ordering}; extern "system" { fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID; } - // store_func() is idempotent, so using relaxed ordering for the atomics - // should be enough. This way, calling a function in this compatibility - // layer (after it's loaded) shouldn't be any slower than a regular DLL - // call. - unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) { + fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str, + fallback: usize) -> usize { let mut module: Vec = module.utf16_units().collect(); module.push(0); let symbol = CString::from_slice(symbol.as_bytes()); - let handle = GetModuleHandleW(module.as_ptr()); - let func: uint = transmute(GetProcAddress(handle, symbol.as_ptr())); - atomic_store_relaxed(ptr, if func == 0 { - fallback - } else { - func - }) + let func = unsafe { + let handle = GetModuleHandleW(module.as_ptr()); + GetProcAddress(handle, symbol.as_ptr()) as usize + }; + let value = if func == 0 {fallback} else {func}; + ptr.store(value, Ordering::SeqCst); + value } /// Macro for creating a compatibility fallback for a Windows function @@ -192,29 +260,36 @@ pub mod compat { /// }) /// ``` /// - /// Note that arguments unused by the fallback implementation should not be called `_` as - /// they are used to be passed to the real function if available. + /// Note that arguments unused by the fallback implementation should not be + /// called `_` as they are used to be passed to the real function if + /// available. macro_rules! compat_fn { ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty { $fallback:expr }) => ( #[inline(always)] pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype { - static mut ptr: extern "system" fn($($argname: $argtype),*) -> $rettype = thunk; - - extern "system" fn thunk($($argname: $argtype),*) -> $rettype { - unsafe { - ::sys::c::compat::store_func(&mut ptr as *mut _ as *mut uint, - stringify!($module), - stringify!($symbol), - fallback as uint); - ::intrinsics::atomic_load_relaxed(&ptr)($($argname),*) - } + use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; + use mem; + + static PTR: AtomicUsize = ATOMIC_USIZE_INIT; + + fn load() -> usize { + ::sys::c::compat::store_func(&PTR, + stringify!($module), + stringify!($symbol), + fallback as usize) } extern "system" fn fallback($($argname: $argtype),*) -> $rettype { $fallback } - ::intrinsics::atomic_load_relaxed(&ptr)($($argname),*) + let addr = match PTR.load(Ordering::SeqCst) { + 0 => load(), + n => n, + }; + let f: extern "system" fn($($argtype),*) -> $rettype = + mem::transmute(addr); + f($($argname),*) } ) } @@ -229,10 +304,7 @@ pub mod compat { use libc::c_uint; use libc::types::os::arch::extra::{DWORD, LPCWSTR, BOOLEAN, HANDLE}; use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED; - - extern "system" { - fn SetLastError(dwErrCode: DWORD); - } + use sys::c::SetLastError; compat_fn! { kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR, @@ -282,4 +354,42 @@ extern "system" { hConsoleOutput: libc::HANDLE, lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO, ) -> libc::BOOL; + + pub fn GetFileAttributesExW(lpFileName: libc::LPCWSTR, + fInfoLevelId: GET_FILEEX_INFO_LEVELS, + lpFileInformation: libc::LPVOID) -> libc::BOOL; + pub fn RemoveDirectoryW(lpPathName: libc::LPCWSTR) -> libc::BOOL; + pub fn SetFileAttributesW(lpFileName: libc::LPCWSTR, + dwFileAttributes: libc::DWORD) -> libc::BOOL; + pub fn GetFileAttributesW(lpFileName: libc::LPCWSTR) -> libc::DWORD; + pub fn GetFileInformationByHandle(hFile: libc::HANDLE, + lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) + -> libc::BOOL; + + pub fn SetLastError(dwErrCode: libc::DWORD); + pub fn GetCommandLineW() -> *mut libc::LPCWSTR; + pub fn LocalFree(ptr: *mut libc::c_void); + pub fn CommandLineToArgvW(lpCmdLine: *mut libc::LPCWSTR, + pNumArgs: *mut libc::c_int) -> *mut *mut u16; + pub fn SetFileTime(hFile: libc::HANDLE, + lpCreationTime: *const libc::FILETIME, + lpLastAccessTime: *const libc::FILETIME, + lpLastWriteTime: *const libc::FILETIME) -> libc::BOOL; + pub fn SetFileInformationByHandle(hFile: libc::HANDLE, + FileInformationClass: FILE_INFO_BY_HANDLE_CLASS, + lpFileInformation: libc::LPVOID, + dwBufferSize: libc::DWORD) -> libc::BOOL; + pub fn GetTempPathW(nBufferLength: libc::DWORD, + lpBuffer: libc::LPCWSTR) -> libc::DWORD; + pub fn OpenProcessToken(ProcessHandle: libc::HANDLE, + DesiredAccess: libc::DWORD, + TokenHandle: *mut libc::HANDLE) -> libc::BOOL; + pub fn GetCurrentProcess() -> libc::HANDLE; +} + +#[link(name = "userenv")] +extern "system" { + pub fn GetUserProfileDirectoryW(hToken: libc::HANDLE, + lpProfileDir: libc::LPCWSTR, + lpcchSize: *mut libc::DWORD) -> libc::BOOL; } diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 80cdf9782f20f..304d7e0153279 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -10,20 +10,15 @@ //! Blocking Windows-based file I/O -use alloc::arc::Arc; use libc::{self, c_int}; use mem; -use sys::os::fill_utf16_buf_and_decode; -use path; use ptr; -use str; use old_io; use prelude::v1::*; use sys; -use sys::os; -use sys_common::{keep_going, eof, mkerr_libc}; +use sys_common::{mkerr_libc}; use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode}; use old_io::{IoResult, IoError, FileStat, SeekStyle}; @@ -262,7 +257,7 @@ pub fn readdir(p: &Path) -> IoResult> { let mut more_files = 1 as libc::BOOL; while more_files != 0 { { - let filename = os::truncate_utf16_at_nul(&wfd.cFileName); + let filename = super::truncate_utf16_at_nul(&wfd.cFileName); match String::from_utf16(filename) { Ok(filename) => paths.push(Path::new(filename)), Err(..) => { @@ -368,19 +363,12 @@ pub fn readlink(p: &Path) -> IoResult { } // Specify (sz - 1) because the documentation states that it's the size // without the null pointer - let ret = fill_utf16_buf_and_decode(|buf, sz| unsafe { + let ret = super::fill_utf16_buf(|buf, sz| unsafe { GetFinalPathNameByHandleW(handle, buf as *const u16, sz - 1, libc::VOLUME_NAME_DOS) - }); - let ret = match ret { - Some(ref s) if s.starts_with(r"\\?\") => { // " - Ok(Path::new(&s[4..])) - } - Some(s) => Ok(Path::new(s)), - None => Err(super::last_error()), - }; + }, super::os2path); assert!(unsafe { libc::CloseHandle(handle) } != 0); return ret; } diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs new file mode 100644 index 0000000000000..6737eeef12532 --- /dev/null +++ b/src/libstd/sys/windows/handle.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::v1::*; + +use libc::{self, HANDLE}; + +pub struct Handle(HANDLE); + +unsafe impl Send for Handle {} +unsafe impl Sync for Handle {} + +impl Handle { + pub fn new(handle: HANDLE) -> Handle { + Handle(handle) + } +} + +impl Drop for Handle { + fn drop(&mut self) { + unsafe { let _ = libc::CloseHandle(self.0); } + } +} + diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index e8b65c9b64ea3..8dd467eba9e2a 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -11,18 +11,14 @@ #![allow(missing_docs)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] -#![allow(unused_imports)] -#![allow(dead_code)] -#![allow(unused_unsafe)] -#![allow(unused_mut)] - -extern crate libc; use prelude::v1::*; -use num; +use ffi::OsStr; +use libc; use mem; use old_io::{self, IoResult, IoError}; +use os::windows::OsStrExt; use sync::{Once, ONCE_INIT}; macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( @@ -38,9 +34,10 @@ macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( pub mod backtrace; pub mod c; -pub mod ext; pub mod condvar; +pub mod ext; pub mod fs; +pub mod handle; pub mod helper_signal; pub mod mutex; pub mod os; @@ -48,12 +45,12 @@ pub mod os_str; pub mod pipe; pub mod process; pub mod rwlock; -pub mod sync; pub mod stack_overflow; +pub mod sync; pub mod tcp; -pub mod time; pub mod thread; pub mod thread_local; +pub mod time; pub mod timer; pub mod tty; pub mod udp; @@ -158,7 +155,7 @@ pub fn ms_to_timeval(ms: u64) -> libc::timeval { pub fn wouldblock() -> bool { let err = os::errno(); - err == libc::WSAEWOULDBLOCK as uint + err == libc::WSAEWOULDBLOCK as i32 } pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> { @@ -191,17 +188,93 @@ pub fn unimpl() -> IoError { } } -pub fn to_utf16(s: Option<&str>) -> IoResult> { +fn to_utf16(s: Option<&str>) -> IoResult> { match s { - Some(s) => Ok({ - let mut s = s.utf16_units().collect::>(); - s.push(0); - s - }), + Some(s) => Ok(to_utf16_os(OsStr::from_str(s))), None => Err(IoError { kind: old_io::InvalidInput, desc: "valid unicode input required", - detail: None - }) + detail: None, + }), + } +} + +fn to_utf16_os(s: &OsStr) -> Vec { + let mut v: Vec<_> = s.encode_wide().collect(); + v.push(0); + v +} + +// Many Windows APIs follow a pattern of where we hand the a buffer and then +// they will report back to us how large the buffer should be or how many bytes +// currently reside in the buffer. This function is an abstraction over these +// functions by making them easier to call. +// +// The first callback, `f1`, is yielded a (pointer, len) pair which can be +// passed to a syscall. The `ptr` is valid for `len` items (u16 in this case). +// The closure is expected to return what the syscall returns which will be +// interpreted by this function to determine if the syscall needs to be invoked +// again (with more buffer space). +// +// Once the syscall has completed (errors bail out early) the second closure is +// yielded the data which has been read from the syscall. The return value +// from this closure is then the return value of the function. +fn fill_utf16_buf(mut f1: F1, f2: F2) -> IoResult + where F1: FnMut(*mut u16, libc::DWORD) -> libc::DWORD, + F2: FnOnce(&[u16]) -> T +{ + // Start off with a stack buf but then spill over to the heap if we end up + // needing more space. + let mut stack_buf = [0u16; 512]; + let mut heap_buf = Vec::new(); + unsafe { + let mut n = stack_buf.len(); + loop { + let buf = if n <= stack_buf.len() { + &mut stack_buf[] + } else { + let extra = n - heap_buf.len(); + heap_buf.reserve(extra); + heap_buf.set_len(n); + &mut heap_buf[] + }; + + // This function is typically called on windows API functions which + // will return the correct length of the string, but these functions + // also return the `0` on error. In some cases, however, the + // returned "correct length" may actually be 0! + // + // To handle this case we call `SetLastError` to reset it to 0 and + // then check it again if we get the "0 error value". If the "last + // error" is still 0 then we interpret it as a 0 length buffer and + // not an actual error. + c::SetLastError(0); + let k = match f1(buf.as_mut_ptr(), n as libc::DWORD) { + 0 if libc::GetLastError() == 0 => 0, + 0 => return Err(IoError::last_error()), + n => n, + } as usize; + if k == n && libc::GetLastError() == + libc::ERROR_INSUFFICIENT_BUFFER as libc::DWORD { + n *= 2; + } else if k >= n { + n = k; + } else { + return Ok(f2(&buf[..k])) + } + } + } +} + +fn os2path(s: &[u16]) -> Path { + // FIXME: this should not be a panicking conversion (aka path reform) + Path::new(String::from_utf16(s).unwrap()) +} + +pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { + match v.iter().position(|c| *c == 0) { + // don't include the 0 + Some(i) => &v[..i], + None => v } } diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 828ad795ed3b4..75495efc7cbb6 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -37,8 +37,6 @@ pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK { // no guarantees of fairness. impl Mutex { - #[inline] - pub unsafe fn new() -> Mutex { MUTEX_INIT } #[inline] pub unsafe fn lock(&self) { ffi::AcquireSRWLockExclusive(self.inner.get()) diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index a82259ad5ec57..c71e2d057c351 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -10,48 +10,32 @@ //! Implementation of `std::os` functionality for Windows -// FIXME: move various extern bindings from here into liblibc or -// something similar +#![allow(bad_style)] use prelude::v1::*; +use os::windows::*; +use error::Error as StdError; +use ffi::{OsString, OsStr, AsOsStr}; use fmt; -use old_io::{IoResult, IoError}; -use iter::repeat; -use libc::{c_int, c_void}; -use libc; -use os; -use path::BytesContainer; +use iter::Range; +use libc::types::os::arch::extra::LPWCH; +use libc::{self, c_int, c_void}; +use mem; +use old_io::{IoError, IoResult}; use ptr; use slice; +use sys::c; use sys::fs::FileDesc; +use sys::handle::Handle as RawHandle; -use os::TMPBUF_SZ; -use libc::types::os::arch::extra::DWORD; +use libc::funcs::extra::kernel32::{ + GetEnvironmentStringsW, + FreeEnvironmentStringsW +}; -const BUF_BYTES : uint = 2048u; - -/// Return a slice of `v` ending at (and not including) the first NUL -/// (0). -pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { - match v.iter().position(|c| *c == 0) { - // don't include the 0 - Some(i) => &v[..i], - None => v - } -} - -pub fn errno() -> uint { - use libc::types::os::arch::extra::DWORD; - - #[link_name = "kernel32"] - extern "system" { - fn GetLastError() -> DWORD; - } - - unsafe { - GetLastError() as uint - } +pub fn errno() -> i32 { + unsafe { libc::GetLastError() as i32 } } /// Get a detailed string description for the given error number @@ -80,7 +64,7 @@ pub fn error_string(errnum: i32) -> String { // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT) let langId = 0x0800 as DWORD; - let mut buf = [0 as WCHAR; TMPBUF_SZ]; + let mut buf = [0 as WCHAR; 2048]; unsafe { let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | @@ -94,200 +78,170 @@ pub fn error_string(errnum: i32) -> String { if res == 0 { // Sometimes FormatMessageW can fail e.g. system doesn't like langId, let fm_err = errno(); - return format!("OS Error {} (FormatMessageW() returned error {})", errnum, fm_err); + return format!("OS Error {} (FormatMessageW() returned error {})", + errnum, fm_err); } - let msg = String::from_utf16(truncate_utf16_at_nul(&buf)); + let b = buf.iter().position(|&b| b == 0).unwrap_or(buf.len()); + let msg = String::from_utf16(&buf[..b]); match msg { - Ok(msg) => format!("OS Error {}: {}", errnum, msg), + Ok(msg) => msg, Err(..) => format!("OS Error {} (FormatMessageW() returned \ invalid UTF-16)", errnum), } } } -pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { - // Windows pipes work subtly differently than unix pipes, and their - // inheritance has to be handled in a different way that I do not - // fully understand. Here we explicitly make the pipe non-inheritable, - // which means to pass it to a subprocess they need to be duplicated - // first, as in std::run. - let mut fds = [0; 2]; - match libc::pipe(fds.as_mut_ptr(), 1024 as ::libc::c_uint, - (libc::O_BINARY | libc::O_NOINHERIT) as c_int) { - 0 => { - assert!(fds[0] != -1 && fds[0] != 0); - assert!(fds[1] != -1 && fds[1] != 0); - Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true))) - } - _ => Err(IoError::last_error()), - } +pub struct Env { + base: LPWCH, + cur: LPWCH, } -pub fn fill_utf16_buf_and_decode(mut f: F) -> Option where - F: FnMut(*mut u16, DWORD) -> DWORD, -{ - unsafe { - let mut n = TMPBUF_SZ as DWORD; - let mut res = None; - let mut done = false; - while !done { - let mut buf: Vec = repeat(0u16).take(n as uint).collect(); - let k = f(buf.as_mut_ptr(), n); - if k == (0 as DWORD) { - done = true; - } else if k == n && - libc::GetLastError() == - libc::ERROR_INSUFFICIENT_BUFFER as DWORD { - n *= 2 as DWORD; - } else if k >= n { - n = k; - } else { - done = true; - } - if k != 0 && done { - let sub = &buf[.. (k as uint)]; - // We want to explicitly catch the case when the - // closure returned invalid UTF-16, rather than - // set `res` to None and continue. - let s = String::from_utf16(sub).ok() - .expect("fill_utf16_buf_and_decode: closure created invalid UTF-16"); - res = Some(s) +impl Iterator for Env { + type Item = (OsString, OsString); + + fn next(&mut self) -> Option<(OsString, OsString)> { + unsafe { + if *self.cur == 0 { return None } + let p = &*self.cur; + let mut len = 0; + while *(p as *const _).offset(len) != 0 { + len += 1; } + let p = p as *const u16; + let s = slice::from_raw_buf(&p, len as usize); + self.cur = self.cur.offset(len + 1); + + let (k, v) = match s.iter().position(|&b| b == '=' as u16) { + Some(n) => (&s[..n], &s[n+1..]), + None => (s, &[][]), + }; + Some((OsStringExt::from_wide(k), OsStringExt::from_wide(v))) } - return res; } } -pub fn getcwd() -> IoResult { - use libc::DWORD; - use libc::GetCurrentDirectoryW; - use old_io::OtherIoError; +impl Drop for Env { + fn drop(&mut self) { + unsafe { FreeEnvironmentStringsW(self.base); } + } +} - let mut buf = [0 as u16; BUF_BYTES]; +pub fn env() -> Env { unsafe { - if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD { - return Err(IoError::last_error()); + let ch = GetEnvironmentStringsW(); + if ch as usize == 0 { + panic!("failure getting env string from OS: {}", + IoError::last_error()); } + Env { base: ch, cur: ch } } +} - match String::from_utf16(truncate_utf16_at_nul(&buf)) { - Ok(ref cwd) => Ok(Path::new(cwd)), - Err(..) => Err(IoError { - kind: OtherIoError, - desc: "GetCurrentDirectoryW returned invalid UTF-16", - detail: None, - }), - } +pub struct SplitPaths<'a> { + data: EncodeWide<'a>, + must_yield: bool, } -pub unsafe fn get_env_pairs() -> Vec> { - use libc::funcs::extra::kernel32::{ - GetEnvironmentStringsW, - FreeEnvironmentStringsW - }; - let ch = GetEnvironmentStringsW(); - if ch as uint == 0 { - panic!("os::env() failure getting env string from OS: {}", - os::last_os_error()); +pub fn split_paths(unparsed: &OsStr) -> SplitPaths { + SplitPaths { + data: unparsed.encode_wide(), + must_yield: true, } - // Here, we lossily decode the string as UTF16. - // - // The docs suggest that the result should be in Unicode, but - // Windows doesn't guarantee it's actually UTF16 -- it doesn't - // validate the environment string passed to CreateProcess nor - // SetEnvironmentVariable. Yet, it's unlikely that returning a - // raw u16 buffer would be of practical use since the result would - // be inherently platform-dependent and introduce additional - // complexity to this code. - // - // Using the non-Unicode version of GetEnvironmentStrings is even - // worse since the result is in an OEM code page. Characters that - // can't be encoded in the code page would be turned into question - // marks. - let mut result = Vec::new(); - let mut i = 0; - while *ch.offset(i) != 0 { - let p = &*ch.offset(i); - let mut len = 0; - while *(p as *const _).offset(len) != 0 { - len += 1; - } - let p = p as *const u16; - let s = slice::from_raw_buf(&p, len as uint); - result.push(String::from_utf16_lossy(s).into_bytes()); - i += len as int + 1; - } - FreeEnvironmentStringsW(ch); - result } -pub fn split_paths(unparsed: &[u8]) -> Vec { - // On Windows, the PATH environment variable is semicolon separated. Double - // quotes are used as a way of introducing literal semicolons (since - // c:\some;dir is a valid Windows path). Double quotes are not themselves - // permitted in path names, so there is no way to escape a double quote. - // Quoted regions can appear in arbitrary locations, so - // - // c:\foo;c:\som"e;di"r;c:\bar - // - // Should parse as [c:\foo, c:\some;dir, c:\bar]. - // - // (The above is based on testing; there is no clear reference available - // for the grammar.) - - let mut parsed = Vec::new(); - let mut in_progress = Vec::new(); - let mut in_quote = false; - - for b in unparsed.iter() { - match *b { - b';' if !in_quote => { - parsed.push(Path::new(in_progress.as_slice())); - in_progress.truncate(0) - } - b'"' => { +impl<'a> Iterator for SplitPaths<'a> { + type Item = Path; + fn next(&mut self) -> Option { + // On Windows, the PATH environment variable is semicolon separated. + // Double quotes are used as a way of introducing literal semicolons + // (since c:\some;dir is a valid Windows path). Double quotes are not + // themselves permitted in path names, so there is no way to escape a + // double quote. Quoted regions can appear in arbitrary locations, so + // + // c:\foo;c:\som"e;di"r;c:\bar + // + // Should parse as [c:\foo, c:\some;dir, c:\bar]. + // + // (The above is based on testing; there is no clear reference available + // for the grammar.) + + + let must_yield = self.must_yield; + self.must_yield = false; + + let mut in_progress = Vec::new(); + let mut in_quote = false; + for b in self.data.by_ref() { + if b == '"' as u16 { in_quote = !in_quote; + } else if b == ';' as u16 && !in_quote { + self.must_yield = true; + break + } else { + in_progress.push(b) } - _ => { - in_progress.push(*b); - } + } + + if !must_yield && in_progress.is_empty() { + None + } else { + Some(super::os2path(&in_progress[])) } } - parsed.push(Path::new(in_progress)); - parsed } -pub fn join_paths(paths: &[T]) -> Result, &'static str> { +#[derive(Show)] +pub struct JoinPathsError; + +pub fn join_paths(paths: I) -> Result + where I: Iterator, T: AsOsStr +{ let mut joined = Vec::new(); - let sep = b';'; + let sep = b';' as u16; - for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() { + for (i, path) in paths.enumerate() { + let path = path.as_os_str(); if i > 0 { joined.push(sep) } - if path.contains(&b'"') { - return Err("path segment contains `\"`"); - } else if path.contains(&sep) { - joined.push(b'"'); - joined.push_all(path); - joined.push(b'"'); + let v = path.encode_wide().collect::>(); + if v.contains(&(b'"' as u16)) { + return Err(JoinPathsError) + } else if v.contains(&sep) { + joined.push(b'"' as u16); + joined.push_all(&v[]); + joined.push(b'"' as u16); } else { - joined.push_all(path); + joined.push_all(&v[]); } } - Ok(joined) + Ok(OsStringExt::from_wide(&joined[])) } -pub fn load_self() -> Option> { - unsafe { - fill_utf16_buf_and_decode(|buf, sz| { - libc::GetModuleFileNameW(ptr::null_mut(), buf, sz) - }).map(|s| s.to_string().into_bytes()) +impl fmt::Display for JoinPathsError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "path segment contains `\"`".fmt(f) } } +impl StdError for JoinPathsError { + fn description(&self) -> &str { "failed to join paths" } +} + +pub fn current_exe() -> IoResult { + super::fill_utf16_buf(|buf, sz| unsafe { + libc::GetModuleFileNameW(ptr::null_mut(), buf, sz) + }, super::os2path) +} + +pub fn getcwd() -> IoResult { + super::fill_utf16_buf(|buf, sz| unsafe { + libc::GetCurrentDirectoryW(sz, buf) + }, super::os2path) +} + pub fn chdir(p: &Path) -> IoResult<()> { - let mut p = p.as_str().unwrap().utf16_units().collect::>(); + let mut p = p.as_os_str().encode_wide().collect::>(); p.push(0); unsafe { @@ -298,39 +252,124 @@ pub fn chdir(p: &Path) -> IoResult<()> { } } -pub fn page_size() -> uint { - use mem; +pub fn getenv(k: &OsStr) -> Option { + let k = super::to_utf16_os(k); + super::fill_utf16_buf(|buf, sz| unsafe { + libc::GetEnvironmentVariableW(k.as_ptr(), buf, sz) + }, |buf| { + OsStringExt::from_wide(buf) + }).ok() +} + +pub fn setenv(k: &OsStr, v: &OsStr) { + let k = super::to_utf16_os(k); + let v = super::to_utf16_os(v); + unsafe { - let mut info = mem::zeroed(); - libc::GetSystemInfo(&mut info); + if libc::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr()) == 0 { + panic!("failed to set env: {}", IoError::last_error()); + } + } +} - return info.dwPageSize as uint; +pub fn unsetenv(n: &OsStr) { + let v = super::to_utf16_os(n); + unsafe { + if libc::SetEnvironmentVariableW(v.as_ptr(), ptr::null()) == 0 { + panic!("failed to unset env: {}", IoError::last_error()); + } } } -#[cfg(test)] -mod tests { - use super::truncate_utf16_at_nul; +pub struct Args { + range: Range, + cur: *mut *mut u16, +} - #[test] - fn test_truncate_utf16_at_nul() { - let v = []; - let b: &[u16] = &[]; - assert_eq!(truncate_utf16_at_nul(&v), b); +impl Iterator for Args { + type Item = OsString; + fn next(&mut self) -> Option { + self.range.next().map(|i| unsafe { + let ptr = *self.cur.offset(i); + let mut len = 0; + while *ptr.offset(len) != 0 { len += 1; } + + // Push it onto the list. + let ptr = ptr as *const u16; + let buf = slice::from_raw_buf(&ptr, len as usize); + OsStringExt::from_wide(buf) + }) + } + fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } +} - let v = [0, 2, 3]; - assert_eq!(truncate_utf16_at_nul(&v), b); +impl Drop for Args { + fn drop(&mut self) { + unsafe { c::LocalFree(self.cur as *mut c_void); } + } +} - let v = [1, 0, 3]; - let b: &[u16] = &[1]; - assert_eq!(truncate_utf16_at_nul(&v), b); +pub fn args() -> Args { + unsafe { + let mut nArgs: c_int = 0; + let lpCmdLine = c::GetCommandLineW(); + let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs); - let v = [1, 2, 0]; - let b: &[u16] = &[1, 2]; - assert_eq!(truncate_utf16_at_nul(&v), b); + Args { cur: szArgList, range: range(0, nArgs as isize) } + } +} - let v = [1, 2, 3]; - let b: &[u16] = &[1, 2, 3]; - assert_eq!(truncate_utf16_at_nul(&v), b); +pub fn page_size() -> usize { + unsafe { + let mut info = mem::zeroed(); + libc::GetSystemInfo(&mut info); + return info.dwPageSize as usize; + } +} + +pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { + // Windows pipes work subtly differently than unix pipes, and their + // inheritance has to be handled in a different way that I do not + // fully understand. Here we explicitly make the pipe non-inheritable, + // which means to pass it to a subprocess they need to be duplicated + // first, as in std::run. + let mut fds = [0; 2]; + match libc::pipe(fds.as_mut_ptr(), 1024 as ::libc::c_uint, + (libc::O_BINARY | libc::O_NOINHERIT) as c_int) { + 0 => { + assert!(fds[0] != -1 && fds[0] != 0); + assert!(fds[1] != -1 && fds[1] != 0); + Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true))) + } + _ => Err(IoError::last_error()), } } + +pub fn temp_dir() -> Path { + super::fill_utf16_buf(|buf, sz| unsafe { + c::GetTempPathW(sz, buf) + }, super::os2path).unwrap() +} + +pub fn home_dir() -> Option { + getenv("HOME".as_os_str()).or_else(|| { + getenv("USERPROFILE".as_os_str()) + }).map(|os| { + // FIXME: OsString => Path + Path::new(os.to_str().unwrap()) + }).or_else(|| unsafe { + let me = c::GetCurrentProcess(); + let mut token = ptr::null_mut(); + if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 { + return None + } + let _handle = RawHandle::new(token); + super::fill_utf16_buf(|buf, mut sz| { + match c::GetUserProfileDirectoryW(token, buf, &mut sz) { + 0 if libc::GetLastError() != 0 => 0, + 0 => sz, + n => n as libc::DWORD, + } + }, super::os2path).ok() + }) +} diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 0bc2a827272e6..1f228b7d32e35 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -352,7 +352,7 @@ impl UnixStream { fn cancel_io(&self) -> IoResult<()> { match unsafe { c::CancelIoEx(self.handle(), ptr::null_mut()) } { - 0 if os::errno() == libc::ERROR_NOT_FOUND as uint => { + 0 if os::errno() == libc::ERROR_NOT_FOUND as i32 => { Ok(()) } 0 => Err(super::last_error()), @@ -374,7 +374,7 @@ impl UnixStream { // acquire the lock. // // See comments in close_read() about why this lock is necessary. - let guard = unsafe { self.inner.lock.lock() }; + let guard = self.inner.lock.lock(); if self.read_closed() { return Err(eof()) } @@ -392,7 +392,7 @@ impl UnixStream { // If our errno doesn't say that the I/O is pending, then we hit some // legitimate error and return immediately. - if os::errno() != libc::ERROR_IO_PENDING as uint { + if os::errno() != libc::ERROR_IO_PENDING as i32 { return Err(super::last_error()) } @@ -417,7 +417,7 @@ impl UnixStream { // If we succeeded, or we failed for some reason other than // CancelIoEx, return immediately if ret != 0 { return Ok(bytes_read as uint) } - if os::errno() != libc::ERROR_OPERATION_ABORTED as uint { + if os::errno() != libc::ERROR_OPERATION_ABORTED as i32 { return Err(super::last_error()) } @@ -450,7 +450,7 @@ impl UnixStream { // going after we woke up. // // See comments in close_read() about why this lock is necessary. - let guard = unsafe { self.inner.lock.lock() }; + let guard = self.inner.lock.lock(); if self.write_closed() { return Err(epipe()) } @@ -465,7 +465,7 @@ impl UnixStream { drop(guard); if ret == 0 { - if err != libc::ERROR_IO_PENDING as uint { + if err != libc::ERROR_IO_PENDING as i32 { return Err(decode_error_detailed(err as i32)) } // Process a timeout if one is pending @@ -481,7 +481,7 @@ impl UnixStream { // aborted, then check to see if the write half was actually // closed or whether we woke up from the read half closing. if ret == 0 { - if os::errno() != libc::ERROR_OPERATION_ABORTED as uint { + if os::errno() != libc::ERROR_OPERATION_ABORTED as i32 { return Err(super::last_error()) } if !wait_succeeded.is_ok() { @@ -525,14 +525,14 @@ impl UnixStream { // close_read() between steps 1 and 2. By atomically executing steps 1 // and 2 with a lock with respect to close_read(), we're guaranteed that // no thread will erroneously sit in a read forever. - let _guard = unsafe { self.inner.lock.lock() }; + let _guard = self.inner.lock.lock(); self.inner.read_closed.store(true, Ordering::SeqCst); self.cancel_io() } pub fn close_write(&mut self) -> IoResult<()> { // see comments in close_read() for why this lock is necessary - let _guard = unsafe { self.inner.lock.lock() }; + let _guard = self.inner.lock.lock(); self.inner.write_closed.store(true, Ordering::SeqCst); self.cancel_io() } diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 3d66718d00ba0..043fdb38805dc 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -10,28 +10,27 @@ use prelude::v1::*; +use collections::hash_map::Hasher; use collections; +use env; use ffi::CString; use hash::Hash; -use collections::hash_map::Hasher; +use libc::{pid_t, c_void}; +use libc; +use mem; use old_io::fs::PathExtensions; -use old_io::process::{ProcessExit, ExitStatus, ExitSignal}; +use old_io::process::{ProcessExit, ExitStatus}; use old_io::{IoResult, IoError}; use old_io; -use libc::{pid_t, c_void, c_int}; -use libc; -use mem; use os; use path::BytesContainer; use ptr; use str; -use sys::fs::FileDesc; use sync::{StaticMutex, MUTEX_INIT}; +use sys::fs::FileDesc; -use sys::fs; -use sys::{self, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer}; -use sys_common::helper_thread::Helper; -use sys_common::{AsInner, mkerr_libc, timeout}; +use sys::timer; +use sys_common::{AsInner, timeout}; pub use sys_common::ProcessConfig; @@ -106,6 +105,7 @@ impl Process { return ret; } + #[allow(deprecated)] pub fn spawn(cfg: &C, in_fd: Option

, out_fd: Option

, err_fd: Option

) -> IoResult @@ -128,7 +128,7 @@ impl Process { use libc::funcs::extra::msvcrt::get_osfhandle; use mem; - use iter::{Iterator, IteratorExt}; + use iter::IteratorExt; use str::StrExt; if cfg.gid().is_some() || cfg.uid().is_some() { @@ -149,7 +149,7 @@ impl Process { // program exists. for path in os::split_paths(v.container_as_bytes()).into_iter() { let path = path.join(cfg.program().as_bytes()) - .with_extension(os::consts::EXE_EXTENSION); + .with_extension(env::consts::EXE_EXTENSION); if path.exists() { return Some(CString::from_slice(path.as_vec())) } diff --git a/src/libstd/sys/windows/rwlock.rs b/src/libstd/sys/windows/rwlock.rs index 88ce85c39f625..76fe352ed7717 100644 --- a/src/libstd/sys/windows/rwlock.rs +++ b/src/libstd/sys/windows/rwlock.rs @@ -18,9 +18,6 @@ pub const RWLOCK_INIT: RWLock = RWLock { }; impl RWLock { - #[inline] - pub unsafe fn new() -> RWLock { RWLOCK_INIT } - #[inline] pub unsafe fn read(&self) { ffi::AcquireSRWLockShared(self.inner.get()) diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs index 0cb4c573ae3ef..b0410701ee101 100644 --- a/src/libstd/sys/windows/stack_overflow.rs +++ b/src/libstd/sys/windows/stack_overflow.rs @@ -14,7 +14,7 @@ use ptr; use mem; use libc; use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL}; -use sys_common::{stack, thread_info}; +use sys_common::stack; pub struct Handler { _data: *mut libc::c_void @@ -30,14 +30,6 @@ impl Drop for Handler { fn drop(&mut self) {} } -// get_task_info is called from an exception / signal handler. -// It returns the guard page of the current task or 0 if that -// guard page doesn't exist. None is returned if there's currently -// no local task. -unsafe fn get_task_guard_page() -> uint { - thread_info::stack_guard() -} - // This is initialized in init() and only read from after static mut PAGE_SIZE: uint = 0; diff --git a/src/libstd/sys/windows/sync.rs b/src/libstd/sys/windows/sync.rs index d60646b7db915..7614104c98bf3 100644 --- a/src/libstd/sys/windows/sync.rs +++ b/src/libstd/sys/windows/sync.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use libc::{BOOL, DWORD, c_void, LPVOID, c_ulong}; +use libc::{BOOL, DWORD, LPVOID, c_ulong}; use libc::types::os::arch::extra::BOOLEAN; pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE; diff --git a/src/libstd/sys/windows/tcp.rs b/src/libstd/sys/windows/tcp.rs index 64e440331c127..4804ca510cb0b 100644 --- a/src/libstd/sys/windows/tcp.rs +++ b/src/libstd/sys/windows/tcp.rs @@ -14,12 +14,11 @@ use libc; use mem; use ptr; use prelude::v1::*; -use super::{last_error, last_net_error, retry, sock_t}; +use super::{last_error, last_net_error, sock_t}; use sync::Arc; use sync::atomic::{AtomicBool, Ordering}; -use sys::fs::FileDesc; use sys::{self, c, set_nonblocking, wouldblock, timer}; -use sys_common::{self, timeout, eof, net}; +use sys_common::{timeout, eof, net}; pub use sys_common::net::TcpStream; @@ -202,10 +201,6 @@ impl TcpAcceptor { Err(eof()) } - pub fn socket_name(&mut self) -> IoResult { - net::sockname(self.socket(), libc::getsockname) - } - pub fn set_timeout(&mut self, timeout: Option) { self.deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index a94adcb3bc7b9..a38dc9b2d3407 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::prelude::*; - use boxed::Box; use cmp; use mem; diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs index 0f8ceed39a6cc..cc731738afe3e 100644 --- a/src/libstd/sys/windows/thread_local.rs +++ b/src/libstd/sys/windows/thread_local.rs @@ -233,6 +233,7 @@ unsafe extern "system" fn on_tls_callback(h: LPVOID, } } +#[allow(dead_code)] // actually called above unsafe fn run_dtors() { let mut any_run = true; for _ in 0..5 { diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs index 34f3c418c558d..d156dd801f974 100644 --- a/src/libstd/sys/windows/timer.rs +++ b/src/libstd/sys/windows/timer.rs @@ -28,8 +28,6 @@ use ptr; use old_io::IoResult; use sync::mpsc::{channel, Sender, Receiver, TryRecvError}; -use sys::c; -use sys::fs::FileDesc; use sys_common::helper_thread::Helper; helper_init! { static HELPER: Helper } diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs index 6ecabfa985304..f02c8e49f4188 100644 --- a/src/libstd/sys/windows/tty.rs +++ b/src/libstd/sys/windows/tty.rs @@ -38,7 +38,7 @@ use str::from_utf8; use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS}; use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT}; use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE}; -use super::c::{ERROR_ILLEGAL_CHARACTER, CONSOLE_SCREEN_BUFFER_INFO}; +use super::c::{CONSOLE_SCREEN_BUFFER_INFO}; use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode}; use super::c::{GetConsoleScreenBufferInfo}; @@ -155,9 +155,6 @@ impl TTY { (info.srWindow.Bottom + 1 - info.srWindow.Top) as int)), } } - - // Let us magically declare this as a TTY - pub fn isatty(&self) -> bool { true } } impl Drop for TTY { diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index 9f6bf352b0404..9aa454ae8d5c9 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -21,7 +21,7 @@ use ext::base; use ext::build::AstBuilder; use parse::token; -use std::os; +use std::env; pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { @@ -30,8 +30,8 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT Some(v) => v }; - let e = match os::getenv(&var[]) { - None => { + let e = match env::var_string(&var[]) { + Err(..) => { cx.expr_path(cx.path_all(sp, true, vec!(cx.ident_of("std"), @@ -48,7 +48,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT ast::MutImmutable)), Vec::new())) } - Some(s) => { + Ok(s) => { cx.expr_call_global(sp, vec!(cx.ident_of("std"), cx.ident_of("option"), @@ -101,12 +101,12 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) } } - let e = match os::getenv(var.get()) { - None => { + let e = match env::var_string(var.get()) { + Err(..) => { cx.span_err(sp, msg.get()); cx.expr_usize(sp, 0) } - Some(s) => cx.expr_str(sp, token::intern_and_get_ident(&s[])) + Ok(s) => cx.expr_str(sp, token::intern_and_get_ident(&s[])) }; MacExpr::new(e) } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 73424136cfbcb..54b37483f8cfd 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -28,11 +28,11 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(core)] +#![feature(env)] #![feature(hash)] #![feature(int_uint)] #![feature(io)] #![feature(libc)] -#![feature(os)] #![feature(path)] #![feature(quote, unsafe_destructor)] #![feature(rustc_private)] diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 27a46fb5a682d..219c9baf4c892 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -55,13 +55,14 @@ #![feature(core)] #![feature(int_uint)] #![feature(io)] -#![feature(os)] #![feature(path)] #![feature(rustc_private)] #![feature(slicing_syntax)] #![feature(staged_api)] #![feature(std_misc)] #![feature(unicode)] +#![feature(env)] +#![cfg_attr(windows, feature(libc))] #[macro_use] extern crate log; diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index d126717ce6817..17c1e8cdb8c6d 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -12,7 +12,7 @@ use std::collections::HashMap; use std::old_io::IoResult; -use std::os; +use std::env; use attr; use color; @@ -172,9 +172,9 @@ impl TerminfoTerminal { /// Returns `None` whenever the terminal cannot be created for some /// reason. pub fn new(out: T) -> Option+Send+'static>> { - let term = match os::getenv("TERM") { - Some(t) => t, - None => { + let term = match env::var_string("TERM") { + Ok(t) => t, + Err(..) => { debug!("TERM environment variable not defined"); return None; } @@ -182,7 +182,7 @@ impl TerminfoTerminal { let entry = open(&term[]); if entry.is_err() { - if os::getenv("MSYSCON").map_or(false, |s| { + if env::var_string("MSYSCON").ok().map_or(false, |s| { "mintty.exe" == s }) { // msys terminal diff --git a/src/libterm/terminfo/searcher.rs b/src/libterm/terminfo/searcher.rs index 1e84c0462d61a..74c986cd9e262 100644 --- a/src/libterm/terminfo/searcher.rs +++ b/src/libterm/terminfo/searcher.rs @@ -14,8 +14,7 @@ use std::old_io::File; use std::old_io::fs::PathExtensions; -use std::os::getenv; -use std::os; +use std::env; /// Return path to database entry for `term` pub fn get_dbpath_for_term(term: &str) -> Option> { @@ -23,21 +22,21 @@ pub fn get_dbpath_for_term(term: &str) -> Option> { return None; } - let homedir = os::homedir(); + let homedir = env::home_dir(); let mut dirs_to_search = Vec::new(); let first_char = term.char_at(0); // Find search directory - match getenv("TERMINFO") { - Some(dir) => dirs_to_search.push(Path::new(dir)), - None => { + match env::var_string("TERMINFO") { + Ok(dir) => dirs_to_search.push(Path::new(dir)), + Err(..) => { if homedir.is_some() { // ncurses compatibility; dirs_to_search.push(homedir.unwrap().join(".terminfo")) } - match getenv("TERMINFO_DIRS") { - Some(dirs) => for i in dirs.split(':') { + match env::var_string("TERMINFO_DIRS") { + Ok(dirs) => for i in dirs.split(':') { if i == "" { dirs_to_search.push(Path::new("/usr/share/terminfo")); } else { @@ -48,7 +47,7 @@ pub fn get_dbpath_for_term(term: &str) -> Option> { // According to /etc/terminfo/README, after looking at // ~/.terminfo, ncurses will search /etc/terminfo, then // /lib/terminfo, and eventually /usr/share/terminfo. - None => { + Err(..) => { dirs_to_search.push(Path::new("/etc/terminfo")); dirs_to_search.push(Path::new("/lib/terminfo")); dirs_to_search.push(Path::new("/usr/share/terminfo")); diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index f22c58c54a685..2295f122822db 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -38,10 +38,10 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(core)] +#![feature(env)] #![feature(hash)] #![feature(int_uint)] #![feature(io)] -#![feature(os)] #![feature(path)] #![feature(rustc_private)] #![feature(staged_api)] @@ -75,7 +75,7 @@ use std::old_io::{File, ChanReader, ChanWriter}; use std::old_io; use std::iter::repeat; use std::num::{Float, Int}; -use std::os; +use std::env; use std::sync::mpsc::{channel, Sender}; use std::thread::{self, Thread}; use std::thunk::{Thunk, Invoke}; @@ -388,7 +388,7 @@ pub fn parse_opts(args: &[String]) -> Option { let mut nocapture = matches.opt_present("nocapture"); if !nocapture { - nocapture = os::getenv("RUST_TEST_NOCAPTURE").is_some(); + nocapture = env::var("RUST_TEST_NOCAPTURE").is_some(); } let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) { @@ -817,15 +817,15 @@ fn run_tests(opts: &TestOpts, fn get_concurrency() -> uint { use std::rt; - match os::getenv("RUST_TEST_TASKS") { - Some(s) => { + match env::var_string("RUST_TEST_TASKS") { + Ok(s) => { let opt_n: Option = s.parse().ok(); match opt_n { Some(n) if n > 0 => n, _ => panic!("RUST_TEST_TASKS is `{}`, should be a positive integer.", s) } } - None => { + Err(..) => { rt::default_sched_threads() } } diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index 4a9c5a91dcf0b..ac32b5848015d 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -48,12 +48,12 @@ use std::simd::f64x2; use std::sync::Arc; use std::thread::Thread; -const ITER: int = 50; +const ITER: usize = 50; const LIMIT: f64 = 2.0; -const WORKERS: uint = 16; +const WORKERS: usize = 16; #[inline(always)] -fn mandelbrot(w: uint, mut out: W) -> old_io::IoResult<()> { +fn mandelbrot(w: usize, mut out: W) -> old_io::IoResult<()> { assert!(WORKERS % 2 == 0); // Ensure w and h are multiples of 8. @@ -198,7 +198,6 @@ fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec) { fn main() { let args = os::args(); - let args = args.as_slice(); let res = if args.len() < 2 { println!("Test mode: do not dump the image because it's not utf8, \ which interferes with the test runner."); diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs index ebcf46f7277d6..960d9ef0f2fb4 100644 --- a/src/test/compile-fail/liveness-unused.rs +++ b/src/test/compile-fail/liveness-unused.rs @@ -12,7 +12,6 @@ #![deny(unused_assignments)] #![allow(dead_code, non_camel_case_types)] #![feature(core)] -#![feature(os)] fn f1(x: isize) { //~^ ERROR unused variable: `x` @@ -98,7 +97,7 @@ fn f5c() { for (_, x) in [1is, 2, 3].iter().enumerate() { //~^ ERROR unused variable: `x` continue; - std::os::set_exit_status(*x); //~ WARNING unreachable statement + drop(*x as i32); //~ WARNING unreachable statement } } diff --git a/src/test/run-pass/env-home-dir.rs b/src/test/run-pass/env-home-dir.rs new file mode 100644 index 0000000000000..5623e98c92885 --- /dev/null +++ b/src/test/run-pass/env-home-dir.rs @@ -0,0 +1,45 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env::*; + +#[cfg(unix)] +fn main() { + let oldhome = var("HOME"); + + set_var("HOME", "/home/MountainView"); + assert!(home_dir() == Some(Path::new("/home/MountainView"))); + + remove_var("HOME"); + assert!(home_dir().is_some()); +} + +#[cfg(windows)] +fn main() { + let oldhome = var("HOME"); + let olduserprofile = var("USERPROFILE"); + + remove_var("HOME"); + remove_var("USERPROFILE"); + + assert!(home_dir().is_some()); + + set_var("HOME", "/home/MountainView"); + assert!(home_dir() == Some(Path::new("/home/MountainView"))); + + remove_var("HOME"); + + set_var("USERPROFILE", "/home/MountainView"); + assert!(home_dir() == Some(Path::new("/home/MountainView"))); + + set_var("HOME", "/home/MountainView"); + set_var("USERPROFILE", "/home/PaloAlto"); + assert!(home_dir() == Some(Path::new("/home/MountainView"))); +} diff --git a/src/test/run-pass/env-vars.rs b/src/test/run-pass/env-vars.rs new file mode 100644 index 0000000000000..892041b964889 --- /dev/null +++ b/src/test/run-pass/env-vars.rs @@ -0,0 +1,22 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env::*; + +fn main() { + for (k, v) in vars() { + let v2 = var(&k); + // MingW seems to set some funky environment variables like + // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned + // from vars() but not visible from var(). + assert!(v2.is_none() || v2.as_ref().map(|s| &**s) == Some(&*v), + "bad vars->var transition: {:?} {:?} {:?}", k, v, v2); + } +} From 0828efd72f0c1a1823426f327cddfbced535117a Mon Sep 17 00:00:00 2001 From: Potpourri Date: Sun, 1 Feb 2015 00:59:58 +0300 Subject: [PATCH 22/36] Reject syntax like `use foo::bar::;` and `use foo:: as bar;` and keywords in view path idents --- src/libsyntax/parse/parser.rs | 11 ++++++++--- .../use-as-where-use-ends-with-mod-sep.rs | 11 +++++++++++ src/test/compile-fail/use-ends-with-mod-sep.rs | 11 +++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/use-as-where-use-ends-with-mod-sep.rs create mode 100644 src/test/compile-fail/use-ends-with-mod-sep.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d99095eeba377..e2b58e6d87ede 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5912,9 +5912,9 @@ impl<'a> Parser<'a> { self.bump(); match self.token { - token::Ident(i, _) => { - self.bump(); - path.push(i); + token::Ident(..) => { + let ident = self.parse_ident(); + path.push(ident); } // foo::bar::{a,b,c} @@ -5954,6 +5954,11 @@ impl<'a> Parser<'a> { return P(spanned(lo, self.span.hi, ViewPathGlob(path))); } + // fall-through for case foo::bar::; + token::Semi => { + self.span_err(self.span, "expected identifier or `{` or `*`, found `;`"); + } + _ => break } } diff --git a/src/test/compile-fail/use-as-where-use-ends-with-mod-sep.rs b/src/test/compile-fail/use-as-where-use-ends-with-mod-sep.rs new file mode 100644 index 0000000000000..ef443fc125deb --- /dev/null +++ b/src/test/compile-fail/use-as-where-use-ends-with-mod-sep.rs @@ -0,0 +1,11 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::any:: as foo; //~ ERROR expected identifier or `{` or `*`, found `as` diff --git a/src/test/compile-fail/use-ends-with-mod-sep.rs b/src/test/compile-fail/use-ends-with-mod-sep.rs new file mode 100644 index 0000000000000..a375a5962a567 --- /dev/null +++ b/src/test/compile-fail/use-ends-with-mod-sep.rs @@ -0,0 +1,11 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::any::; //~ ERROR expected identifier or `{` or `*`, found `;` From 0e4448409ef61c703b98e4c5b2fd99447308942d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 1 Feb 2015 12:15:36 -0800 Subject: [PATCH 23/36] std: Remove extra type params on iter adaptors Now that associated types are fully implemented the iterator adaptors only need type parameters which are associated with actual storage. All other type parameters can either be derived from these (e.g. they are an associated type) or can be bare on the `impl` block itself. This is a breaking change due to the removal of type parameters on these iterator adaptors, but code can fairly easily migrate by just deleting the relevant type parameters for each adaptor. Other behavior should not be affected. Closes #21839 [breaking-change] --- src/libcollections/btree/map.rs | 4 +- src/libcollections/btree/set.rs | 20 +- src/libcollections/vec_map.rs | 8 +- src/libcore/iter.rs | 350 ++++++++---------------- src/libcore/str/mod.rs | 4 +- src/librustc_trans/trans/basic_block.rs | 7 +- src/libstd/collections/hash/map.rs | 18 +- src/libstd/collections/hash/set.rs | 4 +- src/libstd/path/posix.rs | 2 +- src/libstd/path/windows.rs | 4 +- src/libsyntax/parse/mod.rs | 4 +- src/libunicode/u_str.rs | 2 +- 12 files changed, 137 insertions(+), 290 deletions(-) diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index ce5e8f07be1b2..b007f27598045 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -116,13 +116,13 @@ pub struct IntoIter { /// An iterator over a BTreeMap's keys. #[stable(feature = "rust1", since = "1.0.0")] pub struct Keys<'a, K: 'a, V: 'a> { - inner: Map<(&'a K, &'a V), &'a K, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K> + inner: Map, fn((&'a K, &'a V)) -> &'a K> } /// An iterator over a BTreeMap's values. #[stable(feature = "rust1", since = "1.0.0")] pub struct Values<'a, K: 'a, V: 'a> { - inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V> + inner: Map, fn((&'a K, &'a V)) -> &'a V> } /// An iterator over a sub-range of BTreeMap's entries. diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 72d5bf6d79932..1445db12a90d7 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -45,40 +45,40 @@ pub struct Iter<'a, T: 'a> { /// An owning iterator over a BTreeSet's items. #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { - iter: Map<(T, ()), T, ::btree_map::IntoIter, fn((T, ())) -> T> + iter: Map<::btree_map::IntoIter, fn((T, ())) -> T> } /// An iterator over a sub-range of BTreeSet's items. pub struct Range<'a, T: 'a> { - iter: Map<(&'a T, &'a ()), &'a T, ::btree_map::Range<'a, T, ()>, fn((&'a T, &'a ())) -> &'a T> + iter: Map<::btree_map::Range<'a, T, ()>, fn((&'a T, &'a ())) -> &'a T> } /// A lazy iterator producing elements in the set difference (in-order). #[stable(feature = "rust1", since = "1.0.0")] pub struct Difference<'a, T:'a> { - a: Peekable<&'a T, Iter<'a, T>>, - b: Peekable<&'a T, Iter<'a, T>>, + a: Peekable>, + b: Peekable>, } /// A lazy iterator producing elements in the set symmetric difference (in-order). #[stable(feature = "rust1", since = "1.0.0")] pub struct SymmetricDifference<'a, T:'a> { - a: Peekable<&'a T, Iter<'a, T>>, - b: Peekable<&'a T, Iter<'a, T>>, + a: Peekable>, + b: Peekable>, } /// A lazy iterator producing elements in the set intersection (in-order). #[stable(feature = "rust1", since = "1.0.0")] pub struct Intersection<'a, T:'a> { - a: Peekable<&'a T, Iter<'a, T>>, - b: Peekable<&'a T, Iter<'a, T>>, + a: Peekable>, + b: Peekable>, } /// A lazy iterator producing elements in the set union (in-order). #[stable(feature = "rust1", since = "1.0.0")] pub struct Union<'a, T:'a> { - a: Peekable<&'a T, Iter<'a, T>>, - b: Peekable<&'a T, Iter<'a, T>>, + a: Peekable>, + b: Peekable>, } impl BTreeSet { diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index f2a9bb4392ccc..b677b3613004f 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -687,7 +687,7 @@ double_ended_iterator! { impl IterMut -> (uint, &'a mut V), as_mut } /// An iterator over the keys of a map. #[stable(feature = "rust1", since = "1.0.0")] pub struct Keys<'a, V: 'a> { - iter: Map<(uint, &'a V), uint, Iter<'a, V>, fn((uint, &'a V)) -> uint> + iter: Map, fn((uint, &'a V)) -> uint> } // FIXME(#19839) Remove in favor of `#[derive(Clone)]` @@ -702,7 +702,7 @@ impl<'a, V> Clone for Keys<'a, V> { /// An iterator over the values of a map. #[stable(feature = "rust1", since = "1.0.0")] pub struct Values<'a, V: 'a> { - iter: Map<(uint, &'a V), &'a V, Iter<'a, V>, fn((uint, &'a V)) -> &'a V> + iter: Map, fn((uint, &'a V)) -> &'a V> } // FIXME(#19839) Remove in favor of `#[derive(Clone)]` @@ -718,8 +718,6 @@ impl<'a, V> Clone for Values<'a, V> { #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { iter: FilterMap< - (uint, Option), - (uint, V), Enumerate>>, fn((uint, Option)) -> Option<(uint, V)>> } @@ -727,8 +725,6 @@ pub struct IntoIter { #[unstable(feature = "collections")] pub struct Drain<'a, V> { iter: FilterMap< - (uint, Option), - (uint, V), Enumerate>>, fn((uint, Option)) -> Option<(uint, V)>> } diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 751b5959d8bd7..84db07266b847 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -239,9 +239,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn zip(self, other: U) -> Zip where - U: Iterator, - { + fn zip(self, other: U) -> Zip { Zip{a: self, b: other} } @@ -259,7 +257,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn map(self, f: F) -> Map where + fn map(self, f: F) -> Map where F: FnMut(Self::Item) -> B, { Map{iter: self, f: f} @@ -279,7 +277,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn filter

(self, predicate: P) -> Filter where + fn filter

(self, predicate: P) -> Filter where P: FnMut(&Self::Item) -> bool, { Filter{iter: self, predicate: predicate} @@ -299,7 +297,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn filter_map(self, f: F) -> FilterMap where + fn filter_map(self, f: F) -> FilterMap where F: FnMut(Self::Item) -> Option, { FilterMap { iter: self, f: f } @@ -342,7 +340,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn peekable(self) -> Peekable { + fn peekable(self) -> Peekable { Peekable{iter: self, peeked: None} } @@ -362,7 +360,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn skip_while

(self, predicate: P) -> SkipWhile where + fn skip_while

(self, predicate: P) -> SkipWhile where P: FnMut(&Self::Item) -> bool, { SkipWhile{iter: self, flag: false, predicate: predicate} @@ -383,7 +381,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn take_while

(self, predicate: P) -> TakeWhile where + fn take_while

(self, predicate: P) -> TakeWhile where P: FnMut(&Self::Item) -> bool, { TakeWhile{iter: self, flag: false, predicate: predicate} @@ -448,12 +446,8 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn scan( - self, - initial_state: St, - f: F, - ) -> Scan where - F: FnMut(&mut St, Self::Item) -> Option, + fn scan(self, initial_state: St, f: F) -> Scan + where F: FnMut(&mut St, Self::Item) -> Option, { Scan{iter: self, f: f, state: initial_state} } @@ -474,9 +468,8 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn flat_map(self, f: F) -> FlatMap where - U: Iterator, - F: FnMut(Self::Item) -> U, + fn flat_map(self, f: F) -> FlatMap + where U: Iterator, F: FnMut(Self::Item) -> U, { FlatMap{iter: self, f: f, frontiter: None, backiter: None } } @@ -534,7 +527,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn inspect(self, f: F) -> Inspect where + fn inspect(self, f: F) -> Inspect where F: FnMut(&Self::Item), { Inspect{iter: self, f: f} @@ -1077,16 +1070,14 @@ pub trait ExactSizeIterator: Iterator { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Enumerate where I: ExactSizeIterator {} #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Inspect where - I: ExactSizeIterator, - F: FnMut(&A), +impl ExactSizeIterator for Inspect where + F: FnMut(&I::Item), {} #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Rev where I: ExactSizeIterator + DoubleEndedIterator {} #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Map where - I: ExactSizeIterator, - F: FnMut(A) -> B, +impl ExactSizeIterator for Map where + F: FnMut(I::Item) -> B, {} #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Zip where A: ExactSizeIterator, B: ExactSizeIterator {} @@ -1561,28 +1552,15 @@ impl RandomAccessIterator for Zip where /// An iterator that maps the values of `iter` with `f` #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct Map, F: FnMut(A) -> B> { +#[derive(Clone)] +pub struct Map { iter: I, f: F, } -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Map where - I: Clone + Iterator, - F: Clone + FnMut(A) -> B, -{ - fn clone(&self) -> Map { - Map { - iter: self.iter.clone(), - f: self.f.clone(), - } - } -} - -impl Map where I: Iterator, F: FnMut(A) -> B { +impl Map where F: FnMut(I::Item) -> B { #[inline] - fn do_map(&mut self, elt: Option) -> Option { + fn do_map(&mut self, elt: Option) -> Option { match elt { Some(a) => Some((self.f)(a)), _ => None @@ -1591,7 +1569,7 @@ impl Map where I: Iterator, F: FnMut(A) -> B { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Map where I: Iterator, F: FnMut(A) -> B { +impl Iterator for Map where F: FnMut(I::Item) -> B { type Item = B; #[inline] @@ -1607,9 +1585,8 @@ impl Iterator for Map where I: Iterator, F: FnMu } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Map where - I: DoubleEndedIterator, - F: FnMut(A) -> B, +impl DoubleEndedIterator for Map where + F: FnMut(I::Item) -> B, { #[inline] fn next_back(&mut self) -> Option { @@ -1619,9 +1596,8 @@ impl DoubleEndedIterator for Map where } #[unstable(feature = "core", reason = "trait is experimental")] -impl RandomAccessIterator for Map where - I: RandomAccessIterator, - F: FnMut(A) -> B, +impl RandomAccessIterator for Map where + F: FnMut(I::Item) -> B, { #[inline] fn indexable(&self) -> usize { @@ -1638,31 +1614,18 @@ impl RandomAccessIterator for Map where /// An iterator that filters the elements of `iter` with `predicate` #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct Filter where I: Iterator, P: FnMut(&A) -> bool { +#[derive(Clone)] +pub struct Filter { iter: I, predicate: P, } -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Filter where - I: Clone + Iterator, - P: Clone + FnMut(&A) -> bool, -{ - fn clone(&self) -> Filter { - Filter { - iter: self.iter.clone(), - predicate: self.predicate.clone(), - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Filter where I: Iterator, P: FnMut(&A) -> bool { - type Item = A; +impl Iterator for Filter where P: FnMut(&I::Item) -> bool { + type Item = I::Item; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { for x in self.iter.by_ref() { if (self.predicate)(&x) { return Some(x); @@ -1681,12 +1644,11 @@ impl Iterator for Filter where I: Iterator, P: FnMut(& } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Filter where - I: DoubleEndedIterator, - P: FnMut(&A) -> bool, +impl DoubleEndedIterator for Filter + where P: FnMut(&I::Item) -> bool, { #[inline] - fn next_back(&mut self) -> Option { + fn next_back(&mut self) -> Option { for x in self.iter.by_ref().rev() { if (self.predicate)(&x) { return Some(x); @@ -1699,29 +1661,15 @@ impl DoubleEndedIterator for Filter where /// An iterator that uses `f` to both filter and map elements from `iter` #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct FilterMap where I: Iterator, F: FnMut(A) -> Option { +#[derive(Clone)] +pub struct FilterMap { iter: I, f: F, } -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for FilterMap where - I: Clone + Iterator, - F: Clone + FnMut(A) -> Option, -{ - fn clone(&self) -> FilterMap { - FilterMap { - iter: self.iter.clone(), - f: self.f.clone(), - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for FilterMap where - I: Iterator, - F: FnMut(A) -> Option, +impl Iterator for FilterMap + where F: FnMut(I::Item) -> Option, { type Item = B; @@ -1744,9 +1692,8 @@ impl Iterator for FilterMap where } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for FilterMap where - I: DoubleEndedIterator, - F: FnMut(A) -> Option, +impl DoubleEndedIterator for FilterMap + where F: FnMut(I::Item) -> Option, { #[inline] fn next_back(&mut self) -> Option { @@ -1824,20 +1771,28 @@ impl RandomAccessIterator for Enumerate where I: RandomAccessIterator { } /// An iterator with a `peek()` that returns an optional reference to the next element. -#[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct Peekable where I: Iterator { +pub struct Peekable { iter: I, - peeked: Option, + peeked: Option, +} + +impl Clone for Peekable where I::Item: Clone { + fn clone(&self) -> Peekable { + Peekable { + iter: self.iter.clone(), + peeked: self.peeked.clone(), + } + } } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Peekable where I: Iterator { - type Item = T; +impl Iterator for Peekable { + type Item = I::Item; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { if self.peeked.is_some() { self.peeked.take() } else { self.iter.next() } } @@ -1859,14 +1814,14 @@ impl Iterator for Peekable where I: Iterator { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Peekable where I: ExactSizeIterator {} +impl ExactSizeIterator for Peekable {} #[stable(feature = "rust1", since = "1.0.0")] -impl Peekable where I: Iterator { - /// Return a reference to the next element of the iterator with out advancing it, - /// or None if the iterator is exhausted. +impl Peekable { + /// Return a reference to the next element of the iterator with out + /// advancing it, or None if the iterator is exhausted. #[inline] - pub fn peek(&mut self) -> Option<&T> { + pub fn peek(&mut self) -> Option<&I::Item> { if self.peeked.is_none() { self.peeked = self.iter.next(); } @@ -1886,33 +1841,21 @@ impl Peekable where I: Iterator { /// An iterator that rejects elements while `predicate` is true #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct SkipWhile where I: Iterator, P: FnMut(&A) -> bool { +#[derive(Clone)] +pub struct SkipWhile { iter: I, flag: bool, predicate: P, } -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for SkipWhile where - I: Clone + Iterator, - P: Clone + FnMut(&A) -> bool, +impl Iterator for SkipWhile + where P: FnMut(&I::Item) -> bool { - fn clone(&self) -> SkipWhile { - SkipWhile { - iter: self.iter.clone(), - flag: self.flag, - predicate: self.predicate.clone(), - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for SkipWhile where I: Iterator, P: FnMut(&A) -> bool { - type Item = A; + type Item = I::Item; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { for x in self.iter.by_ref() { if self.flag || !(self.predicate)(&x) { self.flag = true; @@ -1932,33 +1875,21 @@ impl Iterator for SkipWhile where I: Iterator, P: FnMu /// An iterator that only accepts elements while `predicate` is true #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct TakeWhile where I: Iterator, P: FnMut(&A) -> bool { +#[derive(Clone)] +pub struct TakeWhile { iter: I, flag: bool, predicate: P, } -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for TakeWhile where - I: Clone + Iterator, - P: Clone + FnMut(&A) -> bool, +impl Iterator for TakeWhile + where P: FnMut(&I::Item) -> bool { - fn clone(&self) -> TakeWhile { - TakeWhile { - iter: self.iter.clone(), - flag: self.flag, - predicate: self.predicate.clone(), - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for TakeWhile where I: Iterator, P: FnMut(&A) -> bool { - type Item = A; + type Item = I::Item; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { if self.flag { None } else { @@ -2118,7 +2049,8 @@ impl ExactSizeIterator for Take where I: ExactSizeIterator {} /// An iterator to maintain state while iterating another iterator #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct Scan where I: Iterator, F: FnMut(&mut St, A) -> Option { +#[derive(Clone)] +pub struct Scan { iter: I, f: F, @@ -2126,26 +2058,9 @@ pub struct Scan where I: Iterator, F: FnMut(&mut St, A) -> Optio pub state: St, } -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Scan where - I: Clone + Iterator, - St: Clone, - F: Clone + FnMut(&mut St, A) -> Option, -{ - fn clone(&self) -> Scan { - Scan { - iter: self.iter.clone(), - f: self.f.clone(), - state: self.state.clone(), - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Scan where - I: Iterator, - F: FnMut(&mut St, A) -> Option, +impl Iterator for Scan where + F: FnMut(&mut St, I::Item) -> Option, { type Item = B; @@ -2166,44 +2081,22 @@ impl Iterator for Scan where /// #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct FlatMap where - I: Iterator, - U: Iterator, - F: FnMut(A) -> U, -{ +#[derive(Clone)] +pub struct FlatMap { iter: I, f: F, frontiter: Option, backiter: Option, } -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for FlatMap where - I: Clone + Iterator, - U: Clone + Iterator, - F: Clone + FnMut(A) -> U, -{ - fn clone(&self) -> FlatMap { - FlatMap { - iter: self.iter.clone(), - f: self.f.clone(), - frontiter: self.frontiter.clone(), - backiter: self.backiter.clone(), - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for FlatMap where - I: Iterator, - U: Iterator, - F: FnMut(A) -> U, +impl Iterator for FlatMap + where F: FnMut(I::Item) -> U, { - type Item = B; + type Item = U::Item; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { loop { for inner in self.frontiter.iter_mut() { for x in inner.by_ref() { @@ -2230,13 +2123,12 @@ impl Iterator for FlatMap where } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for FlatMap where - I: DoubleEndedIterator, - U: DoubleEndedIterator, - F: FnMut(A) -> U, +impl DoubleEndedIterator + for FlatMap + where F: FnMut(I::Item) -> U { #[inline] - fn next_back(&mut self) -> Option { + fn next_back(&mut self) -> Option { loop { for inner in self.backiter.iter_mut() { match inner.next_back() { @@ -2340,28 +2232,15 @@ impl Fuse { /// element before yielding it. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct Inspect where I: Iterator, F: FnMut(&A) { +#[derive(Clone)] +pub struct Inspect { iter: I, f: F, } -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Inspect where - I: Clone + Iterator, - F: Clone + FnMut(&A), -{ - fn clone(&self) -> Inspect { - Inspect { - iter: self.iter.clone(), - f: self.f.clone(), - } - } -} - -impl Inspect where I: Iterator, F: FnMut(&A) { +impl Inspect where F: FnMut(&I::Item) { #[inline] - fn do_inspect(&mut self, elt: Option) -> Option { + fn do_inspect(&mut self, elt: Option) -> Option { match elt { Some(ref a) => (self.f)(a), None => () @@ -2372,11 +2251,11 @@ impl Inspect where I: Iterator, F: FnMut(&A) { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Inspect where I: Iterator, F: FnMut(&A) { - type Item = A; +impl Iterator for Inspect where F: FnMut(&I::Item) { + type Item = I::Item; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { let next = self.iter.next(); self.do_inspect(next) } @@ -2388,21 +2267,19 @@ impl Iterator for Inspect where I: Iterator, F: FnMut( } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Inspect where - I: DoubleEndedIterator, - F: FnMut(&A), +impl DoubleEndedIterator for Inspect + where F: FnMut(&I::Item), { #[inline] - fn next_back(&mut self) -> Option { + fn next_back(&mut self) -> Option { let next = self.iter.next_back(); self.do_inspect(next) } } #[unstable(feature = "core", reason = "trait is experimental")] -impl RandomAccessIterator for Inspect where - I: RandomAccessIterator, - F: FnMut(&A), +impl RandomAccessIterator for Inspect + where F: FnMut(&I::Item), { #[inline] fn indexable(&self) -> usize { @@ -2410,7 +2287,7 @@ impl RandomAccessIterator for Inspect where } #[inline] - fn idx(&mut self, index: usize) -> Option { + fn idx(&mut self, index: usize) -> Option { let element = self.iter.idx(index); self.do_inspect(element) } @@ -2426,9 +2303,11 @@ impl RandomAccessIterator for Inspect where /// use std::iter::Unfold; /// use std::num::Int; // For `.checked_add()` /// -/// // This iterator will yield up to the last Fibonacci number before the max value of `u32`. -/// // You can simply change `u32` to `u64` in this line if you want higher values than that. -/// let mut fibonacci = Unfold::new((Some(0u32), Some(1u32)), |&mut (ref mut x2, ref mut x1)| { +/// // This iterator will yield up to the last Fibonacci number before the max +/// // value of `u32`. You can simply change `u32` to `u64` in this line if +/// // you want higher values than that. +/// let mut fibonacci = Unfold::new((Some(0u32), Some(1u32)), +/// |&mut (ref mut x2, ref mut x1)| { /// // Attempt to get the next Fibonacci number /// // `x1` will be `None` if previously overflowed. /// let next = match (*x2, *x1) { @@ -2449,32 +2328,19 @@ impl RandomAccessIterator for Inspect where /// } /// ``` #[unstable(feature = "core")] -pub struct Unfold where F: FnMut(&mut St) -> Option { +#[derive(Clone)] +pub struct Unfold { f: F, /// Internal state that will be passed to the closure on the next iteration pub state: St, } -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Unfold where - F: Clone + FnMut(&mut St) -> Option, - St: Clone, -{ - fn clone(&self) -> Unfold { - Unfold { - f: self.f.clone(), - state: self.state.clone(), - } - } -} - #[unstable(feature = "core")] -impl Unfold where F: FnMut(&mut St) -> Option { +impl Unfold where F: FnMut(&mut St) -> Option { /// Creates a new iterator with the specified closure as the "iterator /// function" and an initial state to eventually pass to the closure #[inline] - pub fn new(initial_state: St, f: F) -> Unfold { + pub fn new(initial_state: St, f: F) -> Unfold { Unfold { f: f, state: initial_state @@ -2483,7 +2349,7 @@ impl Unfold where F: FnMut(&mut St) -> Option { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Unfold where F: FnMut(&mut St) -> Option { +impl Iterator for Unfold where F: FnMut(&mut St) -> Option { type Item = A; #[inline] @@ -2921,7 +2787,7 @@ type IterateState = (F, Option, bool); /// An iterator that repeatedly applies a given function, starting /// from a given seed value. #[unstable(feature = "core")] -pub type Iterate = Unfold, fn(&mut IterateState) -> Option>; +pub type Iterate = Unfold, fn(&mut IterateState) -> Option>; /// Create a new iterator that produces an infinite sequence of /// repeated applications of the given function `f`. diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index cb7af3b3d35a1..85b4a2026447f 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -478,7 +478,7 @@ impl<'a> DoubleEndedIterator for CharIndices<'a> { /// Created with `StrExt::bytes` #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] -pub struct Bytes<'a>(Map<&'a u8, u8, slice::Iter<'a, u8>, BytesDeref>); +pub struct Bytes<'a>(Map, BytesDeref>); delegate_iter!{exact u8 : Bytes<'a>} /// A temporary fn new type that ensures that the `Bytes` iterator @@ -526,7 +526,7 @@ pub struct Lines<'a> { /// An iterator over the lines of a string, separated by either `\n` or (`\r\n`). #[stable(feature = "rust1", since = "1.0.0")] pub struct LinesAny<'a> { - inner: Map<&'a str, &'a str, Lines<'a>, fn(&str) -> &str>, + inner: Map, fn(&str) -> &str>, } impl<'a, Sep> CharSplits<'a, Sep> { diff --git a/src/librustc_trans/trans/basic_block.rs b/src/librustc_trans/trans/basic_block.rs index d3ff432b5e418..f11c3154274e7 100644 --- a/src/librustc_trans/trans/basic_block.rs +++ b/src/librustc_trans/trans/basic_block.rs @@ -16,12 +16,7 @@ use std::iter::{Filter, Map}; #[derive(Copy)] pub struct BasicBlock(pub BasicBlockRef); -pub type Preds = Map< - Value, - BasicBlock, - Filter bool>, - fn(Value) -> BasicBlock, ->; +pub type Preds = Map bool>, fn(Value) -> BasicBlock>; /// Wrapper for LLVM BasicBlockRef impl BasicBlock { diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 3e2c7627dbe55..852d5a86fc0e1 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1300,18 +1300,13 @@ pub struct IterMut<'a, K: 'a, V: 'a> { /// HashMap move iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { - inner: iter::Map< - (SafeHash, K, V), - (K, V), - table::IntoIter, - fn((SafeHash, K, V)) -> (K, V), - > + inner: iter::Map, fn((SafeHash, K, V)) -> (K, V)> } /// HashMap keys iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct Keys<'a, K: 'a, V: 'a> { - inner: Map<(&'a K, &'a V), &'a K, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K> + inner: Map, fn((&'a K, &'a V)) -> &'a K> } // FIXME(#19839) Remove in favor of `#[derive(Clone)]` @@ -1326,7 +1321,7 @@ impl<'a, K, V> Clone for Keys<'a, K, V> { /// HashMap values iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct Values<'a, K: 'a, V: 'a> { - inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V> + inner: Map, fn((&'a K, &'a V)) -> &'a V> } // FIXME(#19839) Remove in favor of `#[derive(Clone)]` @@ -1342,12 +1337,7 @@ impl<'a, K, V> Clone for Values<'a, K, V> { #[unstable(feature = "std_misc", reason = "matches collection reform specification, waiting for dust to settle")] pub struct Drain<'a, K: 'a, V: 'a> { - inner: iter::Map< - (SafeHash, K, V), - (K, V), - table::Drain<'a, K, V>, - fn((SafeHash, K, V)) -> (K, V), - > + inner: iter::Map, fn((SafeHash, K, V)) -> (K, V)> } /// A view into a single occupied location in a HashMap. diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index c6dcb0d230ff7..e6b06e5ef1f87 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -794,13 +794,13 @@ pub struct Iter<'a, K: 'a> { /// HashSet move iterator #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { - iter: Map<(K, ()), K, map::IntoIter, fn((K, ())) -> K> + iter: Map, fn((K, ())) -> K> } /// HashSet drain iterator #[stable(feature = "rust1", since = "1.0.0")] pub struct Drain<'a, K: 'a> { - iter: Map<(K, ()), K, map::Drain<'a, K, ()>, fn((K, ())) -> K>, + iter: Map, fn((K, ())) -> K>, } /// Intersection iterator diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 6a0c8a9301070..69f815e3f8b77 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -31,7 +31,7 @@ pub type Components<'a> = Split<'a, u8, fn(&u8) -> bool>; /// Iterator that yields successive components of a Path as Option<&str> pub type StrComponents<'a> = - Map<&'a [u8], Option<&'a str>, Components<'a>, fn(&[u8]) -> Option<&str>>; + Map, fn(&[u8]) -> Option<&str>>; /// Represents a POSIX file path #[derive(Clone)] diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index b524b89ef9fb2..750af47ff8c10 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -40,11 +40,11 @@ use super::{contains_nul, BytesContainer, GenericPath, GenericPathUnsafe}; /// Each component is yielded as Option<&str> for compatibility with PosixPath, but /// every component in WindowsPath is guaranteed to be Some. pub type StrComponents<'a> = - Map<&'a str, Option<&'a str>, SplitTerminator<'a, char>, fn(&'a str) -> Option<&'a str>>; + Map, fn(&'a str) -> Option<&'a str>>; /// Iterator that yields successive components of a Path as &[u8] pub type Components<'a> = - Map, &'a [u8], StrComponents<'a>, fn(Option<&str>) -> &[u8]>; + Map, fn(Option<&str>) -> &[u8]>; /// Represents a Windows path // Notes for Windows path impl: diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 8ac5b6e52747a..3e8eab39d8877 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -436,7 +436,7 @@ pub fn str_lit(lit: &str) -> String { let error = |&: i| format!("lexer should have rejected {} at {}", lit, i); /// Eat everything up to a non-whitespace - fn eat<'a>(it: &mut iter::Peekable<(usize, char), str::CharIndices<'a>>) { + fn eat<'a>(it: &mut iter::Peekable>) { loop { match it.peek().map(|x| x.1) { Some(' ') | Some('\n') | Some('\r') | Some('\t') => { @@ -605,7 +605,7 @@ pub fn binary_lit(lit: &str) -> Rc> { let error = |&: i| format!("lexer should have rejected {} at {}", lit, i); /// Eat everything up to a non-whitespace - fn eat<'a, I: Iterator>(it: &mut iter::Peekable<(usize, u8), I>) { + fn eat<'a, I: Iterator>(it: &mut iter::Peekable) { loop { match it.peek().map(|x| x.1) { Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') => { diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index 9a757c0c980dd..0e3aacbc09a9a 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -32,7 +32,7 @@ use tables::grapheme::GraphemeCat; /// An iterator over the words of a string, separated by a sequence of whitespace #[stable(feature = "rust1", since = "1.0.0")] pub struct Words<'a> { - inner: Filter<&'a str, Split<'a, fn(char) -> bool>, fn(&&str) -> bool>, + inner: Filter bool>, fn(&&str) -> bool>, } /// Methods for Unicode string slices From 8d57f8c0a04e1afa7c13b75137c658b6048f7d8b Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 2 Feb 2015 03:45:52 +0530 Subject: [PATCH 24/36] Fix stale doc link (guide -> book) --- src/libtest/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index f22c58c54a685..1bb841120c7ce 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -16,7 +16,7 @@ //! benchmarks themselves) should be done via the `#[test]` and //! `#[bench]` attributes. //! -//! See the [Testing Guide](../guide-testing.html) for more details. +//! See the [Testing Chapter](../book/testing.html) of the book for more details. // Currently, not much of this is meant for users. It is intended to // support the simplest interface possible for representing and From 0187ea61a66be23741830c8bc3c2262556e1dd56 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 1 Feb 2015 14:25:55 -0800 Subject: [PATCH 25/36] rustc: Change an unconditional `warn` to a `note` There [have been reports][issue] of an unconditional warning causing tooling to go awry. This isn't actually a warning per se, it's more of a note anyway! [issue]: https://github.com/rust-lang/cargo/issues/1260 Closes rust-lang/cargo#1260 --- src/librustc_trans/back/link.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 93a2b6eaa4f02..590632d7140e0 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -740,7 +740,7 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) { let _ = ab.build(); if !all_native_libs.is_empty() { - sess.warn("link against the following native artifacts when linking against \ + sess.note("link against the following native artifacts when linking against \ this static library"); sess.note("the order and any duplication can be significant on some platforms, \ and so may need to be preserved"); From f371af48158b667eba717f2d1829a271aaecae39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Szczepa=C5=84ski?= Date: Mon, 2 Feb 2015 00:46:34 +0000 Subject: [PATCH 26/36] Closes issue #21850 --- src/doc/trpl/strings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/strings.md b/src/doc/trpl/strings.md index e05c6e172a49e..8ebebc98baf6b 100644 --- a/src/doc/trpl/strings.md +++ b/src/doc/trpl/strings.md @@ -36,7 +36,7 @@ s.push_str(", world."); println!("{}", s); ``` -`String`s will coerece into `&str` with an `&`: +`String`s will coerce into `&str` with an `&`: ``` fn takes_slice(slice: &str) { From 6342af8c51acc6345c8c566e6cb326381bdbd01f Mon Sep 17 00:00:00 2001 From: Jason Fager Date: Sat, 31 Jan 2015 09:45:00 -0500 Subject: [PATCH 27/36] Add test, closes #20454 --- src/test/run-pass/issue-20454.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/run-pass/issue-20454.rs diff --git a/src/test/run-pass/issue-20454.rs b/src/test/run-pass/issue-20454.rs new file mode 100644 index 0000000000000..fbc4cca800875 --- /dev/null +++ b/src/test/run-pass/issue-20454.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::thread; + +fn main() { + thread::Thread::spawn(move || { // no need for -> () + loop { + println!("hello"); + } + }); +} From 597b4fa984d866154f5e23244a4a48c787af43fd Mon Sep 17 00:00:00 2001 From: P1start Date: Fri, 16 Jan 2015 16:04:28 +1300 Subject: [PATCH 28/36] =?UTF-8?q?Tweak=20some=20=E2=80=98expected=E2=80=A6?= =?UTF-8?q?=E2=80=99=20error=20messages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #21153. --- src/libsyntax/parse/attr.rs | 9 +- src/libsyntax/parse/parser.rs | 117 +++++++++--------- src/libsyntax/parse/token.rs | 2 +- src/test/compile-fail/better-expected.rs | 2 +- src/test/compile-fail/empty-impl-semicolon.rs | 2 +- src/test/compile-fail/extern-no-fn.rs | 3 +- src/test/compile-fail/issue-20711-2.rs | 2 +- src/test/compile-fail/issue-20711.rs | 2 +- src/test/compile-fail/issue-21153.rs | 13 ++ src/test/compile-fail/multitrait.rs | 3 +- src/test/compile-fail/pat-range-bad-dots.rs | 2 +- .../removed-syntax-closure-lifetime.rs | 2 +- .../removed-syntax-enum-newtype.rs | 2 +- .../removed-syntax-extern-const.rs | 3 +- .../compile-fail/removed-syntax-fixed-vec.rs | 2 +- .../compile-fail/removed-syntax-mut-vec-ty.rs | 2 +- .../removed-syntax-ptr-lifetime.rs | 2 +- .../compile-fail/removed-syntax-static-fn.rs | 3 +- .../removed-syntax-uniq-mut-ty.rs | 2 +- .../struct-literal-in-match-discriminant.rs | 2 +- 20 files changed, 100 insertions(+), 77 deletions(-) create mode 100644 src/test/compile-fail/issue-21153.rs diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 54ec9c7b146d7..06e8728d23672 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -13,7 +13,7 @@ use ast; use codemap::{spanned, Spanned, mk_sp, Span}; use parse::common::*; //resolve bug? use parse::token; -use parse::parser::Parser; +use parse::parser::{Parser, TokenType}; use ptr::P; /// A parser that can parse attributes. @@ -69,7 +69,9 @@ impl<'a> ParserAttr for Parser<'a> { let lo = self.span.lo; self.bump(); - let style = if self.eat(&token::Not) { + if permit_inner { self.expected_tokens.push(TokenType::Token(token::Not)); } + let style = if self.token == token::Not { + self.bump(); if !permit_inner { let span = self.span; self.span_err(span, @@ -96,7 +98,8 @@ impl<'a> ParserAttr for Parser<'a> { } }; - if permit_inner && self.eat(&token::Semi) { + if permit_inner && self.token == token::Semi { + self.bump(); self.span_warn(span, "this inner attribute syntax is deprecated. \ The new syntax is `#![foo]`, with a bang and no semicolon"); style = ast::AttrInner; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d99095eeba377..66f5cdfd1e357 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -290,6 +290,7 @@ pub struct Parser<'a> { #[derive(PartialEq, Eq, Clone)] pub enum TokenType { Token(token::Token), + Keyword(keywords::Keyword), Operator, } @@ -298,6 +299,7 @@ impl TokenType { match *self { TokenType::Token(ref t) => format!("`{}`", Parser::token_to_string(t)), TokenType::Operator => "an operator".to_string(), + TokenType::Keyword(kw) => format!("`{}`", token::get_name(kw.to_name())), } } } @@ -365,9 +367,9 @@ impl<'a> Parser<'a> { token_str)[]); } - pub fn unexpected(&self) -> ! { - let this_token = self.this_token_to_string(); - self.fatal(&format!("unexpected token: `{}`", this_token)[]); + pub fn unexpected(&mut self) -> ! { + self.expect_one_of(&[], &[]); + unreachable!() } /// Expect and consume the token t. Signal an error if @@ -425,10 +427,13 @@ impl<'a> Parser<'a> { let expect = tokens_to_string(&expected[]); let actual = self.this_token_to_string(); self.fatal( - &(if expected.len() != 1 { + &(if expected.len() > 1 { (format!("expected one of {}, found `{}`", expect, actual)) + } else if expected.len() == 0 { + (format!("unexpected token: `{}`", + actual)) } else { (format!("expected {}, found `{}`", expect, @@ -515,7 +520,7 @@ impl<'a> Parser<'a> { pub fn parse_path_list_item(&mut self) -> ast::PathListItem { let lo = self.span.lo; - let node = if self.eat_keyword(keywords::Mod) { + let node = if self.eat_keyword_noexpect(keywords::Mod) { let span = self.last_span; self.span_warn(span, "deprecated syntax; use the `self` keyword now"); ast::PathListMod { id: ast::DUMMY_NODE_ID } @@ -547,9 +552,23 @@ impl<'a> Parser<'a> { is_present } + pub fn check_keyword(&mut self, kw: keywords::Keyword) -> bool { + self.expected_tokens.push(TokenType::Keyword(kw)); + self.token.is_keyword(kw) + } + /// If the next token is the given keyword, eat it and return /// true. Otherwise, return false. pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> bool { + if self.check_keyword(kw) { + self.bump(); + true + } else { + false + } + } + + pub fn eat_keyword_noexpect(&mut self, kw: keywords::Keyword) -> bool { if self.token.is_keyword(kw) { self.bump(); true @@ -563,10 +582,7 @@ impl<'a> Parser<'a> { /// Otherwise, eat it. pub fn expect_keyword(&mut self, kw: keywords::Keyword) { if !self.eat_keyword(kw) { - let id_interned_str = token::get_name(kw.to_name()); - let token_str = self.this_token_to_string(); - self.fatal(&format!("expected `{}`, found `{}`", - id_interned_str, token_str)[]) + self.expect_one_of(&[], &[]); } } @@ -593,6 +609,7 @@ impl<'a> Parser<'a> { /// Expect and consume an `&`. If `&&` is seen, replace it with a single /// `&` and continue. If an `&` is not seen, signal an error. fn expect_and(&mut self) { + self.expected_tokens.push(TokenType::Token(token::BinOp(token::And))); match self.token { token::BinOp(token::And) => self.bump(), token::AndAnd => { @@ -601,12 +618,7 @@ impl<'a> Parser<'a> { self.replace_token(token::BinOp(token::And), lo, span.hi) } _ => { - let token_str = self.this_token_to_string(); - let found_token = - Parser::token_to_string(&token::BinOp(token::And)); - self.fatal(&format!("expected `{}`, found `{}`", - found_token, - token_str)[]) + self.expect_one_of(&[], &[]); } } } @@ -614,6 +626,7 @@ impl<'a> Parser<'a> { /// Expect and consume a `|`. If `||` is seen, replace it with a single /// `|` and continue. If a `|` is not seen, signal an error. fn expect_or(&mut self) { + self.expected_tokens.push(TokenType::Token(token::BinOp(token::Or))); match self.token { token::BinOp(token::Or) => self.bump(), token::OrOr => { @@ -622,12 +635,7 @@ impl<'a> Parser<'a> { self.replace_token(token::BinOp(token::Or), lo, span.hi) } _ => { - let found_token = self.this_token_to_string(); - let token_str = - Parser::token_to_string(&token::BinOp(token::Or)); - self.fatal(&format!("expected `{}`, found `{}`", - token_str, - found_token)[]) + self.expect_one_of(&[], &[]); } } } @@ -652,6 +660,7 @@ impl<'a> Parser<'a> { /// This is meant to be used when parsing generics on a path to get the /// starting token. fn eat_lt(&mut self) -> bool { + self.expected_tokens.push(TokenType::Token(token::Lt)); match self.token { token::Lt => { self.bump(); true } token::BinOp(token::Shl) => { @@ -666,11 +675,7 @@ impl<'a> Parser<'a> { fn expect_lt(&mut self) { if !self.eat_lt() { - let found_token = self.this_token_to_string(); - let token_str = Parser::token_to_string(&token::Lt); - self.fatal(&format!("expected `{}`, found `{}`", - token_str, - found_token)[]) + self.expect_one_of(&[], &[]); } } @@ -700,6 +705,7 @@ impl<'a> Parser<'a> { /// with a single > and continue. If a GT is not seen, /// signal an error. pub fn expect_gt(&mut self) { + self.expected_tokens.push(TokenType::Token(token::Gt)); match self.token { token::Gt => self.bump(), token::BinOp(token::Shr) => { @@ -998,14 +1004,14 @@ impl<'a> Parser<'a> { /// Is the current token one of the keywords that signals a bare function /// type? pub fn token_is_bare_fn_keyword(&mut self) -> bool { - self.token.is_keyword(keywords::Fn) || - self.token.is_keyword(keywords::Unsafe) || - self.token.is_keyword(keywords::Extern) + self.check_keyword(keywords::Fn) || + self.check_keyword(keywords::Unsafe) || + self.check_keyword(keywords::Extern) } /// Is the current token one of the keywords that signals a closure type? pub fn token_is_closure_keyword(&mut self) -> bool { - self.token.is_keyword(keywords::Unsafe) + self.check_keyword(keywords::Unsafe) } pub fn get_lifetime(&mut self) -> ast::Ident { @@ -1035,7 +1041,7 @@ impl<'a> Parser<'a> { let lifetime_defs = self.parse_late_bound_lifetime_defs(); // examine next token to decide to do - if self.eat_keyword(keywords::Proc) { + if self.eat_keyword_noexpect(keywords::Proc) { self.parse_proc_type(lifetime_defs) } else if self.token_is_bare_fn_keyword() || self.token_is_closure_keyword() { self.parse_ty_bare_fn_or_ty_closure(lifetime_defs) @@ -1166,11 +1172,11 @@ impl<'a> Parser<'a> { // Closure: [unsafe] <'lt> |S| [:Bounds] -> T // Fn: [unsafe] [extern "ABI"] fn <'lt> (S) -> T - if self.token.is_keyword(keywords::Fn) { + if self.check_keyword(keywords::Fn) { self.parse_ty_bare_fn(lifetime_defs) - } else if self.token.is_keyword(keywords::Extern) { + } else if self.check_keyword(keywords::Extern) { self.parse_ty_bare_fn(lifetime_defs) - } else if self.token.is_keyword(keywords::Unsafe) { + } else if self.check_keyword(keywords::Unsafe) { if self.look_ahead(1, |t| t.is_keyword(keywords::Fn) || t.is_keyword(keywords::Extern)) { self.parse_ty_bare_fn(lifetime_defs) @@ -1480,7 +1486,7 @@ impl<'a> Parser<'a> { // BORROWED POINTER self.expect_and(); self.parse_borrowed_pointee() - } else if self.token.is_keyword(keywords::For) { + } else if self.check_keyword(keywords::For) { self.parse_for_in_type() } else if self.token_is_bare_fn_keyword() || self.token_is_closure_keyword() { @@ -1494,14 +1500,14 @@ impl<'a> Parser<'a> { })) { // CLOSURE self.parse_ty_closure(Vec::new()) - } else if self.eat_keyword(keywords::Typeof) { + } else if self.eat_keyword_noexpect(keywords::Typeof) { // TYPEOF // In order to not be ambiguous, the type must be surrounded by parens. self.expect(&token::OpenDelim(token::Paren)); let e = self.parse_expr(); self.expect(&token::CloseDelim(token::Paren)); TyTypeof(e) - } else if self.eat_keyword(keywords::Proc) { + } else if self.eat_keyword_noexpect(keywords::Proc) { self.parse_proc_type(Vec::new()) } else if self.eat_lt() { // QUALIFIED PATH `::item` @@ -2092,6 +2098,7 @@ impl<'a> Parser<'a> { } fn expect_open_delim(&mut self) -> token::DelimToken { + self.expected_tokens.push(TokenType::Token(token::Gt)); match self.token { token::OpenDelim(delim) => { self.bump(); @@ -2233,7 +2240,7 @@ impl<'a> Parser<'a> { if self.eat_keyword(keywords::Move) { return self.parse_lambda_expr(CaptureByValue); } - if self.eat_keyword(keywords::Proc) { + if self.eat_keyword_noexpect(keywords::Proc) { let span = self.last_span; let _ = self.parse_proc_decl(); let _ = self.parse_expr(); @@ -2307,8 +2314,8 @@ impl<'a> Parser<'a> { hi = self.span.hi; } else if self.check(&token::ModSep) || self.token.is_ident() && - !self.token.is_keyword(keywords::True) && - !self.token.is_keyword(keywords::False) { + !self.check_keyword(keywords::True) && + !self.check_keyword(keywords::False) { let pth = self.parse_path(LifetimeAndTypesWithColons); @@ -2792,7 +2799,7 @@ impl<'a> Parser<'a> { ex = ExprAddrOf(m, e); } token::Ident(_, _) => { - if !self.token.is_keyword(keywords::Box) { + if !self.check_keyword(keywords::Box) { return self.parse_dot_or_call_expr(); } @@ -2879,7 +2886,7 @@ impl<'a> Parser<'a> { } } None => { - if AS_PREC >= min_prec && self.eat_keyword(keywords::As) { + if AS_PREC >= min_prec && self.eat_keyword_noexpect(keywords::As) { let rhs = self.parse_ty(); let _as = self.mk_expr(lhs.span.lo, rhs.span.hi, @@ -3002,7 +3009,7 @@ impl<'a> Parser<'a> { /// Parse an 'if' or 'if let' expression ('if' token already eaten) pub fn parse_if_expr(&mut self) -> P { - if self.token.is_keyword(keywords::Let) { + if self.check_keyword(keywords::Let) { return self.parse_if_let_expr(); } let lo = self.last_span.lo; @@ -3655,7 +3662,7 @@ impl<'a> Parser<'a> { } let lo = self.span.lo; - if self.token.is_keyword(keywords::Let) { + if self.check_keyword(keywords::Let) { check_expected_item(self, &item_attrs[]); self.expect_keyword(keywords::Let); let decl = self.parse_let(); @@ -5302,7 +5309,7 @@ impl<'a> Parser<'a> { let (maybe_path, ident) = match self.token { token::Ident(..) => { let the_ident = self.parse_ident(); - let path = if self.eat_keyword(keywords::As) { + let path = if self.eat_keyword_noexpect(keywords::As) { // skip the ident if there is one if self.token.is_ident() { self.bump(); } @@ -5595,14 +5602,13 @@ impl<'a> Parser<'a> { token_str)[]); } - if self.eat_keyword(keywords::Virtual) { + if self.eat_keyword_noexpect(keywords::Virtual) { let span = self.span; self.span_err(span, "`virtual` structs have been removed from the language"); } - if self.token.is_keyword(keywords::Static) { + if self.eat_keyword(keywords::Static) { // STATIC ITEM - self.bump(); let m = if self.eat_keyword(keywords::Mut) {MutMutable} else {MutImmutable}; let (ident, item_, extra_attrs) = self.parse_item_const(Some(m)); let last_span = self.last_span; @@ -5614,9 +5620,8 @@ impl<'a> Parser<'a> { maybe_append(attrs, extra_attrs)); return Ok(item); } - if self.token.is_keyword(keywords::Const) { + if self.eat_keyword(keywords::Const) { // CONST ITEM - self.bump(); if self.eat_keyword(keywords::Mut) { let last_span = self.last_span; self.span_err(last_span, "const globals cannot be mutable"); @@ -5632,7 +5637,7 @@ impl<'a> Parser<'a> { maybe_append(attrs, extra_attrs)); return Ok(item); } - if self.token.is_keyword(keywords::Unsafe) && + if self.check_keyword(keywords::Unsafe) && self.look_ahead(1us, |t| t.is_keyword(keywords::Trait)) { // UNSAFE TRAIT ITEM @@ -5649,7 +5654,7 @@ impl<'a> Parser<'a> { maybe_append(attrs, extra_attrs)); return Ok(item); } - if self.token.is_keyword(keywords::Unsafe) && + if self.check_keyword(keywords::Unsafe) && self.look_ahead(1us, |t| t.is_keyword(keywords::Impl)) { // IMPL ITEM @@ -5665,7 +5670,7 @@ impl<'a> Parser<'a> { maybe_append(attrs, extra_attrs)); return Ok(item); } - if self.token.is_keyword(keywords::Fn) { + if self.check_keyword(keywords::Fn) { // FUNCTION ITEM self.bump(); let (ident, item_, extra_attrs) = @@ -5679,7 +5684,7 @@ impl<'a> Parser<'a> { maybe_append(attrs, extra_attrs)); return Ok(item); } - if self.token.is_keyword(keywords::Unsafe) + if self.check_keyword(keywords::Unsafe) && self.look_ahead(1us, |t| *t != token::OpenDelim(token::Brace)) { // UNSAFE FUNCTION ITEM self.bump(); @@ -5784,11 +5789,11 @@ impl<'a> Parser<'a> { let visibility = self.parse_visibility(); - if self.token.is_keyword(keywords::Static) { + if self.check_keyword(keywords::Static) { // FOREIGN STATIC ITEM return Ok(self.parse_item_foreign_static(visibility, attrs)); } - if self.token.is_keyword(keywords::Fn) || self.token.is_keyword(keywords::Unsafe) { + if self.check_keyword(keywords::Fn) || self.check_keyword(keywords::Unsafe) { // FOREIGN FUNCTION ITEM return Ok(self.parse_item_foreign_fn(visibility, attrs)); } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 5531ce7b119eb..5c3892e49c058 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -456,7 +456,7 @@ macro_rules! declare_special_idents_and_keywords {( pub use self::Keyword::*; use ast; - #[derive(Copy)] + #[derive(Copy, Clone, PartialEq, Eq)] pub enum Keyword { $( $sk_variant, )* $( $rk_variant, )* diff --git a/src/test/compile-fail/better-expected.rs b/src/test/compile-fail/better-expected.rs index 0d84a5e7d0280..e07f4b8e54900 100644 --- a/src/test/compile-fail/better-expected.rs +++ b/src/test/compile-fail/better-expected.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - let x: [isize 3]; //~ ERROR expected one of `(`, `+`, `::`, `;`, or `]`, found `3` + let x: [isize 3]; //~ ERROR expected one of `(`, `+`, `::`, `;`, `<`, or `]`, found `3` } diff --git a/src/test/compile-fail/empty-impl-semicolon.rs b/src/test/compile-fail/empty-impl-semicolon.rs index a598252f1b65e..70c7d42feb53f 100644 --- a/src/test/compile-fail/empty-impl-semicolon.rs +++ b/src/test/compile-fail/empty-impl-semicolon.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -impl Foo; //~ ERROR expected one of `(`, `+`, `::`, or `{`, found `;` +impl Foo; //~ ERROR expected one of `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;` diff --git a/src/test/compile-fail/extern-no-fn.rs b/src/test/compile-fail/extern-no-fn.rs index 164cbe5417402..69e2f3ae60be5 100644 --- a/src/test/compile-fail/extern-no-fn.rs +++ b/src/test/compile-fail/extern-no-fn.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:unexpected token extern { - f(); + f(); //~ ERROR expected one of `fn`, `pub`, `static`, `unsafe`, or `}`, found `f` } fn main() { diff --git a/src/test/compile-fail/issue-20711-2.rs b/src/test/compile-fail/issue-20711-2.rs index 9f0e81a662f55..a6c4570c60f7f 100644 --- a/src/test/compile-fail/issue-20711-2.rs +++ b/src/test/compile-fail/issue-20711-2.rs @@ -14,7 +14,7 @@ impl Foo { fn foo() {} #[stable(feature = "rust1", since = "1.0.0")] -} //~ ERROR expected `fn`, found `}` +} //~ ERROR expected one of `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}` fn main() {} diff --git a/src/test/compile-fail/issue-20711.rs b/src/test/compile-fail/issue-20711.rs index 5f0f0fc05a929..3b329d7823749 100644 --- a/src/test/compile-fail/issue-20711.rs +++ b/src/test/compile-fail/issue-20711.rs @@ -12,6 +12,6 @@ struct Foo; impl Foo { #[stable(feature = "rust1", since = "1.0.0")] -} //~ ERROR expected `fn`, found `}` +} //~ ERROR expected one of `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}` fn main() {} diff --git a/src/test/compile-fail/issue-21153.rs b/src/test/compile-fail/issue-21153.rs new file mode 100644 index 0000000000000..e2b6deb0ad93a --- /dev/null +++ b/src/test/compile-fail/issue-21153.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait MyTrait: Iterator { + Item = T; //~ ERROR expected one of `extern`, `fn`, `pub`, `type`, or `unsafe`, found `Item` +} diff --git a/src/test/compile-fail/multitrait.rs b/src/test/compile-fail/multitrait.rs index a0e210aed40e6..f182eb8fa5ba6 100644 --- a/src/test/compile-fail/multitrait.rs +++ b/src/test/compile-fail/multitrait.rs @@ -12,7 +12,8 @@ struct S { y: isize } -impl Cmp, ToString for S { //~ ERROR: expected one of `(`, `+`, `::`, or `{`, found `,` +impl Cmp, ToString for S { +//~^ ERROR: expected one of `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `,` fn eq(&&other: S) { false } fn to_string(&self) -> String { "hi".to_string() } } diff --git a/src/test/compile-fail/pat-range-bad-dots.rs b/src/test/compile-fail/pat-range-bad-dots.rs index b48d3e8871b20..c52fb8c9b6797 100644 --- a/src/test/compile-fail/pat-range-bad-dots.rs +++ b/src/test/compile-fail/pat-range-bad-dots.rs @@ -10,7 +10,7 @@ pub fn main() { match 22 { - 0 .. 3 => {} //~ ERROR expected one of `...`, `=>`, or `|`, found `..` + 0 .. 3 => {} //~ ERROR expected one of `...`, `=>`, `if`, or `|`, found `..` _ => {} } } diff --git a/src/test/compile-fail/removed-syntax-closure-lifetime.rs b/src/test/compile-fail/removed-syntax-closure-lifetime.rs index a07832d5bb761..0cea87dba19bb 100644 --- a/src/test/compile-fail/removed-syntax-closure-lifetime.rs +++ b/src/test/compile-fail/removed-syntax-closure-lifetime.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type closure = Box; //~ ERROR expected one of `(`, `+`, `,`, `::`, or `>`, found `/` +type closure = Box; //~ ERROR expected one of `(`, `+`, `,`, `::`, `<`, or `>`, found `/` diff --git a/src/test/compile-fail/removed-syntax-enum-newtype.rs b/src/test/compile-fail/removed-syntax-enum-newtype.rs index 3b45fd81288fd..b067cee03d257 100644 --- a/src/test/compile-fail/removed-syntax-enum-newtype.rs +++ b/src/test/compile-fail/removed-syntax-enum-newtype.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum e = isize; //~ ERROR expected one of `<` or `{`, found `=` +enum e = isize; //~ ERROR expected one of `<`, `where`, or `{`, found `=` diff --git a/src/test/compile-fail/removed-syntax-extern-const.rs b/src/test/compile-fail/removed-syntax-extern-const.rs index 98eec0977e0c1..a0e1d04a3dc5d 100644 --- a/src/test/compile-fail/removed-syntax-extern-const.rs +++ b/src/test/compile-fail/removed-syntax-extern-const.rs @@ -9,5 +9,6 @@ // except according to those terms. extern { - const i: isize; //~ ERROR unexpected token: `const` + const i: isize; + //~^ ERROR expected one of `fn`, `pub`, `static`, `unsafe`, or `}`, found `const` } diff --git a/src/test/compile-fail/removed-syntax-fixed-vec.rs b/src/test/compile-fail/removed-syntax-fixed-vec.rs index 0ca2380ef68c7..0e8e20b389187 100644 --- a/src/test/compile-fail/removed-syntax-fixed-vec.rs +++ b/src/test/compile-fail/removed-syntax-fixed-vec.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type v = [isize * 3]; //~ ERROR expected one of `(`, `+`, `::`, `;`, or `]`, found `*` +type v = [isize * 3]; //~ ERROR expected one of `(`, `+`, `::`, `;`, `<`, or `]`, found `*` diff --git a/src/test/compile-fail/removed-syntax-mut-vec-ty.rs b/src/test/compile-fail/removed-syntax-mut-vec-ty.rs index 0f67a1d04eec3..9a7570a92f002 100644 --- a/src/test/compile-fail/removed-syntax-mut-vec-ty.rs +++ b/src/test/compile-fail/removed-syntax-mut-vec-ty.rs @@ -10,4 +10,4 @@ type v = [mut isize]; //~^ ERROR expected identifier, found keyword `mut` - //~^^ ERROR expected one of `(`, `+`, `::`, `;`, or `]`, found `isize` + //~^^ ERROR expected one of `(`, `+`, `::`, `;`, `<`, or `]`, found `isize` diff --git a/src/test/compile-fail/removed-syntax-ptr-lifetime.rs b/src/test/compile-fail/removed-syntax-ptr-lifetime.rs index d94f2ec1e073e..44c65d98c0b72 100644 --- a/src/test/compile-fail/removed-syntax-ptr-lifetime.rs +++ b/src/test/compile-fail/removed-syntax-ptr-lifetime.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type bptr = &lifetime/isize; //~ ERROR expected one of `(`, `+`, `::`, or `;`, found `/` +type bptr = &lifetime/isize; //~ ERROR expected one of `(`, `+`, `::`, `;`, or `<`, found `/` diff --git a/src/test/compile-fail/removed-syntax-static-fn.rs b/src/test/compile-fail/removed-syntax-static-fn.rs index e3e1cb0f3cac8..caf939e7b8aa9 100644 --- a/src/test/compile-fail/removed-syntax-static-fn.rs +++ b/src/test/compile-fail/removed-syntax-static-fn.rs @@ -11,5 +11,6 @@ struct S; impl S { - static fn f() {} //~ ERROR expected `fn`, found `static` + static fn f() {} + //~^ ERROR expected one of `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `static` } diff --git a/src/test/compile-fail/removed-syntax-uniq-mut-ty.rs b/src/test/compile-fail/removed-syntax-uniq-mut-ty.rs index c051059aee6f4..d1c2fc69f5233 100644 --- a/src/test/compile-fail/removed-syntax-uniq-mut-ty.rs +++ b/src/test/compile-fail/removed-syntax-uniq-mut-ty.rs @@ -10,4 +10,4 @@ type mut_box = Box; //~^ ERROR expected identifier, found keyword `mut` - //~^^ ERROR expected one of `(`, `+`, `,`, `::`, or `>`, found `isize` + //~^^ ERROR expected one of `(`, `+`, `,`, `::`, `<`, or `>`, found `isize` diff --git a/src/test/compile-fail/struct-literal-in-match-discriminant.rs b/src/test/compile-fail/struct-literal-in-match-discriminant.rs index 8f50940806a58..e6948b7c7c995 100644 --- a/src/test/compile-fail/struct-literal-in-match-discriminant.rs +++ b/src/test/compile-fail/struct-literal-in-match-discriminant.rs @@ -14,7 +14,7 @@ struct Foo { fn main() { match Foo { - x: 3 //~ ERROR expected one of `!`, `=>`, `@`, or `|`, found `:` + x: 3 //~ ERROR expected one of `!`, `=>`, `@`, `if`, or `|`, found `:` } { Foo { x: x From deed093a38243ced1f52927ebf7511c099a3bf36 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 1 Feb 2015 18:53:47 -0800 Subject: [PATCH 29/36] std: Deprecate RefCell::{try_borrow, try_borrow_mut} The existence of these two functions is at odds with our current [error conventions][conventions] which recommend that panicking and `Result`-like variants should not be provided together. [conventions]: https://github.com/rust-lang/rfcs/blob/master/text/0236-error-conventions.md#do-not-provide-both-result-and-fail-variants This commit adds a new `borrow_state` function returning a `BorrowState` enum to `RefCell` which serves as a replacemnt for the `try_borrow` and `try_borrow_mut` functions. --- src/libcore/cell.rs | 55 +++++++++++++++++++++++++++++++++-------- src/libcore/fmt/mod.rs | 10 +++++--- src/libcoretest/cell.rs | 4 +++ 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 65dccc8c2444c..15e745b0e713e 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -266,6 +266,18 @@ pub struct RefCell { borrow: Cell, } +/// An enumeration of values returned from the `state` method on a `RefCell`. +#[derive(Copy, Clone, PartialEq)] +#[unstable(feature = "std_misc")] +pub enum BorrowState { + /// The cell is currently being read, there is at least one active `borrow`. + Reading, + /// The cell is currently being written to, there is an active `borrow_mut`. + Writing, + /// There are no outstanding borrows on this cell. + Unused, +} + // Values [1, MAX-1] represent the number of `Ref` active // (will not outgrow its range since `uint` is the size of the address space) type BorrowFlag = uint; @@ -310,6 +322,19 @@ impl RefCell { unsafe { self.value.into_inner() } } + /// Query the current state of this `RefCell` + /// + /// The returned value can be dispatched on to determine if a call to + /// `borrow` or `borrow_mut` would succeed. + #[unstable(feature = "std_misc")] + pub fn borrow_state(&self) -> BorrowState { + match self.borrow.get() { + WRITING => BorrowState::Writing, + UNUSED => BorrowState::Unused, + _ => BorrowState::Reading, + } + } + /// Attempts to immutably borrow the wrapped value. /// /// The borrow lasts until the returned `Ref` exits scope. Multiple @@ -317,6 +342,8 @@ impl RefCell { /// /// Returns `None` if the value is currently mutably borrowed. #[unstable(feature = "core", reason = "may be renamed or removed")] + #[deprecated(since = "1.0.0", + reason = "dispatch on `cell.borrow_state()` instead")] pub fn try_borrow<'a>(&'a self) -> Option> { match BorrowRef::new(&self.borrow) { Some(b) => Some(Ref { _value: unsafe { &*self.value.get() }, _borrow: b }), @@ -326,8 +353,8 @@ impl RefCell { /// Immutably borrows the wrapped value. /// - /// The borrow lasts until the returned `Ref` exits scope. Multiple immutable borrows can be - /// taken out at the same time. + /// The borrow lasts until the returned `Ref` exits scope. Multiple + /// immutable borrows can be taken out at the same time. /// /// # Panics /// @@ -361,9 +388,12 @@ impl RefCell { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn borrow<'a>(&'a self) -> Ref<'a, T> { - match self.try_borrow() { - Some(ptr) => ptr, - None => panic!("RefCell already mutably borrowed") + match BorrowRef::new(&self.borrow) { + Some(b) => Ref { + _value: unsafe { &*self.value.get() }, + _borrow: b, + }, + None => panic!("RefCell already mutably borrowed"), } } @@ -374,6 +404,8 @@ impl RefCell { /// /// Returns `None` if the value is currently borrowed. #[unstable(feature = "core", reason = "may be renamed or removed")] + #[deprecated(since = "1.0.0", + reason = "dispatch on `cell.borrow_state()` instead")] pub fn try_borrow_mut<'a>(&'a self) -> Option> { match BorrowRefMut::new(&self.borrow) { Some(b) => Some(RefMut { _value: unsafe { &mut *self.value.get() }, _borrow: b }), @@ -383,8 +415,8 @@ impl RefCell { /// Mutably borrows the wrapped value. /// - /// The borrow lasts until the returned `RefMut` exits scope. The value cannot be borrowed - /// while this borrow is active. + /// The borrow lasts until the returned `RefMut` exits scope. The value + /// cannot be borrowed while this borrow is active. /// /// # Panics /// @@ -417,9 +449,12 @@ impl RefCell { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> { - match self.try_borrow_mut() { - Some(ptr) => ptr, - None => panic!("RefCell already borrowed") + match BorrowRefMut::new(&self.borrow) { + Some(b) => RefMut { + _value: unsafe { &mut *self.value.get() }, + _borrow: b, + }, + None => panic!("RefCell already borrowed"), } } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 2ff67ebd550ab..a82246ccb33ee 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -13,7 +13,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use any; -use cell::{Cell, RefCell, Ref, RefMut}; +use cell::{Cell, RefCell, Ref, RefMut, BorrowState}; use char::CharExt; use iter::{Iterator, IteratorExt}; use marker::{Copy, Sized}; @@ -973,9 +973,11 @@ impl Debug for Cell { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for RefCell { fn fmt(&self, f: &mut Formatter) -> Result { - match self.try_borrow() { - Some(val) => write!(f, "RefCell {{ value: {:?} }}", val), - None => write!(f, "RefCell {{ }}") + match self.borrow_state() { + BorrowState::Unused | BorrowState::Reading => { + write!(f, "RefCell {{ value: {:?} }}", self.borrow()) + } + BorrowState::Writing => write!(f, "RefCell {{ }}"), } } } diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs index 5815dbc0accfd..8939bd61fe4ae 100644 --- a/src/libcoretest/cell.rs +++ b/src/libcoretest/cell.rs @@ -60,6 +60,7 @@ fn no_mut_then_imm_borrow() { let x = RefCell::new(0); let _b1 = x.borrow_mut(); assert!(x.try_borrow().is_none()); + assert_eq!(x.borrow_state(), BorrowState::Writing); } #[test] @@ -67,13 +68,16 @@ fn no_imm_then_borrow_mut() { let x = RefCell::new(0); let _b1 = x.borrow(); assert!(x.try_borrow_mut().is_none()); + assert_eq!(x.borrow_state(), BorrowState::Reading); } #[test] fn no_double_borrow_mut() { let x = RefCell::new(0); + assert_eq!(x.borrow_state(), BorrowState::Unused); let _b1 = x.borrow_mut(); assert!(x.try_borrow_mut().is_none()); + assert_eq!(x.borrow_state(), BorrowState::Writing); } #[test] From 9683745fed09daf7f8acc55d679b41d3bc660ec4 Mon Sep 17 00:00:00 2001 From: Alfie John Date: Wed, 28 Jan 2015 01:01:48 +0000 Subject: [PATCH 30/36] Omit integer suffix when unnecessary See PR # 21378 for context --- src/libsyntax/ast_util.rs | 20 ++++---- src/libsyntax/codemap.rs | 18 +++---- src/libsyntax/diagnostic.rs | 32 ++++++------ src/libsyntax/ext/deriving/generic/mod.rs | 16 +++--- src/libsyntax/ext/expand.rs | 4 +- src/libsyntax/ext/quote.rs | 2 +- src/libsyntax/ext/tt/macro_parser.rs | 34 ++++++------- src/libsyntax/ext/tt/transcribe.rs | 2 +- src/libsyntax/parse/lexer/comments.rs | 6 +-- src/libsyntax/parse/lexer/mod.rs | 26 +++++----- src/libsyntax/parse/mod.rs | 10 ++-- src/libsyntax/parse/parser.rs | 16 +++--- src/libsyntax/print/pp.rs | 32 ++++++------ src/libsyntax/print/pprust.rs | 62 +++++++++++------------ src/libsyntax/test.rs | 4 +- 15 files changed, 142 insertions(+), 142 deletions(-) diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 7f1264ac9a1d3..252dbfd964a6b 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -322,21 +322,21 @@ pub fn struct_field_visibility(field: ast::StructField) -> Visibility { pub fn operator_prec(op: ast::BinOp_) -> usize { match op { // 'as' sits here with 12 - BiMul | BiDiv | BiRem => 11us, - BiAdd | BiSub => 10us, - BiShl | BiShr => 9us, - BiBitAnd => 8us, - BiBitXor => 7us, - BiBitOr => 6us, - BiLt | BiLe | BiGe | BiGt | BiEq | BiNe => 3us, - BiAnd => 2us, - BiOr => 1us + BiMul | BiDiv | BiRem => 11, + BiAdd | BiSub => 10, + BiShl | BiShr => 9, + BiBitAnd => 8, + BiBitXor => 7, + BiBitOr => 6, + BiLt | BiLe | BiGe | BiGt | BiEq | BiNe => 3, + BiAnd => 2, + BiOr => 1 } } /// Precedence of the `as` operator, which is a binary operator /// not appearing in the prior table. -pub const AS_PREC: usize = 12us; +pub const AS_PREC: usize = 12; pub fn empty_generics() -> Generics { Generics { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 8adb9b2422239..13b6a7a037a6c 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -431,7 +431,7 @@ impl CodeMap { let lo = self.lookup_char_pos(sp.lo); let hi = self.lookup_char_pos(sp.hi); let mut lines = Vec::new(); - for i in lo.line - 1us..hi.line as usize { + for i in lo.line - 1..hi.line as usize { lines.push(i); }; FileLines {file: lo.file, lines: lines} @@ -499,10 +499,10 @@ impl CodeMap { let files = self.files.borrow(); let files = &*files; let len = files.len(); - let mut a = 0us; + let mut a = 0; let mut b = len; - while b - a > 1us { - let m = (a + b) / 2us; + while b - a > 1 { + let m = (a + b) / 2; if files[m].start_pos > pos { b = m; } else { @@ -538,12 +538,12 @@ impl CodeMap { let files = self.files.borrow(); let f = (*files)[idx].clone(); - let mut a = 0us; + let mut a = 0; { let lines = f.lines.borrow(); let mut b = lines.len(); - while b - a > 1us { - let m = (a + b) / 2us; + while b - a > 1 { + let m = (a + b) / 2; if (*lines)[m] > pos { b = m; } else { a = m; } } } @@ -552,7 +552,7 @@ impl CodeMap { fn lookup_pos(&self, pos: BytePos) -> Loc { let FileMapAndLine {fm: f, line: a} = self.lookup_line(pos); - let line = a + 1us; // Line numbers start at 1 + let line = a + 1; // Line numbers start at 1 let chpos = self.bytepos_to_file_charpos(pos); let linebpos = (*f.lines.borrow())[a]; let linechpos = self.bytepos_to_file_charpos(linebpos); @@ -763,7 +763,7 @@ mod test { assert_eq!(file_lines.file.name, "blork.rs"); assert_eq!(file_lines.lines.len(), 1); - assert_eq!(file_lines.lines[0], 1us); + assert_eq!(file_lines.lines[0], 1); } #[test] diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 821ac8e2f89bc..f920ca9e233c9 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -25,7 +25,7 @@ use term::WriterWrapper; use term; /// maximum number of lines we will print for each error; arbitrary. -static MAX_LINES: usize = 6us; +static MAX_LINES: usize = 6; #[derive(Clone, Copy)] pub enum RenderSpan { @@ -155,19 +155,19 @@ impl Handler { self.bump_err_count(); } pub fn bump_err_count(&self) { - self.err_count.set(self.err_count.get() + 1us); + self.err_count.set(self.err_count.get() + 1); } pub fn err_count(&self) -> usize { self.err_count.get() } pub fn has_errors(&self) -> bool { - self.err_count.get() > 0us + self.err_count.get() > 0 } pub fn abort_if_errors(&self) { let s; match self.err_count.get() { - 0us => return, - 1us => s = "aborting due to previous error".to_string(), + 0 => return, + 1 => s = "aborting due to previous error".to_string(), _ => { s = format!("aborting due to {} previous errors", self.err_count.get()); @@ -457,7 +457,7 @@ fn highlight_lines(err: &mut EmitterWriter, let mut elided = false; let mut display_lines = &lines.lines[]; if display_lines.len() > MAX_LINES { - display_lines = &display_lines[0us..MAX_LINES]; + display_lines = &display_lines[0..MAX_LINES]; elided = true; } // Print the offending lines @@ -468,32 +468,32 @@ fn highlight_lines(err: &mut EmitterWriter, } } if elided { - let last_line = display_lines[display_lines.len() - 1us]; - let s = format!("{}:{} ", fm.name, last_line + 1us); + let last_line = display_lines[display_lines.len() - 1]; + let s = format!("{}:{} ", fm.name, last_line + 1); try!(write!(&mut err.dst, "{0:1$}...\n", "", s.len())); } // FIXME (#3260) // If there's one line at fault we can easily point to the problem - if lines.lines.len() == 1us { + if lines.lines.len() == 1 { let lo = cm.lookup_char_pos(sp.lo); - let mut digits = 0us; - let mut num = (lines.lines[0] + 1us) / 10us; + let mut digits = 0; + let mut num = (lines.lines[0] + 1) / 10; // how many digits must be indent past? - while num > 0us { num /= 10us; digits += 1us; } + while num > 0 { num /= 10; digits += 1; } // indent past |name:## | and the 0-offset column location - let left = fm.name.len() + digits + lo.col.to_usize() + 3us; + let left = fm.name.len() + digits + lo.col.to_usize() + 3; let mut s = String::new(); // Skip is the number of characters we need to skip because they are // part of the 'filename:line ' part of the previous line. - let skip = fm.name.len() + digits + 3us; + let skip = fm.name.len() + digits + 3; for _ in 0..skip { s.push(' '); } if let Some(orig) = fm.get_line(lines.lines[0]) { - for pos in 0us..left - skip { + for pos in 0..left - skip { let cur_char = orig.as_bytes()[pos] as char; // Whenever a tab occurs on the previous line, we insert one on // the error-point-squiggly-line as well (instead of a space). @@ -511,7 +511,7 @@ fn highlight_lines(err: &mut EmitterWriter, let hi = cm.lookup_char_pos(sp.hi); if hi.col != lo.col { // the ^ already takes up one space - let num_squigglies = hi.col.to_usize() - lo.col.to_usize() - 1us; + let num_squigglies = hi.col.to_usize() - lo.col.to_usize() - 1; for _ in 0..num_squigglies { s.push('~'); } diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 1b84d93738d5e..dc88ce6d1907c 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -770,7 +770,7 @@ impl<'a> MethodDef<'a> { let mut raw_fields = Vec::new(); // ~[[fields of self], // [fields of next Self arg], [etc]] let mut patterns = Vec::new(); - for i in 0us..self_args.len() { + for i in 0..self_args.len() { let struct_path= cx.path(DUMMY_SP, vec!( type_ident )); let (pat, ident_expr) = trait_.create_struct_pattern(cx, @@ -859,8 +859,8 @@ impl<'a> MethodDef<'a> { /// (&A2(ref __self_0), /// &A2(ref __arg_1_0)) => (*__self_0).eq(&(*__arg_1_0)), /// _ => { - /// let __self_vi = match *self { A1(..) => 0us, A2(..) => 1us }; - /// let __arg_1_vi = match *__arg_1 { A1(..) => 0us, A2(..) => 1us }; + /// let __self_vi = match *self { A1(..) => 0, A2(..) => 1 }; + /// let __arg_1_vi = match *__arg_1 { A1(..) => 0, A2(..) => 1 }; /// false /// } /// } @@ -904,8 +904,8 @@ impl<'a> MethodDef<'a> { /// (Variant2, Variant2, Variant2) => ... // delegate Matching on Variant2 /// ... /// _ => { - /// let __this_vi = match this { Variant1 => 0us, Variant2 => 1us, ... }; - /// let __that_vi = match that { Variant1 => 0us, Variant2 => 1us, ... }; + /// let __this_vi = match this { Variant1 => 0, Variant2 => 1, ... }; + /// let __that_vi = match that { Variant1 => 0, Variant2 => 1, ... }; /// ... // catch-all remainder can inspect above variant index values. /// } /// } @@ -1067,13 +1067,13 @@ impl<'a> MethodDef<'a> { // // ``` // let __self0_vi = match self { - // A => 0us, B(..) => 1us, C(..) => 2us + // A => 0, B(..) => 1, C(..) => 2 // }; // let __self1_vi = match __arg1 { - // A => 0us, B(..) => 1us, C(..) => 2us + // A => 0, B(..) => 1, C(..) => 2 // }; // let __self2_vi = match __arg2 { - // A => 0us, B(..) => 1us, C(..) => 2us + // A => 0, B(..) => 1, C(..) => 2 // }; // ``` let mut index_let_stmts: Vec> = Vec::new(); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 5736400313e95..68723d327393d 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -362,7 +362,7 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, // in this file. // Token-tree macros: MacInvocTT(pth, tts, _) => { - if pth.segments.len() > 1us { + if pth.segments.len() > 1 { fld.cx.span_err(pth.span, "expected macro name without module \ separators"); @@ -931,7 +931,7 @@ fn expand_pat(p: P, fld: &mut MacroExpander) -> P { }, _ => unreachable!() }; - if pth.segments.len() > 1us { + if pth.segments.len() > 1 { fld.cx.span_err(pth.span, "expected macro name without module separators"); return DummyResult::raw_pat(span); } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 0f617302c9219..1d22f79bfb291 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -709,7 +709,7 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) // try removing it when enough of them are gone. let mut p = cx.new_parser_from_tts(tts); - p.quote_depth += 1us; + p.quote_depth += 1; let cx_expr = p.parse_expr(); if !p.eat(&token::Comma) { diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index e3211c7c337e6..69c7d10a82c9a 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -171,11 +171,11 @@ pub fn initial_matcher_pos(ms: Rc>, sep: Option, lo: ByteP stack: vec![], top_elts: TtSeq(ms), sep: sep, - idx: 0us, + idx: 0, up: None, matches: matches, - match_lo: 0us, - match_cur: 0us, + match_lo: 0, + match_cur: 0, match_hi: match_idx_hi, sp_lo: lo } @@ -238,7 +238,7 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc]) } } let mut ret_val = HashMap::new(); - let mut idx = 0us; + let mut idx = 0; for m in ms.iter() { n_rec(p_s, m, res, &mut ret_val, &mut idx) } ret_val } @@ -383,7 +383,7 @@ pub fn parse(sess: &ParseSess, if seq.op == ast::ZeroOrMore { let mut new_ei = ei.clone(); new_ei.match_cur += seq.num_captures; - new_ei.idx += 1us; + new_ei.idx += 1; //we specifically matched zero repeats. for idx in ei.match_cur..ei.match_cur + seq.num_captures { (&mut new_ei.matches[idx]).push(Rc::new(MatchedSeq(vec![], sp))); @@ -398,7 +398,7 @@ pub fn parse(sess: &ParseSess, cur_eis.push(box MatcherPos { stack: vec![], sep: seq.separator.clone(), - idx: 0us, + idx: 0, matches: matches, match_lo: ei_t.match_cur, match_cur: ei_t.match_cur, @@ -442,20 +442,20 @@ pub fn parse(sess: &ParseSess, /* error messages here could be improved with links to orig. rules */ if token_name_eq(&tok, &token::Eof) { - if eof_eis.len() == 1us { + if eof_eis.len() == 1 { let mut v = Vec::new(); for dv in (&mut eof_eis[0]).matches.iter_mut() { v.push(dv.pop().unwrap()); } return Success(nameize(sess, ms, &v[])); - } else if eof_eis.len() > 1us { + } else if eof_eis.len() > 1 { return Error(sp, "ambiguity: multiple successful parses".to_string()); } else { return Failure(sp, "unexpected end of macro invocation".to_string()); } } else { - if (bb_eis.len() > 0us && next_eis.len() > 0us) - || bb_eis.len() > 1us { + if (bb_eis.len() > 0 && next_eis.len() > 0) + || bb_eis.len() > 1 { let nts = bb_eis.iter().map(|ei| { match ei.top_elts.get_tt(ei.idx) { TtToken(_, MatchNt(bind, name, _, _)) => { @@ -469,12 +469,12 @@ pub fn parse(sess: &ParseSess, "local ambiguity: multiple parsing options: \ built-in NTs {} or {} other options.", nts, next_eis.len()).to_string()); - } else if bb_eis.len() == 0us && next_eis.len() == 0us { + } else if bb_eis.len() == 0 && next_eis.len() == 0 { return Failure(sp, format!("no rules expected the token `{}`", pprust::token_to_string(&tok)).to_string()); - } else if next_eis.len() > 0us { + } else if next_eis.len() > 0 { /* Now process the next token */ - while next_eis.len() > 0us { + while next_eis.len() > 0 { cur_eis.push(next_eis.pop().unwrap()); } rdr.next_token(); @@ -488,7 +488,7 @@ pub fn parse(sess: &ParseSess, let match_cur = ei.match_cur; (&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal( parse_nt(&mut rust_parser, span, name_string.get())))); - ei.idx += 1us; + ei.idx += 1; ei.match_cur += 1; } _ => panic!() @@ -501,16 +501,16 @@ pub fn parse(sess: &ParseSess, } } - assert!(cur_eis.len() > 0us); + assert!(cur_eis.len() > 0); } } pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal { match name { "tt" => { - p.quote_depth += 1us; //but in theory, non-quoted tts might be useful + p.quote_depth += 1; //but in theory, non-quoted tts might be useful let res = token::NtTT(P(p.parse_token_tree())); - p.quote_depth -= 1us; + p.quote_depth -= 1; return res; } _ => {} diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 0bf20b8f3e151..83234e3b7a5d8 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -223,7 +223,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { r.repeat_len.pop(); } } else { /* repeat */ - *r.repeat_idx.last_mut().unwrap() += 1us; + *r.repeat_idx.last_mut().unwrap() += 1; r.stack.last_mut().unwrap().idx = 0; match r.stack.last().unwrap().sep.clone() { Some(tk) => { diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index 926385ccd119e..a026b8feee1d0 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -62,7 +62,7 @@ pub fn doc_comment_style(comment: &str) -> ast::AttrStyle { pub fn strip_doc_comment_decoration(comment: &str) -> String { /// remove whitespace-only lines from the start/end of lines fn vertical_trim(lines: Vec ) -> Vec { - let mut i = 0us; + let mut i = 0; let mut j = lines.len(); // first line of all-stars should be omitted if lines.len() > 0 && @@ -158,7 +158,7 @@ fn push_blank_line_comment(rdr: &StringReader, comments: &mut Vec) { fn consume_whitespace_counting_blank_lines(rdr: &mut StringReader, comments: &mut Vec) { while is_whitespace(rdr.curr) && !rdr.is_eof() { - if rdr.col == CharPos(0us) && rdr.curr_is('\n') { + if rdr.col == CharPos(0) && rdr.curr_is('\n') { push_blank_line_comment(rdr, &mut *comments); } rdr.bump(); @@ -305,7 +305,7 @@ fn read_block_comment(rdr: &mut StringReader, let mut style = if code_to_the_left { Trailing } else { Isolated }; rdr.consume_non_eol_whitespace(); - if !rdr.is_eof() && !rdr.curr_is('\n') && lines.len() == 1us { + if !rdr.is_eof() && !rdr.curr_is('\n') && lines.len() == 1 { style = Mixed; } debug!("<<< block comment"); diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 2cf6058a43379..65051ff8360b7 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -279,7 +279,7 @@ impl<'a> StringReader<'a> { /// Converts CRLF to LF in the given string, raising an error on bare CR. fn translate_crlf<'b>(&self, start: BytePos, s: &'b str, errmsg: &'b str) -> CowString<'b> { - let mut i = 0us; + let mut i = 0; while i < s.len() { let str::CharRange { ch, next } = s.char_range_at(i); if ch == '\r' { @@ -331,10 +331,10 @@ impl<'a> StringReader<'a> { let byte_offset_diff = next.next - current_byte_offset; self.pos = self.pos + Pos::from_usize(byte_offset_diff); self.curr = Some(next.ch); - self.col = self.col + CharPos(1us); + self.col = self.col + CharPos(1); if last_char == '\n' { self.filemap.next_line(self.last_pos); - self.col = CharPos(0us); + self.col = CharPos(0); } if byte_offset_diff > 1 { @@ -472,7 +472,7 @@ impl<'a> StringReader<'a> { cmap.files.borrow_mut().push(self.filemap.clone()); let loc = cmap.lookup_char_pos_adj(self.last_pos); debug!("Skipping a shebang"); - if loc.line == 1us && loc.col == CharPos(0us) { + if loc.line == 1 && loc.col == CharPos(0) { // FIXME: Add shebang "token", return it let start = self.last_pos; while !self.curr_is('\n') && !self.is_eof() { self.bump(); } @@ -646,7 +646,7 @@ impl<'a> StringReader<'a> { /// Scan through any digits (base `radix`) or underscores, and return how /// many digits there were. fn scan_digits(&mut self, radix: usize) -> usize { - let mut len = 0us; + let mut len = 0; loop { let c = self.curr; if c == Some('_') { debug!("skipping a _"); self.bump(); continue; } @@ -799,14 +799,14 @@ impl<'a> StringReader<'a> { if self.curr == Some('{') { self.scan_unicode_escape(delim) } else { - let res = self.scan_hex_digits(4us, delim, false); + let res = self.scan_hex_digits(4, delim, false); let sp = codemap::mk_sp(escaped_pos, self.last_pos); self.old_escape_warning(sp); res } } 'U' if !ascii_only => { - let res = self.scan_hex_digits(8us, delim, false); + let res = self.scan_hex_digits(8, delim, false); let sp = codemap::mk_sp(escaped_pos, self.last_pos); self.old_escape_warning(sp); res @@ -877,7 +877,7 @@ impl<'a> StringReader<'a> { fn scan_unicode_escape(&mut self, delim: char) -> bool { self.bump(); // past the { let start_bpos = self.last_pos; - let mut count = 0us; + let mut count = 0; let mut accum_int = 0; while !self.curr_is('}') && count <= 6 { @@ -937,10 +937,10 @@ impl<'a> StringReader<'a> { /// error if it isn't. fn check_float_base(&mut self, start_bpos: BytePos, last_bpos: BytePos, base: usize) { match base { - 16us => self.err_span_(start_bpos, last_bpos, "hexadecimal float literal is not \ + 16 => self.err_span_(start_bpos, last_bpos, "hexadecimal float literal is not \ supported"), - 8us => self.err_span_(start_bpos, last_bpos, "octal float literal is not supported"), - 2us => self.err_span_(start_bpos, last_bpos, "binary float literal is not supported"), + 8 => self.err_span_(start_bpos, last_bpos, "octal float literal is not supported"), + 2 => self.err_span_(start_bpos, last_bpos, "binary float literal is not supported"), _ => () } } @@ -1189,7 +1189,7 @@ impl<'a> StringReader<'a> { 'r' => { let start_bpos = self.last_pos; self.bump(); - let mut hash_count = 0us; + let mut hash_count = 0; while self.curr_is('#') { self.bump(); hash_count += 1; @@ -1374,7 +1374,7 @@ impl<'a> StringReader<'a> { fn scan_raw_byte_string(&mut self) -> token::Lit { let start_bpos = self.last_pos; self.bump(); - let mut hash_count = 0us; + let mut hash_count = 0; while self.curr_is('#') { self.bump(); hash_count += 1; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 8ac5b6e52747a..af594ce7ca222 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -181,7 +181,7 @@ pub fn parse_tts_from_source_str(name: String, name, source ); - p.quote_depth += 1us; + p.quote_depth += 1; // right now this is re-creating the token trees from ... token trees. maybe_aborted(p.parse_all_token_trees(),p) } @@ -324,7 +324,7 @@ pub mod with_hygiene { name, source ); - p.quote_depth += 1us; + p.quote_depth += 1; // right now this is re-creating the token trees from ... token trees. maybe_aborted(p.parse_all_token_trees(),p) } @@ -683,9 +683,9 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> match suffix { Some(suf) if looks_like_width_suffix(&['f'], suf) => { match base { - 16us => sd.span_err(sp, "hexadecimal float literal is not supported"), - 8us => sd.span_err(sp, "octal float literal is not supported"), - 2us => sd.span_err(sp, "binary float literal is not supported"), + 16 => sd.span_err(sp, "hexadecimal float literal is not supported"), + 8 => sd.span_err(sp, "octal float literal is not supported"), + 2 => sd.span_err(sp, "binary float literal is not supported"), _ => () } let ident = token::intern_and_get_ident(&*s); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d99095eeba377..de12e3703812a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -740,7 +740,7 @@ impl<'a> Parser<'a> { // would encounter a `>` and stop. This lets the parser handle trailing // commas in generic parameters, because it can stop either after // parsing a type or after parsing a comma. - for i in iter::count(0us, 1) { + for i in iter::count(0, 1) { if self.check(&token::Gt) || self.token == token::BinOp(token::Shr) || self.token == token::Ge @@ -917,7 +917,7 @@ impl<'a> Parser<'a> { }; self.span = next.sp; self.token = next.tok; - self.tokens_consumed += 1us; + self.tokens_consumed += 1; self.expected_tokens.clear(); // check after each token self.check_unknown_macro_variable(); @@ -2625,7 +2625,7 @@ impl<'a> Parser<'a> { } pub fn check_unknown_macro_variable(&mut self) { - if self.quote_depth == 0us { + if self.quote_depth == 0 { match self.token { token::SubstNt(name, _) => self.fatal(&format!("unknown macro variable `{}`", @@ -2694,7 +2694,7 @@ impl<'a> Parser<'a> { token_str)[]) }, /* we ought to allow different depths of unquotation */ - token::Dollar | token::SubstNt(..) if p.quote_depth > 0us => { + token::Dollar | token::SubstNt(..) if p.quote_depth > 0 => { p.parse_unquoted() } _ => { @@ -5633,7 +5633,7 @@ impl<'a> Parser<'a> { return Ok(item); } if self.token.is_keyword(keywords::Unsafe) && - self.look_ahead(1us, |t| t.is_keyword(keywords::Trait)) + self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) { // UNSAFE TRAIT ITEM self.expect_keyword(keywords::Unsafe); @@ -5650,7 +5650,7 @@ impl<'a> Parser<'a> { return Ok(item); } if self.token.is_keyword(keywords::Unsafe) && - self.look_ahead(1us, |t| t.is_keyword(keywords::Impl)) + self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) { // IMPL ITEM self.expect_keyword(keywords::Unsafe); @@ -5680,7 +5680,7 @@ impl<'a> Parser<'a> { return Ok(item); } if self.token.is_keyword(keywords::Unsafe) - && self.look_ahead(1us, |t| *t != token::OpenDelim(token::Brace)) { + && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) { // UNSAFE FUNCTION ITEM self.bump(); let abi = if self.eat_keyword(keywords::Extern) { @@ -5958,7 +5958,7 @@ impl<'a> Parser<'a> { } } } - let mut rename_to = path[path.len() - 1us]; + let mut rename_to = path[path.len() - 1]; let path = ast::Path { span: mk_sp(lo, self.last_span.hi), global: false, diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 70d6a5f695a8d..707b3c72ecdd7 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -132,15 +132,15 @@ pub fn buf_str(toks: &[Token], let mut i = left; let mut l = lim; let mut s = string::String::from_str("["); - while i != right && l != 0us { - l -= 1us; + while i != right && l != 0 { + l -= 1; if i != left { s.push_str(", "); } s.push_str(&format!("{}={}", szs[i], tok_str(&toks[i]))[]); - i += 1us; + i += 1; i %= n; } s.push(']'); @@ -326,8 +326,8 @@ impl Printer { if self.scan_stack_empty { self.left_total = 1; self.right_total = 1; - self.left = 0us; - self.right = 0us; + self.left = 0; + self.right = 0; } else { self.advance_right(); } debug!("pp Begin({})/buffer ~[{},{}]", b.offset, self.left, self.right); @@ -355,8 +355,8 @@ impl Printer { if self.scan_stack_empty { self.left_total = 1; self.right_total = 1; - self.left = 0us; - self.right = 0us; + self.left = 0; + self.right = 0; } else { self.advance_right(); } debug!("pp Break({})/buffer ~[{},{}]", b.offset, self.left, self.right); @@ -410,7 +410,7 @@ impl Printer { if self.scan_stack_empty { self.scan_stack_empty = false; } else { - self.top += 1us; + self.top += 1; self.top %= self.buf_len; assert!((self.top != self.bottom)); } @@ -422,7 +422,7 @@ impl Printer { if self.top == self.bottom { self.scan_stack_empty = true; } else { - self.top += self.buf_len - 1us; self.top %= self.buf_len; + self.top += self.buf_len - 1; self.top %= self.buf_len; } return x; } @@ -436,12 +436,12 @@ impl Printer { if self.top == self.bottom { self.scan_stack_empty = true; } else { - self.bottom += 1us; self.bottom %= self.buf_len; + self.bottom += 1; self.bottom %= self.buf_len; } return x; } pub fn advance_right(&mut self) { - self.right += 1us; + self.right += 1; self.right %= self.buf_len; assert!((self.right != self.left)); } @@ -471,7 +471,7 @@ impl Printer { break; } - self.left += 1us; + self.left += 1; self.left %= self.buf_len; left_size = self.size[self.left]; @@ -520,7 +520,7 @@ impl Printer { pub fn get_top(&mut self) -> PrintStackElem { let print_stack = &mut self.print_stack; let n = print_stack.len(); - if n != 0us { + if n != 0 { (*print_stack)[n - 1] } else { PrintStackElem { @@ -565,7 +565,7 @@ impl Printer { Token::End => { debug!("print End -> pop End"); let print_stack = &mut self.print_stack; - assert!((print_stack.len() != 0us)); + assert!((print_stack.len() != 0)); print_stack.pop().unwrap(); Ok(()) } @@ -667,11 +667,11 @@ pub fn spaces(p: &mut Printer, n: usize) -> old_io::IoResult<()> { } pub fn zerobreak(p: &mut Printer) -> old_io::IoResult<()> { - spaces(p, 0us) + spaces(p, 0) } pub fn space(p: &mut Printer) -> old_io::IoResult<()> { - spaces(p, 1us) + spaces(p, 1) } pub fn hardbreak(p: &mut Printer) -> old_io::IoResult<()> { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 5367ccc1357c9..a7ff486c634c5 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -92,10 +92,10 @@ pub fn rust_printer_annotated<'a>(writer: Box, } #[allow(non_upper_case_globals)] -pub const indent_unit: usize = 4us; +pub const indent_unit: usize = 4; #[allow(non_upper_case_globals)] -pub const default_columns: usize = 78us; +pub const default_columns: usize = 78; /// Requires you to pass an input filename and reader so that /// it can scan the input text for comments and literals to @@ -377,7 +377,7 @@ pub fn block_to_string(blk: &ast::Block) -> String { // containing cbox, will be closed by print-block at } try!(s.cbox(indent_unit)); // head-ibox, will be closed by print-block after { - try!(s.ibox(0us)); + try!(s.ibox(0)); s.print_block(blk) }) } @@ -516,7 +516,7 @@ impl<'a> State<'a> { pub fn bclose_maybe_open (&mut self, span: codemap::Span, indented: usize, close_box: bool) -> IoResult<()> { try!(self.maybe_print_comment(span.hi)); - try!(self.break_offset_if_not_bol(1us, -(indented as isize))); + try!(self.break_offset_if_not_bol(1, -(indented as isize))); try!(word(&mut self.s, "}")); if close_box { try!(self.end()); // close the outer-box @@ -591,7 +591,7 @@ impl<'a> State<'a> { pub fn commasep(&mut self, b: Breaks, elts: &[T], mut op: F) -> IoResult<()> where F: FnMut(&mut State, &T) -> IoResult<()>, { - try!(self.rbox(0us, b)); + try!(self.rbox(0, b)); let mut first = true; for elt in elts.iter() { if first { first = false; } else { try!(self.word_space(",")); } @@ -609,13 +609,13 @@ impl<'a> State<'a> { F: FnMut(&mut State, &T) -> IoResult<()>, G: FnMut(&T) -> codemap::Span, { - try!(self.rbox(0us, b)); + try!(self.rbox(0, b)); let len = elts.len(); - let mut i = 0us; + let mut i = 0; for elt in elts.iter() { try!(self.maybe_print_comment(get_span(elt).hi)); try!(op(self, elt)); - i += 1us; + i += 1; if i < len { try!(word(&mut self.s, ",")); try!(self.maybe_print_trailing_comment(get_span(elt), @@ -660,7 +660,7 @@ impl<'a> State<'a> { pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> { try!(self.maybe_print_comment(ty.span.lo)); - try!(self.ibox(0us)); + try!(self.ibox(0)); match ty.node { ast::TyVec(ref ty) => { try!(word(&mut self.s, "[")); @@ -880,7 +880,7 @@ impl<'a> State<'a> { } ast::ItemTy(ref ty, ref params) => { try!(self.ibox(indent_unit)); - try!(self.ibox(0us)); + try!(self.ibox(0)); try!(self.word_nbsp(&visibility_qualified(item.vis, "type")[])); try!(self.print_ident(item.ident)); try!(self.print_generics(params)); @@ -1277,7 +1277,7 @@ impl<'a> State<'a> { pub fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) -> IoResult<()> { - let mut count = 0us; + let mut count = 0; for attr in attrs.iter() { match attr.node.style { ast::AttrOuter => { @@ -1295,7 +1295,7 @@ impl<'a> State<'a> { pub fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) -> IoResult<()> { - let mut count = 0us; + let mut count = 0; for attr in attrs.iter() { match attr.node.style { ast::AttrInner => { @@ -1416,8 +1416,8 @@ impl<'a> State<'a> { match _else.node { // "another else-if" ast::ExprIf(ref i, ref then, ref e) => { - try!(self.cbox(indent_unit - 1us)); - try!(self.ibox(0us)); + try!(self.cbox(indent_unit - 1)); + try!(self.ibox(0)); try!(word(&mut self.s, " else if ")); try!(self.print_expr(&**i)); try!(space(&mut self.s)); @@ -1426,8 +1426,8 @@ impl<'a> State<'a> { } // "another else-if-let" ast::ExprIfLet(ref pat, ref expr, ref then, ref e) => { - try!(self.cbox(indent_unit - 1us)); - try!(self.ibox(0us)); + try!(self.cbox(indent_unit - 1)); + try!(self.ibox(0)); try!(word(&mut self.s, " else if let ")); try!(self.print_pat(&**pat)); try!(space(&mut self.s)); @@ -1439,8 +1439,8 @@ impl<'a> State<'a> { } // "final else" ast::ExprBlock(ref b) => { - try!(self.cbox(indent_unit - 1us)); - try!(self.ibox(0us)); + try!(self.cbox(indent_unit - 1)); + try!(self.ibox(0)); try!(word(&mut self.s, " else ")); self.print_block(&**b) } @@ -1606,7 +1606,7 @@ impl<'a> State<'a> { try!(self.print_expr(&*args[0])); try!(word(&mut self.s, ".")); try!(self.print_ident(ident.node)); - if tys.len() > 0us { + if tys.len() > 0 { try!(word(&mut self.s, "::<")); try!(self.commasep(Inconsistent, tys, |s, ty| s.print_type(&**ty))); @@ -1777,7 +1777,7 @@ impl<'a> State<'a> { // containing cbox, will be closed by print-block at } try!(self.cbox(indent_unit)); // head-box, will be closed by print-block after { - try!(self.ibox(0us)); + try!(self.ibox(0)); try!(self.print_block(&**blk)); } ast::ExprAssign(ref lhs, ref rhs) => { @@ -2154,7 +2154,7 @@ impl<'a> State<'a> { }, |f| f.node.pat.span)); if etc { - if fields.len() != 0us { try!(self.word_space(",")); } + if fields.len() != 0 { try!(self.word_space(",")); } try!(word(&mut self.s, "..")); } try!(space(&mut self.s)); @@ -2221,7 +2221,7 @@ impl<'a> State<'a> { try!(space(&mut self.s)); } try!(self.cbox(indent_unit)); - try!(self.ibox(0us)); + try!(self.ibox(0)); try!(self.print_outer_attributes(&arm.attrs[])); let mut first = true; for p in arm.pats.iter() { @@ -2307,7 +2307,7 @@ impl<'a> State<'a> { -> IoResult<()> { // It is unfortunate to duplicate the commasep logic, but we want the // self type and the args all in the same box. - try!(self.rbox(0us, Inconsistent)); + try!(self.rbox(0, Inconsistent)); let mut first = true; for &explicit_self in opt_explicit_self.iter() { let m = match explicit_self { @@ -2457,7 +2457,7 @@ impl<'a> State<'a> { try!(word(&mut self.s, "<")); let mut ints = Vec::new(); - for i in 0us..total { + for i in 0..total { ints.push(i); } @@ -2707,7 +2707,7 @@ impl<'a> State<'a> { if span.hi < (*cmnt).pos && (*cmnt).pos < next && span_line.line == comment_line.line { try!(self.print_comment(cmnt)); - self.cur_cmnt_and_lit.cur_cmnt += 1us; + self.cur_cmnt_and_lit.cur_cmnt += 1; } } _ => () @@ -2725,7 +2725,7 @@ impl<'a> State<'a> { match self.next_comment() { Some(ref cmnt) => { try!(self.print_comment(cmnt)); - self.cur_cmnt_and_lit.cur_cmnt += 1us; + self.cur_cmnt_and_lit.cur_cmnt += 1; } _ => break } @@ -2807,7 +2807,7 @@ impl<'a> State<'a> { while self.cur_cmnt_and_lit.cur_lit < lits.len() { let ltrl = (*lits)[self.cur_cmnt_and_lit.cur_lit].clone(); if ltrl.pos > pos { return None; } - self.cur_cmnt_and_lit.cur_lit += 1us; + self.cur_cmnt_and_lit.cur_lit += 1; if ltrl.pos == pos { return Some(ltrl); } } None @@ -2822,7 +2822,7 @@ impl<'a> State<'a> { Some(ref cmnt) => { if (*cmnt).pos < pos { try!(self.print_comment(cmnt)); - self.cur_cmnt_and_lit.cur_cmnt += 1us; + self.cur_cmnt_and_lit.cur_cmnt += 1; } else { break; } } _ => break @@ -2835,7 +2835,7 @@ impl<'a> State<'a> { cmnt: &comments::Comment) -> IoResult<()> { match cmnt.style { comments::Mixed => { - assert_eq!(cmnt.lines.len(), 1us); + assert_eq!(cmnt.lines.len(), 1); try!(zerobreak(&mut self.s)); try!(word(&mut self.s, &cmnt.lines[0][])); zerobreak(&mut self.s) @@ -2854,11 +2854,11 @@ impl<'a> State<'a> { } comments::Trailing => { try!(word(&mut self.s, " ")); - if cmnt.lines.len() == 1us { + if cmnt.lines.len() == 1 { try!(word(&mut self.s, &cmnt.lines[0][])); hardbreak(&mut self.s) } else { - try!(self.ibox(0us)); + try!(self.ibox(0)); for line in cmnt.lines.iter() { if !line.is_empty() { try!(word(&mut self.s, &line[])); diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index a7679adca2e17..61ce664d2c790 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -356,8 +356,8 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { let tparm_cnt = generics.ty_params.len(); // NB: inadequate check, but we're running // well before resolve, can't get too deep. - input_cnt == 1us - && no_output && tparm_cnt == 0us + input_cnt == 1 + && no_output && tparm_cnt == 0 } _ => false } From 4197e5fe03477eebcaaffa784d272b3dbdeb881d Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 2 Feb 2015 04:40:57 -0500 Subject: [PATCH 31/36] Fix discrepencies in the testing chapter Fixes #21501 --- src/doc/trpl/testing.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/doc/trpl/testing.md b/src/doc/trpl/testing.md index 1c93fd351b6e4..9c46c8724d497 100644 --- a/src/doc/trpl/testing.md +++ b/src/doc/trpl/testing.md @@ -552,9 +552,7 @@ extern crate test; # struct X; # impl X { fn iter(&self, _: F) where F: FnMut() -> T {} } let b = X; b.iter(|| { - let mut n = 1000_u32; - - test::black_box(&mut n); // pretend to modify `n` + let n = test::black_box(1000); range(0, n).fold(0, |a, b| a ^ b) }) @@ -569,7 +567,7 @@ Performing either of the above changes gives the following benchmarking results ```text running 1 test -test bench_xor_1000_ints ... bench: 1 ns/iter (+/- 0) +test bench_xor_1000_ints ... bench: 131 ns/iter (+/- 3) test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured ``` From fcf1a57cea9d608190ace07f90b38164b3d9c017 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Fri, 23 Jan 2015 16:43:16 -0500 Subject: [PATCH 32/36] Documenting libcore/char.rs --- src/libcore/char.rs | 194 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 174 insertions(+), 20 deletions(-) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 22bfd47893c97..70a42900553aa 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -67,7 +67,25 @@ static MAX_THREE_B: u32 = 0x10000u32; #[stable(feature = "rust1", since = "1.0.0")] pub const MAX: char = '\u{10ffff}'; -/// Converts from `u32` to a `char` +/// Converts a `u32` to an `Option`. +/// +/// # Examples +/// +/// ``` +/// use std::char; +/// +/// let c = char::from_u32(10084); // produces `Some(❤)` +/// assert_eq!(c, Some('❤')); +/// ``` +/// +/// An invalid character: +/// +/// ``` +/// use std::char; +/// +/// let none = char::from_u32(1114112); +/// assert_eq!(none, None); +/// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_u32(i: u32) -> Option { @@ -79,8 +97,7 @@ pub fn from_u32(i: u32) -> Option { } } -/// -/// Converts a number to the character representing it +/// Converts a number to the character representing it. /// /// # Return value /// @@ -91,6 +108,15 @@ pub fn from_u32(i: u32) -> Option { /// /// Panics if given an `radix` > 36. /// +/// # Examples +/// +/// ``` +/// use std::char; +/// +/// let c = char::from_digit(4, 10); +/// +/// assert_eq!(c, '4') +/// ``` #[inline] #[unstable(feature = "core", reason = "pending integer conventions")] pub fn from_digit(num: uint, radix: uint) -> Option { @@ -126,6 +152,16 @@ pub trait CharExt { /// # Panics /// /// Panics if given a radix > 36. + /// + /// # Examples + /// + /// ``` + /// let c = '1'; + /// + /// assert!(c.is_digit(10)); + /// + /// assert!('f'.is_digit(16)); + /// ``` #[unstable(feature = "core", reason = "pending integer conventions")] fn is_digit(self, radix: uint) -> bool; @@ -141,16 +177,53 @@ pub trait CharExt { /// # Panics /// /// Panics if given a radix outside the range [0..36]. + /// + /// # Examples + /// + /// ``` + /// let c = '1'; + /// + /// assert_eq!(1, c.to_digit(10)); + /// + /// assert_eq!(15, 'f'.to_digit(16)); + /// ``` #[unstable(feature = "core", reason = "pending integer conventions")] fn to_digit(self, radix: uint) -> Option; - /// Returns an iterator that yields the hexadecimal Unicode escape - /// of a character, as `char`s. + /// Returns an iterator that yields the hexadecimal Unicode escape of a character, as `char`s. + /// + /// All characters are escaped with Rust syntax of the form `\\u{NNNN}` where `NNNN` is the + /// shortest hexadecimal representation of the code point. + /// + /// # Examples + /// + /// ``` + /// for i in '❤'.escape_unicode() { + /// println!("{}", i); + /// } + /// ``` /// - /// All characters are escaped with Rust syntax of the form `\\u{NNNN}` - /// where `NNNN` is the shortest hexadecimal representation of the code - /// point. + /// This prints: + /// + /// ```text + /// \ + /// u + /// { + /// 2 + /// 7 + /// 6 + /// 4 + /// } + /// ``` + /// + /// Collecting into a `String`: + /// + /// ``` + /// let heart: String = '❤'.escape_unicode().collect(); + /// + /// assert_eq!(heart, r"\u{2764}"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn escape_unicode(self) -> EscapeUnicode; @@ -166,32 +239,113 @@ pub trait CharExt { /// escaped. /// * Any other chars in the range [0x20,0x7e] are not escaped. /// * Any other chars are given hex Unicode escapes; see `escape_unicode`. + /// + /// # Examples + /// + /// ``` + /// for i in '"'.escape_default() { + /// println!("{}", i); + /// } + /// ``` + /// + /// This prints: + /// + /// ```text + /// \ + /// " + /// ``` + /// + /// Collecting into a `String`: + /// + /// ``` + /// let quote: String = '"'.escape_default().collect(); + /// + /// assert_eq!(quote, r"\""); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn escape_default(self) -> EscapeDefault; - /// Returns the amount of bytes this character would need if encoded in - /// UTF-8. + /// Returns the number of bytes this character would need if encoded in UTF-8. + /// + /// # Examples + /// + /// ``` + /// let n = 'ß'.len_utf8(); + /// + /// assert_eq!(n, 2); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn len_utf8(self) -> uint; - /// Returns the amount of bytes this character would need if encoded in - /// UTF-16. + /// Returns the number of bytes this character would need if encoded in UTF-16. + /// + /// # Examples + /// + /// ``` + /// let n = 'ß'.len_utf16(); + /// + /// assert_eq!(n, 1); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn len_utf16(self) -> uint; - /// Encodes this character as UTF-8 into the provided byte buffer, - /// and then returns the number of bytes written. + /// Encodes this character as UTF-8 into the provided byte buffer, and then returns the number + /// of bytes written. + /// + /// If the buffer is not large enough, nothing will be written into it and a `None` will be + /// returned. + /// + /// # Examples + /// + /// In both of these examples, 'ß' takes two bytes to encode. + /// + /// ``` + /// let mut b = [0; 2]; /// - /// If the buffer is not large enough, nothing will be written into it - /// and a `None` will be returned. + /// let result = 'ß'.encode_utf8(&mut b); + /// + /// assert_eq!(result, Some(2)); + /// ``` + /// + /// A buffer that's too small: + /// + /// ``` + /// let mut b = [0; 1]; + /// + /// let result = 'ß'.encode_utf8(&mut b); + /// + /// assert_eq!(result, None); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn encode_utf8(self, dst: &mut [u8]) -> Option; - /// Encodes this character as UTF-16 into the provided `u16` buffer, - /// and then returns the number of `u16`s written. + /// Encodes this character as UTF-16 into the provided `u16` buffer, and then returns the + /// number of `u16`s written. + /// + /// If the buffer is not large enough, nothing will be written into it and a `None` will be + /// returned. + /// + /// # Examples + /// + /// In both of these examples, 'ß' takes one byte to encode. + /// + /// ``` + /// let mut b = [0; 1]; + /// + /// let result = 'ß'.encode_utf16(&mut b); + /// + /// assert_eq!(result, Some(1)); + /// ``` + /// + /// A buffer that's too small: + /// + /// ``` + /// let mut b = [0; 0]; + /// + /// let result = 'ß'.encode_utf8(&mut b); /// - /// If the buffer is not large enough, nothing will be written into it - /// and a `None` will be returned. + /// assert_eq!(result, None); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn encode_utf16(self, dst: &mut [u16]) -> Option; } From b9a67e32366bf111099ca73b0fc500eca408a52e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Sun, 18 Jan 2015 15:44:41 +0100 Subject: [PATCH 33/36] Do not warn when deriving `Copy` for raw pointers Fixes #21272 and #21296 --- src/librustc/lint/builtin.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index e8e8d35fe072a..d69f1f8c23124 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -592,7 +592,15 @@ impl LintPass for RawPointerDerive { return } let did = match item.node { - ast::ItemImpl(..) => { + ast::ItemImpl(_, _, _, ref t_ref_opt, _, _) => { + // Deriving the Copy trait does not cause a warning + if let &Some(ref trait_ref) = t_ref_opt { + let def_id = ty::trait_ref_to_def_id(cx.tcx, trait_ref); + if Some(def_id) == cx.tcx.lang_items.copy_trait() { + return + } + } + match ty::node_id_to_type(cx.tcx, item.id).sty { ty::ty_enum(did, _) => did, ty::ty_struct(did, _) => did, From 8b84f097fbc8d381fd59c8915c50672758913f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Sun, 18 Jan 2015 15:57:08 +0100 Subject: [PATCH 34/36] Add test for #21296 --- src/test/run-pass/issue-21296.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/test/run-pass/issue-21296.rs diff --git a/src/test/run-pass/issue-21296.rs b/src/test/run-pass/issue-21296.rs new file mode 100644 index 0000000000000..f91fb064ae27f --- /dev/null +++ b/src/test/run-pass/issue-21296.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[forbid(raw_pointer_derive)] +#[derive(Copy)] +struct Test(*const i32); + +fn main() {} From 431baa9a19fefeab66ad9399d2271aa1efb69c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Mon, 2 Feb 2015 18:58:24 +0100 Subject: [PATCH 35/36] Remove a bogus match from type_is_unique The inner match will always result in `true`, so we can as well replace it with just that. --- src/librustc/middle/ty.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 1544db8ce4a3f..143b3261ed720 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3099,10 +3099,7 @@ pub fn type_is_unsafe_ptr(ty: Ty) -> bool { pub fn type_is_unique(ty: Ty) -> bool { match ty.sty { - ty_uniq(_) => match ty.sty { - ty_trait(..) => false, - _ => true - }, + ty_uniq(_) => true, _ => false } } From 9ece22ee00033cdf0b6b418c451112c92c8ad922 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 2 Feb 2015 11:04:58 -0800 Subject: [PATCH 36/36] Test fixes and rebase conflicts --- src/compiletest/util.rs | 8 ++++---- src/libcore/cell.rs | 2 +- src/libcore/char.rs | 8 ++++---- src/libstd/sys/unix/os.rs | 18 ++++++++++++------ src/rustllvm/llvm-auto-clean-trigger | 2 +- src/test/compile-fail/issue-2149.rs | 2 +- .../lint-unknown-feature-default.rs | 2 ++ .../use-as-where-use-ends-with-mod-sep.rs | 3 ++- src/test/compile-fail/use-mod-4.rs | 15 +++++++++++++++ src/test/compile-fail/use-mod.rs | 3 --- src/test/run-make/tools.mk | 5 +++-- src/test/run-pass/env-home-dir.rs | 6 +++++- 12 files changed, 50 insertions(+), 24 deletions(-) create mode 100644 src/test/compile-fail/use-mod-4.rs diff --git a/src/compiletest/util.rs b/src/compiletest/util.rs index 078d992277af3..078eb7bba20a4 100644 --- a/src/compiletest/util.rs +++ b/src/compiletest/util.rs @@ -11,7 +11,7 @@ use common::Config; #[cfg(target_os = "windows")] -use std::os::getenv; +use std::env; /// Conversion table from triple OS name to Rust SYSNAME static OS_TABLE: &'static [(&'static str, &'static str)] = &[ @@ -40,11 +40,11 @@ pub fn make_new_path(path: &str) -> String { // Windows just uses PATH as the library search path, so we have to // maintain the current value while adding our own - match getenv(lib_path_env_var()) { - Some(curr) => { + match env::var_string(lib_path_env_var()) { + Ok(curr) => { format!("{}{}{}", path, path_div(), curr) } - None => path.to_string() + Err(..) => path.to_string() } } diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 15e745b0e713e..c82d8c531d243 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -267,7 +267,7 @@ pub struct RefCell { } /// An enumeration of values returned from the `state` method on a `RefCell`. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, PartialEq, Debug)] #[unstable(feature = "std_misc")] pub enum BorrowState { /// The cell is currently being read, there is at least one active `borrow`. diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 70a42900553aa..28e0247f00a25 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -115,7 +115,7 @@ pub fn from_u32(i: u32) -> Option { /// /// let c = char::from_digit(4, 10); /// -/// assert_eq!(c, '4') +/// assert_eq!(c, Some('4')); /// ``` #[inline] #[unstable(feature = "core", reason = "pending integer conventions")] @@ -183,9 +183,9 @@ pub trait CharExt { /// ``` /// let c = '1'; /// - /// assert_eq!(1, c.to_digit(10)); + /// assert_eq!(c.to_digit(10), Some(1)); /// - /// assert_eq!(15, 'f'.to_digit(16)); + /// assert_eq!('f'.to_digit(16), Some(15)); /// ``` #[unstable(feature = "core", reason = "pending integer conventions")] @@ -260,7 +260,7 @@ pub trait CharExt { /// ``` /// let quote: String = '"'.escape_default().collect(); /// - /// assert_eq!(quote, r"\""); + /// assert_eq!(quote, "\\\""); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn escape_default(self) -> EscapeDefault; diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index e93c3794a5a25..b3f3796294580 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -116,8 +116,7 @@ pub fn chdir(p: &Path) -> IoResult<()> { } pub struct SplitPaths<'a> { - iter: iter::Map<&'a [u8], Path, - slice::Split<'a, u8, fn(&u8) -> bool>, + iter: iter::Map bool>, fn(&'a [u8]) -> Path>, } @@ -450,7 +449,16 @@ pub fn temp_dir() -> Path { } pub fn home_dir() -> Option { - getenv("HOME".as_os_str()).or_else(|| unsafe { + return getenv("HOME".as_os_str()).or_else(|| unsafe { + fallback() + }).map(|os| { + Path::new(os.into_vec()) + }); + + #[cfg(target_os = "android")] + unsafe fn fallback() -> Option { None } + #[cfg(not(target_os = "android"))] + unsafe fn fallback() -> Option { let mut amt = match libc::sysconf(c::_SC_GETPW_R_SIZE_MAX) { n if n < 0 => 512 as usize, n => n as usize, @@ -470,7 +478,5 @@ pub fn home_dir() -> Option { let bytes = ffi::c_str_to_bytes(&ptr).to_vec(); return Some(OsStringExt::from_vec(bytes)) } - }).map(|os| { - Path::new(os.into_vec()) - }) + } } diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index e159e9729b635..c8003bb9581fb 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2015-01-30 +2015-02-02 diff --git a/src/test/compile-fail/issue-2149.rs b/src/test/compile-fail/issue-2149.rs index 998b9587b965e..45b7bebfc281e 100644 --- a/src/test/compile-fail/issue-2149.rs +++ b/src/test/compile-fail/issue-2149.rs @@ -16,7 +16,7 @@ impl vec_monad for Vec { fn bind(&self, mut f: F) where F: FnMut(A) -> Vec { let mut r = panic!(); for elt in self { r = r + f(*elt); } - //~^ ERROR the type of this value must be known + //~^ ERROR binary operation `+` cannot be applied to type `collections::vec::Vec` } } fn main() { diff --git a/src/test/compile-fail/lint-unknown-feature-default.rs b/src/test/compile-fail/lint-unknown-feature-default.rs index d5e9cc630c359..afd1a3933bf85 100644 --- a/src/test/compile-fail/lint-unknown-feature-default.rs +++ b/src/test/compile-fail/lint-unknown-feature-default.rs @@ -10,6 +10,8 @@ // Tests the default for the unused_features lint +#![deny(warnings)] + #![feature(this_is_not_a_feature)] //~ ERROR: unused or unknown feature fn main() { } diff --git a/src/test/compile-fail/use-as-where-use-ends-with-mod-sep.rs b/src/test/compile-fail/use-as-where-use-ends-with-mod-sep.rs index ef443fc125deb..524fd01b94c51 100644 --- a/src/test/compile-fail/use-as-where-use-ends-with-mod-sep.rs +++ b/src/test/compile-fail/use-as-where-use-ends-with-mod-sep.rs @@ -8,4 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::any:: as foo; //~ ERROR expected identifier or `{` or `*`, found `as` +use std::any:: as foo; //~ ERROR expected identifier, found keyword `as` +//~^ ERROR: expected one of `::`, `;`, or `as`, found `foo` diff --git a/src/test/compile-fail/use-mod-4.rs b/src/test/compile-fail/use-mod-4.rs new file mode 100644 index 0000000000000..a8b551b5376c9 --- /dev/null +++ b/src/test/compile-fail/use-mod-4.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use foo::self; +//~^ ERROR expected identifier, found keyword `self` + +fn main() {} + diff --git a/src/test/compile-fail/use-mod.rs b/src/test/compile-fail/use-mod.rs index 493991835e8a2..15640e386dfa0 100644 --- a/src/test/compile-fail/use-mod.rs +++ b/src/test/compile-fail/use-mod.rs @@ -19,9 +19,6 @@ use foo::bar::{ use {self}; //~^ ERROR `self` import can only appear in an import list with a non-empty prefix -use foo::self; -//~^ ERROR `self` imports are only allowed within a { } list - mod foo { pub mod bar { pub struct Bar; diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk index accb2f7faa719..23c422bc7a7fe 100644 --- a/src/test/run-make/tools.mk +++ b/src/test/run-make/tools.mk @@ -53,14 +53,15 @@ endif # Extra flags needed to compile a working executable with the standard library ifdef IS_WINDOWS - EXTRACFLAGS := -lws2_32 + EXTRACFLAGS := -lws2_32 -luserenv else ifeq ($(shell uname),Darwin) else ifeq ($(shell uname),FreeBSD) EXTRACFLAGS := -lm -lpthread -lgcc_s +else ifeq ($(shell uname),OpenBSD) - EXTRACFLAGS := -lm -lpthread + EXTRACFLAGS := -lm -lpthread else EXTRACFLAGS := -lm -lrt -ldl -lpthread endif diff --git a/src/test/run-pass/env-home-dir.rs b/src/test/run-pass/env-home-dir.rs index 5623e98c92885..0e1ab73c02d08 100644 --- a/src/test/run-pass/env-home-dir.rs +++ b/src/test/run-pass/env-home-dir.rs @@ -18,7 +18,11 @@ fn main() { assert!(home_dir() == Some(Path::new("/home/MountainView"))); remove_var("HOME"); - assert!(home_dir().is_some()); + if cfg!(target_os = "android") { + assert!(home_dir().is_none()); + } else { + assert!(home_dir().is_some()); + } } #[cfg(windows)]