Auto merge of #37090 - GuillaumeGomez:rollup, r=GuillaumeGomez

Rollup of 9 pull requests

- Successful merges: #36679, #36699, #36997, #37040, #37060, #37065, #37072, #37073, #37081
- Failed merges:
This commit is contained in:
bors 2016-10-11 13:29:02 -07:00 committed by GitHub
commit 0b2c356420
16 changed files with 836 additions and 238 deletions

View File

@ -56,8 +56,12 @@ To fix this, we have to make sure that step four never happens after step
three. The ownership system in Rust does this through a concept called three. The ownership system in Rust does this through a concept called
lifetimes, which describe the scope that a reference is valid for. lifetimes, which describe the scope that a reference is valid for.
When we have a function that takes an argument by reference, we can be **Note** It's important to understand that lifetime annotations are
implicit or explicit about the lifetime of the reference: _descriptive_, not _prescriptive_. This means that how long a reference is valid
is determined by the code, not by the annotations. The annotations, however,
give information about lifetimes to the compiler that uses them to check the
validity of references. The compiler can do so without annotations in simple
cases, but needs the programmers support in complex scenarios.
```rust ```rust
// implicit // implicit

View File

@ -327,7 +327,7 @@
//! format := '{' [ argument ] [ ':' format_spec ] '}' //! format := '{' [ argument ] [ ':' format_spec ] '}'
//! argument := integer | identifier //! argument := integer | identifier
//! //!
//! format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type] //! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type]
//! fill := character //! fill := character
//! align := '<' | '^' | '>' //! align := '<' | '^' | '>'
//! sign := '+' | '-' //! sign := '+' | '-'

View File

@ -1789,4 +1789,24 @@ impl str {
String::from_utf8_unchecked(slice.into_vec()) String::from_utf8_unchecked(slice.into_vec())
} }
} }
/// Create a [`String`] by repeating a string `n` times.
///
/// [`String`]: string/struct.String.html
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(repeat_str)]
///
/// assert_eq!("abc".repeat(4), String::from("abcabcabcabc"));
/// ```
#[unstable(feature = "repeat_str", issue = "37079")]
pub fn repeat(&self, n: usize) -> String {
let mut s = String::with_capacity(self.len() * n);
s.extend((0..n).map(|_| self));
s
}
} }

View File

@ -14,12 +14,11 @@
//! [`ToString`]s, and several error types that may result from working with //! [`ToString`]s, and several error types that may result from working with
//! [`String`]s. //! [`String`]s.
//! //!
//! [`String`]: struct.String.html
//! [`ToString`]: trait.ToString.html //! [`ToString`]: trait.ToString.html
//! //!
//! # Examples //! # Examples
//! //!
//! There are multiple ways to create a new `String` from a string literal: //! There are multiple ways to create a new [`String`] from a string literal:
//! //!
//! ``` //! ```
//! let s = "Hello".to_string(); //! let s = "Hello".to_string();
@ -28,9 +27,11 @@
//! let s: String = "also this".into(); //! let s: String = "also this".into();
//! ``` //! ```
//! //!
//! You can create a new `String` from an existing one by concatenating with //! You can create a new [`String`] from an existing one by concatenating with
//! `+`: //! `+`:
//! //!
//! [`String`]: struct.String.html
//!
//! ``` //! ```
//! let s = "Hello".to_string(); //! let s = "Hello".to_string();
//! //!

View File

@ -19,6 +19,7 @@
#![feature(enumset)] #![feature(enumset)]
#![feature(pattern)] #![feature(pattern)]
#![feature(rand)] #![feature(rand)]
#![feature(repeat_str)]
#![feature(step_by)] #![feature(step_by)]
#![feature(str_escape)] #![feature(str_escape)]
#![feature(str_replacen)] #![feature(str_replacen)]

View File

@ -1286,6 +1286,13 @@ fn test_cow_from() {
} }
} }
#[test]
fn test_repeat() {
assert_eq!("".repeat(3), "");
assert_eq!("abc".repeat(0), "");
assert_eq!("α".repeat(3), "ααα");
}
mod pattern { mod pattern {
use std::str::pattern::Pattern; use std::str::pattern::Pattern;
use std::str::pattern::{Searcher, ReverseSearcher}; use std::str::pattern::{Searcher, ReverseSearcher};

View File

@ -1238,8 +1238,10 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> {
match pat.node { match pat.node {
PatKind::Binding(.., ref subpat) => { PatKind::Binding(.., ref subpat) => {
if !self.bindings_allowed { if !self.bindings_allowed {
span_err!(self.cx.tcx.sess, pat.span, E0303, struct_span_err!(self.cx.tcx.sess, pat.span, E0303,
"pattern bindings are not allowed after an `@`"); "pattern bindings are not allowed after an `@`")
.span_label(pat.span, &format!("not allowed after `@`"))
.emit();
} }
if subpat.is_some() { if subpat.is_some() {

View File

@ -42,7 +42,7 @@ pub struct UnsafetySpace(pub hir::Unsafety);
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct ConstnessSpace(pub hir::Constness); pub struct ConstnessSpace(pub hir::Constness);
/// Wrapper struct for properly emitting a method declaration. /// Wrapper struct for properly emitting a method declaration.
pub struct Method<'a>(pub &'a clean::FnDecl); pub struct Method<'a>(pub &'a clean::FnDecl, pub &'a str);
/// Similar to VisSpace, but used for mutability /// Similar to VisSpace, but used for mutability
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct MutableSpace(pub clean::Mutability); pub struct MutableSpace(pub clean::Mutability);
@ -84,7 +84,7 @@ impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, item) in self.0.iter().enumerate() { for (i, item) in self.0.iter().enumerate() {
if i != 0 { write!(f, ", ")?; } if i != 0 { write!(f, ", ")?; }
write!(f, "{}", item)?; fmt::Display::fmt(item, f)?;
} }
Ok(()) Ok(())
} }
@ -97,7 +97,7 @@ impl<'a> fmt::Display for TyParamBounds<'a> {
if i > 0 { if i > 0 {
f.write_str(" + ")?; f.write_str(" + ")?;
} }
write!(f, "{}", *bound)?; fmt::Display::fmt(bound, f)?;
} }
Ok(()) Ok(())
} }
@ -106,35 +106,51 @@ impl<'a> fmt::Display for TyParamBounds<'a> {
impl fmt::Display for clean::Generics { impl fmt::Display for clean::Generics {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.lifetimes.is_empty() && self.type_params.is_empty() { return Ok(()) } if self.lifetimes.is_empty() && self.type_params.is_empty() { return Ok(()) }
f.write_str("&lt;")?; if f.alternate() {
f.write_str("<")?;
} else {
f.write_str("&lt;")?;
}
for (i, life) in self.lifetimes.iter().enumerate() { for (i, life) in self.lifetimes.iter().enumerate() {
if i > 0 { if i > 0 {
f.write_str(",&nbsp;")?; f.write_str(", ")?;
} }
write!(f, "{}", *life)?; write!(f, "{}", *life)?;
} }
if !self.type_params.is_empty() { if !self.type_params.is_empty() {
if !self.lifetimes.is_empty() { if !self.lifetimes.is_empty() {
f.write_str(",&nbsp;")?; f.write_str(", ")?;
} }
for (i, tp) in self.type_params.iter().enumerate() { for (i, tp) in self.type_params.iter().enumerate() {
if i > 0 { if i > 0 {
f.write_str(",&nbsp;")? f.write_str(", ")?
} }
f.write_str(&tp.name)?; f.write_str(&tp.name)?;
if !tp.bounds.is_empty() { if !tp.bounds.is_empty() {
write!(f, ":&nbsp;{}", TyParamBounds(&tp.bounds))?; if f.alternate() {
write!(f, ": {:#}", TyParamBounds(&tp.bounds))?;
} else {
write!(f, ":&nbsp;{}", TyParamBounds(&tp.bounds))?;
}
} }
if let Some(ref ty) = tp.default { if let Some(ref ty) = tp.default {
write!(f, "&nbsp;=&nbsp;{}", ty)?; if f.alternate() {
write!(f, " = {:#}", ty)?;
} else {
write!(f, "&nbsp;=&nbsp;{}", ty)?;
}
}; };
} }
} }
f.write_str("&gt;")?; if f.alternate() {
f.write_str(">")?;
} else {
f.write_str("&gt;")?;
}
Ok(()) Ok(())
} }
} }
@ -145,7 +161,11 @@ impl<'a> fmt::Display for WhereClause<'a> {
if gens.where_predicates.is_empty() { if gens.where_predicates.is_empty() {
return Ok(()); return Ok(());
} }
f.write_str(" <span class='where'>where ")?; if f.alternate() {
f.write_str(" ")?;
} else {
f.write_str(" <span class='where'>where ")?;
}
for (i, pred) in gens.where_predicates.iter().enumerate() { for (i, pred) in gens.where_predicates.iter().enumerate() {
if i > 0 { if i > 0 {
f.write_str(", ")?; f.write_str(", ")?;
@ -153,7 +173,11 @@ impl<'a> fmt::Display for WhereClause<'a> {
match pred { match pred {
&clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => { &clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => {
let bounds = bounds; let bounds = bounds;
write!(f, "{}: {}", ty, TyParamBounds(bounds))?; if f.alternate() {
write!(f, "{:#}: {:#}", ty, TyParamBounds(bounds))?;
} else {
write!(f, "{}: {}", ty, TyParamBounds(bounds))?;
}
} }
&clean::WherePredicate::RegionPredicate { ref lifetime, &clean::WherePredicate::RegionPredicate { ref lifetime,
ref bounds } => { ref bounds } => {
@ -167,11 +191,17 @@ impl<'a> fmt::Display for WhereClause<'a> {
} }
} }
&clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => { &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => {
write!(f, "{} == {}", lhs, rhs)?; if f.alternate() {
write!(f, "{:#} == {:#}", lhs, rhs)?;
} else {
write!(f, "{} == {}", lhs, rhs)?;
}
} }
} }
} }
f.write_str("</span>")?; if !f.alternate() {
f.write_str("</span>")?;
}
Ok(()) Ok(())
} }
} }
@ -186,16 +216,28 @@ impl fmt::Display for clean::Lifetime {
impl fmt::Display for clean::PolyTrait { impl fmt::Display for clean::PolyTrait {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if !self.lifetimes.is_empty() { if !self.lifetimes.is_empty() {
f.write_str("for&lt;")?; if f.alternate() {
f.write_str("for<")?;
} else {
f.write_str("for&lt;")?;
}
for (i, lt) in self.lifetimes.iter().enumerate() { for (i, lt) in self.lifetimes.iter().enumerate() {
if i > 0 { if i > 0 {
f.write_str(", ")?; f.write_str(", ")?;
} }
write!(f, "{}", lt)?; write!(f, "{}", lt)?;
} }
f.write_str("&gt; ")?; if f.alternate() {
f.write_str("> ")?;
} else {
f.write_str("&gt; ")?;
}
}
if f.alternate() {
write!(f, "{:#}", self.trait_)
} else {
write!(f, "{}", self.trait_)
} }
write!(f, "{}", self.trait_)
} }
} }
@ -210,7 +252,11 @@ impl fmt::Display for clean::TyParamBound {
hir::TraitBoundModifier::None => "", hir::TraitBoundModifier::None => "",
hir::TraitBoundModifier::Maybe => "?", hir::TraitBoundModifier::Maybe => "?",
}; };
write!(f, "{}{}", modifier_str, *ty) if f.alternate() {
write!(f, "{}{:#}", modifier_str, *ty)
} else {
write!(f, "{}{}", modifier_str, *ty)
}
} }
} }
} }
@ -223,30 +269,46 @@ impl fmt::Display for clean::PathParameters {
ref lifetimes, ref types, ref bindings ref lifetimes, ref types, ref bindings
} => { } => {
if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() { if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
f.write_str("&lt;")?; if f.alternate() {
f.write_str("<")?;
} else {
f.write_str("&lt;")?;
}
let mut comma = false; let mut comma = false;
for lifetime in lifetimes { for lifetime in lifetimes {
if comma { if comma {
f.write_str(",&nbsp;")?; f.write_str(", ")?;
} }
comma = true; comma = true;
write!(f, "{}", *lifetime)?; write!(f, "{}", *lifetime)?;
} }
for ty in types { for ty in types {
if comma { if comma {
f.write_str(",&nbsp;")?; f.write_str(", ")?;
} }
comma = true; comma = true;
write!(f, "{}", *ty)?; if f.alternate() {
write!(f, "{:#}", *ty)?;
} else {
write!(f, "{}", *ty)?;
}
} }
for binding in bindings { for binding in bindings {
if comma { if comma {
f.write_str(",&nbsp;")?; f.write_str(", ")?;
} }
comma = true; comma = true;
write!(f, "{}", *binding)?; if f.alternate() {
write!(f, "{:#}", *binding)?;
} else {
write!(f, "{}", *binding)?;
}
}
if f.alternate() {
f.write_str(">")?;
} else {
f.write_str("&gt;")?;
} }
f.write_str("&gt;")?;
} }
} }
clean::PathParameters::Parenthesized { ref inputs, ref output } => { clean::PathParameters::Parenthesized { ref inputs, ref output } => {
@ -257,12 +319,19 @@ impl fmt::Display for clean::PathParameters {
f.write_str(", ")?; f.write_str(", ")?;
} }
comma = true; comma = true;
write!(f, "{}", *ty)?; if f.alternate() {
write!(f, "{:#}", *ty)?;
} else {
write!(f, "{}", *ty)?;
}
} }
f.write_str(")")?; f.write_str(")")?;
if let Some(ref ty) = *output { if let Some(ref ty) = *output {
f.write_str(" -&gt; ")?; if f.alternate() {
write!(f, "{}", ty)?; write!(f, " -> {:#}", ty)?;
} else {
write!(f, " -&gt; {}", ty)?;
}
} }
} }
} }
@ -273,7 +342,11 @@ impl fmt::Display for clean::PathParameters {
impl fmt::Display for clean::PathSegment { impl fmt::Display for clean::PathSegment {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.name)?; f.write_str(&self.name)?;
write!(f, "{}", self.params) if f.alternate() {
write!(f, "{:#}", self.params)
} else {
write!(f, "{}", self.params)
}
} }
} }
@ -287,7 +360,11 @@ impl fmt::Display for clean::Path {
if i > 0 { if i > 0 {
f.write_str("::")? f.write_str("::")?
} }
write!(f, "{}", seg)?; if f.alternate() {
write!(f, "{:#}", seg)?;
} else {
write!(f, "{}", seg)?;
}
} }
Ok(()) Ok(())
} }
@ -349,7 +426,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
match rel_root { match rel_root {
Some(mut root) => { Some(mut root) => {
for seg in &path.segments[..amt] { for seg in &path.segments[..amt] {
if "super" == seg.name || "self" == seg.name { if "super" == seg.name || "self" == seg.name || w.alternate() {
write!(w, "{}::", seg.name)?; write!(w, "{}::", seg.name)?;
} else { } else {
root.push_str(&seg.name); root.push_str(&seg.name);
@ -368,7 +445,11 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
} }
} }
} }
write!(w, "{}{}", HRef::new(did, &last.name), last.params)?; if w.alternate() {
write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.params)?;
} else {
write!(w, "{}{}", HRef::new(did, &last.name), last.params)?;
}
Ok(()) Ok(())
} }
@ -377,33 +458,35 @@ fn primitive_link(f: &mut fmt::Formatter,
name: &str) -> fmt::Result { name: &str) -> fmt::Result {
let m = cache(); let m = cache();
let mut needs_termination = false; let mut needs_termination = false;
match m.primitive_locations.get(&prim) { if !f.alternate() {
Some(&LOCAL_CRATE) => { match m.primitive_locations.get(&prim) {
let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); Some(&LOCAL_CRATE) => {
let len = if len == 0 {0} else {len - 1}; let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
write!(f, "<a class='primitive' href='{}primitive.{}.html'>", let len = if len == 0 {0} else {len - 1};
repeat("../").take(len).collect::<String>(), write!(f, "<a class='primitive' href='{}primitive.{}.html'>",
prim.to_url_str())?; repeat("../").take(len).collect::<String>(),
needs_termination = true;
}
Some(&cnum) => {
let loc = match m.extern_locations[&cnum] {
(ref cname, render::Remote(ref s)) => Some((cname, s.to_string())),
(ref cname, render::Local) => {
let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
Some((cname, repeat("../").take(len).collect::<String>()))
}
(_, render::Unknown) => None,
};
if let Some((cname, root)) = loc {
write!(f, "<a class='primitive' href='{}{}/primitive.{}.html'>",
root,
cname,
prim.to_url_str())?; prim.to_url_str())?;
needs_termination = true; needs_termination = true;
} }
Some(&cnum) => {
let loc = match m.extern_locations[&cnum] {
(ref cname, render::Remote(ref s)) => Some((cname, s.to_string())),
(ref cname, render::Local) => {
let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
Some((cname, repeat("../").take(len).collect::<String>()))
}
(_, render::Unknown) => None,
};
if let Some((cname, root)) = loc {
write!(f, "<a class='primitive' href='{}{}/primitive.{}.html'>",
root,
cname,
prim.to_url_str())?;
needs_termination = true;
}
}
None => {}
} }
None => {}
} }
write!(f, "{}", name)?; write!(f, "{}", name)?;
if needs_termination { if needs_termination {
@ -419,7 +502,7 @@ fn tybounds(w: &mut fmt::Formatter,
Some(ref params) => { Some(ref params) => {
for param in params { for param in params {
write!(w, " + ")?; write!(w, " + ")?;
write!(w, "{}", *param)?; fmt::Display::fmt(param, w)?;
} }
Ok(()) Ok(())
} }
@ -436,10 +519,12 @@ impl<'a> HRef<'a> {
impl<'a> fmt::Display for HRef<'a> { impl<'a> fmt::Display for HRef<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match href(self.did) { match href(self.did) {
Some((url, shortty, fqp)) => { Some((url, shortty, fqp)) => if !f.alternate() {
write!(f, "<a class='{}' href='{}' title='{}'>{}</a>", write!(f, "<a class='{}' href='{}' title='{}'>{}</a>",
shortty, url, fqp.join("::"), self.text) shortty, url, fqp.join("::"), self.text)
} } else {
write!(f, "{}", self.text)
},
_ => write!(f, "{}", self.text), _ => write!(f, "{}", self.text),
} }
} }
@ -459,49 +544,68 @@ impl fmt::Display for clean::Type {
clean::Infer => write!(f, "_"), clean::Infer => write!(f, "_"),
clean::Primitive(prim) => primitive_link(f, prim, prim.as_str()), clean::Primitive(prim) => primitive_link(f, prim, prim.as_str()),
clean::BareFunction(ref decl) => { clean::BareFunction(ref decl) => {
write!(f, "{}{}fn{}{}", if f.alternate() {
UnsafetySpace(decl.unsafety), write!(f, "{}{}fn{:#}{:#}",
AbiSpace(decl.abi), UnsafetySpace(decl.unsafety),
decl.generics, AbiSpace(decl.abi),
decl.decl) decl.generics,
decl.decl)
} else {
write!(f, "{}{}fn{}{}",
UnsafetySpace(decl.unsafety),
AbiSpace(decl.abi),
decl.generics,
decl.decl)
}
} }
clean::Tuple(ref typs) => { clean::Tuple(ref typs) => {
match &typs[..] { match &typs[..] {
&[] => primitive_link(f, PrimitiveType::Tuple, "()"), &[] => primitive_link(f, PrimitiveType::Tuple, "()"),
&[ref one] => { &[ref one] => {
primitive_link(f, PrimitiveType::Tuple, "(")?; primitive_link(f, PrimitiveType::Tuple, "(")?;
write!(f, "{},", one)?; //carry f.alternate() into this display w/o branching manually
primitive_link(f, PrimitiveType::Tuple, ")") fmt::Display::fmt(one, f)?;
primitive_link(f, PrimitiveType::Tuple, ",)")
} }
many => { many => {
primitive_link(f, PrimitiveType::Tuple, "(")?; primitive_link(f, PrimitiveType::Tuple, "(")?;
write!(f, "{}", CommaSep(&many))?; fmt::Display::fmt(&CommaSep(&many), f)?;
primitive_link(f, PrimitiveType::Tuple, ")") primitive_link(f, PrimitiveType::Tuple, ")")
} }
} }
} }
clean::Vector(ref t) => { clean::Vector(ref t) => {
primitive_link(f, PrimitiveType::Slice, &format!("["))?; primitive_link(f, PrimitiveType::Slice, &format!("["))?;
write!(f, "{}", t)?; fmt::Display::fmt(t, f)?;
primitive_link(f, PrimitiveType::Slice, &format!("]")) primitive_link(f, PrimitiveType::Slice, &format!("]"))
} }
clean::FixedVector(ref t, ref s) => { clean::FixedVector(ref t, ref s) => {
primitive_link(f, PrimitiveType::Array, "[")?; primitive_link(f, PrimitiveType::Array, "[")?;
write!(f, "{}", t)?; fmt::Display::fmt(t, f)?;
primitive_link(f, PrimitiveType::Array, if f.alternate() {
&format!("; {}]", Escape(s))) primitive_link(f, PrimitiveType::Array,
&format!("; {}]", s))
} else {
primitive_link(f, PrimitiveType::Array,
&format!("; {}]", Escape(s)))
}
} }
clean::Never => f.write_str("!"), clean::Never => f.write_str("!"),
clean::RawPointer(m, ref t) => { clean::RawPointer(m, ref t) => {
match **t { match **t {
clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => { clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => {
primitive_link(f, clean::PrimitiveType::RawPointer, if f.alternate() {
&format!("*{}{}", RawMutableSpace(m), t)) primitive_link(f, clean::PrimitiveType::RawPointer,
&format!("*{}{:#}", RawMutableSpace(m), t))
} else {
primitive_link(f, clean::PrimitiveType::RawPointer,
&format!("*{}{}", RawMutableSpace(m), t))
}
} }
_ => { _ => {
primitive_link(f, clean::PrimitiveType::RawPointer, primitive_link(f, clean::PrimitiveType::RawPointer,
&format!("*{}", RawMutableSpace(m)))?; &format!("*{}", RawMutableSpace(m)))?;
write!(f, "{}", t) fmt::Display::fmt(t, f)
} }
} }
} }
@ -515,18 +619,33 @@ impl fmt::Display for clean::Type {
clean::Vector(ref bt) => { // BorrowedRef{ ... Vector(T) } is &[T] clean::Vector(ref bt) => { // BorrowedRef{ ... Vector(T) } is &[T]
match **bt { match **bt {
clean::Generic(_) => clean::Generic(_) =>
primitive_link(f, PrimitiveType::Slice, if f.alternate() {
&format!("&amp;{}{}[{}]", lt, m, **bt)), primitive_link(f, PrimitiveType::Slice,
&format!("&{}{}[{:#}]", lt, m, **bt))
} else {
primitive_link(f, PrimitiveType::Slice,
&format!("&amp;{}{}[{}]", lt, m, **bt))
},
_ => { _ => {
primitive_link(f, PrimitiveType::Slice, if f.alternate() {
&format!("&amp;{}{}[", lt, m))?; primitive_link(f, PrimitiveType::Slice,
write!(f, "{}", **bt)?; &format!("&{}{}[", lt, m))?;
write!(f, "{:#}", **bt)?;
} else {
primitive_link(f, PrimitiveType::Slice,
&format!("&amp;{}{}[", lt, m))?;
write!(f, "{}", **bt)?;
}
primitive_link(f, PrimitiveType::Slice, "]") primitive_link(f, PrimitiveType::Slice, "]")
} }
} }
} }
_ => { _ => {
write!(f, "&amp;{}{}{}", lt, m, **ty) if f.alternate() {
write!(f, "&{}{}{:#}", lt, m, **ty)
} else {
write!(f, "&amp;{}{}{}", lt, m, **ty)
}
} }
} }
} }
@ -535,7 +654,11 @@ impl fmt::Display for clean::Type {
if i != 0 { if i != 0 {
write!(f, " + ")?; write!(f, " + ")?;
} }
write!(f, "{}", *bound)?; if f.alternate() {
write!(f, "{:#}", *bound)?;
} else {
write!(f, "{}", *bound)?;
}
} }
Ok(()) Ok(())
} }
@ -545,7 +668,11 @@ impl fmt::Display for clean::Type {
if i != 0 { if i != 0 {
write!(f, " + ")?; write!(f, " + ")?;
} }
write!(f, "{}", *bound)?; if f.alternate() {
write!(f, "{:#}", *bound)?;
} else {
write!(f, "{}", *bound)?;
}
} }
Ok(()) Ok(())
} }
@ -564,7 +691,11 @@ impl fmt::Display for clean::Type {
ref self_type, ref self_type,
trait_: box clean::ResolvedPath { did, ref typarams, .. }, trait_: box clean::ResolvedPath { did, ref typarams, .. },
} => { } => {
write!(f, "{}::", self_type)?; if f.alternate() {
write!(f, "{:#}::", self_type)?;
} else {
write!(f, "{}::", self_type)?;
}
let path = clean::Path::singleton(name.clone()); let path = clean::Path::singleton(name.clone());
resolved_path(f, did, &path, false)?; resolved_path(f, did, &path, false)?;
@ -573,7 +704,11 @@ impl fmt::Display for clean::Type {
Ok(()) Ok(())
} }
clean::QPath { ref name, ref self_type, ref trait_ } => { clean::QPath { ref name, ref self_type, ref trait_ } => {
write!(f, "&lt;{} as {}&gt;::{}", self_type, trait_, name) if f.alternate() {
write!(f, "<{:#} as {:#}>::{}", self_type, trait_, name)
} else {
write!(f, "&lt;{} as {}&gt;::{}", self_type, trait_, name)
}
} }
clean::Unique(..) => { clean::Unique(..) => {
panic!("should have been cleaned") panic!("should have been cleaned")
@ -583,24 +718,30 @@ impl fmt::Display for clean::Type {
} }
fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::Result { fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::Result {
write!(f, "impl{} ", i.generics)?; if f.alternate() {
write!(f, "impl{:#} ", i.generics)?;
} else {
write!(f, "impl{} ", i.generics)?;
}
if let Some(ref ty) = i.trait_ { if let Some(ref ty) = i.trait_ {
write!(f, "{}", write!(f, "{}",
if i.polarity == Some(clean::ImplPolarity::Negative) { "!" } else { "" })?; if i.polarity == Some(clean::ImplPolarity::Negative) { "!" } else { "" })?;
if link_trait { if link_trait {
write!(f, "{}", *ty)?; fmt::Display::fmt(ty, f)?;
} else { } else {
match *ty { match *ty {
clean::ResolvedPath{ typarams: None, ref path, is_generic: false, .. } => { clean::ResolvedPath{ typarams: None, ref path, is_generic: false, .. } => {
let last = path.segments.last().unwrap(); let last = path.segments.last().unwrap();
write!(f, "{}{}", last.name, last.params)?; fmt::Display::fmt(&last.name, f)?;
fmt::Display::fmt(&last.params, f)?;
} }
_ => unreachable!(), _ => unreachable!(),
} }
} }
write!(f, " for ")?; write!(f, " for ")?;
} }
write!(f, "{}{}", i.for_, WhereClause(&i.generics))?; fmt::Display::fmt(&i.for_, f)?;
fmt::Display::fmt(&WhereClause(&i.generics), f)?;
Ok(()) Ok(())
} }
@ -618,11 +759,15 @@ pub fn fmt_impl_for_trait_page(i: &clean::Impl, f: &mut fmt::Formatter) -> fmt::
impl fmt::Display for clean::Arguments { impl fmt::Display for clean::Arguments {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, input) in self.values.iter().enumerate() { for (i, input) in self.values.iter().enumerate() {
if i > 0 { write!(f, ", ")?; }
if !input.name.is_empty() { if !input.name.is_empty() {
write!(f, "{}: ", input.name)?; write!(f, "{}: ", input.name)?;
} }
write!(f, "{}", input.type_)?; if f.alternate() {
write!(f, "{:#}", input.type_)?;
} else {
write!(f, "{}", input.type_)?;
}
if i + 1 < self.values.len() { write!(f, ", ")?; }
} }
Ok(()) Ok(())
} }
@ -632,6 +777,7 @@ impl fmt::Display for clean::FunctionRetTy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
clean::Return(clean::Tuple(ref tys)) if tys.is_empty() => Ok(()), clean::Return(clean::Tuple(ref tys)) if tys.is_empty() => Ok(()),
clean::Return(ref ty) if f.alternate() => write!(f, " -> {:#}", ty),
clean::Return(ref ty) => write!(f, " -&gt; {}", ty), clean::Return(ref ty) => write!(f, " -&gt; {}", ty),
clean::DefaultReturn => Ok(()), clean::DefaultReturn => Ok(()),
} }
@ -641,9 +787,17 @@ impl fmt::Display for clean::FunctionRetTy {
impl fmt::Display for clean::FnDecl { impl fmt::Display for clean::FnDecl {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.variadic { if self.variadic {
write!(f, "({args}, ...){arrow}", args = self.inputs, arrow = self.output) if f.alternate() {
write!(f, "({args:#}, ...){arrow:#}", args = self.inputs, arrow = self.output)
} else {
write!(f, "({args}, ...){arrow}", args = self.inputs, arrow = self.output)
}
} else { } else {
write!(f, "({args}){arrow}", args = self.inputs, arrow = self.output) if f.alternate() {
write!(f, "({args:#}){arrow:#}", args = self.inputs, arrow = self.output)
} else {
write!(f, "({args}){arrow}", args = self.inputs, arrow = self.output)
}
} }
} }
} }
@ -651,30 +805,89 @@ impl fmt::Display for clean::FnDecl {
impl<'a> fmt::Display for Method<'a> { impl<'a> fmt::Display for Method<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let decl = self.0; let decl = self.0;
let indent = self.1;
let amp = if f.alternate() { "&" } else { "&amp;" };
let mut args = String::new(); let mut args = String::new();
let mut args_plain = String::new();
for (i, input) in decl.inputs.values.iter().enumerate() { for (i, input) in decl.inputs.values.iter().enumerate() {
if i > 0 || !args.is_empty() { args.push_str(", "); }
if let Some(selfty) = input.to_self() { if let Some(selfty) = input.to_self() {
match selfty { match selfty {
clean::SelfValue => args.push_str("self"), clean::SelfValue => {
args.push_str("self");
args_plain.push_str("self");
}
clean::SelfBorrowed(Some(ref lt), mtbl) => { clean::SelfBorrowed(Some(ref lt), mtbl) => {
args.push_str(&format!("&amp;{} {}self", *lt, MutableSpace(mtbl))); args.push_str(&format!("{}{} {}self", amp, *lt, MutableSpace(mtbl)));
args_plain.push_str(&format!("&{} {}self", *lt, MutableSpace(mtbl)));
} }
clean::SelfBorrowed(None, mtbl) => { clean::SelfBorrowed(None, mtbl) => {
args.push_str(&format!("&amp;{}self", MutableSpace(mtbl))); args.push_str(&format!("{}{}self", amp, MutableSpace(mtbl)));
args_plain.push_str(&format!("&{}self", MutableSpace(mtbl)));
} }
clean::SelfExplicit(ref typ) => { clean::SelfExplicit(ref typ) => {
args.push_str(&format!("self: {}", *typ)); if f.alternate() {
args.push_str(&format!("self: {:#}", *typ));
} else {
args.push_str(&format!("self: {}", *typ));
}
args_plain.push_str(&format!("self: {:#}", *typ));
} }
} }
} else { } else {
if i > 0 {
args.push_str("<br> ");
args_plain.push_str(" ");
}
if !input.name.is_empty() { if !input.name.is_empty() {
args.push_str(&format!("{}: ", input.name)); args.push_str(&format!("{}: ", input.name));
args_plain.push_str(&format!("{}: ", input.name));
} }
args.push_str(&format!("{}", input.type_));
if f.alternate() {
args.push_str(&format!("{:#}", input.type_));
} else {
args.push_str(&format!("{}", input.type_));
}
args_plain.push_str(&format!("{:#}", input.type_));
}
if i + 1 < decl.inputs.values.len() {
args.push_str(",");
args_plain.push_str(",");
} }
} }
write!(f, "({args}){arrow}", args = args, arrow = decl.output)
if decl.variadic {
args.push_str(",<br> ...");
args_plain.push_str(", ...");
}
let arrow_plain = format!("{:#}", decl.output);
let arrow = if f.alternate() {
format!("{:#}", decl.output)
} else {
format!("{}", decl.output)
};
let mut output: String;
let plain: String;
if arrow.is_empty() {
output = format!("({})", args);
plain = format!("{}({})", indent.replace("&nbsp;", " "), args_plain);
} else {
output = format!("({args})<br>{arrow}", args = args, arrow = arrow);
plain = format!("{indent}({args}){arrow}",
indent = indent.replace("&nbsp;", " "),
args = args_plain,
arrow = arrow_plain);
}
if plain.len() > 80 {
let pad = format!("<br>{}", indent);
output = output.replace("<br>", &pad);
} else {
output = output.replace("<br>", "");
}
write!(f, "{}", output)
} }
} }
@ -768,7 +981,11 @@ impl fmt::Display for clean::ViewListIdent {
impl fmt::Display for clean::TypeBinding { impl fmt::Display for clean::TypeBinding {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}={}", self.name, self.ty) if f.alternate() {
write!(f, "{}={:#}", self.name, self.ty)
} else {
write!(f, "{}={}", self.name, self.ty)
}
} }
} }
@ -792,10 +1009,11 @@ impl fmt::Display for RawMutableSpace {
impl fmt::Display for AbiSpace { impl fmt::Display for AbiSpace {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let quot = if f.alternate() { "\"" } else { "&quot;" };
match self.0 { match self.0 {
Abi::Rust => Ok(()), Abi::Rust => Ok(()),
Abi::C => write!(f, "extern "), Abi::C => write!(f, "extern "),
abi => write!(f, "extern &quot;{}&quot; ", abi.name()), abi => write!(f, "extern {0}{1}{0} ", quot, abi.name()),
} }
} }
} }

View File

@ -1967,6 +1967,14 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
UnstableFeatures::Allow => f.constness, UnstableFeatures::Allow => f.constness,
_ => hir::Constness::NotConst _ => hir::Constness::NotConst
}; };
let prefix = format!("{}{}{}{:#}fn {}{:#}",
VisSpace(&it.visibility),
ConstnessSpace(vis_constness),
UnsafetySpace(f.unsafety),
AbiSpace(f.abi),
it.name.as_ref().unwrap(),
f.generics);
let indent = repeat("&nbsp;").take(prefix.len()).collect::<String>();
write!(w, "<pre class='rust fn'>{vis}{constness}{unsafety}{abi}fn \ write!(w, "<pre class='rust fn'>{vis}{constness}{unsafety}{abi}fn \
{name}{generics}{decl}{where_clause}</pre>", {name}{generics}{decl}{where_clause}</pre>",
vis = VisSpace(&it.visibility), vis = VisSpace(&it.visibility),
@ -1976,7 +1984,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
name = it.name.as_ref().unwrap(), name = it.name.as_ref().unwrap(),
generics = f.generics, generics = f.generics,
where_clause = WhereClause(&f.generics), where_clause = WhereClause(&f.generics),
decl = f.decl)?; decl = Method(&f.decl, &indent))?;
document(w, cx, it) document(w, cx, it)
} }
@ -2246,6 +2254,13 @@ fn render_assoc_item(w: &mut fmt::Formatter,
UnstableFeatures::Allow => constness, UnstableFeatures::Allow => constness,
_ => hir::Constness::NotConst _ => hir::Constness::NotConst
}; };
let prefix = format!("{}{}{:#}fn {}{:#}",
ConstnessSpace(vis_constness),
UnsafetySpace(unsafety),
AbiSpace(abi),
name,
*g);
let indent = repeat("&nbsp;").take(prefix.len()).collect::<String>();
write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\ write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
{generics}{decl}{where_clause}", {generics}{decl}{where_clause}",
ConstnessSpace(vis_constness), ConstnessSpace(vis_constness),
@ -2254,7 +2269,7 @@ fn render_assoc_item(w: &mut fmt::Formatter,
href = href, href = href,
name = name, name = name,
generics = *g, generics = *g,
decl = Method(d), decl = Method(d, &indent),
where_clause = WhereClause(g)) where_clause = WhereClause(g))
} }
match item.inner { match item.inner {

View File

@ -125,9 +125,8 @@ impl fmt::Display for Token {
} }
} }
fn buf_str(toks: &[Token], szs: &[isize], left: usize, right: usize, lim: usize) -> String { fn buf_str(buf: &[BufEntry], left: usize, right: usize, lim: usize) -> String {
let n = toks.len(); let n = buf.len();
assert_eq!(n, szs.len());
let mut i = left; let mut i = left;
let mut l = lim; let mut l = lim;
let mut s = String::from("["); let mut s = String::from("[");
@ -136,7 +135,7 @@ fn buf_str(toks: &[Token], szs: &[isize], left: usize, right: usize, lim: usize)
if i != left { if i != left {
s.push_str(", "); s.push_str(", ");
} }
s.push_str(&format!("{}={}", szs[i], &toks[i])); s.push_str(&format!("{}={}", buf[i].size, &buf[i].token));
i += 1; i += 1;
i %= n; i %= n;
} }
@ -159,13 +158,9 @@ pub struct PrintStackElem {
const SIZE_INFINITY: isize = 0xffff; const SIZE_INFINITY: isize = 0xffff;
pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> { pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
// Yes 55, it makes the ring buffers big enough to never // Yes 55, it makes the ring buffers big enough to never fall behind.
// fall behind.
let n: usize = 55 * linewidth; let n: usize = 55 * linewidth;
debug!("mk_printer {}", linewidth); debug!("mk_printer {}", linewidth);
let token = vec![Token::Eof; n];
let size = vec![0; n];
let scan_stack = VecDeque::with_capacity(n);
Printer { Printer {
out: out, out: out,
buf_len: n, buf_len: n,
@ -173,11 +168,10 @@ pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
space: linewidth as isize, space: linewidth as isize,
left: 0, left: 0,
right: 0, right: 0,
token: token, buf: vec![BufEntry { token: Token::Eof, size: 0 }; n],
size: size,
left_total: 0, left_total: 0,
right_total: 0, right_total: 0,
scan_stack: scan_stack, scan_stack: VecDeque::new(),
print_stack: Vec::new(), print_stack: Vec::new(),
pending_indentation: 0 pending_indentation: 0
} }
@ -269,10 +263,8 @@ pub struct Printer<'a> {
left: usize, left: usize,
/// Index of right side of input stream /// Index of right side of input stream
right: usize, right: usize,
/// Ring-buffer stream goes through /// Ring-buffer of tokens and calculated sizes
token: Vec<Token> , buf: Vec<BufEntry>,
/// Ring-buffer of calculated sizes
size: Vec<isize> ,
/// Running size of stream "...left" /// Running size of stream "...left"
left_total: isize, left_total: isize,
/// Running size of stream "...right" /// Running size of stream "...right"
@ -283,20 +275,26 @@ pub struct Printer<'a> {
/// Begin (if there is any) on top of it. Stuff is flushed off the /// Begin (if there is any) on top of it. Stuff is flushed off the
/// bottom as it becomes irrelevant due to the primary ring-buffer /// bottom as it becomes irrelevant due to the primary ring-buffer
/// advancing. /// advancing.
scan_stack: VecDeque<usize> , scan_stack: VecDeque<usize>,
/// Stack of blocks-in-progress being flushed by print /// Stack of blocks-in-progress being flushed by print
print_stack: Vec<PrintStackElem> , print_stack: Vec<PrintStackElem> ,
/// Buffered indentation to avoid writing trailing whitespace /// Buffered indentation to avoid writing trailing whitespace
pending_indentation: isize, pending_indentation: isize,
} }
#[derive(Clone)]
struct BufEntry {
token: Token,
size: isize,
}
impl<'a> Printer<'a> { impl<'a> Printer<'a> {
pub fn last_token(&mut self) -> Token { pub fn last_token(&mut self) -> Token {
self.token[self.right].clone() self.buf[self.right].token.clone()
} }
// be very careful with this! // be very careful with this!
pub fn replace_last_token(&mut self, t: Token) { pub fn replace_last_token(&mut self, t: Token) {
self.token[self.right] = t; self.buf[self.right].token = t;
} }
pub fn pretty_print(&mut self, token: Token) -> io::Result<()> { pub fn pretty_print(&mut self, token: Token) -> io::Result<()> {
debug!("pp Vec<{},{}>", self.left, self.right); debug!("pp Vec<{},{}>", self.left, self.right);
@ -318,8 +316,7 @@ impl<'a> Printer<'a> {
} else { self.advance_right(); } } else { self.advance_right(); }
debug!("pp Begin({})/buffer Vec<{},{}>", debug!("pp Begin({})/buffer Vec<{},{}>",
b.offset, self.left, self.right); b.offset, self.left, self.right);
self.token[self.right] = token; self.buf[self.right] = BufEntry { token: token, size: -self.right_total };
self.size[self.right] = -self.right_total;
let right = self.right; let right = self.right;
self.scan_push(right); self.scan_push(right);
Ok(()) Ok(())
@ -331,8 +328,7 @@ impl<'a> Printer<'a> {
} else { } else {
debug!("pp End/buffer Vec<{},{}>", self.left, self.right); debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
self.advance_right(); self.advance_right();
self.token[self.right] = token; self.buf[self.right] = BufEntry { token: token, size: -1 };
self.size[self.right] = -1;
let right = self.right; let right = self.right;
self.scan_push(right); self.scan_push(right);
Ok(()) Ok(())
@ -350,8 +346,7 @@ impl<'a> Printer<'a> {
self.check_stack(0); self.check_stack(0);
let right = self.right; let right = self.right;
self.scan_push(right); self.scan_push(right);
self.token[self.right] = token; self.buf[self.right] = BufEntry { token: token, size: -self.right_total };
self.size[self.right] = -self.right_total;
self.right_total += b.blank_space; self.right_total += b.blank_space;
Ok(()) Ok(())
} }
@ -364,8 +359,7 @@ impl<'a> Printer<'a> {
debug!("pp String('{}')/buffer Vec<{},{}>", debug!("pp String('{}')/buffer Vec<{},{}>",
s, self.left, self.right); s, self.left, self.right);
self.advance_right(); self.advance_right();
self.token[self.right] = Token::String(s, len); self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len };
self.size[self.right] = len;
self.right_total += len; self.right_total += len;
self.check_stream() self.check_stream()
} }
@ -381,7 +375,7 @@ impl<'a> Printer<'a> {
if Some(&self.left) == self.scan_stack.back() { if Some(&self.left) == self.scan_stack.back() {
debug!("setting {} to infinity and popping", self.left); debug!("setting {} to infinity and popping", self.left);
let scanned = self.scan_pop_bottom(); let scanned = self.scan_pop_bottom();
self.size[scanned] = SIZE_INFINITY; self.buf[scanned].size = SIZE_INFINITY;
} }
self.advance_left()?; self.advance_left()?;
if self.left != self.right { if self.left != self.right {
@ -410,12 +404,12 @@ impl<'a> Printer<'a> {
} }
pub fn advance_left(&mut self) -> io::Result<()> { pub fn advance_left(&mut self) -> io::Result<()> {
debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right, debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right,
self.left, self.size[self.left]); self.left, self.buf[self.left].size);
let mut left_size = self.size[self.left]; let mut left_size = self.buf[self.left].size;
while left_size >= 0 { while left_size >= 0 {
let left = self.token[self.left].clone(); let left = self.buf[self.left].token.clone();
let len = match left { let len = match left {
Token::Break(b) => b.blank_space, Token::Break(b) => b.blank_space,
@ -437,7 +431,7 @@ impl<'a> Printer<'a> {
self.left += 1; self.left += 1;
self.left %= self.buf_len; self.left %= self.buf_len;
left_size = self.size[self.left]; left_size = self.buf[self.left].size;
} }
Ok(()) Ok(())
@ -445,23 +439,23 @@ impl<'a> Printer<'a> {
pub fn check_stack(&mut self, k: isize) { pub fn check_stack(&mut self, k: isize) {
if !self.scan_stack.is_empty() { if !self.scan_stack.is_empty() {
let x = self.scan_top(); let x = self.scan_top();
match self.token[x] { match self.buf[x].token {
Token::Begin(_) => { Token::Begin(_) => {
if k > 0 { if k > 0 {
let popped = self.scan_pop(); let popped = self.scan_pop();
self.size[popped] = self.size[x] + self.right_total; self.buf[popped].size = self.buf[x].size + self.right_total;
self.check_stack(k - 1); self.check_stack(k - 1);
} }
} }
Token::End => { Token::End => {
// paper says + not =, but that makes no sense. // paper says + not =, but that makes no sense.
let popped = self.scan_pop(); let popped = self.scan_pop();
self.size[popped] = 1; self.buf[popped].size = 1;
self.check_stack(k + 1); self.check_stack(k + 1);
} }
_ => { _ => {
let popped = self.scan_pop(); let popped = self.scan_pop();
self.size[popped] = self.size[x] + self.right_total; self.buf[popped].size = self.buf[x].size + self.right_total;
if k > 0 { if k > 0 {
self.check_stack(k); self.check_stack(k);
} }
@ -499,8 +493,7 @@ impl<'a> Printer<'a> {
pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> { pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> {
debug!("print {} {} (remaining line space={})", token, l, debug!("print {} {} (remaining line space={})", token, l,
self.space); self.space);
debug!("{}", buf_str(&self.token, debug!("{}", buf_str(&self.buf,
&self.size,
self.left, self.left,
self.right, self.right,
6)); 6));

View File

@ -15,6 +15,7 @@ fn main() {
//~^ ERROR E0007 //~^ ERROR E0007
//~| NOTE binds an already bound by-move value by moving it //~| NOTE binds an already bound by-move value by moving it
//~| ERROR E0303 //~| ERROR E0303
//~| NOTE not allowed after `@`
None => {}, None => {},
} }
} }

View File

@ -10,8 +10,12 @@
fn main() { fn main() {
match Some("hi".to_string()) { match Some("hi".to_string()) {
ref op_string_ref @ Some(s) => {}, //~ ERROR E0303 ref op_string_ref @ Some(s) => {},
//~^ ERROR E0009 //~^ ERROR pattern bindings are not allowed after an `@` [E0303]
//~| NOTE not allowed after `@`
//~| ERROR E0009
//~| NOTE by-move pattern here
//~| NOTE both by-ref and by-move used
None => {}, None => {},
} }
} }

View File

@ -0,0 +1,132 @@
// Copyright 2016 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.
// This test case tests the incremental compilation hash (ICH) implementation
// for consts.
// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
// must-compile-successfully
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph
#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]
// Change const visibility ---------------------------------------------------
#[cfg(cfail1)]
const CONST_VISIBILITY: u8 = 0;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub const CONST_VISIBILITY: u8 = 0;
// Change type from i32 to u32 ------------------------------------------------
#[cfg(cfail1)]
const CONST_CHANGE_TYPE_1: i32 = 0;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
const CONST_CHANGE_TYPE_1: u32 = 0;
// Change type from Option<u32> to Option<u64> --------------------------------
#[cfg(cfail1)]
const CONST_CHANGE_TYPE_2: Option<u32> = None;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
const CONST_CHANGE_TYPE_2: Option<u64> = None;
// Change value between simple literals ---------------------------------------
#[cfg(cfail1)]
const CONST_CHANGE_VALUE_1: i16 = 1;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
const CONST_CHANGE_VALUE_1: i16 = 2;
// Change value between expressions -------------------------------------------
#[cfg(cfail1)]
const CONST_CHANGE_VALUE_2: i16 = 1 + 1;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
const CONST_CHANGE_VALUE_2: i16 = 1 + 2;
#[cfg(cfail1)]
const CONST_CHANGE_VALUE_3: i16 = 2 + 3;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
const CONST_CHANGE_VALUE_3: i16 = 2 * 3;
#[cfg(cfail1)]
const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 3;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 4;
// Change type indirectly -----------------------------------------------------
struct ReferencedType1;
struct ReferencedType2;
mod const_change_type_indirectly {
#[cfg(cfail1)]
use super::ReferencedType1 as Type;
#[cfg(not(cfail1))]
use super::ReferencedType2 as Type;
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
const CONST_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
}

View File

@ -0,0 +1,185 @@
// Copyright 2016 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.
// This test case tests the incremental compilation hash (ICH) implementation
// for statics.
// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
// must-compile-successfully
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph
#![allow(warnings)]
#![feature(rustc_attrs)]
#![feature(linkage)]
#![feature(thread_local)]
#![crate_type="rlib"]
// Change static visibility ---------------------------------------------------
#[cfg(cfail1)]
static STATIC_VISIBILITY: u8 = 0;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub static STATIC_VISIBILITY: u8 = 0;
// Change static mutability ---------------------------------------------------
#[cfg(cfail1)]
static STATIC_MUTABILITY: u8 = 0;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
static mut STATIC_MUTABILITY: u8 = 0;
// Add linkage attribute ------------------------------------------------------
#[cfg(cfail1)]
static STATIC_LINKAGE: u8 = 0;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[linkage="weak_odr"]
static STATIC_LINKAGE: u8 = 0;
// Add no_mangle attribute ----------------------------------------------------
#[cfg(cfail1)]
static STATIC_NO_MANGLE: u8 = 0;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[no_mangle]
static STATIC_NO_MANGLE: u8 = 0;
// Add thread_local attribute -------------------------------------------------
#[cfg(cfail1)]
static STATIC_THREAD_LOCAL: u8 = 0;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[thread_local]
static STATIC_THREAD_LOCAL: u8 = 0;
// Change type from i16 to u64 ------------------------------------------------
#[cfg(cfail1)]
static STATIC_CHANGE_TYPE_1: i16 = 0;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
static STATIC_CHANGE_TYPE_1: u64 = 0;
// Change type from Option<i8> to Option<u16> ---------------------------------
#[cfg(cfail1)]
static STATIC_CHANGE_TYPE_2: Option<i8> = None;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
static STATIC_CHANGE_TYPE_2: Option<u16> = None;
// Change value between simple literals ---------------------------------------
#[cfg(cfail1)]
static STATIC_CHANGE_VALUE_1: i16 = 1;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
static STATIC_CHANGE_VALUE_1: i16 = 2;
// Change value between expressions -------------------------------------------
#[cfg(cfail1)]
static STATIC_CHANGE_VALUE_2: i16 = 1 + 1;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
static STATIC_CHANGE_VALUE_2: i16 = 1 + 2;
#[cfg(cfail1)]
static STATIC_CHANGE_VALUE_3: i16 = 2 + 3;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
static STATIC_CHANGE_VALUE_3: i16 = 2 * 3;
#[cfg(cfail1)]
static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 3;
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 4;
// Change type indirectly -----------------------------------------------------
struct ReferencedType1;
struct ReferencedType2;
mod static_change_type_indirectly {
#[cfg(cfail1)]
use super::ReferencedType1 as Type;
#[cfg(not(cfail1))]
use super::ReferencedType2 as Type;
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
}

View File

@ -46,16 +46,15 @@ pub trait TraitVisibility { }
// Change trait unsafety ---------------------------------------------------------- // Change trait unsafety ----------------------------------------------------------
// FIXME: this should work but doesn't yet. #[cfg(cfail1)]
// #[cfg(cfail1)] trait TraitUnsafety { }
// trait TraitUnsafety { }
// #[cfg(not(cfail1))] #[cfg(not(cfail1))]
// #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_dirty(label="Hir", cfg="cfail2")]
// #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
// #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_dirty(cfg="cfail2")]
// #[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
// unsafe trait TraitUnsafety { } unsafe trait TraitUnsafety { }
@ -178,20 +177,19 @@ trait TraitChangeMethodParameterType {
// Change type of method parameter (&i32 => &mut i32) ----------------------------- // Change type of method parameter (&i32 => &mut i32) -----------------------------
// FIXME: this should work but doesn't yet. #[cfg(cfail1)]
// #[cfg(cfail1)] trait TraitChangeMethodParameterTypeRef {
// trait TraitChangeMethodParameterTypeRef { fn method(a: &i32);
// fn method(a: &i32); }
// }
// #[cfg(not(cfail1))] #[cfg(not(cfail1))]
// #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_dirty(label="Hir", cfg="cfail2")]
// #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
// #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_dirty(cfg="cfail2")]
// #[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
// trait TraitChangeMethodParameterTypeRef { trait TraitChangeMethodParameterTypeRef {
// fn method(a: &mut i32); fn method(a: &mut i32);
// } }
@ -249,35 +247,35 @@ trait TraitChangeOrderOfMethods {
// Change mode of self parameter -------------------------------------------------- // Change mode of self parameter --------------------------------------------------
// FIXME: this should work but doesn't yet. #[cfg(cfail1)]
// #[cfg(cfail1)] trait TraitChangeModeSelfRefToMut {
// trait TraitChangeModeSelfRefToMut { fn method(&self);
// fn method(&self); }
// }
// #[cfg(not(cfail1))] #[cfg(not(cfail1))]
// #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_dirty(label="Hir", cfg="cfail2")]
// #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
// #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_dirty(cfg="cfail2")]
// #[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
// trait TraitChangeModeSelfRefToMut { trait TraitChangeModeSelfRefToMut {
// fn method(&mut self); fn method(&mut self);
// } }
// FIXME: this should work but doesn't yet.
// #[cfg(cfail1)]
// trait TraitChangeModeSelfOwnToMut {
// fn method(self);
// }
// #[cfg(not(cfail1))]
// #[rustc_dirty(label="Hir", cfg="cfail2")] #[cfg(cfail1)]
// #[rustc_clean(label="Hir", cfg="cfail3")] trait TraitChangeModeSelfOwnToMut {
// #[rustc_metadata_dirty(cfg="cfail2")] fn method(self);
// #[rustc_metadata_clean(cfg="cfail3")] }
// trait TraitChangeModeSelfOwnToMut {
// fn method(mut self); #[cfg(not(cfail1))]
// } #[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
trait TraitChangeModeSelfOwnToMut {
fn method(mut self);
}
@ -298,56 +296,53 @@ trait TraitChangeModeSelfOwnToRef {
// Add unsafe modifier to method -------------------------------------------------- // Add unsafe modifier to method --------------------------------------------------
// FIXME: this should work but doesn't yet. #[cfg(cfail1)]
// #[cfg(cfail1)] trait TraitAddUnsafeModifier {
// trait TraitAddUnsafeModifier { fn method();
// fn method(); }
// }
// #[cfg(not(cfail1))] #[cfg(not(cfail1))]
// #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_dirty(label="Hir", cfg="cfail2")]
// #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
// #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_dirty(cfg="cfail2")]
// #[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
// trait TraitAddUnsafeModifier { trait TraitAddUnsafeModifier {
// unsafe fn method(); unsafe fn method();
// } }
// Add extern modifier to method -------------------------------------------------- // Add extern modifier to method --------------------------------------------------
// FIXME: this should work but doesn't yet. #[cfg(cfail1)]
// #[cfg(cfail1)] trait TraitAddExternModifier {
// trait TraitAddExternModifier { fn method();
// fn method(); }
// }
// #[cfg(not(cfail1))] #[cfg(not(cfail1))]
// #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_dirty(label="Hir", cfg="cfail2")]
// #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
// #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_dirty(cfg="cfail2")]
// #[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
// trait TraitAddExternModifier { trait TraitAddExternModifier {
// extern fn method(); extern fn method();
// } }
// Change extern "C" to extern "rust-intrinsic" ----------------------------------- // Change extern "C" to extern "rust-intrinsic" -----------------------------------
// FIXME: this should work but doesn't yet. #[cfg(cfail1)]
// #[cfg(cfail1)] trait TraitChangeExternCToRustIntrinsic {
// trait TraitChangeExternCToRustIntrinsic { extern "C" fn method();
// extern "C" fn method(); }
// }
// #[cfg(not(cfail1))] #[cfg(not(cfail1))]
// #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_dirty(label="Hir", cfg="cfail2")]
// #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
// #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_dirty(cfg="cfail2")]
// #[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
// trait TraitChangeExternCToRustIntrinsic { trait TraitChangeExternCToRustIntrinsic {
// extern "rust-intrinsic" fn method(); extern "rust-intrinsic" fn method();
// } }
@ -1118,4 +1113,3 @@ mod change_method_type_parameter_bound_indirectly_where {
fn method(a: T); fn method(a: T);
} }
} }

View File

@ -0,0 +1,21 @@
// Copyright 2016 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.
#![crate_name = "foo"]
//@count foo/fn.function_with_a_really_long_name.html //pre/br 2
pub fn function_with_a_really_long_name(parameter_one: i32,
parameter_two: i32)
-> Option<i32> {
Some(parameter_one + parameter_two)
}
//@count foo/fn.short_name.html //pre/br 0
pub fn short_name(param: i32) -> i32 { param + 1 }