From 892b50ba74c12c3fa397d283f16b9209b27aad8f Mon Sep 17 00:00:00 2001 From: arcnmx Date: Fri, 6 Nov 2015 04:51:03 -0500 Subject: [PATCH 1/5] Preserve public static items across LTO --- src/librustc/metadata/csearch.rs | 5 +++++ src/librustc/metadata/decoder.rs | 8 ++++++++ src/librustc_trans/trans/base.rs | 3 ++- src/test/run-make/issue-14500/foo.c | 3 ++- src/test/run-make/issue-14500/foo.rs | 3 +++ 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index e04df51dc6862..09dec375a69a5 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -344,6 +344,11 @@ pub fn is_const_fn(cstore: &cstore::CStore, did: DefId) -> bool { decoder::is_const_fn(&*cdata, did.index) } +pub fn is_static(cstore: &cstore::CStore, did: DefId) -> bool { + let cdata = cstore.get_crate_data(did.krate); + decoder::is_static(&*cdata, did.index) +} + pub fn is_impl(cstore: &cstore::CStore, did: DefId) -> bool { let cdata = cstore.get_crate_data(did.krate); decoder::is_impl(&*cdata, did.index) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 0780252fc887b..b102213eff021 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1425,6 +1425,14 @@ pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool { } } +pub fn is_static(cdata: Cmd, id: DefIndex) -> bool { + let item_doc = cdata.lookup_item(id); + match item_family(item_doc) { + ImmStatic | MutStatic => true, + _ => false, + } +} + pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool { let item_doc = cdata.lookup_item(id); match item_family(item_doc) { diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index a536060efbd0f..4a99f2142d790 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2875,7 +2875,8 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>, sess.cstore.iter_crate_data(|cnum, _| { let syms = csearch::get_reachable_ids(&sess.cstore, cnum); reachable_symbols.extend(syms.into_iter().filter(|did| { - csearch::is_extern_fn(&sess.cstore, *did, shared_ccx.tcx()) + csearch::is_extern_fn(&sess.cstore, *did, shared_ccx.tcx()) || + csearch::is_static(&sess.cstore, *did) }).map(|did| { csearch::get_symbol(&sess.cstore, did) })); diff --git a/src/test/run-make/issue-14500/foo.c b/src/test/run-make/issue-14500/foo.c index 25098ac479d06..e84b5509c5036 100644 --- a/src/test/run-make/issue-14500/foo.c +++ b/src/test/run-make/issue-14500/foo.c @@ -9,8 +9,9 @@ // except according to those terms. extern void foo(); +extern char FOO_STATIC; int main() { foo(); - return 0; + return (int)FOO_STATIC; } diff --git a/src/test/run-make/issue-14500/foo.rs b/src/test/run-make/issue-14500/foo.rs index ceca907403f91..a91d8d6a21df4 100644 --- a/src/test/run-make/issue-14500/foo.rs +++ b/src/test/run-make/issue-14500/foo.rs @@ -10,3 +10,6 @@ #[no_mangle] pub extern fn foo() {} + +#[no_mangle] +pub static FOO_STATIC: u8 = 0; From 43e1f9ac5ad90090667379b468ebd1b03a6c92a2 Mon Sep 17 00:00:00 2001 From: angelsl Date: Sat, 7 Nov 2015 00:26:44 +0800 Subject: [PATCH 2/5] Update compiler-rt --- src/compiler-rt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler-rt b/src/compiler-rt index 93d0384373750..b6087e82ba138 160000 --- a/src/compiler-rt +++ b/src/compiler-rt @@ -1 +1 @@ -Subproject commit 93d0384373750b52996fd7f8249adaae39f562d8 +Subproject commit b6087e82ba1384c4af3adf2dc68e92316f0d4caf From 5eacf66c48db342b0e1056531307dbe318d9f16d Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Fri, 6 Nov 2015 17:42:53 +0100 Subject: [PATCH 3/5] Make a note about "gigabyte" Fixes #28461 --- src/doc/trpl/the-stack-and-the-heap.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doc/trpl/the-stack-and-the-heap.md b/src/doc/trpl/the-stack-and-the-heap.md index 0bc2ca263d5b7..f835322ee716e 100644 --- a/src/doc/trpl/the-stack-and-the-heap.md +++ b/src/doc/trpl/the-stack-and-the-heap.md @@ -74,7 +74,9 @@ visualize what’s going on with memory. Your operating system presents a view o memory to your program that’s pretty simple: a huge list of addresses, from 0 to a large number, representing how much RAM your computer has. For example, if you have a gigabyte of RAM, your addresses go from `0` to `1,073,741,823`. That -number comes from 230, the number of bytes in a gigabyte. +number comes from 230, the number of bytes in a gigabyte. [^gigabyte] + +[^gigabyte]: ‘Gigabyte’ can mean two things: 10^9, or 2^30. The SI standard resolved this by stating that ‘gigabyte’ is 10^9, and ‘gibibyte’ is 2^30. However, very few people use this terminology, and rely on context to differentiate. We follow in that tradition here. This memory is kind of like a giant array: addresses start at zero and go up to the final number. So here’s a diagram of our first stack frame: From 586eb3d50fa964fe3d9bd7f36b6f2a4341774e00 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Thu, 5 Nov 2015 15:58:08 +0100 Subject: [PATCH 4/5] Add multi-line string literals to TRPL Fixes #29591 --- src/doc/trpl/strings.md | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/doc/trpl/strings.md b/src/doc/trpl/strings.md index 1848366498981..f61b4d8ed8d5c 100644 --- a/src/doc/trpl/strings.md +++ b/src/doc/trpl/strings.md @@ -24,9 +24,29 @@ compiled program, and exists for the entire duration it runs. The `greeting` binding is a reference to this statically allocated string. String slices have a fixed size, and cannot be mutated. -A `String`, on the other hand, is a heap-allocated string. This string is -growable, and is also guaranteed to be UTF-8. `String`s are commonly created by -converting from a string slice using the `to_string` method. +String literals can span multiple lines. There are two forms. The first will +include the newline and the leading spaces: + +```rust +let s = "foo + bar"; + +assert_eq!("foo\n bar", s); +``` + +The second, with a `\`, does not trim the spaces: + +```rust +let s = "foo\ + bar"; + +assert_eq!("foobar", s); +``` + +Rust has more than just `&str`s though. A `String`, is a heap-allocated string. +This string is growable, and is also guaranteed to be UTF-8. `String`s are +commonly created by converting from a string slice using the `to_string` +method. ```rust let mut s = "Hello".to_string(); // mut s: String From 801f83ff65fd51423cf64aada972722f44b9d789 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Thu, 5 Nov 2015 17:29:36 +0100 Subject: [PATCH 5/5] sleep_ms -> sleep Now that thread::sleep is a real thing, let's use it Fixes #29621 --- src/doc/trpl/concurrency.md | 12 ++++++++---- src/doc/trpl/dining-philosophers.md | 23 +++++++++++++---------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/doc/trpl/concurrency.md b/src/doc/trpl/concurrency.md index 7b3f13a3ed223..cc6cfc2f4a097 100644 --- a/src/doc/trpl/concurrency.md +++ b/src/doc/trpl/concurrency.md @@ -121,6 +121,7 @@ languages. It will not compile: ```ignore use std::thread; +use std::time::Duration; fn main() { let mut data = vec![1, 2, 3]; @@ -131,7 +132,7 @@ fn main() { }); } - thread::sleep_ms(50); + thread::sleep(Duration::from_millis(50)); } ``` @@ -165,6 +166,7 @@ indivisible operations which can't have data races. ```ignore use std::thread; use std::sync::Arc; +use std::time::Duration; fn main() { let mut data = Arc::new(vec![1, 2, 3]); @@ -176,7 +178,7 @@ fn main() { }); } - thread::sleep_ms(50); + thread::sleep(Duration::from_millis(50)); } ``` @@ -207,6 +209,7 @@ Here's the working version: ```rust use std::sync::{Arc, Mutex}; use std::thread; +use std::time::Duration; fn main() { let data = Arc::new(Mutex::new(vec![1, 2, 3])); @@ -219,7 +222,7 @@ fn main() { }); } - thread::sleep_ms(50); + thread::sleep(Duration::from_millis(50)); } ``` @@ -241,6 +244,7 @@ Let's examine the body of the thread more closely: ```rust # use std::sync::{Arc, Mutex}; # use std::thread; +# use std::time::Duration; # fn main() { # let data = Arc::new(Mutex::new(vec![1, 2, 3])); # for i in 0..3 { @@ -250,7 +254,7 @@ thread::spawn(move || { data[i] += 1; }); # } -# thread::sleep_ms(50); +# thread::sleep(Duration::from_millis(50)); # } ``` diff --git a/src/doc/trpl/dining-philosophers.md b/src/doc/trpl/dining-philosophers.md index e81ae4648ad43..5f66a5b9e297c 100644 --- a/src/doc/trpl/dining-philosophers.md +++ b/src/doc/trpl/dining-philosophers.md @@ -264,6 +264,7 @@ eat. Here’s the next version: ```rust use std::thread; +use std::time::Duration; struct Philosopher { name: String, @@ -279,7 +280,7 @@ impl Philosopher { fn eat(&self) { println!("{} is eating.", self.name); - thread::sleep_ms(1000); + thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); } @@ -313,13 +314,13 @@ from the standard library, and so we need to `use` it. fn eat(&self) { println!("{} is eating.", self.name); - thread::sleep_ms(1000); + thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); } ``` -We now print out two messages, with a `sleep_ms()` in the middle. This will +We now print out two messages, with a `sleep` in the middle. This will simulate the time it takes a philosopher to eat. If you run this program, you should see each philosopher eat in turn: @@ -345,6 +346,7 @@ Here’s the next iteration: ```rust use std::thread; +use std::time::Duration; struct Philosopher { name: String, @@ -360,7 +362,7 @@ impl Philosopher { fn eat(&self) { println!("{} is eating.", self.name); - thread::sleep_ms(1000); + thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); } @@ -493,6 +495,7 @@ Let’s modify the program to use the `Table`: ```rust use std::thread; +use std::time::Duration; use std::sync::{Mutex, Arc}; struct Philosopher { @@ -512,12 +515,12 @@ impl Philosopher { fn eat(&self, table: &Table) { let _left = table.forks[self.left].lock().unwrap(); - thread::sleep_ms(150); + thread::sleep(Duration::from_millis(150)); let _right = table.forks[self.right].lock().unwrap(); println!("{} is eating.", self.name); - thread::sleep_ms(1000); + thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); } @@ -598,12 +601,12 @@ We now need to construct those `left` and `right` values, so we add them to ```rust,ignore fn eat(&self, table: &Table) { let _left = table.forks[self.left].lock().unwrap(); - thread::sleep_ms(150); + thread::sleep(Duration::from_millis(150)); let _right = table.forks[self.right].lock().unwrap(); println!("{} is eating.", self.name); - thread::sleep_ms(1000); + thread::sleep(Duration::from_millis(1000)); println!("{} is done eating.", self.name); } @@ -614,8 +617,8 @@ We have three new lines. We’ve added an argument, `table`. We access the the fork at that particular index. That gives us access to the `Mutex` at that index, and we call `lock()` on it. If the mutex is currently being accessed by someone else, we’ll block until it becomes available. We have also a call to -`thread::sleep_ms` between the moment first fork is picked and the moment the -second forked is picked, as the process of picking up the fork is not +`thread::sleep` between the moment the first fork is picked and the moment the +second forked is picked, as the process of picking up the fork is not immediate. The call to `lock()` might fail, and if it does, we want to crash. In this