auto merge of #14712 : alexcrichton/rust/rollup, r=alexcrichton

Closes #14675 (rustc: Encode argument names for traits)
Closes #14681 (rustc: Avoid UB with signed division/remainder)
Closes #14682 (librustc: Update AutoObject adjustment in writeback.)
Closes #14683 (Avoid 16-byte filenames in rlibs)
Closes #14687 (rustdoc: Inline static documentation across crates)
Closes #14689 (Remove reference to ~str in documentation)
Closes #14692 (Rename Iterator::len to count)
Closes #14693 (Implement Eq for HashSet and HashMap)
Closes #14699 (url: encode small bytes correctly.)
Closes #14700 (rustdoc: Submit examples to play.rust-lang.org)
Closes #14701 (mk: Run doc tests with --cfg dox)
Closes #14710 (rustc: Preserve reachable extern fns with LTO)
Closes #14711 (Removing unused wrapper to libc::close.)
This commit is contained in:
bors 2014-06-06 20:42:01 -07:00
commit e87e18064e
77 changed files with 645 additions and 234 deletions

View file

@ -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

View file

@ -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)):

View file

@ -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()
}

View file

@ -5,3 +5,5 @@ or the <a href="http://opensource.org/licenses/MIT">MIT license</a>, at your opt
</p><p>
This file may not be copied, modified, or distributed except according to those terms.
</p></footer>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="playpen.js"></script>

View file

@ -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.

View file

@ -523,6 +523,7 @@ vectors provided from C, using idiomatic Rust practices.
```
#![no_std]
#![feature(globs)]
# extern crate libc;
extern crate core;

View file

@ -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;

View file

@ -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_,

View file

@ -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!") }

View file

@ -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> {

View file

@ -1131,7 +1131,7 @@ mod tests {
let v = &[0, ..128];
let m: DList<int> = 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<int> = 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<int> = 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<int> = v.iter().map(|&x|x).collect();
b.iter(|| {
assert!(m.mut_iter().rev().len() == 128);
assert!(m.mut_iter().rev().count() == 128);
})
}
}

View file

@ -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]

View file

@ -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();
}

View file

@ -31,7 +31,7 @@ pub struct SmallIntMap<T> {
impl<V> Container for SmallIntMap<V> {
/// 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

View file

@ -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]

View file

@ -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]

View file

@ -529,11 +529,11 @@ pub trait Iterator<A> {
/// ```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<A> {
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<A> : DoubleEndedIterator<A> {
}
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<int>>() ==
vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]);
assert!(range(0i, 5).rev().collect::<Vec<int>>() == 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<int>>() ==
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<int>>() == vec![200]);
assert!(range_inclusive(200, 200).rev().collect::<Vec<int>>() == vec![200]);
}

View file

@ -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)]

View file

@ -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<T> 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};

View file

@ -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 {

View file

@ -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)]

View file

@ -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;

View file

@ -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)]

View file

@ -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)]

View file

@ -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)]

View file

@ -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]

View file

@ -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)]

View file

@ -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);

View file

@ -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()) {

View file

@ -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!");

View file

@ -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,

View file

@ -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<ast::DefId>
{
let cdata = cstore.get_crate_data(cnum);
decoder::get_reachable_extern_fns(&*cdata)
}

View file

@ -1325,3 +1325,17 @@ pub fn get_method_arg_names(cdata: Cmd, id: ast::NodeId) -> Vec<String> {
}
return ret;
}
pub fn get_reachable_extern_fns(cdata: Cmd) -> Vec<ast::DefId> {
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;
}

View file

@ -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<EncodeInlinedItem<'a>>,
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<PI: Iterator<PathElem> + 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.

View file

@ -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));

View file

@ -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

View file

@ -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 {

View file

@ -191,11 +191,11 @@ fn ast_path_substs<AC:AstConv,RS:RegionScope>(
};
// 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<AC:AstConv,
if path.segments
.iter()
.flat_map(|s| s.types.iter())
.len() > 1 {
.count() > 1 {
this.tcx()
.sess
.span_err(path.span,

View file

@ -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()

View file

@ -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);
}

View file

@ -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(

View file

@ -456,7 +456,7 @@ pub fn parameterized(cx: &ctxt,
Some(default) => default.subst(cx, &substs) == actual,
None => false
}
}).len()
}).count()
} else {
0
};

View file

@ -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
}
}

View file

@ -35,6 +35,8 @@ pub struct VisSpace(pub Option<ast::Visibility>);
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<ast::Visibility> {
@ -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, "&amp;{}{}{}",
lt,
match mutability {
clean::Mutable => "mut ",
clean::Immutable => "",
},
**ty)
write!(f, "&amp;{}{}{}", 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!("&amp;{} self", *lt).as_slice());
clean::SelfBorrowed(Some(ref lt), mtbl) => {
args.push_str(format!("&amp;{} {}self", *lt,
MutableSpace(mtbl)).as_slice());
}
clean::SelfBorrowed(Some(ref lt), clean::Mutable) => {
args.push_str(format!("&amp;{} mut self", *lt).as_slice());
}
clean::SelfBorrowed(None, clean::Mutable) => {
args.push_str("&amp;mut self");
}
clean::SelfBorrowed(None, clean::Immutable) => {
args.push_str("&amp;self");
clean::SelfBorrowed(None, mtbl) => {
args.push_str(format!("&amp;{}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 "),
}
}
}

View file

@ -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, "<pre class='rust {}'>\n", class.unwrap_or("")));
try!(write!(out, "<pre "));
match id {
Some(id) => 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;

View file

@ -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##"<!DOCTYPE html>
</div>
<script>
var rootPath = "{root_path}";
var currentCrate = "{krate}";
window.rootPath = "{root_path}";
window.currentCrate = "{krate}";
window.playgroundUrl = "{play_url}";
</script>
<script src="{root_path}jquery.js"></script>
<script src="{root_path}main.js"></script>
{play_js}
<script async src="{root_path}search-index.js"></script>
</body>
</html>"##,
@ -124,6 +127,12 @@ r##"<!DOCTYPE html>
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#"<script src="{}playpen.js"></script>"#, page.root_path)
},
)
}

View file

@ -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<HashMap<String, uint>>)
local_data_key!(test_idx: Cell<uint>)
// None == render an example, but there's no crate name
local_data_key!(pub playground_krate: Option<String>)
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::<Vec<&str>>().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::<Vec<&str>>().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!("<span id='rust-example-raw-{}' \
class='rusttest'>{}</span>",
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> {

View file

@ -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, "
<tr>
<td><code>{}static {}: {}</code>{}</td>
<td><code>{}static {}{}: {}</code>{}</td>
<td class='docblock'>{}&nbsp;</td>
</tr>
",
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<String, Vec<String>> {
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, "<span id='{0:u}'>{0:1$u}</span>\n", i, cols));
}
try!(write!(fmt, "</pre>"));
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)
}

View file

@ -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;

View file

@ -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');

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*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 = $('<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();
});
}
}());

View file

@ -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()
}
}

View file

@ -126,7 +126,9 @@ pub fn opts() -> Vec<getopts::OptGroup> {
optmulti("", "markdown-after-content",
"files to include inline between the content and </body> of a rendered \
Markdown file",
"FILES")
"FILES"),
optopt("", "markdown-playground-url",
"URL to send code snippets to", "URL")
)
}

View file

@ -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}
<h1 class="title">{title}</h1>
{text}
<script type="text/javascript">
window.playgroundUrl = "{playground}";
</script>
{after_content}
</body>
</html>"#,
@ -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<Path>, mut test_args: Vec<String>) -> 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);

View file

@ -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<Path>, 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<Path>, 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<String>,
cratename: String,
loose_feature_gating: bool
}
impl Collector {
pub fn new(cratename: String, libs: HashSet<Path>,
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);
}),
});
}

View file

@ -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

View file

@ -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<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V,
}
}
impl<K: Eq + Hash<S>, V: Eq, S, H: Hasher<S>> Eq for HashMap<K, V, H> {}
impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, r"\{"));
@ -1486,7 +1488,7 @@ pub type SetMoveItems<K> =
/// 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<T, H = sip::SipHasher> {
map: HashMap<T, (), H>
@ -1500,6 +1502,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
}
}
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {}
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Container for HashSet<T, H> {
fn len(&self) -> uint { self.map.len() }
}

View file

@ -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)]

View file

@ -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 */ }) )

View file

@ -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;

View file

@ -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;

View file

@ -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::<u8>().take(0).len(), 0u);
assert_eq!(r.gen_iter::<u8>().take(10).len(), 10u);
assert_eq!(r.gen_iter::<f64>().take(16).len(), 16u);
assert_eq!(r.gen_iter::<u8>().take(0).count(), 0u);
assert_eq!(r.gen_iter::<u8>().take(10).count(), 10u);
assert_eq!(r.gen_iter::<f64>().take(16).count(), 16u);
}
#[test]

View file

@ -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;

View file

@ -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)]

View file

@ -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)]

View file

@ -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)]

View file

@ -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]

View file

@ -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)]

View file

@ -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)

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate foo;

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern void foo();
int main() {
foo();
return 0;
}

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[no_mangle]
pub extern fn foo() {}

View file

@ -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)

View file

@ -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))

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// #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<G>(b: &B<G>) {
foo(b); // Coercion should work
foo(b as &A); // Explicit cast should work as well
}
fn main() {}

View file

@ -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()
}
}

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use 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());
}