From 18bf88407aa1b164aec5f393f552217366511b8b Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Sun, 19 May 2013 18:13:14 +0200 Subject: [PATCH 01/24] Use assert_eq! rather than assert! where possible --- src/libstd/arc.rs | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index df49771258e29..fb546468c7f43 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -501,7 +501,7 @@ mod tests { let arc_v = p.recv(); let v = copy *arc::get::<~[int]>(&arc_v); - assert!(v[3] == 4); + assert_eq!(v[3],4); }; let c = p.recv(); @@ -545,7 +545,7 @@ mod tests { do arc2.access_cond |one, cond| { cond.signal(); // Parent should fail when it wakes up. - assert!(*one == 0); + assert_eq!(*one, 0); } } @@ -562,11 +562,11 @@ mod tests { let arc2 = ~arc.clone(); do task::try || { do arc2.access |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } }; do arc.access |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] #[should_fail] #[ignore(cfg(windows))] @@ -575,11 +575,11 @@ mod tests { let arc2 = (*arc).clone(); do task::try || { do arc2.write |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } }; do arc.read |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] #[should_fail] #[ignore(cfg(windows))] @@ -588,11 +588,11 @@ mod tests { let arc2 = (*arc).clone(); do task::try || { do arc2.write |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } }; do arc.write |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] #[should_fail] #[ignore(cfg(windows))] @@ -602,12 +602,12 @@ mod tests { do task::try || { do arc2.write_downgrade |mut write_mode| { do write_mode.write |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } } }; do arc.write |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] #[ignore(cfg(windows))] @@ -616,11 +616,11 @@ mod tests { let arc2 = (*arc).clone(); do task::try || { do arc2.read |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } }; do arc.read |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] #[ignore(cfg(windows))] @@ -629,11 +629,11 @@ mod tests { let arc2 = (*arc).clone(); do task::try || { do arc2.read |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } }; do arc.write |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] #[ignore(cfg(windows))] @@ -644,12 +644,12 @@ mod tests { do arc2.write_downgrade |write_mode| { let read_mode = arc2.downgrade(write_mode); do (&read_mode).read |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } } }; do arc.write |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] @@ -691,7 +691,7 @@ mod tests { // Wait for writer to finish p.recv(); do arc.read |num| { - assert!(*num == 10); + assert_eq!(*num, 10); } } #[test] @@ -713,7 +713,7 @@ mod tests { do task::spawn || { rp1.recv(); // wait for downgrader to give go-ahead do arcn.read |state| { - assert!(*state == 31337); + assert_eq!(*state, 31337); rc2.send(()); } } @@ -725,7 +725,7 @@ mod tests { do task::spawn || { wp1.recv(); do arc2.write_cond |state, cond| { - assert!(*state == 0); + assert_eq!(*state, 0); *state = 42; cond.signal(); } @@ -733,7 +733,7 @@ mod tests { do arc2.write |state| { // This shouldn't happen until after the downgrade read // section, and all other readers, finish. - assert!(*state == 31337); + assert_eq!(*state, 31337); *state = 42; } wc2.send(()); @@ -746,7 +746,7 @@ mod tests { while *state == 0 { cond.wait(); } - assert!(*state == 42); + assert_eq!(*state, 42); *state = 31337; // send to other readers for reader_convos.each |x| { @@ -764,7 +764,7 @@ mod tests { } } wc1.send(()); // tell writer to try again - assert!(*state == 31337); + assert_eq!(*state, 31337); } } From 20033c99906eeadebdbf5480e13fe5ac55c5a4d7 Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Sun, 19 May 2013 18:14:01 +0200 Subject: [PATCH 02/24] Typo corrected and updated copyright years --- src/libstd/arc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index fb546468c7f43..cac0f38470393 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -21,7 +21,7 @@ use core::unstable::sync::UnsafeAtomicRcBox; use core::ptr; use core::task; -/// As sync::condvar, a mechanism for unlock-and-descheduling and signalling. +/// As sync::condvar, a mechanism for unlock-and-descheduling and signaling. pub struct Condvar<'self> { is_mutex: bool, failed: &'self mut bool, From efd965cde7850e74005861d06de79dbd629bb214 Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Sun, 19 May 2013 20:19:16 +0200 Subject: [PATCH 03/24] Add the get method to std::arc::ARC --- src/libstd/arc.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index cac0f38470393..e99b1c7692512 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -96,6 +96,11 @@ pub fn get<'a, T:Const + Owned>(rc: &'a ARC) -> &'a T { unsafe { &*rc.x.get_immut() } } +impl ARC { + pub fn get<'a>(&'a self) -> &'a T { + get(self) + } +} /** * Duplicate an atomically reference counted wrapper. * @@ -507,7 +512,8 @@ mod tests { let c = p.recv(); c.send(arc::clone(&arc_v)); - assert!((*arc::get(&arc_v))[2] == 3); + assert_eq!((*arc::get(&arc_v))[2], 3); + assert_eq!(arc_v.get()[4], 5); info!(arc_v); } From f0f4d2d044299030c0658ef7b421d6f3ceb93467 Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Sun, 19 May 2013 21:05:52 +0200 Subject: [PATCH 04/24] Implement the get function on ARC from the method --- src/libstd/arc.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index e99b1c7692512..a08d13d758a92 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -93,12 +93,12 @@ pub fn ARC(data: T) -> ARC { * wrapper. */ pub fn get<'a, T:Const + Owned>(rc: &'a ARC) -> &'a T { - unsafe { &*rc.x.get_immut() } + rc.get() } -impl ARC { +impl ARC { pub fn get<'a>(&'a self) -> &'a T { - get(self) + unsafe { &*self.x.get_immut() } } } /** From e0b1bdca5b56a104d8c221cb3bbb7eb16b5fcec4 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 19 May 2013 12:06:39 -0700 Subject: [PATCH 05/24] Add additional documentation in core::io. Added docs for stdout, stderr, print, and println. --- src/libcore/io.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 77b486ca44619..820d810a36f8c 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -1561,13 +1561,55 @@ pub fn buffered_file_writer(path: &Path) -> Result<@Writer, ~str> { // FIXME (#2004) it would be great if this could be a const // FIXME (#2004) why are these different from the way stdin() is // implemented? + + +/** +* Gives a `Writer` which allows you to write to the standard output. +* +* # Examples +* ~~~ +* let stdout = core::io::stdout(); +* stdout.write_str("hello\n"); +* ~~~ +*/ pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) } + +/** +* Gives a `Writer` which allows you to write to standard error. +* +* # Examples +* ~~~ +* let stderr = core::io::stderr(); +* stderr.write_str("hello\n"); +* ~~~ +*/ pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) } +/** +* Prints a string to standard output. +* +* This string will not have an implicit newline at the end. If you want +* an implicit newline, please see `println`. +* +* # Examples +* ~~~ +* core::io::print("hello"); +* ~~~ +*/ pub fn print(s: &str) { stdout().write_str(s); } +/** +* Prints a string to standard output, followed by a newline. +* +* If you do not want an implicit newline, please see `print`. +* +* # Examples +* ~~~ +* core::io::println("hello"); +* ~~~ +*/ pub fn println(s: &str) { stdout().write_line(s); } From a389d86fa46d4a01b7839560a8851d84b7b2153d Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 19 May 2013 12:33:01 -0700 Subject: [PATCH 06/24] Add docs for stdin in core::io. --- src/libcore/io.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 77b486ca44619..677903433e01c 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -1010,6 +1010,16 @@ pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader { // top-level functions that take a reader, or a set of default methods on // reader (which can then be called reader) +/** +* Gives a `Reader` that allows you to read values from standard input. +* +* # Examples +* ~~~ +* let stdin = core::io::stdin(); +* let line = stdin.read_line(); +* core::io::print(line); +* ~~~ +*/ pub fn stdin() -> @Reader { unsafe { @rustrt::rust_get_stdin() as @Reader From 929050de73c1edb22211fa05e891068fe9a1a0d2 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 19 May 2013 12:42:00 -0700 Subject: [PATCH 07/24] Added note about prelude inclusion. --- src/libcore/io.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 820d810a36f8c..feceb9f4b17d7 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -1593,7 +1593,8 @@ pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) } * * # Examples * ~~~ -* core::io::print("hello"); +* // print is imported into the prelude, and so is always available. +* print("hello"); * ~~~ */ pub fn print(s: &str) { @@ -1607,7 +1608,8 @@ pub fn print(s: &str) { * * # Examples * ~~~ -* core::io::println("hello"); +* // println is imported into the prelude, and so is always available. +* println("hello"); * ~~~ */ pub fn println(s: &str) { From 507ca420bcbf6dcaac1d3f04a6a5b4e51cccf286 Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Sun, 19 May 2013 22:35:36 +0200 Subject: [PATCH 08/24] Add an example --- src/libstd/arc.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index a08d13d758a92..470cd531e86e7 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -8,9 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/** +/*! * Concurrency-enabled mechanisms for sharing mutable and/or immutable state * between tasks. + * + * # Example + * + * In this example, a large vector of floats is shared between several tasks. + * With simple pipes, without ARC, a copy would have to be made for each task. + * + * ~~~ + * # extern mod std; + * # use std::arc; + * let numbers=vec::from_fn(100, |ind| (ind as float)*rand::random()); + * let shared_numbers=arc::ARC(numbers); + * + * for 10.times { + * let (port, chan) = stream(); + * chan.send(shared_numbers.clone()); + * + * do spawn { + * let shared_numbers=port.recv(); + * let local_numbers=shared_numbers.get(); + * + * // Work with the local numbers + * } + * } + * ~~~ */ use sync; From 99a170469e68e72a0e306c5f3d6c0364d4cdbcfb Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Sun, 19 May 2013 22:43:32 +0200 Subject: [PATCH 09/24] Typos in the example --- src/libstd/arc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index 470cd531e86e7..130deb38f3336 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -18,8 +18,8 @@ * With simple pipes, without ARC, a copy would have to be made for each task. * * ~~~ - * # extern mod std; - * # use std::arc; + * extern mod std; + * use std::arc; * let numbers=vec::from_fn(100, |ind| (ind as float)*rand::random()); * let shared_numbers=arc::ARC(numbers); * From 58777272857526eb301bfedd909e6826e5edf716 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 19 May 2013 15:31:19 -0700 Subject: [PATCH 10/24] Fix trailing whitespace --- src/libcore/io.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index feceb9f4b17d7..2060964173d37 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -1587,7 +1587,7 @@ pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) } /** * Prints a string to standard output. -* +* * This string will not have an implicit newline at the end. If you want * an implicit newline, please see `println`. * @@ -1603,7 +1603,7 @@ pub fn print(s: &str) { /** * Prints a string to standard output, followed by a newline. -* +* * If you do not want an implicit newline, please see `print`. * * # Examples From e02716e6d3a65bde24f49207274a74a22790a201 Mon Sep 17 00:00:00 2001 From: Tom Lee Date: Sat, 11 May 2013 21:46:30 -0700 Subject: [PATCH 11/24] Reexport static trait methods on traits in the same module. --- src/librustc/metadata/encoder.rs | 6 ++++-- .../auxiliary/mod_trait_with_static_methods_lib.rs | 10 ++++++++++ .../run-pass/trait_with_static_methods_cross_crate.rs | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 8c21998768e95..78adee4b4f2f1 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -386,8 +386,10 @@ fn encode_reexported_static_methods(ecx: @EncodeContext, match ecx.tcx.trait_methods_cache.find(&exp.def_id) { Some(methods) => { match ecx.tcx.items.find(&exp.def_id.node) { - Some(&ast_map::node_item(_, path)) => { - if mod_path != *path { + Some(&ast_map::node_item(item, path)) => { + let interner = ecx.tcx.sess.parse_sess.interner; + let original_name = ecx.tcx.sess.str_of(item.ident); + if mod_path != *path || *exp.name != *original_name { for methods.each |&m| { if m.explicit_self == ast::sty_static { encode_reexported_static_method(ecx, diff --git a/src/test/auxiliary/mod_trait_with_static_methods_lib.rs b/src/test/auxiliary/mod_trait_with_static_methods_lib.rs index 2099c6a2f2f2f..3591ff7931855 100644 --- a/src/test/auxiliary/mod_trait_with_static_methods_lib.rs +++ b/src/test/auxiliary/mod_trait_with_static_methods_lib.rs @@ -9,6 +9,15 @@ // except according to those terms. pub use sub_foo::Foo; +pub use Baz = self::Bar; + +pub trait Bar { + pub fn bar() -> Self; +} + +impl Bar for int { + pub fn bar() -> int { 84 } +} pub mod sub_foo { pub trait Foo { @@ -18,4 +27,5 @@ pub mod sub_foo { impl Foo for int { pub fn foo() -> int { 42 } } + } diff --git a/src/test/run-pass/trait_with_static_methods_cross_crate.rs b/src/test/run-pass/trait_with_static_methods_cross_crate.rs index 20dcbf3267b70..4402881c43ddd 100644 --- a/src/test/run-pass/trait_with_static_methods_cross_crate.rs +++ b/src/test/run-pass/trait_with_static_methods_cross_crate.rs @@ -13,7 +13,9 @@ extern mod mod_trait_with_static_methods_lib; use mod_trait_with_static_methods_lib::Foo; +use mod_trait_with_static_methods_lib::Baz; pub fn main() { assert_eq!(42, Foo::foo()); + assert_eq!(84, Baz::bar()); } From cac97d7ee565eef14b9e7385d1c088c1eb0a9295 Mon Sep 17 00:00:00 2001 From: Tom Lee Date: Sun, 12 May 2013 12:19:28 -0700 Subject: [PATCH 12/24] Remove unused variable. --- src/librustc/metadata/encoder.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 78adee4b4f2f1..110d17b9b15bf 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -387,7 +387,6 @@ fn encode_reexported_static_methods(ecx: @EncodeContext, Some(methods) => { match ecx.tcx.items.find(&exp.def_id.node) { Some(&ast_map::node_item(item, path)) => { - let interner = ecx.tcx.sess.parse_sess.interner; let original_name = ecx.tcx.sess.str_of(item.ident); if mod_path != *path || *exp.name != *original_name { for methods.each |&m| { From e3a91f60c58d537945abc4c83b1b9f6ddcbe21fe Mon Sep 17 00:00:00 2001 From: Tom Lee Date: Sat, 18 May 2013 21:31:55 -0700 Subject: [PATCH 13/24] Explain an odd conditional check. --- src/librustc/metadata/encoder.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 110d17b9b15bf..460da5d60b33f 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -388,6 +388,17 @@ fn encode_reexported_static_methods(ecx: @EncodeContext, match ecx.tcx.items.find(&exp.def_id.node) { Some(&ast_map::node_item(item, path)) => { let original_name = ecx.tcx.sess.str_of(item.ident); + + // + // We don't need to reexport static methods on traits + // declared in the same module as our `pub use ...` since + // that's done when we encode the trait item. + // + // The only exception is when the reexport *changes* the + // name e.g. `pub use Foo = self::Bar` -- we have + // encoded metadata for static methods relative to Bar, + // but not yet for Foo. + // if mod_path != *path || *exp.name != *original_name { for methods.each |&m| { if m.explicit_self == ast::sty_static { From b1e805694b914613ec30619764bec961e78bbbac Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 19 May 2013 18:59:21 -0700 Subject: [PATCH 14/24] Add a better introduction for the io module. Let's actually give a top-level description of what's in here, eh? --- src/libcore/io.rs | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 77b486ca44619..d23f2fa7e2c75 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -10,7 +10,37 @@ /*! -Basic input/output +The `io` module contains basic input and output routines. + +A quick summary: + +## `Reader` and `Writer` traits + +These traits define the simplest amount of methods that anything that can do +input and output should implement. + +## `ReaderUtil` and `WriterUtil` traits + +Richer methods that allow you to do more. `Reader` only lets you read a certain +amount of bytes into a buffer, while `ReaderUtil` allows you to read a whole +line, for example. + +Generally, these richer methods are probably the ones you want to actually +use in day-to-day Rust. + +Furthermore, because there is an implementation of `ReaderUtil` for +``, when your input or output code implements `Reader`, you get +all of these methods for free. + +## `print` and `println` + +These very useful functions are defined here. You generally don't need to +import them, though, as the prelude already does. + +## `stdin`, `stdout`, and `stderr` + +These functions return references to the classic three file descriptors. They +implement `Reader` and `Writer`, where appropriate. */ From e42fcb958cd89d11dbe8f493cfac0a1fca4b1bb1 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sun, 19 May 2013 16:03:52 -0400 Subject: [PATCH 15/24] Implement unimplemented const binops --- src/librustc/lib/llvm.rs | 5 ++ src/librustc/middle/trans/consts.rs | 56 +++++++++++--- src/test/run-pass/const-binops.rs | 116 ++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 src/test/run-pass/const-binops.rs diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index d06bf1480c989..cdc128c6eeb61 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -220,6 +220,7 @@ pub mod llvm { use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef}; use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef}; use super::{ValueRef}; + use super::{IntPredicate, RealPredicate}; use core::libc::{c_char, c_int, c_longlong, c_uint, c_ulonglong}; @@ -451,6 +452,10 @@ pub mod llvm { /* all zeroes */ #[fast_ffi] pub unsafe fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef; + #[fast_ffi] + pub unsafe fn LLVMConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; + #[fast_ffi] + pub unsafe fn LLVMConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; /* only for int/vector */ #[fast_ffi] pub unsafe fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index e08cc536a701f..6df523976f2b0 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -9,8 +9,10 @@ // except according to those terms. use back::abi; -use lib::llvm::{llvm, SetLinkage, PrivateLinkage, - ValueRef, TypeRef, Bool, True, False}; +use lib::llvm::{llvm, SetLinkage, PrivateLinkage, ValueRef, TypeRef, Bool, True, False}; +use lib::llvm::{IntEQ, IntNE, IntUGT, IntUGE, IntULT, IntULE, IntSGT, IntSGE, IntSLT, IntSLE, + RealOEQ, RealOGT, RealOGE, RealOLT, RealOLE, RealONE}; + use metadata::csearch; use middle::const_eval; use middle::trans::adt; @@ -280,8 +282,8 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { else if signed { llvm::LLVMConstSRem(te1, te2) } else { llvm::LLVMConstURem(te1, te2) } } - ast::and | - ast::or => cx.sess.span_unimpl(e.span, "binop logic"), + ast::and => llvm::LLVMConstAnd(te1, te2), + ast::or => llvm::LLVMConstOr(te1, te2), ast::bitxor => llvm::LLVMConstXor(te1, te2), ast::bitand => llvm::LLVMConstAnd(te1, te2), ast::bitor => llvm::LLVMConstOr(te1, te2), @@ -290,14 +292,44 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { if signed { llvm::LLVMConstAShr(te1, te2) } else { llvm::LLVMConstLShr(te1, te2) } } - ast::eq | - ast::lt | - ast::le | - ast::ne | - ast::ge | - ast::gt => cx.sess.span_unimpl(e.span, "binop comparator") - } - } + ast::eq => { + if is_float { llvm::LLVMConstFCmp(RealOEQ, te1, te2) } + else { llvm::LLVMConstICmp(IntEQ, te1, te2) } + }, + ast::lt => { + if is_float { llvm::LLVMConstFCmp(RealOLT, te1, te2) } + else { + if signed { llvm::LLVMConstICmp(IntSLT, te1, te2) } + else { llvm::LLVMConstICmp(IntULT, te1, te2) } + } + }, + ast::le => { + if is_float { llvm::LLVMConstFCmp(RealOLE, te1, te2) } + else { + if signed { llvm::LLVMConstICmp(IntSLE, te1, te2) } + else { llvm::LLVMConstICmp(IntULE, te1, te2) } + } + }, + ast::ne => { + if is_float { llvm::LLVMConstFCmp(RealONE, te1, te2) } + else { llvm::LLVMConstICmp(IntNE, te1, te2) } + }, + ast::ge => { + if is_float { llvm::LLVMConstFCmp(RealOGE, te1, te2) } + else { + if signed { llvm::LLVMConstICmp(IntSGE, te1, te2) } + else { llvm::LLVMConstICmp(IntUGE, te1, te2) } + } + }, + ast::gt => { + if is_float { llvm::LLVMConstFCmp(RealOGT, te1, te2) } + else { + if signed { llvm::LLVMConstICmp(IntSGT, te1, te2) } + else { llvm::LLVMConstICmp(IntUGT, te1, te2) } + } + }, + }; + }, ast::expr_unary(u, e) => { let te = const_expr(cx, e); let ty = ty::expr_ty(cx.tcx, e); diff --git a/src/test/run-pass/const-binops.rs b/src/test/run-pass/const-binops.rs new file mode 100644 index 0000000000000..507f68dc3a146 --- /dev/null +++ b/src/test/run-pass/const-binops.rs @@ -0,0 +1,116 @@ +static a: int = -4 + 3; +static a2: uint = 3 + 3; +static b: float = 3.0 + 2.7; + +static c: int = 3 - 4; +static d: uint = 3 - 3; +static e: float = 3.0 - 2.7; + +static e2: int = -3 * 3; +static f: uint = 3 * 3; +static g: float = 3.3 * 3.3; + +static h: int = 3 / -1; +static i: uint = 3 / 3; +static j: float = 3.3 / 3.3; + +static n: bool = true && false; + +static o: bool = true || false; + +static p: int = 3 & 1; +static q: uint = 1 & 3; + +static r: int = 3 | 1; +static s: uint = 1 | 3; + +static t: int = 3 ^ 1; +static u: uint = 1 ^ 3; + +static v: int = 1 << 3; + +// NOTE: better shr coverage +static w: int = 1024 >> 4; +static x: uint = 1024 >> 4; + +static y: bool = 1 == 1; +static z: bool = 1.0 == 1.0; + +static aa: bool = 1 <= 2; +static ab: bool = -1 <= 2; +static ac: bool = 1.0 <= 2; + +static ad: bool = 1 < 2; +static ae: bool = -1 < 2; +static af: bool = 1.0 < 2; + +static ag: bool = 1 != 2; +static ah: bool = -1 != 2; +static ai: bool = 1.0 != 2; + +static aj: bool = 2 >= 1; +static ak: bool = 2 >= -2; +static al: bool = 1.0 >= -2; + +static am: bool = 2 > 1; +static an: bool = 2 > -2; +static ao: bool = 1.0 > -2; + +fn main() { + assert_eq!(a, -1); + assert_eq!(a2, 6); + assert_approx_eq!(b, 5.7); + + assert_eq!(c, -1); + assert_eq!(d, 0); + assert_approx_eq!(e, -0.3); + + assert_eq!(e2, -9); + assert_eq!(f, 9); + assert_approx_eq!(g, 10.89); + + assert_eq!(h, -3); + assert_eq!(i, 1); + assert_approx_eq!(j, 1.0); + + assert_eq!(n, false); + + assert_eq!(o, true); + + assert_eq!(p, 1); + assert_eq!(q, 1); + + assert_eq!(r, 3); + assert_eq!(s, 3); + + assert_eq!(t, 2); + assert_eq!(u, 2); + + assert_eq!(v, 8); + + assert_eq!(w, 64); + assert_eq!(x, 64); + + assert_eq!(y, true); + assert_eq!(z, true); + + assert_eq!(aa, true); + assert_eq!(ab, true); + assert_eq!(ac, true); + + assert_eq!(ad, true); + assert_eq!(ae, true); + assert_eq!(af, true); + + assert_eq!(ag, true); + assert_eq!(ah, true); + assert_eq!(ai, true); + + assert_eq!(aj, true); + assert_eq!(ak, true); + assert_eq!(al, true); + + assert_eq!(am, true); + assert_eq!(an, true); + assert_eq!(ao, true); +} From b97642758fb2c060ec689c540576d308fc081f1e Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sun, 19 May 2013 20:18:56 -0400 Subject: [PATCH 16/24] Fix LLVMConst{I,F}Cmp --- src/librustc/lib/llvm.rs | 15 ++++++++++--- src/librustc/middle/trans/consts.rs | 35 +++++++++++++++-------------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index cdc128c6eeb61..bf3d09d848dad 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -220,7 +220,6 @@ pub mod llvm { use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef}; use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef}; use super::{ValueRef}; - use super::{IntPredicate, RealPredicate}; use core::libc::{c_char, c_int, c_longlong, c_uint, c_ulonglong}; @@ -453,9 +452,9 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef; #[fast_ffi] - pub unsafe fn LLVMConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; + pub unsafe fn LLVMConstICmp(Pred: c_uint, V1: ValueRef, V2: ValueRef) -> ValueRef; #[fast_ffi] - pub unsafe fn LLVMConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; + pub unsafe fn LLVMConstFCmp(Pred: c_uint, V1: ValueRef, V2: ValueRef) -> ValueRef; /* only for int/vector */ #[fast_ffi] pub unsafe fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; @@ -1919,6 +1918,16 @@ pub fn SetLinkage(Global: ValueRef, Link: Linkage) { } } +pub fn ConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef { + unsafe { + llvm::LLVMConstICmp(Pred as c_uint, V1, V2) + } +} +pub fn ConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef { + unsafe { + llvm::LLVMConstICmp(Pred as c_uint, V1, V2) + } +} /* Memory-managed object interface to type handles. */ pub struct TypeNames { diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 6df523976f2b0..22014fa330414 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -9,7 +9,8 @@ // except according to those terms. use back::abi; -use lib::llvm::{llvm, SetLinkage, PrivateLinkage, ValueRef, TypeRef, Bool, True, False}; +use lib::llvm::{llvm, ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, TypeRef, Bool, + True, False}; use lib::llvm::{IntEQ, IntNE, IntUGT, IntUGE, IntULT, IntULE, IntSGT, IntSGE, IntSLT, IntSLE, RealOEQ, RealOGT, RealOGE, RealOLT, RealOLE, RealONE}; @@ -293,39 +294,39 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { else { llvm::LLVMConstLShr(te1, te2) } } ast::eq => { - if is_float { llvm::LLVMConstFCmp(RealOEQ, te1, te2) } - else { llvm::LLVMConstICmp(IntEQ, te1, te2) } + if is_float { ConstFCmp(RealOEQ, te1, te2) } + else { ConstICmp(IntEQ, te1, te2) } }, ast::lt => { - if is_float { llvm::LLVMConstFCmp(RealOLT, te1, te2) } + if is_float { ConstFCmp(RealOLT, te1, te2) } else { - if signed { llvm::LLVMConstICmp(IntSLT, te1, te2) } - else { llvm::LLVMConstICmp(IntULT, te1, te2) } + if signed { ConstICmp(IntSLT, te1, te2) } + else { ConstICmp(IntULT, te1, te2) } } }, ast::le => { - if is_float { llvm::LLVMConstFCmp(RealOLE, te1, te2) } + if is_float { ConstFCmp(RealOLE, te1, te2) } else { - if signed { llvm::LLVMConstICmp(IntSLE, te1, te2) } - else { llvm::LLVMConstICmp(IntULE, te1, te2) } + if signed { ConstICmp(IntSLE, te1, te2) } + else { ConstICmp(IntULE, te1, te2) } } }, ast::ne => { - if is_float { llvm::LLVMConstFCmp(RealONE, te1, te2) } - else { llvm::LLVMConstICmp(IntNE, te1, te2) } + if is_float { ConstFCmp(RealONE, te1, te2) } + else { ConstICmp(IntNE, te1, te2) } }, ast::ge => { - if is_float { llvm::LLVMConstFCmp(RealOGE, te1, te2) } + if is_float { ConstFCmp(RealOGE, te1, te2) } else { - if signed { llvm::LLVMConstICmp(IntSGE, te1, te2) } - else { llvm::LLVMConstICmp(IntUGE, te1, te2) } + if signed { ConstICmp(IntSGE, te1, te2) } + else { ConstICmp(IntUGE, te1, te2) } } }, ast::gt => { - if is_float { llvm::LLVMConstFCmp(RealOGT, te1, te2) } + if is_float { ConstFCmp(RealOGT, te1, te2) } else { - if signed { llvm::LLVMConstICmp(IntSGT, te1, te2) } - else { llvm::LLVMConstICmp(IntUGT, te1, te2) } + if signed { ConstICmp(IntSGT, te1, te2) } + else { ConstICmp(IntUGT, te1, te2) } } }, }; From 808c5b8d4e479b5e0fd336f8290fda2f0c429257 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sun, 19 May 2013 22:08:59 -0400 Subject: [PATCH 17/24] Test fixes, use LLVMConstFCmp in ConstFCmp --- src/librustc/lib/llvm.rs | 12 ++++++------ src/test/run-pass/const-binops.rs | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index bf3d09d848dad..9198991e5360e 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -9,7 +9,7 @@ // except according to those terms. use core::hashmap::HashMap; -use core::libc::c_uint; +use core::libc::{c_uint, c_ushort}; pub type Opcode = u32; pub type Bool = c_uint; @@ -221,7 +221,7 @@ pub mod llvm { use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef}; use super::{ValueRef}; - use core::libc::{c_char, c_int, c_longlong, c_uint, c_ulonglong}; + use core::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong}; #[link_args = "-Lrustllvm -lrustllvm"] #[link_name = "rustllvm"] @@ -452,9 +452,9 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef; #[fast_ffi] - pub unsafe fn LLVMConstICmp(Pred: c_uint, V1: ValueRef, V2: ValueRef) -> ValueRef; + pub unsafe fn LLVMConstICmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef) -> ValueRef; #[fast_ffi] - pub unsafe fn LLVMConstFCmp(Pred: c_uint, V1: ValueRef, V2: ValueRef) -> ValueRef; + pub unsafe fn LLVMConstFCmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef) -> ValueRef; /* only for int/vector */ #[fast_ffi] pub unsafe fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; @@ -1920,12 +1920,12 @@ pub fn SetLinkage(Global: ValueRef, Link: Linkage) { pub fn ConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef { unsafe { - llvm::LLVMConstICmp(Pred as c_uint, V1, V2) + llvm::LLVMConstICmp(Pred as c_ushort, V1, V2) } } pub fn ConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef { unsafe { - llvm::LLVMConstICmp(Pred as c_uint, V1, V2) + llvm::LLVMConstFCmp(Pred as c_ushort, V1, V2) } } /* Memory-managed object interface to type handles. */ diff --git a/src/test/run-pass/const-binops.rs b/src/test/run-pass/const-binops.rs index 507f68dc3a146..cd87ca3ab537e 100644 --- a/src/test/run-pass/const-binops.rs +++ b/src/test/run-pass/const-binops.rs @@ -38,23 +38,23 @@ static z: bool = 1.0 == 1.0; static aa: bool = 1 <= 2; static ab: bool = -1 <= 2; -static ac: bool = 1.0 <= 2; +static ac: bool = 1.0 <= 2.0; static ad: bool = 1 < 2; static ae: bool = -1 < 2; -static af: bool = 1.0 < 2; +static af: bool = 1.0 < 2.0; static ag: bool = 1 != 2; static ah: bool = -1 != 2; -static ai: bool = 1.0 != 2; +static ai: bool = 1.0 != 2.0; static aj: bool = 2 >= 1; static ak: bool = 2 >= -2; -static al: bool = 1.0 >= -2; +static al: bool = 1.0 >= -2.0; static am: bool = 2 > 1; static an: bool = 2 > -2; -static ao: bool = 1.0 > -2; +static ao: bool = 1.0 > -2.0; fn main() { assert_eq!(a, -1); @@ -63,7 +63,7 @@ fn main() { assert_eq!(c, -1); assert_eq!(d, 0); - assert_approx_eq!(e, -0.3); + assert_approx_eq!(e, 0.3); assert_eq!(e2, -9); assert_eq!(f, 9); From 91d3e7f1a0757bf314ab3a4c4be8f910e2355d35 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 19 May 2013 20:39:02 -0600 Subject: [PATCH 18/24] Fix wording per feedback Thanks @catamorphism! --- src/libcore/io.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index d23f2fa7e2c75..ffb49177b64f2 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -16,13 +16,13 @@ A quick summary: ## `Reader` and `Writer` traits -These traits define the simplest amount of methods that anything that can do +These traits define the minimal set of methods that anything that can do input and output should implement. ## `ReaderUtil` and `WriterUtil` traits Richer methods that allow you to do more. `Reader` only lets you read a certain -amount of bytes into a buffer, while `ReaderUtil` allows you to read a whole +number of bytes into a buffer, while `ReaderUtil` allows you to read a whole line, for example. Generally, these richer methods are probably the ones you want to actually From e89bec3133099de3c90946f8db666dd72214816b Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Mon, 20 May 2013 08:20:56 +0200 Subject: [PATCH 19/24] Rebase --- src/libstd/arc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index f0158acfa79fa..97e541d4bbcb6 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -501,7 +501,7 @@ mod tests { let arc_v = p.recv(); let v = copy *arc::get::<~[int]>(&arc_v); - assert_eq!(v[3], 4); + assert_eq!(v[3],4); }; let c = p.recv(); From b7040720c9a2452379251c69f442960fdcb49071 Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Sun, 19 May 2013 18:14:01 +0200 Subject: [PATCH 20/24] Typo corrected and updated copyright years --- src/libstd/arc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index 97e541d4bbcb6..c1def777d73bf 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -21,7 +21,7 @@ use core::unstable::sync::UnsafeAtomicRcBox; use core::ptr; use core::task; -/// As sync::condvar, a mechanism for unlock-and-descheduling and signalling. +/// As sync::condvar, a mechanism for unlock-and-descheduling and signaling. pub struct Condvar<'self> { is_mutex: bool, failed: &'self mut bool, From 7bb89e96a5dfe28b5d717192aa7e1a3b0f16536e Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Sun, 19 May 2013 20:19:16 +0200 Subject: [PATCH 21/24] Add the get method to std::arc::ARC --- src/libstd/arc.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index c1def777d73bf..e99b1c7692512 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -96,6 +96,11 @@ pub fn get<'a, T:Const + Owned>(rc: &'a ARC) -> &'a T { unsafe { &*rc.x.get_immut() } } +impl ARC { + pub fn get<'a>(&'a self) -> &'a T { + get(self) + } +} /** * Duplicate an atomically reference counted wrapper. * @@ -508,6 +513,7 @@ mod tests { c.send(arc::clone(&arc_v)); assert_eq!((*arc::get(&arc_v))[2], 3); + assert_eq!(arc_v.get()[4], 5); info!(arc_v); } From 8c34414737e03141fc9ba183baeab3dded089361 Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Sun, 19 May 2013 21:05:52 +0200 Subject: [PATCH 22/24] Implement the get function on ARC from the method --- src/libstd/arc.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index e99b1c7692512..a08d13d758a92 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -93,12 +93,12 @@ pub fn ARC(data: T) -> ARC { * wrapper. */ pub fn get<'a, T:Const + Owned>(rc: &'a ARC) -> &'a T { - unsafe { &*rc.x.get_immut() } + rc.get() } -impl ARC { +impl ARC { pub fn get<'a>(&'a self) -> &'a T { - get(self) + unsafe { &*self.x.get_immut() } } } /** From 4ca089e72dd58d64d1c62fdccfb9aae2cc0615b5 Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Sun, 19 May 2013 22:35:36 +0200 Subject: [PATCH 23/24] Add an example --- src/libstd/arc.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index a08d13d758a92..470cd531e86e7 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -8,9 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/** +/*! * Concurrency-enabled mechanisms for sharing mutable and/or immutable state * between tasks. + * + * # Example + * + * In this example, a large vector of floats is shared between several tasks. + * With simple pipes, without ARC, a copy would have to be made for each task. + * + * ~~~ + * # extern mod std; + * # use std::arc; + * let numbers=vec::from_fn(100, |ind| (ind as float)*rand::random()); + * let shared_numbers=arc::ARC(numbers); + * + * for 10.times { + * let (port, chan) = stream(); + * chan.send(shared_numbers.clone()); + * + * do spawn { + * let shared_numbers=port.recv(); + * let local_numbers=shared_numbers.get(); + * + * // Work with the local numbers + * } + * } + * ~~~ */ use sync; From dfb9c5340177e80ea73462fcfb4cd4075fd02af9 Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Sun, 19 May 2013 22:43:32 +0200 Subject: [PATCH 24/24] Typos in the example --- src/libstd/arc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index 470cd531e86e7..130deb38f3336 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -18,8 +18,8 @@ * With simple pipes, without ARC, a copy would have to be made for each task. * * ~~~ - * # extern mod std; - * # use std::arc; + * extern mod std; + * use std::arc; * let numbers=vec::from_fn(100, |ind| (ind as float)*rand::random()); * let shared_numbers=arc::ARC(numbers); *