diff --git a/mk/docs.mk b/mk/docs.mk index 90f85079464bb..dab40cb165431 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -43,7 +43,9 @@ L10N_LANGS := ja # The options are passed to the documentation generators. RUSTDOC_HTML_OPTS_NO_CSS = --markdown-before-content=doc/version_info.html \ - --markdown-in-header=doc/favicon.inc --markdown-after-content=doc/footer.inc + --markdown-in-header=doc/favicon.inc \ + --markdown-after-content=doc/footer.inc \ + --markdown-playground-url='http://play.rust-lang.org/' RUSTDOC_HTML_OPTS = $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css rust.css diff --git a/mk/tests.mk b/mk/tests.mk index c67fa0042f814..dacea3a4bfc49 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -818,7 +818,7 @@ endif ifeq ($(2),$$(CFG_BUILD)) $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-crate-$(4)): $$(CRATEDOCTESTDEP_$(1)_$(2)_$(3)_$(4)) @$$(call E, run doc-crate-$(4) [$(2)]) - $$(Q)$$(RUSTDOC_$(1)_T_$(2)_H_$(3)) --test \ + $$(Q)$$(RUSTDOC_$(1)_T_$(2)_H_$(3)) --test --cfg dox \ $$(CRATEFILE_$(4)) --test-args "$$(TESTARGS)" && touch $$@ else $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-crate-$(4)): diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 10428244b7115..8da984a414bda 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -1545,7 +1545,7 @@ fn disassemble_extract(config: &Config, _props: &TestProps, fn count_extracted_lines(p: &Path) -> uint { let x = File::open(&p.with_extension("ll")).read_to_end().unwrap(); let x = str::from_utf8(x.as_slice()).unwrap(); - x.lines().len() + x.lines().count() } diff --git a/src/doc/footer.inc b/src/doc/footer.inc index a103a4908f6bf..4e7d60586f23d 100644 --- a/src/doc/footer.inc +++ b/src/doc/footer.inc @@ -5,3 +5,5 @@ or the MIT license, at your opt

This file may not be copied, modified, or distributed except according to those terms.

+ + diff --git a/src/doc/guide-macros.md b/src/doc/guide-macros.md index b86a6aa1b619c..45745c7b7bc7a 100644 --- a/src/doc/guide-macros.md +++ b/src/doc/guide-macros.md @@ -11,7 +11,7 @@ which both pattern-match on their input and both return early in one case, doing nothing otherwise: ~~~~ -# enum T { SpecialA(uint), SpecialB(uint) }; +# enum T { SpecialA(uint), SpecialB(uint) } # fn f() -> uint { # let input_1 = SpecialA(0); # let input_2 = SpecialA(0); @@ -37,7 +37,8 @@ lightweight custom syntax extensions, themselves defined using the the pattern in the above code: ~~~~ -# enum T { SpecialA(uint), SpecialB(uint) }; +# #![feature(macro_rules)] +# enum T { SpecialA(uint), SpecialB(uint) } # fn f() -> uint { # let input_1 = SpecialA(0); # let input_2 = SpecialA(0); @@ -55,6 +56,7 @@ early_return!(input_1 SpecialA); early_return!(input_2 SpecialB); # return 0; # } +# fn main() {} ~~~~ Macros are defined in pattern-matching style: in the above example, the text @@ -155,7 +157,8 @@ separator token (a comma-separated list could be written `$(...),*`), and `+` instead of `*` to mean "at least one". ~~~~ -# enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)}; +# #![feature(macro_rules)] +# enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)} # fn f() -> uint { # let input_1 = SpecialA(0); # let input_2 = SpecialA(0); @@ -175,6 +178,7 @@ early_return!(input_1, [SpecialA|SpecialC|SpecialD]); early_return!(input_2, [SpecialB]); # return 0; # } +# fn main() {} ~~~~ ### Transcription @@ -215,9 +219,10 @@ solves the problem. Now consider code like the following: ~~~~ -# enum T1 { Good1(T2, uint), Bad1}; +# #![feature(macro_rules)] +# enum T1 { Good1(T2, uint), Bad1} # struct T2 { body: T3 } -# enum T3 { Good2(uint), Bad2}; +# enum T3 { Good2(uint), Bad2} # fn f(x: T1) -> uint { match x { Good1(g1, val) => { @@ -232,6 +237,7 @@ match x { _ => return 0 // default value } # } +# fn main() {} ~~~~ All the complicated stuff is deeply indented, and the error-handling code is @@ -240,6 +246,7 @@ a match, but with a syntax that suits the problem better. The following macro can solve the problem: ~~~~ +# #![feature(macro_rules)] macro_rules! biased_match ( // special case: `let (x) = ...` is illegal, so use `let x = ...` instead ( ($e:expr) ~ ($p:pat) else $err:stmt ; @@ -261,9 +268,9 @@ macro_rules! biased_match ( ) ) -# enum T1 { Good1(T2, uint), Bad1}; +# enum T1 { Good1(T2, uint), Bad1} # struct T2 { body: T3 } -# enum T3 { Good2(uint), Bad2}; +# enum T3 { Good2(uint), Bad2} # fn f(x: T1) -> uint { biased_match!((x) ~ (Good1(g1, val)) else { return 0 }; binds g1, val ) @@ -273,6 +280,7 @@ biased_match!((g1.body) ~ (Good2(result) ) // complicated stuff goes here return result + val; # } +# fn main() {} ~~~~ This solves the indentation problem. But if we have a lot of chained matches @@ -280,6 +288,8 @@ like this, we might prefer to write a single macro invocation. The input pattern we want is clear: ~~~~ +# #![feature(macro_rules)] +# fn main() {} # macro_rules! b( ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )* binds $( $bind_res:ident ),* @@ -301,14 +311,18 @@ process the semicolon-terminated lines, one-by-one. So, we want the following input patterns: ~~~~ +# #![feature(macro_rules)] # macro_rules! b( ( binds $( $bind_res:ident ),* ) # => (0)) +# fn main() {} ~~~~ ...and: ~~~~ +# #![feature(macro_rules)] +# fn main() {} # macro_rules! b( ( ($e :expr) ~ ($p :pat) else $err :stmt ; $( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )* @@ -322,6 +336,8 @@ The resulting macro looks like this. Note that the separation into piece of syntax (the `let`) which we only want to transcribe once. ~~~~ +# #![feature(macro_rules)] +# fn main() { macro_rules! biased_match_rec ( // Handle the first layer @@ -365,9 +381,9 @@ macro_rules! biased_match ( ) -# enum T1 { Good1(T2, uint), Bad1}; +# enum T1 { Good1(T2, uint), Bad1} # struct T2 { body: T3 } -# enum T3 { Good2(uint), Bad2}; +# enum T3 { Good2(uint), Bad2} # fn f(x: T1) -> uint { biased_match!( (x) ~ (Good1(g1, val)) else { return 0 }; @@ -376,6 +392,7 @@ biased_match!( // complicated stuff goes here return result + val; # } +# } ~~~~ This technique applies to many cases where transcribing a result all at once is not possible. diff --git a/src/doc/guide-unsafe.md b/src/doc/guide-unsafe.md index e0a48682963b4..1431c8a5c9ae4 100644 --- a/src/doc/guide-unsafe.md +++ b/src/doc/guide-unsafe.md @@ -523,6 +523,7 @@ vectors provided from C, using idiomatic Rust practices. ``` #![no_std] +#![feature(globs)] # extern crate libc; extern crate core; diff --git a/src/doc/rust.css b/src/doc/rust.css index d60dd54a67d14..3957231a195a5 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -313,6 +313,19 @@ table th { padding: 5px; } +/* Code snippets */ + +.rusttest { display: none; } +pre.rust { position: relative; } +pre.rust a { transform: scaleX(-1); } +.test-arrow { + display: inline-block; + position: absolute; + top: 0; + right: 10px; + font-size: 150%; +} + @media (min-width: 1170px) { pre { font-size: 15px; diff --git a/src/doc/rust.md b/src/doc/rust.md index 06c9da2fe0e5a..619e24af36063 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -1260,6 +1260,8 @@ a = Cat; Enumeration constructors can have either named or unnamed fields: ~~~~ +# #![feature(struct_variant)] +# fn main() { enum Animal { Dog (String, f64), Cat { name: String, weight: f64 } @@ -1267,6 +1269,7 @@ enum Animal { let mut a: Animal = Dog("Cocoa".to_string(), 37.2); a = Cat { name: "Spotty".to_string(), weight: 2.7 }; +# } ~~~~ In this example, `Cat` is a _struct-like enum variant_, diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 917704a2faacd..3b4164ffbc618 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -774,6 +774,7 @@ fn point_from_direction(dir: Direction) -> Point { Enum variants may also be structs. For example: ~~~~ +# #![feature(struct_variant)] use std::f64; # struct Point { x: f64, y: f64 } # fn square(x: f64) -> f64 { x * x } @@ -789,6 +790,7 @@ fn area(sh: Shape) -> f64 { } } } +# fn main() {} ~~~~ > *Note:* This feature of the compiler is currently gated behind the @@ -3046,6 +3048,7 @@ use farm::{chicken, cow}; 2. Import everything in a module with a wildcard: ~~~ +# #![feature(globs)] use farm::*; # mod farm { # pub fn cow() { println!("Bat-chicken? What a stupid name!") } diff --git a/src/libcollections/bitv.rs b/src/libcollections/bitv.rs index 11c777034fe6e..58f081b25e3e5 100644 --- a/src/libcollections/bitv.rs +++ b/src/libcollections/bitv.rs @@ -241,17 +241,17 @@ enum Op {Union, Intersect, Assign, Difference} /// bv.set(5, true); /// bv.set(7, true); /// println!("{}", bv.to_str()); -/// println!("total bits set to true: {}", bv.iter().count(|x| x)); +/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count()); /// /// // flip all values in bitvector, producing non-primes less than 10 /// bv.negate(); /// println!("{}", bv.to_str()); -/// println!("total bits set to true: {}", bv.iter().count(|x| x)); +/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count()); /// /// // reset bitvector to empty /// bv.clear(); /// println!("{}", bv.to_str()); -/// println!("total bits set to true: {}", bv.iter().count(|x| x)); +/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count()); /// ``` #[deriving(Clone)] pub struct Bitv { @@ -461,7 +461,7 @@ impl Bitv { /// bv.set(5, true); /// bv.set(8, true); /// // Count bits set to 1; result should be 5 - /// println!("{}", bv.iter().count(|x| x)); + /// println!("{}", bv.iter().filter(|x| *x).count()); /// ``` #[inline] pub fn iter<'a>(&'a self) -> Bits<'a> { diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index 8e3a49eecf339..94c617b58e8d2 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -1131,7 +1131,7 @@ mod tests { let v = &[0, ..128]; let m: DList = v.iter().map(|&x|x).collect(); b.iter(|| { - assert!(m.iter().len() == 128); + assert!(m.iter().count() == 128); }) } #[bench] @@ -1139,7 +1139,7 @@ mod tests { let v = &[0, ..128]; let mut m: DList = v.iter().map(|&x|x).collect(); b.iter(|| { - assert!(m.mut_iter().len() == 128); + assert!(m.mut_iter().count() == 128); }) } #[bench] @@ -1147,7 +1147,7 @@ mod tests { let v = &[0, ..128]; let m: DList = v.iter().map(|&x|x).collect(); b.iter(|| { - assert!(m.iter().rev().len() == 128); + assert!(m.iter().rev().count() == 128); }) } #[bench] @@ -1155,7 +1155,7 @@ mod tests { let v = &[0, ..128]; let mut m: DList = v.iter().map(|&x|x).collect(); b.iter(|| { - assert!(m.mut_iter().rev().len() == 128); + assert!(m.mut_iter().rev().count() == 128); }) } } diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 2004285ecb91b..a65c06107ce34 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -17,7 +17,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, managed_boxes, default_type_params, phase, globs)] #![no_std] diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 0b339a9726294..e631b8b77cf9c 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -2155,7 +2155,7 @@ mod tests { #[test] fn test_mut_splitator() { let mut xs = [0,1,0,2,3,0,0,4,5,0]; - assert_eq!(xs.mut_split(|x| *x == 0).len(), 6); + assert_eq!(xs.mut_split(|x| *x == 0).count(), 6); for slice in xs.mut_split(|x| *x == 0) { slice.reverse(); } diff --git a/src/libcollections/smallintmap.rs b/src/libcollections/smallintmap.rs index 829986e64ee66..f3118181bdcdd 100644 --- a/src/libcollections/smallintmap.rs +++ b/src/libcollections/smallintmap.rs @@ -31,7 +31,7 @@ pub struct SmallIntMap { impl Container for SmallIntMap { /// Return the number of elements in the map fn len(&self) -> uint { - self.v.iter().count(|elt| elt.is_some()) + self.v.iter().filter(|elt| elt.is_some()).count() } /// Return true if there are no elements in the map diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index ab1b1d1bd816b..5fd133b450f76 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -2181,7 +2181,7 @@ mod bench { let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; let len = s.char_len(); - b.iter(|| assert_eq!(s.chars().len(), len)); + b.iter(|| assert_eq!(s.chars().count(), len)); } #[bench] @@ -2194,7 +2194,7 @@ mod bench { Mary had a little lamb, Little lamb"; let len = s.char_len(); - b.iter(|| assert_eq!(s.chars().len(), len)); + b.iter(|| assert_eq!(s.chars().count(), len)); } #[bench] @@ -2202,7 +2202,7 @@ mod bench { let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; let len = s.char_len(); - b.iter(|| assert_eq!(s.chars().rev().len(), len)); + b.iter(|| assert_eq!(s.chars().rev().count(), len)); } #[bench] @@ -2210,7 +2210,7 @@ mod bench { let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; let len = s.char_len(); - b.iter(|| assert_eq!(s.char_indices().len(), len)); + b.iter(|| assert_eq!(s.char_indices().count(), len)); } #[bench] @@ -2218,14 +2218,14 @@ mod bench { let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; let len = s.char_len(); - b.iter(|| assert_eq!(s.char_indices().rev().len(), len)); + b.iter(|| assert_eq!(s.char_indices().rev().count(), len)); } #[bench] fn split_unicode_ascii(b: &mut Bencher) { let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam"; - b.iter(|| assert_eq!(s.split('V').len(), 3)); + b.iter(|| assert_eq!(s.split('V').count(), 3)); } #[bench] @@ -2240,16 +2240,16 @@ mod bench { } let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam"; - b.iter(|| assert_eq!(s.split(NotAscii('V')).len(), 3)); + b.iter(|| assert_eq!(s.split(NotAscii('V')).count(), 3)); } #[bench] fn split_ascii(b: &mut Bencher) { let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').len(); + let len = s.split(' ').count(); - b.iter(|| assert_eq!(s.split(' ').len(), len)); + b.iter(|| assert_eq!(s.split(' ').count(), len)); } #[bench] @@ -2264,34 +2264,34 @@ mod bench { fn only_ascii(&self) -> bool { false } } let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').len(); + let len = s.split(' ').count(); - b.iter(|| assert_eq!(s.split(NotAscii(' ')).len(), len)); + b.iter(|| assert_eq!(s.split(NotAscii(' ')).count(), len)); } #[bench] fn split_extern_fn(b: &mut Bencher) { let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').len(); + let len = s.split(' ').count(); fn pred(c: char) -> bool { c == ' ' } - b.iter(|| assert_eq!(s.split(pred).len(), len)); + b.iter(|| assert_eq!(s.split(pred).count(), len)); } #[bench] fn split_closure(b: &mut Bencher) { let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').len(); + let len = s.split(' ').count(); - b.iter(|| assert_eq!(s.split(|c: char| c == ' ').len(), len)); + b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len)); } #[bench] fn split_slice(b: &mut Bencher) { let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').len(); + let len = s.split(' ').count(); - b.iter(|| assert_eq!(s.split(&[' ']).len(), len)); + b.iter(|| assert_eq!(s.split(&[' ']).count(), len)); } #[bench] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index aa80a131811c2..6ca21262f51cc 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1772,23 +1772,23 @@ mod tests { assert_eq!(v.pop(), Some(())); assert_eq!(v.pop(), None); - assert_eq!(v.iter().len(), 0); + assert_eq!(v.iter().count(), 0); v.push(()); - assert_eq!(v.iter().len(), 1); + assert_eq!(v.iter().count(), 1); v.push(()); - assert_eq!(v.iter().len(), 2); + assert_eq!(v.iter().count(), 2); for &() in v.iter() {} - assert_eq!(v.mut_iter().len(), 2); + assert_eq!(v.mut_iter().count(), 2); v.push(()); - assert_eq!(v.mut_iter().len(), 3); + assert_eq!(v.mut_iter().count(), 3); v.push(()); - assert_eq!(v.mut_iter().len(), 4); + assert_eq!(v.mut_iter().count(), 4); for &() in v.mut_iter() {} unsafe { v.set_len(0); } - assert_eq!(v.mut_iter().len(), 0); + assert_eq!(v.mut_iter().count(), 0); } #[test] diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 875c852d8ae61..64c53b658eff1 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -529,11 +529,11 @@ pub trait Iterator { /// ```rust /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); - /// assert!(it.len() == 5); - /// assert!(it.len() == 0); + /// assert!(it.count() == 5); + /// assert!(it.count() == 0); /// ``` #[inline] - fn len(&mut self) -> uint { + fn count(&mut self) -> uint { self.fold(0, |cnt, _x| cnt + 1) } @@ -591,16 +591,6 @@ pub trait Iterator { None } - /// Count the number of elements satisfying the specified predicate - #[inline] - fn count(&mut self, predicate: |A| -> bool) -> uint { - let mut i = 0; - for x in *self { - if predicate(x) { i += 1 } - } - i - } - /// Return the element that gives the maximum value from the /// specified function. /// @@ -738,6 +728,14 @@ pub trait ExactSize : DoubleEndedIterator { } None } + + #[inline] + /// Return the exact length of the iterator. + fn len(&self) -> uint { + let (lower, upper) = self.size_hint(); + assert!(upper == Some(lower)); + lower + } } // All adaptors that preserve the size of the wrapped iterator are fine @@ -2594,9 +2592,9 @@ mod tests { #[test] fn test_iterator_len() { let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v.slice(0, 4).iter().len(), 4); - assert_eq!(v.slice(0, 10).iter().len(), 10); - assert_eq!(v.slice(0, 0).iter().len(), 0); + assert_eq!(v.slice(0, 4).iter().count(), 4); + assert_eq!(v.slice(0, 10).iter().count(), 10); + assert_eq!(v.slice(0, 0).iter().count(), 0); } #[test] @@ -2712,9 +2710,9 @@ mod tests { #[test] fn test_count() { let xs = &[1, 2, 2, 1, 5, 9, 0, 2]; - assert_eq!(xs.iter().count(|x| *x == 2), 3); - assert_eq!(xs.iter().count(|x| *x == 5), 1); - assert_eq!(xs.iter().count(|x| *x == 95), 0); + assert_eq!(xs.iter().filter(|x| **x == 2).count(), 3); + assert_eq!(xs.iter().filter(|x| **x == 5).count(), 1); + assert_eq!(xs.iter().filter(|x| **x == 95).count(), 0); } #[test] @@ -3044,10 +3042,10 @@ mod tests { assert!(range(-10i, -1).collect::>() == vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]); assert!(range(0i, 5).rev().collect::>() == vec![4, 3, 2, 1, 0]); - assert_eq!(range(200, -5).len(), 0); - assert_eq!(range(200, -5).rev().len(), 0); - assert_eq!(range(200, 200).len(), 0); - assert_eq!(range(200, 200).rev().len(), 0); + assert_eq!(range(200, -5).count(), 0); + assert_eq!(range(200, -5).rev().count(), 0); + assert_eq!(range(200, 200).count(), 0); + assert_eq!(range(200, 200).rev().count(), 0); assert_eq!(range(0i, 100).size_hint(), (100, Some(100))); // this test is only meaningful when sizeof uint < sizeof u64 @@ -3062,8 +3060,8 @@ mod tests { vec![0i, 1, 2, 3, 4, 5]); assert!(range_inclusive(0i, 5).rev().collect::>() == vec![5i, 4, 3, 2, 1, 0]); - assert_eq!(range_inclusive(200, -5).len(), 0); - assert_eq!(range_inclusive(200, -5).rev().len(), 0); + assert_eq!(range_inclusive(200, -5).count(), 0); + assert_eq!(range_inclusive(200, -5).rev().count(), 0); assert!(range_inclusive(200, 200).collect::>() == vec![200]); assert!(range_inclusive(200, 200).rev().collect::>() == vec![200]); } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 6aa07415e9cc7..2ccf431fc22e1 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -50,7 +50,8 @@ #![crate_type = "rlib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![no_std] #![feature(globs, macro_rules, managed_boxes, phase, simd)] diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 0257911e8c086..4dea1fd75a4bf 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -252,7 +252,7 @@ pub mod traits { use super::*; use cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering, Equiv}; - use iter::{order, Iterator}; + use iter::order; use container::Container; impl<'a,T:PartialEq> PartialEq for &'a [T] { @@ -1141,7 +1141,6 @@ impl<'a, T:Clone> MutableCloneableVector for &'a mut [T] { /// Unsafe operations pub mod raw { use mem::transmute; - use iter::Iterator; use ptr::RawPtr; use raw::Slice; use option::{None, Option, Some}; diff --git a/src/libcore/str.rs b/src/libcore/str.rs index c08f30152d592..936b698d4b10a 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -867,7 +867,6 @@ static TAG_CONT_U8: u8 = 128u8; pub mod raw { use mem; use container::Container; - use iter::Iterator; use ptr::RawPtr; use raw::Slice; use slice::{ImmutableVector}; @@ -1725,7 +1724,7 @@ impl<'a> StrSlice<'a> for &'a str { fn is_alphanumeric(&self) -> bool { self.chars().all(char::is_alphanumeric) } #[inline] - fn char_len(&self) -> uint { self.chars().len() } + fn char_len(&self) -> uint { self.chars().count() } #[inline] fn slice(&self, begin: uint, end: uint) -> &'a str { diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index ddfe8380e09dd..10584223486c0 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -84,7 +84,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(globs, phase)] #![deny(missing_doc)] #![deny(deprecated_owned_vector)] diff --git a/src/libglob/lib.rs b/src/libglob/lib.rs index 86753fbb811cb..f3e1da77ce5c7 100644 --- a/src/libglob/lib.rs +++ b/src/libglob/lib.rs @@ -29,8 +29,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] - + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![deny(deprecated_owned_vector)] use std::cell::Cell; diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs index 31fd8950c804c..c75d69480ce0d 100644 --- a/src/libgreen/lib.rs +++ b/src/libgreen/lib.rs @@ -203,7 +203,8 @@ #![crate_type = "dylib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] // NB this does *not* include globs, please keep it that way. #![feature(macro_rules, phase)] diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index ff5805599690d..daacf8b3c4761 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -111,7 +111,8 @@ if logging is disabled, none of the components of the log will be executed. #![crate_type = "dylib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules)] #![deny(missing_doc, deprecated_owned_vector)] diff --git a/src/libnum/lib.rs b/src/libnum/lib.rs index 29cf769ffc9d8..fae21e80f3072 100644 --- a/src/libnum/lib.rs +++ b/src/libnum/lib.rs @@ -50,7 +50,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![deny(deprecated_owned_vector)] diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 3ed086e9b13cc..7a12dcf9f7f31 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -21,7 +21,8 @@ #![crate_type = "rlib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, phase, globs)] #![no_std] diff --git a/src/libregex/lib.rs b/src/libregex/lib.rs index a48760913c161..44c206162ab25 100644 --- a/src/libregex/lib.rs +++ b/src/libregex/lib.rs @@ -360,7 +360,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, phase)] #![deny(missing_doc, deprecated_owned_vector)] diff --git a/src/librustc/back/archive.rs b/src/librustc/back/archive.rs index 0b6540640b4cf..4d921fb97dc50 100644 --- a/src/librustc/back/archive.rs +++ b/src/librustc/back/archive.rs @@ -109,7 +109,7 @@ impl<'a> Archive<'a> { pub fn add_rlib(&mut self, rlib: &Path, name: &str, lto: bool) -> io::IoResult<()> { let object = format!("{}.o", name); - let bytecode = format!("{}.bc.deflate", name); + let bytecode = format!("{}.bytecode.deflate", name); let mut ignore = vec!(bytecode.as_slice(), METADATA_FILENAME); if lto { ignore.push(object.as_slice()); @@ -166,6 +166,15 @@ impl<'a> Archive<'a> { if filename.contains(".SYMDEF") { continue } let filename = format!("r-{}-{}", name, filename); + // LLDB (as mentioned in back::link) crashes on filenames of exactly + // 16 bytes in length. If we're including an object file with + // exactly 16-bytes of characters, give it some prefix so that it's + // not 16 bytes. + let filename = if filename.len() == 16 { + format!("lldb-fix-{}", filename) + } else { + filename + }; let new_filename = file.with_filename(filename); try!(fs::rename(file, &new_filename)); inputs.push(new_filename); diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 546182aac34e2..14369c7bbcd23 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -958,8 +958,13 @@ fn link_rlib<'a>(sess: &'a Session, // For LTO purposes, the bytecode of this library is also inserted // into the archive. + // + // Note that we make sure that the bytecode filename in the archive + // is never exactly 16 bytes long by adding a 16 byte extension to + // it. This is to work around a bug in LLDB that would cause it to + // crash if the name of a file in an archive was exactly 16 bytes. let bc = obj_filename.with_extension("bc"); - let bc_deflated = obj_filename.with_extension("bc.deflate"); + let bc_deflated = obj_filename.with_extension("bytecode.deflate"); match fs::File::open(&bc).read_to_end().and_then(|data| { fs::File::create(&bc_deflated) .write(match flate::deflate_bytes(data.as_slice()) { diff --git a/src/librustc/back/lto.rs b/src/librustc/back/lto.rs index 09dfc91896795..7449622366fc2 100644 --- a/src/librustc/back/lto.rs +++ b/src/librustc/back/lto.rs @@ -55,10 +55,10 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, let archive = ArchiveRO::open(&path).expect("wanted an rlib"); debug!("reading {}", name); let bc = time(sess.time_passes(), - format!("read {}.bc.deflate", name).as_slice(), + format!("read {}.bytecode.deflate", name).as_slice(), (), |_| { - archive.read(format!("{}.bc.deflate", + archive.read(format!("{}.bytecode.deflate", name).as_slice()) }); let bc = bc.expect("missing compressed bytecode in archive!"); diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 8aeef3dca9867..6287683c1a141 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -209,6 +209,9 @@ pub static tag_dylib_dependency_formats: uint = 0x67; pub static tag_method_argument_names: uint = 0x8e; pub static tag_method_argument_name: uint = 0x8f; +pub static tag_reachable_extern_fns: uint = 0x90; +pub static tag_reachable_extern_fn_id: uint = 0x91; + #[deriving(Clone, Show)] pub struct LinkMeta { pub crateid: CrateId, diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 74a804763e83e..c7ad74dce571c 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -314,3 +314,10 @@ pub fn get_method_arg_names(cstore: &cstore::CStore, did: ast::DefId) let cdata = cstore.get_crate_data(did.krate); decoder::get_method_arg_names(&*cdata, did.node) } + +pub fn get_reachable_extern_fns(cstore: &cstore::CStore, cnum: ast::CrateNum) + -> Vec +{ + let cdata = cstore.get_crate_data(cnum); + decoder::get_reachable_extern_fns(&*cdata) +} diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 6469462734e55..c67b5bf1a6007 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1325,3 +1325,17 @@ pub fn get_method_arg_names(cdata: Cmd, id: ast::NodeId) -> Vec { } return ret; } + +pub fn get_reachable_extern_fns(cdata: Cmd) -> Vec { + let mut ret = Vec::new(); + let items = reader::get_doc(ebml::Doc::new(cdata.data()), + tag_reachable_extern_fns); + reader::tagged_docs(items, tag_reachable_extern_fn_id, |doc| { + ret.push(ast::DefId { + krate: cdata.cnum, + node: reader::doc_as_u32(doc), + }); + true + }); + return ret; +} diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 2cc06f7a32dde..37cb75e4697b3 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -75,6 +75,7 @@ pub struct EncodeParams<'a> { pub link_meta: &'a LinkMeta, pub cstore: &'a cstore::CStore, pub encode_inlined_item: EncodeInlinedItem<'a>, + pub reachable: &'a NodeSet, } pub struct EncodeContext<'a> { @@ -87,6 +88,7 @@ pub struct EncodeContext<'a> { pub cstore: &'a cstore::CStore, pub encode_inlined_item: RefCell>, pub type_abbrevs: tyencode::abbrev_map, + pub reachable: &'a NodeSet, } fn encode_name(ebml_w: &mut Encoder, name: Name) { @@ -351,7 +353,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext, fn encode_path + Clone>(ebml_w: &mut Encoder, mut path: PI) { ebml_w.start_tag(tag_path); - ebml_w.wr_tagged_u32(tag_path_len, path.clone().len() as u32); + ebml_w.wr_tagged_u32(tag_path_len, path.clone().count() as u32); for pe in path { let tag = match pe { ast_map::PathMod(_) => tag_path_elem_mod, @@ -1196,6 +1198,7 @@ fn encode_info_for_item(ecx: &EncodeContext, &Required(ref tm) => { encode_attributes(ebml_w, tm.attrs.as_slice()); encode_method_sort(ebml_w, 'r'); + encode_method_argument_names(ebml_w, &*tm.decl); } &Provided(m) => { @@ -1210,6 +1213,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_method_sort(ebml_w, 'p'); encode_inlined_item(ecx, ebml_w, IIMethodRef(def_id, true, m)); + encode_method_argument_names(ebml_w, &*m.decl); } } @@ -1700,6 +1704,26 @@ fn encode_misc_info(ecx: &EncodeContext, ebml_w.end_tag(); } +fn encode_reachable_extern_fns(ecx: &EncodeContext, ebml_w: &mut Encoder) { + ebml_w.start_tag(tag_reachable_extern_fns); + + for id in ecx.reachable.iter() { + match ecx.tcx.map.find(*id) { + Some(ast_map::NodeItem(i)) => { + match i.node { + ast::ItemFn(_, _, abi, _, _) if abi != abi::Rust => { + ebml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id); + } + _ => {} + } + } + _ => {} + } + } + + ebml_w.end_tag(); +} + fn encode_crate_dep(ebml_w: &mut Encoder, dep: decoder::CrateDep) { ebml_w.start_tag(tag_crate_dep); @@ -1799,6 +1823,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) encode_inlined_item, link_meta, non_inlineable_statics, + reachable, .. } = parms; let ecx = EncodeContext { @@ -1811,6 +1836,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) cstore: cstore, encode_inlined_item: RefCell::new(encode_inlined_item), type_abbrevs: RefCell::new(HashMap::new()), + reachable: reachable, }; let mut ebml_w = writer::Encoder::new(wr); @@ -1862,6 +1888,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) // Encode miscellaneous info. i = ebml_w.writer.tell().unwrap(); encode_misc_info(&ecx, krate, &mut ebml_w); + encode_reachable_extern_fns(&ecx, &mut ebml_w); stats.misc_bytes = ebml_w.writer.tell().unwrap() - i; // Encode and index the items. diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 1b7ed90237fd9..9a5f226bb73ce 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -82,7 +82,7 @@ fn find_item(item: &Item, ctxt: &mut EntryContext) { ItemFn(..) => { if item.ident.name == ctxt.main_name { ctxt.ast_map.with_path(item.id, |mut path| { - if path.len() == 1 { + if path.count() == 1 { // This is a top-level function so can be 'main' if ctxt.main_fn.is_none() { ctxt.main_fn = Some((item.id, item.span)); diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 96d059c2f84ce..09f5d2a350769 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -80,6 +80,7 @@ use libc::{c_uint, uint64_t}; use std::c_str::ToCStr; use std::cell::{Cell, RefCell}; use std::rc::Rc; +use std::{i8, i16, i32, i64}; use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic}; use syntax::ast_util::{local_def, is_local}; use syntax::attr::AttrMetaMethods; @@ -777,35 +778,77 @@ pub fn cast_shift_rhs(op: ast::BinOp, } } -pub fn fail_if_zero<'a>( +pub fn fail_if_zero_or_overflows<'a>( cx: &'a Block<'a>, span: Span, divrem: ast::BinOp, + lhs: ValueRef, rhs: ValueRef, rhs_t: ty::t) -> &'a Block<'a> { - let text = if divrem == ast::BiDiv { - "attempted to divide by zero" + let (zero_text, overflow_text) = if divrem == ast::BiDiv { + ("attempted to divide by zero", + "attempted to divide with overflow") } else { - "attempted remainder with a divisor of zero" + ("attempted remainder with a divisor of zero", + "attempted remainder with overflow") }; - let is_zero = match ty::get(rhs_t).sty { - ty::ty_int(t) => { - let zero = C_integral(Type::int_from_ty(cx.ccx(), t), 0u64, false); - ICmp(cx, lib::llvm::IntEQ, rhs, zero) - } - ty::ty_uint(t) => { - let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0u64, false); - ICmp(cx, lib::llvm::IntEQ, rhs, zero) - } - _ => { - cx.sess().bug(format!("fail-if-zero on unexpected type: {}", - ty_to_str(cx.tcx(), rhs_t)).as_slice()); - } + let (is_zero, is_signed) = match ty::get(rhs_t).sty { + ty::ty_int(t) => { + let zero = C_integral(Type::int_from_ty(cx.ccx(), t), 0u64, false); + (ICmp(cx, lib::llvm::IntEQ, rhs, zero), true) + } + ty::ty_uint(t) => { + let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0u64, false); + (ICmp(cx, lib::llvm::IntEQ, rhs, zero), false) + } + _ => { + cx.sess().bug(format!("fail-if-zero on unexpected type: {}", + ty_to_str(cx.tcx(), rhs_t)).as_slice()); + } }; - with_cond(cx, is_zero, |bcx| { - controlflow::trans_fail(bcx, span, InternedString::new(text)) - }) + let bcx = with_cond(cx, is_zero, |bcx| { + controlflow::trans_fail(bcx, span, InternedString::new(zero_text)) + }); + + // To quote LLVM's documentation for the sdiv instruction: + // + // Division by zero leads to undefined behavior. Overflow also leads + // to undefined behavior; this is a rare case, but can occur, for + // example, by doing a 32-bit division of -2147483648 by -1. + // + // In order to avoid undefined behavior, we perform runtime checks for + // signed division/remainder which would trigger overflow. For unsigned + // integers, no action beyond checking for zero need be taken. + if is_signed { + let (llty, min) = match ty::get(rhs_t).sty { + ty::ty_int(t) => { + let llty = Type::int_from_ty(cx.ccx(), t); + let min = match t { + ast::TyI if llty == Type::i32(cx.ccx()) => i32::MIN as u64, + ast::TyI => i64::MIN as u64, + ast::TyI8 => i8::MIN as u64, + ast::TyI16 => i16::MIN as u64, + ast::TyI32 => i32::MIN as u64, + ast::TyI64 => i64::MIN as u64, + }; + (llty, min) + } + _ => unreachable!(), + }; + let minus_one = ICmp(bcx, lib::llvm::IntEQ, rhs, + C_integral(llty, -1, false)); + with_cond(bcx, minus_one, |bcx| { + let is_min = ICmp(bcx, lib::llvm::IntEQ, lhs, + C_integral(llty, min, true)); + with_cond(bcx, is_min, |bcx| { + controlflow::trans_fail(bcx, span, + InternedString::new(overflow_text)) + }) + }) + } else { + bcx + } } pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> ValueRef { @@ -2195,6 +2238,7 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::EncodeI link_meta: &cx.link_meta, cstore: &cx.sess().cstore, encode_inlined_item: ie, + reachable: &cx.reachable, } } @@ -2331,6 +2375,16 @@ pub fn trans_crate(krate: ast::Crate, ccx.item_symbols.borrow().find(id).map(|s| s.to_string()) }).collect(); + // For the purposes of LTO, we add to the reachable set all of the upstream + // reachable extern fns. These functions are all part of the public ABI of + // the final product, so LTO needs to preserve them. + ccx.sess().cstore.iter_crate_data(|cnum, _| { + let syms = csearch::get_reachable_extern_fns(&ccx.sess().cstore, cnum); + reachable.extend(syms.move_iter().map(|did| { + csearch::get_symbol(&ccx.sess().cstore, did) + })); + }); + // Make sure that some other crucial symbols are not eliminated from the // module. This includes the main function, the crate map (used for debug // log settings and I/O), and finally the curious rust_stack_exhausted diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index d9ae9b0838170..9f90de61cfeb6 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -1297,8 +1297,8 @@ fn trans_eager_binop<'a>( FDiv(bcx, lhs, rhs) } else { // Only zero-check integers; fp /0 is NaN - bcx = base::fail_if_zero(bcx, binop_expr.span, - op, rhs, rhs_t); + bcx = base::fail_if_zero_or_overflows(bcx, binop_expr.span, + op, lhs, rhs, rhs_t); if is_signed { SDiv(bcx, lhs, rhs) } else { @@ -1311,8 +1311,8 @@ fn trans_eager_binop<'a>( FRem(bcx, lhs, rhs) } else { // Only zero-check integers; fp %0 is NaN - bcx = base::fail_if_zero(bcx, binop_expr.span, - op, rhs, rhs_t); + bcx = base::fail_if_zero_or_overflows(bcx, binop_expr.span, + op, lhs, rhs, rhs_t); if is_signed { SRem(bcx, lhs, rhs) } else { diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index f8821a86e7177..bdb23aea06708 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -191,11 +191,11 @@ fn ast_path_substs( }; // Convert the type parameters supplied by the user. - let supplied_ty_param_count = path.segments.iter().flat_map(|s| s.types.iter()).len(); + let supplied_ty_param_count = path.segments.iter().flat_map(|s| s.types.iter()).count(); let formal_ty_param_count = decl_generics.type_param_defs().len(); let required_ty_param_count = decl_generics.type_param_defs().iter() .take_while(|x| x.default.is_none()) - .len(); + .count(); if supplied_ty_param_count < required_ty_param_count { let expected = if required_ty_param_count < formal_ty_param_count { "expected at least" @@ -407,7 +407,7 @@ pub fn ast_ty_to_builtin_ty 1 { + .count() > 1 { this.tcx() .sess .span_err(path.span, diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index a09c92d4db01f..d25fc9cc5bcdb 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1615,7 +1615,7 @@ fn check_type_parameter_positions_in_path(function_context: &FnCtxt, let formal_ty_param_count = generics.type_param_defs().len(); let required_ty_param_count = generics.type_param_defs().iter() .take_while(|x| x.default.is_none()) - .len(); + .count(); let supplied_ty_param_count = trait_segment.types.len(); if supplied_ty_param_count < required_ty_param_count { let msg = if required_ty_param_count < generics.type_param_defs().len() { @@ -3876,7 +3876,7 @@ pub fn instantiate_path(fcx: &FnCtxt, let ty_param_count = tpt.generics.type_param_defs().len(); let ty_param_req = tpt.generics.type_param_defs().iter() .take_while(|x| x.default.is_none()) - .len(); + .count(); let mut ty_substs_len = 0; for segment in pth.segments.iter() { ty_substs_len += segment.types.len() diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index e1db465424af8..e488a946d4a14 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -432,7 +432,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { // function check_cast_for_escaping_regions() in kind.rs // explaining how it goes about doing that. - let source_ty = rcx.fcx.expr_ty(expr); + let source_ty = rcx.resolve_node_type(expr.id); constrain_regions_in_type(rcx, trait_region, infer::RelateObjectBound(expr.span), source_ty); } diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 63dc122f7cbf6..b93550384ae3b 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -260,7 +260,14 @@ impl<'cx> WritebackCx<'cx> { }) } - adjustment => adjustment + ty::AutoObject(trait_store, bb, def_id, substs) => { + ty::AutoObject( + self.resolve(&trait_store, reason), + self.resolve(&bb, reason), + def_id, + self.resolve(&substs, reason) + ) + } }; debug!("Adjustments for node {}: {:?}", id, resolved_adjustment); self.tcx().adjustments.borrow_mut().insert( diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index a9ac1e76f1187..eb84ed32335b9 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -456,7 +456,7 @@ pub fn parameterized(cx: &ctxt, Some(default) => default.subst(cx, &substs) == actual, None => false } - }).len() + }).count() } else { 0 }; diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 9db9a0e7612a6..2a4774ffd84d4 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -88,6 +88,10 @@ fn try_inline_def(cx: &core::DocContext, record_extern_fqn(cx, did, clean::TypeModule); clean::ModuleItem(build_module(cx, tcx, did)) } + def::DefStatic(did, mtbl) => { + record_extern_fqn(cx, did, clean::TypeStatic); + clean::StaticItem(build_static(tcx, did, mtbl)) + } _ => return None, }; let fqn = csearch::get_item_path(tcx, did); @@ -343,3 +347,13 @@ fn build_module(cx: &core::DocContext, tcx: &ty::ctxt, is_crate: false, } } + +fn build_static(tcx: &ty::ctxt, + did: ast::DefId, + mutable: bool) -> clean::Static { + clean::Static { + type_: ty::lookup_item_type(tcx, did).ty.clean(), + mutability: if mutable {clean::Mutable} else {clean::Immutable}, + expr: "\n\n\n".to_string(), // trigger the "[definition]" links + } +} diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 51d2a67d6cbf4..1706f00b70a6f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -35,6 +35,8 @@ pub struct VisSpace(pub Option); pub struct FnStyleSpace(pub ast::FnStyle); /// Wrapper struct for properly emitting a method declaration. pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl); +/// Similar to VisSpace, but used for mutability +pub struct MutableSpace(pub clean::Mutability); impl VisSpace { pub fn get(&self) -> Option { @@ -438,24 +440,14 @@ impl fmt::Show for clean::Type { clean::Unique(ref t) => write!(f, "~{}", **t), clean::Managed(ref t) => write!(f, "@{}", **t), clean::RawPointer(m, ref t) => { - write!(f, "*{}{}", - match m { - clean::Mutable => "mut ", - clean::Immutable => "", - }, **t) + write!(f, "*{}{}", MutableSpace(m), **t) } clean::BorrowedRef{ lifetime: ref l, mutability, type_: ref ty} => { let lt = match *l { Some(ref l) => format!("{} ", *l), _ => "".to_string(), }; - write!(f, "&{}{}{}", - lt, - match mutability { - clean::Mutable => "mut ", - clean::Immutable => "", - }, - **ty) + write!(f, "&{}{}{}", lt, MutableSpace(mutability), **ty) } } } @@ -494,17 +486,13 @@ impl<'a> fmt::Show for Method<'a> { clean::SelfStatic => {}, clean::SelfValue => args.push_str("self"), clean::SelfOwned => args.push_str("~self"), - clean::SelfBorrowed(Some(ref lt), clean::Immutable) => { - args.push_str(format!("&{} self", *lt).as_slice()); - } - clean::SelfBorrowed(Some(ref lt), clean::Mutable) => { - args.push_str(format!("&{} mut self", *lt).as_slice()); - } - clean::SelfBorrowed(None, clean::Mutable) => { - args.push_str("&mut self"); + clean::SelfBorrowed(Some(ref lt), mtbl) => { + args.push_str(format!("&{} {}self", *lt, + MutableSpace(mtbl)).as_slice()); } - clean::SelfBorrowed(None, clean::Immutable) => { - args.push_str("&self"); + clean::SelfBorrowed(None, mtbl) => { + args.push_str(format!("&{}self", + MutableSpace(mtbl)).as_slice()); } } for (i, input) in d.inputs.values.iter().enumerate() { @@ -605,3 +593,12 @@ impl fmt::Show for clean::ViewListIdent { } } } + +impl fmt::Show for MutableSpace { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + MutableSpace(clean::Immutable) => Ok(()), + MutableSpace(clean::Mutable) => write!(f, "mut "), + } + } +} diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index f544e1e0973f3..3c9358b03a983 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -25,7 +25,7 @@ use html::escape::Escape; use t = syntax::parse::token; /// Highlights some source code, returning the HTML output. -pub fn highlight(src: &str, class: Option<&str>) -> String { +pub fn highlight(src: &str, class: Option<&str>, id: Option<&str>) -> String { debug!("highlighting: ================\n{}\n==============", src); let sess = parse::new_parse_sess(); let fm = parse::string_to_filemap(&sess, @@ -36,6 +36,7 @@ pub fn highlight(src: &str, class: Option<&str>) -> String { doit(&sess, lexer::StringReader::new(&sess.span_diagnostic, fm), class, + id, &mut out).unwrap(); str::from_utf8_lossy(out.unwrap().as_slice()).to_string() } @@ -47,11 +48,17 @@ pub fn highlight(src: &str, class: Option<&str>) -> String { /// it's used. All source code emission is done as slices from the source map, /// not from the tokens themselves, in order to stay true to the original /// source. -fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader, class: Option<&str>, +fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader, + class: Option<&str>, id: Option<&str>, out: &mut Writer) -> io::IoResult<()> { use syntax::parse::lexer::Reader; - try!(write!(out, "
\n", class.unwrap_or("")));
+    try!(write!(out, "
 try!(write!(out, "id='{}' ", id)),
+        None => {}
+    }
+    try!(write!(out, "class='rust {}'>\n", class.unwrap_or("")));
     let mut last = BytePos(0);
     let mut is_attribute = false;
     let mut is_macro = false;
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 80653878247fa..e2fa57148c2c7 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -16,6 +16,7 @@ pub struct Layout {
     pub logo: String,
     pub favicon: String,
     pub krate: String,
+    pub playground_url: String,
 }
 
 pub struct Page<'a> {
@@ -108,11 +109,13 @@ r##"
     
 
     
     
     
+    {play_js}
     
 
 "##,
@@ -124,6 +127,12 @@ r##"
     favicon   = nonestr(layout.favicon.as_slice()),
     sidebar   = *sidebar,
     krate     = layout.krate,
+    play_url  = layout.playground_url,
+    play_js   = if layout.playground_url.len() == 0 {
+        "".to_string()
+    } else {
+        format!(r#""#, page.root_path)
+    },
     )
 }
 
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index d1e2b5dffddd4..260d26c543736 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -27,7 +27,7 @@
 #![allow(non_camel_case_types)]
 
 use libc;
-use std::cell::RefCell;
+use std::cell::{RefCell, Cell};
 use std::fmt;
 use std::slice;
 use std::str;
@@ -35,6 +35,8 @@ use std::collections::HashMap;
 
 use html::toc::TocBuilder;
 use html::highlight;
+use html::escape::Escape;
+use test;
 
 /// A unit struct which has the `fmt::Show` trait implemented. When
 /// formatted, this struct will emit the HTML corresponding to the rendered
@@ -139,6 +141,9 @@ fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> {
 }
 
 local_data_key!(used_header_map: RefCell>)
+local_data_key!(test_idx: Cell)
+// None == render an example, but there's no crate name
+local_data_key!(pub playground_krate: Option)
 
 pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
     extern fn block(ob: *mut hoedown_buffer, text: *hoedown_buffer,
@@ -149,9 +154,9 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
             let opaque = opaque as *mut hoedown_html_renderer_state;
             let my_opaque: &MyOpaque = &*((*opaque).opaque as *MyOpaque);
             slice::raw::buf_as_slice((*text).data, (*text).size as uint, |text| {
-                let text = str::from_utf8(text).unwrap();
+                let origtext = str::from_utf8(text).unwrap();
                 debug!("docblock: ==============\n{}\n=======", text);
-                let mut lines = text.lines().filter(|l| {
+                let mut lines = origtext.lines().filter(|l| {
                     stripped_filtered_line(*l).is_none()
                 });
                 let text = lines.collect::>().connect("\n");
@@ -180,9 +185,26 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
                 };
 
                 if !rendered {
-                    let output = highlight::highlight(text.as_slice(),
-                                                      None).as_slice()
-                                                           .to_c_str();
+                    let mut s = String::new();
+                    let id = playground_krate.get().map(|krate| {
+                        let idx = test_idx.get().unwrap();
+                        let i = idx.get();
+                        idx.set(i + 1);
+
+                        let test = origtext.lines().map(|l| {
+                            stripped_filtered_line(l).unwrap_or(l)
+                        }).collect::>().connect("\n");
+                        let krate = krate.as_ref().map(|s| s.as_slice());
+                        let test = test::maketest(test.as_slice(), krate, false);
+                        s.push_str(format!("{}",
+                                           i, Escape(test.as_slice())).as_slice());
+                        format!("rust-example-rendered-{}", i)
+                    });
+                    let id = id.as_ref().map(|a| a.as_slice());
+                    s.push_str(highlight::highlight(text.as_slice(), None, id)
+                                         .as_slice());
+                    let output = s.to_c_str();
                     output.with_ref(|r| {
                         hoedown_buffer_puts(ob, r)
                     })
@@ -377,6 +399,7 @@ fn parse_lang_string(string: &str) -> (bool,bool,bool,bool) {
 /// previous state (if any).
 pub fn reset_headers() {
     used_header_map.replace(Some(RefCell::new(HashMap::new())));
+    test_idx.replace(Some(Cell::new(0)));
 }
 
 impl<'a> fmt::Show for Markdown<'a> {
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 4ef3297912f9e..eab4a2c137a58 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -51,7 +51,7 @@ use rustc::util::nodemap::NodeSet;
 use clean;
 use doctree;
 use fold::DocFolder;
-use html::format::{VisSpace, Method, FnStyleSpace};
+use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace};
 use html::highlight;
 use html::item_type::{ItemType, shortty};
 use html::item_type;
@@ -230,6 +230,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
             logo: "".to_string(),
             favicon: "".to_string(),
             krate: krate.name.clone(),
+            playground_url: "".to_string(),
         },
         include_sources: true,
         render_redirect_pages: false,
@@ -250,6 +251,14 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
                             if "html_logo_url" == x.as_slice() => {
                         cx.layout.logo = s.to_string();
                     }
+                    clean::NameValue(ref x, ref s)
+                            if "html_playground_url" == x.as_slice() => {
+                        cx.layout.playground_url = s.to_string();
+                        let name = krate.name.clone();
+                        if markdown::playground_krate.get().is_none() {
+                            markdown::playground_krate.replace(Some(Some(name)));
+                        }
+                    }
                     clean::Word(ref x)
                             if "html_no_source" == x.as_slice() => {
                         cx.include_sources = false;
@@ -450,6 +459,7 @@ fn write_shared(cx: &Context,
     try!(write(cx.dst.join("jquery.js"),
                include_bin!("static/jquery-2.1.0.min.js")));
     try!(write(cx.dst.join("main.js"), include_bin!("static/main.js")));
+    try!(write(cx.dst.join("playpen.js"), include_bin!("static/playpen.js")));
     try!(write(cx.dst.join("main.css"), include_bin!("static/main.css")));
     try!(write(cx.dst.join("normalize.css"),
                include_bin!("static/normalize.css")));
@@ -1441,11 +1451,12 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
 
                 try!(write!(w, "
                     
-                        {}static {}: {}{}
+                        {}static {}{}: {}{}
                         {} 
                     
                 ",
                 VisSpace(myitem.visibility),
+                MutableSpace(s.mutability),
                 *myitem.name.get_ref(),
                 s.type_,
                 Initializer(s.expr.as_slice(), Item { cx: cx, item: myitem }),
@@ -2042,7 +2053,7 @@ fn build_sidebar(m: &clean::Module) -> HashMap> {
 impl<'a> fmt::Show for Source<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let Source(s) = *self;
-        let lines = s.lines().len();
+        let lines = s.lines().count();
         let mut cols = 0;
         let mut tmp = lines;
         while tmp > 0 {
@@ -2054,14 +2065,15 @@ impl<'a> fmt::Show for Source<'a> {
             try!(write!(fmt, "{0:1$u}\n", i, cols));
         }
         try!(write!(fmt, "
")); - try!(write!(fmt, "{}", highlight::highlight(s.as_slice(), None))); + try!(write!(fmt, "{}", highlight::highlight(s.as_slice(), None, None))); Ok(()) } } fn item_macro(w: &mut fmt::Formatter, it: &clean::Item, t: &clean::Macro) -> fmt::Result { - try!(w.write(highlight::highlight(t.source.as_slice(), Some("macro")).as_bytes())); + try!(w.write(highlight::highlight(t.source.as_slice(), Some("macro"), + None).as_bytes())); document(w, it) } diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index 7831f10ab9195..07dd1a6c173cc 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -156,7 +156,7 @@ nav.sub { padding: 0 10px; margin-bottom: 10px; } -.block h2 { +.block h2 { margin-top: 0; text-align: center; } @@ -396,6 +396,17 @@ pre.rust .doccomment { color: #4D4D4C; } pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; } pre.rust .lifetime { color: #B76514; } +.rusttest { display: none; } +pre.rust { position: relative; } +pre.rust a { transform: scaleX(-1); } +.test-arrow { + display: inline-block; + position: absolute; + top: 0; + right: 10px; + font-size: 150%; +} + .methods .section-header { /* Override parent class attributes. */ border-bottom: none !important; diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 440b829c80c4d..195028c85bfa9 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -678,7 +678,7 @@ window.register_implementors(window.pending_implementors); } - // See documentaiton in html/render.rs for what this is doing. + // See documentation in html/render.rs for what this is doing. var query = getQueryStringParams(); if (query['gotosrc']) { window.location = $('#src-' + query['gotosrc']).attr('href'); diff --git a/src/librustdoc/html/static/playpen.js b/src/librustdoc/html/static/playpen.js new file mode 100644 index 0000000000000..5d2fe9c216602 --- /dev/null +++ b/src/librustdoc/html/static/playpen.js @@ -0,0 +1,29 @@ +// 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. + +/*jslint browser: true, es5: true */ +/*globals $: true, rootPath: true */ + +(function() { + if (window.playgroundUrl) { + $('pre.rust').hover(function() { + var id = '#' + $(this).attr('id').replace('rendered', 'raw'); + var a = $('
').text('⇱').attr('class', 'test-arrow'); + var code = $(id).text(); + a.attr('href', window.playgroundUrl + '?code=' + + encodeURIComponent(code)); + a.attr('target', '_blank'); + $(this).append(a); + }, function() { + $(this).find('a').remove(); + }); + } +}()); + diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs index 2356d4c754fa9..5bc6d8031ac29 100644 --- a/src/librustdoc/html/toc.rs +++ b/src/librustdoc/html/toc.rs @@ -32,7 +32,7 @@ pub struct Toc { impl Toc { fn count_entries_with_level(&self, level: u32) -> uint { - self.entries.iter().count(|e| e.level == level) + self.entries.iter().filter(|e| e.level == level).count() } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 28443fc453f83..e623d54675c25 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -126,7 +126,9 @@ pub fn opts() -> Vec { optmulti("", "markdown-after-content", "files to include inline between the content and of a rendered \ Markdown file", - "FILES") + "FILES"), + optopt("", "markdown-playground-url", + "URL to send code snippets to", "URL") ) } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 961c92940be81..3b6203ef668f7 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -16,6 +16,7 @@ use getopts; use testing; use html::escape::Escape; +use html::markdown; use html::markdown::{MarkdownWithToc, find_testable_code, reset_headers}; use test::Collector; @@ -84,6 +85,11 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int } let input_str = load_or_return!(input, 1, 2); + let playground = matches.opt_str("markdown-playground-url"); + if playground.is_some() { + markdown::playground_krate.replace(Some(None)); + } + let playground = playground.unwrap_or("".to_string()); let (in_header, before_content, after_content) = match (load_external_files(matches.opt_strs("markdown-in-header") @@ -148,6 +154,9 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int {before_content}

{title}

{text} + {after_content} "#, @@ -156,7 +165,9 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int in_header = in_header, before_content = before_content, text = MarkdownWithToc(text), - after_content = after_content); + after_content = after_content, + playground = playground, + ); match err { Err(e) => { @@ -173,7 +184,7 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int pub fn test(input: &str, libs: HashSet, mut test_args: Vec) -> int { let input_str = load_or_return!(input, 1, 2); - let mut collector = Collector::new(input.to_string(), libs, true, true); + let mut collector = Collector::new(input.to_string(), libs, true); find_testable_code(input_str.as_slice(), &mut collector); test_args.unshift("rustdoctest".to_string()); testing::test_main(test_args.as_slice(), collector.tests); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index ed53b2ac314a8..bc1da5b629e13 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -91,7 +91,6 @@ pub fn run(input: &str, let mut collector = Collector::new(krate.name.to_string(), libs, - false, false); collector.fold_crate(krate); @@ -103,8 +102,8 @@ pub fn run(input: &str, } fn runtest(test: &str, cratename: &str, libs: HashSet, should_fail: bool, - no_run: bool, loose_feature_gating: bool) { - let test = maketest(test, cratename, loose_feature_gating); + no_run: bool) { + let test = maketest(test, Some(cratename), true); let input = driver::StrInput(test.to_string()); let sessopts = config::Options { @@ -201,29 +200,31 @@ fn runtest(test: &str, cratename: &str, libs: HashSet, should_fail: bool, } } -fn maketest(s: &str, cratename: &str, loose_feature_gating: bool) -> String { - let mut prog = String::from_str(r" +pub fn maketest(s: &str, cratename: Option<&str>, lints: bool) -> String { + let mut prog = String::new(); + if lints { + prog.push_str(r" #![deny(warnings)] #![allow(unused_variable, dead_assignment, unused_mut, attribute_usage, dead_code)] "); - - if loose_feature_gating { - // FIXME #12773: avoid inserting these when the tutorial & manual - // etc. have been updated to not use them so prolifically. - prog.push_str("#![feature(macro_rules, globs, struct_variant, managed_boxes) ]\n"); } if !s.contains("extern crate") { - if s.contains(cratename) { - prog.push_str(format!("extern crate {};\n", - cratename).as_slice()); + match cratename { + Some(cratename) => { + if s.contains(cratename) { + prog.push_str(format!("extern crate {};\n", + cratename).as_slice()); + } + } + None => {} } } if s.contains("fn main") { prog.push_str(s); } else { - prog.push_str("fn main() {\n"); - prog.push_str(s); + prog.push_str("fn main() {\n "); + prog.push_str(s.replace("\n", "\n ").as_slice()); prog.push_str("\n}"); } @@ -238,13 +239,11 @@ pub struct Collector { use_headers: bool, current_header: Option, cratename: String, - - loose_feature_gating: bool } impl Collector { pub fn new(cratename: String, libs: HashSet, - use_headers: bool, loose_feature_gating: bool) -> Collector { + use_headers: bool) -> Collector { Collector { tests: Vec::new(), names: Vec::new(), @@ -253,8 +252,6 @@ impl Collector { use_headers: use_headers, current_header: None, cratename: cratename, - - loose_feature_gating: loose_feature_gating } } @@ -268,7 +265,6 @@ impl Collector { self.cnt += 1; let libs = self.libs.clone(); let cratename = self.cratename.to_string(); - let loose_feature_gating = self.loose_feature_gating; debug!("Creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { @@ -281,8 +277,7 @@ impl Collector { cratename.as_slice(), libs, should_fail, - no_run, - loose_feature_gating); + no_run); }), }); } diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 904c7da4da2e9..08348c9633382 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -20,7 +20,8 @@ Core encoding and decoding interfaces. #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, managed_boxes, default_type_params, phase)] // test harness access diff --git a/src/libstd/collections/hashmap.rs b/src/libstd/collections/hashmap.rs index 5dba7a533a1db..571c579470441 100644 --- a/src/libstd/collections/hashmap.rs +++ b/src/libstd/collections/hashmap.rs @@ -684,8 +684,8 @@ impl DefaultResizePolicy { /// denial-of-service attacks (Hash DoS). This behaviour can be /// overridden with one of the constructors. /// -/// It is required that the keys implement the `PartialEq` and `Hash` traits, although -/// this can frequently be achieved by using `#[deriving(PartialEq, Hash)]`. +/// It is required that the keys implement the `Eq` and `Hash` traits, although +/// this can frequently be achieved by using `#[deriving(Eq, Hash)]`. /// /// Relevant papers/articles: /// @@ -1422,6 +1422,8 @@ impl, V: PartialEq, S, H: Hasher> PartialEq for HashMap, V: Eq, S, H: Hasher> Eq for HashMap {} + impl + Show, V: Show, S, H: Hasher> Show for HashMap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, r"\{")); @@ -1486,7 +1488,7 @@ pub type SetMoveItems = /// An implementation of a hash set using the underlying representation of a /// HashMap where the value is (). As with the `HashMap` type, a `HashSet` -/// requires that the elements implement the `PartialEq` and `Hash` traits. +/// requires that the elements implement the `Eq` and `Hash` traits. #[deriving(Clone)] pub struct HashSet { map: HashMap @@ -1500,6 +1502,8 @@ impl, S, H: Hasher> PartialEq for HashSet { } } +impl, S, H: Hasher> Eq for HashSet {} + impl, S, H: Hasher> Container for HashSet { fn len(&self) -> uint { self.map.len() } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 90d6677d61228..109832b7c4795 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -101,7 +101,8 @@ #![crate_type = "dylib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, globs, asm, managed_boxes, thread_local, link_args, linkage, default_type_params, phase, concat_idents, quad_precision_float)] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 0b9fc250636f4..805da8021ed2c 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -212,7 +212,7 @@ macro_rules! unimplemented( () => (fail!("not yet implemented")) ) -/// Use the syntax described in `std::fmt` to create a value of type `~str`. +/// Use the syntax described in `std::fmt` to create a value of type `String`. /// See `std::fmt` for more information. /// /// # Example @@ -465,7 +465,7 @@ pub mod builtin { /// ``` /// let rust = bytes!("r", 'u', "st", 255); /// assert_eq!(rust[1], 'u' as u8); - /// assert_eq!(rust[5], 255); + /// assert_eq!(rust[4], 255); /// ``` #[macro_export] macro_rules! bytes( ($($e:expr),*) => ({ /* compiler built-in */ }) ) @@ -482,10 +482,14 @@ pub mod builtin { /// # Example /// /// ``` + /// #![feature(concat_idents)] + /// + /// # fn main() { /// fn foobar() -> int { 23 } /// /// let f = concat_idents!(foo, bar); /// println!("{}", f()); + /// # } /// ``` #[macro_export] macro_rules! concat_idents( ($($e:ident),*) => ({ /* compiler built-in */ }) ) diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 54ca579780490..133a8db90facc 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -13,7 +13,6 @@ use char; use clone::Clone; use container::Container; -use iter::Iterator; use num::{NumCast, Zero, One, cast, Int}; use num::{Float, FPNaN, FPInfinite, ToPrimitive}; use num; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 1f75754f4d53e..381ebc0820064 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -56,12 +56,6 @@ use libc::c_char; #[cfg(windows)] use str::OwnedStr; -/// Delegates to the libc close() function, returning the same return value. -pub fn close(fd: int) -> int { - unsafe { - libc::close(fd as c_int) as int - } -} pub static TMPBUF_SZ : uint = 1000u; static BUF_BYTES : uint = 2048u; diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index 61a2ffd383d0a..ee1935628871e 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -353,17 +353,17 @@ mod test { #[test] fn test_gen_ascii_str() { let mut r = task_rng(); - assert_eq!(r.gen_ascii_chars().take(0).len(), 0u); - assert_eq!(r.gen_ascii_chars().take(10).len(), 10u); - assert_eq!(r.gen_ascii_chars().take(16).len(), 16u); + assert_eq!(r.gen_ascii_chars().take(0).count(), 0u); + assert_eq!(r.gen_ascii_chars().take(10).count(), 10u); + assert_eq!(r.gen_ascii_chars().take(16).count(), 16u); } #[test] fn test_gen_vec() { let mut r = task_rng(); - assert_eq!(r.gen_iter::().take(0).len(), 0u); - assert_eq!(r.gen_iter::().take(10).len(), 10u); - assert_eq!(r.gen_iter::().take(16).len(), 16u); + assert_eq!(r.gen_iter::().take(0).count(), 0u); + assert_eq!(r.gen_iter::().take(10).count(), 10u); + assert_eq!(r.gen_iter::().take(16).count(), 16u); } #[test] diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index ac421bf78be7e..94472ee72414c 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -84,7 +84,7 @@ fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { if i == 0 { valid = chars.next().is_none(); break - } else if chars.by_ref().take(i - 1).len() != i - 1 { + } else if chars.by_ref().take(i - 1).count() != i - 1 { valid = false; } } @@ -505,7 +505,6 @@ mod imp { use c_str::CString; use container::Container; use io::{IoResult, Writer}; - use iter::Iterator; use libc; use mem; use ops::Drop; diff --git a/src/libsync/lib.rs b/src/libsync/lib.rs index e0cc57a4967fe..fc4d5fec5f52a 100644 --- a/src/libsync/lib.rs +++ b/src/libsync/lib.rs @@ -18,7 +18,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(phase)] #![deny(deprecated_owned_vector)] diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index f2ae0c15860ab..cc813262576ad 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -45,7 +45,8 @@ #![crate_type = "dylib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, phase)] diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index 90af1da78a457..f087b9289c3d7 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -17,7 +17,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(phase)] #![deny(deprecated_owned_vector)] diff --git a/src/liburl/lib.rs b/src/liburl/lib.rs index 12db15df31109..30054ea4c9238 100644 --- a/src/liburl/lib.rs +++ b/src/liburl/lib.rs @@ -16,7 +16,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(default_type_params)] use std::collections::HashMap; @@ -161,10 +162,10 @@ fn encode_inner(s: &str, full_url: bool) -> String { out.push_char(ch); } - _ => out.push_str(format!("%{:X}", ch as uint).as_slice()) + _ => out.push_str(format!("%{:02X}", ch as uint).as_slice()) } } else { - out.push_str(format!("%{:X}", ch as uint).as_slice()); + out.push_str(format!("%{:02X}", ch as uint).as_slice()); } } } @@ -1178,6 +1179,8 @@ mod tests { assert_eq!(encode("@"), "@".to_string()); assert_eq!(encode("["), "[".to_string()); assert_eq!(encode("]"), "]".to_string()); + assert_eq!(encode("\0"), "%00".to_string()); + assert_eq!(encode("\n"), "%0A".to_string()); } #[test] @@ -1207,6 +1210,8 @@ mod tests { assert_eq!(encode_component("@"), "%40".to_string()); assert_eq!(encode_component("["), "%5B".to_string()); assert_eq!(encode_component("]"), "%5D".to_string()); + assert_eq!(encode_component("\0"), "%00".to_string()); + assert_eq!(encode_component("\n"), "%0A".to_string()); } #[test] diff --git a/src/libuuid/lib.rs b/src/libuuid/lib.rs index 68c545802adb7..2459a7fc273a9 100644 --- a/src/libuuid/lib.rs +++ b/src/libuuid/lib.rs @@ -60,7 +60,8 @@ Examples of string representations: #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(default_type_params)] diff --git a/src/test/run-make/issue-14500/Makefile b/src/test/run-make/issue-14500/Makefile new file mode 100644 index 0000000000000..c1087b0f55ecf --- /dev/null +++ b/src/test/run-make/issue-14500/Makefile @@ -0,0 +1,14 @@ +-include ../tools.mk + +# Test to make sure that reachable extern fns are always available in final +# productcs, including when LTO is used. In this test, the `foo` crate has a +# reahable symbol, and is a dependency of the `bar` crate. When the `bar` crate +# is compiled with LTO, it shouldn't strip the symbol from `foo`, and that's the +# only way that `foo.c` will successfully compile. + +all: + $(RUSTC) foo.rs --crate-type=rlib + $(RUSTC) bar.rs --crate-type=staticlib -Zlto -L. -o $(TMPDIR)/libbar.a + $(CC) foo.c -lbar -o $(call RUN_BINFILE,foo) $(EXTRACFLAGS) + $(call RUN,foo) + diff --git a/src/test/run-make/issue-14500/bar.rs b/src/test/run-make/issue-14500/bar.rs new file mode 100644 index 0000000000000..4b4916fe96d63 --- /dev/null +++ b/src/test/run-make/issue-14500/bar.rs @@ -0,0 +1,11 @@ +// 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. + +extern crate foo; diff --git a/src/test/run-make/issue-14500/foo.c b/src/test/run-make/issue-14500/foo.c new file mode 100644 index 0000000000000..25098ac479d06 --- /dev/null +++ b/src/test/run-make/issue-14500/foo.c @@ -0,0 +1,16 @@ +// 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. + +extern void foo(); + +int main() { + foo(); + return 0; +} diff --git a/src/test/run-make/issue-14500/foo.rs b/src/test/run-make/issue-14500/foo.rs new file mode 100644 index 0000000000000..ceca907403f91 --- /dev/null +++ b/src/test/run-make/issue-14500/foo.rs @@ -0,0 +1,12 @@ +// 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. + +#[no_mangle] +pub extern fn foo() {} diff --git a/src/test/run-make/lto-smoke-c/Makefile b/src/test/run-make/lto-smoke-c/Makefile index 49a04ce42a0ae..9b44c3e582a71 100644 --- a/src/test/run-make/lto-smoke-c/Makefile +++ b/src/test/run-make/lto-smoke-c/Makefile @@ -1,23 +1,10 @@ -include ../tools.mk -ifdef IS_WINDOWS - EXTRAFLAGS := -else -ifeq ($(shell uname),Darwin) -else -ifeq ($(shell uname),FreeBSD) - EXTRAFLAGS := -lm -lpthread -lgcc_s -else - EXTRAFLAGS := -lm -lrt -ldl -lpthread -endif -endif -endif - # Apparently older versions of GCC segfault if -g is passed... CC := $(CC:-g=) all: $(RUSTC) foo.rs -Z lto ln -s $(call STATICLIB,foo-*) $(call STATICLIB,foo) - $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(EXTRAFLAGS) -lstdc++ + $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(EXTRACFLAGS) -lstdc++ $(call RUN,bar) diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk index dedd739052ca0..c9c4c455e4f80 100644 --- a/src/test/run-make/tools.mk +++ b/src/test/run-make/tools.mk @@ -53,6 +53,20 @@ RPATH_LINK_SEARCH = -Wl,-rpath-link=$(1) endif endif +# Extra flags needed to compile a working executable with the standard library +ifdef IS_WINDOWS + EXTRACFLAGS := +else +ifeq ($(shell uname),Darwin) +else +ifeq ($(shell uname),FreeBSD) + EXTRACFLAGS := -lm -lpthread -lgcc_s +else + EXTRACFLAGS := -lm -lrt -ldl -lpthread +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/issue-11612.rs b/src/test/run-pass/issue-11612.rs new file mode 100644 index 0000000000000..5fb2274a446fe --- /dev/null +++ b/src/test/run-pass/issue-11612.rs @@ -0,0 +1,30 @@ +// 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. + +// #11612 +// We weren't updating the auto adjustments with all the resolved +// type information after type check. + +trait A {} + +struct B<'a, T> { + f: &'a T +} + +impl<'a, T> A for B<'a, T> {} + +fn foo(_: &A) {} + +fn bar(b: &B) { + foo(b); // Coercion should work + foo(b as &A); // Explicit cast should work as well +} + +fn main() {} diff --git a/src/test/run-pass/issue-13204.rs b/src/test/run-pass/issue-13204.rs index 5fb9119849cab..f9b542dea56f0 100644 --- a/src/test/run-pass/issue-13204.rs +++ b/src/test/run-pass/issue-13204.rs @@ -14,7 +14,7 @@ pub trait Foo { fn bar<'a, I: Iterator<&'a ()>>(&self, it: I) -> uint { let mut xs = it.filter(|_| true); - xs.len() + xs.count() } } diff --git a/src/test/run-pass/issue-8460.rs b/src/test/run-pass/issue-8460.rs new file mode 100644 index 0000000000000..762152c92038f --- /dev/null +++ b/src/test/run-pass/issue-8460.rs @@ -0,0 +1,35 @@ +// 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 std::{int, i8, i16, i32, i64}; +use std::task; + +fn main() { + assert!(task::try(proc() int::MIN / -1).is_err()); + assert!(task::try(proc() i8::MIN / -1).is_err()); + assert!(task::try(proc() i16::MIN / -1).is_err()); + assert!(task::try(proc() i32::MIN / -1).is_err()); + assert!(task::try(proc() i64::MIN / -1).is_err()); + assert!(task::try(proc() 1i / 0).is_err()); + assert!(task::try(proc() 1i8 / 0).is_err()); + assert!(task::try(proc() 1i16 / 0).is_err()); + assert!(task::try(proc() 1i32 / 0).is_err()); + assert!(task::try(proc() 1i64 / 0).is_err()); + assert!(task::try(proc() int::MIN % -1).is_err()); + assert!(task::try(proc() i8::MIN % -1).is_err()); + assert!(task::try(proc() i16::MIN % -1).is_err()); + assert!(task::try(proc() i32::MIN % -1).is_err()); + assert!(task::try(proc() i64::MIN % -1).is_err()); + assert!(task::try(proc() 1i % 0).is_err()); + assert!(task::try(proc() 1i8 % 0).is_err()); + assert!(task::try(proc() 1i16 % 0).is_err()); + assert!(task::try(proc() 1i32 % 0).is_err()); + assert!(task::try(proc() 1i64 % 0).is_err()); +}