From 9cfd4ef38f99d4574049b1b1c641b80672cd1cff Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Fri, 23 Sep 2016 09:19:24 -0500 Subject: [PATCH 01/19] rustdoc: print arguments to bare functions on their own line --- src/librustdoc/html/format.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index adcdc7aaab4..7131e993d77 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -618,11 +618,15 @@ pub fn fmt_impl_for_trait_page(i: &clean::Impl, f: &mut fmt::Formatter) -> fmt:: impl fmt::Display for clean::Arguments { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for (i, input) in self.values.iter().enumerate() { - if i > 0 { write!(f, ", ")?; } + write!(f, "\n ")?; if !input.name.is_empty() { write!(f, "{}: ", input.name)?; } write!(f, "{}", input.type_)?; + if i + 1 < self.values.len() { write!(f, ",")?; } + } + if !self.values.is_empty() { + write!(f, "\n")?; } Ok(()) } From fccfc5392aa36a788abf329cb8c251241adc28d0 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Fri, 23 Sep 2016 12:56:08 -0500 Subject: [PATCH 02/19] rustdoc: format non-self arguments for struct methods on their own line --- src/librustdoc/html/format.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 7131e993d77..853741db7ae 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -657,7 +657,6 @@ impl<'a> fmt::Display for Method<'a> { let decl = self.0; let mut args = String::new(); 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() { match selfty { clean::SelfValue => args.push_str("self"), @@ -672,11 +671,16 @@ impl<'a> fmt::Display for Method<'a> { } } } else { + args.push_str("\n "); if !input.name.is_empty() { args.push_str(&format!("{}: ", input.name)); } args.push_str(&format!("{}", input.type_)); } + if i + 1 < decl.inputs.values.len() { args.push_str(","); } + } + if let Some(None) = decl.inputs.values.iter().last().map(|val| val.to_self()) { + args.push_str("\n"); } write!(f, "({args}){arrow}", args = args, arrow = decl.output) } From 2a274e720fe8046d8db154ca2661701a519a0033 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Mon, 26 Sep 2016 16:02:21 -0500 Subject: [PATCH 03/19] rustdoc: format struct methods like rustfmt * ignore signatures 80 characters or shorter * otherwise, put arguments and return arrow on their own line, indented to the opening parenthesis in doing this, most of a plain-text output has been written for rustdoc, accessible through "alternate" Display printing: "{:#}" --- src/librustdoc/html/format.rs | 403 +++++++++++++++++++++++++--------- src/librustdoc/html/render.rs | 17 +- 2 files changed, 320 insertions(+), 100 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 853741db7ae..84057fddf5a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -42,7 +42,7 @@ pub struct UnsafetySpace(pub hir::Unsafety); #[derive(Copy, Clone)] pub struct ConstnessSpace(pub hir::Constness); /// 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 #[derive(Copy, Clone)] 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 { for (i, item) in self.0.iter().enumerate() { if i != 0 { write!(f, ", ")?; } - write!(f, "{}", item)?; + fmt::Display::fmt(item, f)?; } Ok(()) } @@ -97,7 +97,7 @@ impl<'a> fmt::Display for TyParamBounds<'a> { if i > 0 { f.write_str(" + ")?; } - write!(f, "{}", *bound)?; + fmt::Display::fmt(bound, f)?; } Ok(()) } @@ -106,35 +106,51 @@ impl<'a> fmt::Display for TyParamBounds<'a> { impl fmt::Display for clean::Generics { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.lifetimes.is_empty() && self.type_params.is_empty() { return Ok(()) } - f.write_str("<")?; + if f.alternate() { + f.write_str("<")?; + } else { + f.write_str("<")?; + } for (i, life) in self.lifetimes.iter().enumerate() { if i > 0 { - f.write_str(", ")?; + f.write_str(", ")?; } write!(f, "{}", *life)?; } if !self.type_params.is_empty() { if !self.lifetimes.is_empty() { - f.write_str(", ")?; + f.write_str(", ")?; } for (i, tp) in self.type_params.iter().enumerate() { if i > 0 { - f.write_str(", ")? + f.write_str(", ")? } f.write_str(&tp.name)?; if !tp.bounds.is_empty() { - write!(f, ": {}", TyParamBounds(&tp.bounds))?; + if f.alternate() { + write!(f, ": {:#}", TyParamBounds(&tp.bounds))?; + } else { + write!(f, ": {}", TyParamBounds(&tp.bounds))?; + } } if let Some(ref ty) = tp.default { - write!(f, " = {}", ty)?; + if f.alternate() { + write!(f, " = {:#}", ty)?; + } else { + write!(f, " = {}", ty)?; + } }; } } - f.write_str(">")?; + if f.alternate() { + f.write_str(">")?; + } else { + f.write_str(">")?; + } Ok(()) } } @@ -145,7 +161,11 @@ impl<'a> fmt::Display for WhereClause<'a> { if gens.where_predicates.is_empty() { return Ok(()); } - f.write_str(" where ")?; + if f.alternate() { + f.write_str(" ")?; + } else { + f.write_str(" where ")?; + } for (i, pred) in gens.where_predicates.iter().enumerate() { if i > 0 { f.write_str(", ")?; @@ -153,7 +173,11 @@ impl<'a> fmt::Display for WhereClause<'a> { match pred { &clean::WherePredicate::BoundPredicate { ref ty, ref 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, ref bounds } => { @@ -167,11 +191,17 @@ impl<'a> fmt::Display for WhereClause<'a> { } } &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("")?; + if !f.alternate() { + f.write_str("")?; + } Ok(()) } } @@ -186,16 +216,28 @@ impl fmt::Display for clean::Lifetime { impl fmt::Display for clean::PolyTrait { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if !self.lifetimes.is_empty() { - f.write_str("for<")?; + if f.alternate() { + f.write_str("for<")?; + } else { + f.write_str("for<")?; + } for (i, lt) in self.lifetimes.iter().enumerate() { if i > 0 { f.write_str(", ")?; } write!(f, "{}", lt)?; } - f.write_str("> ")?; + if f.alternate() { + f.write_str("> ")?; + } else { + f.write_str("> ")?; + } + } + 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::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 } => { if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() { - f.write_str("<")?; + if f.alternate() { + f.write_str("<")?; + } else { + f.write_str("<")?; + } let mut comma = false; for lifetime in lifetimes { if comma { - f.write_str(", ")?; + f.write_str(", ")?; } comma = true; write!(f, "{}", *lifetime)?; } for ty in types { if comma { - f.write_str(", ")?; + f.write_str(", ")?; } comma = true; - write!(f, "{}", *ty)?; + if f.alternate() { + write!(f, "{:#}", *ty)?; + } else { + write!(f, "{}", *ty)?; + } } for binding in bindings { if comma { - f.write_str(", ")?; + f.write_str(", ")?; } 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(">")?; } - f.write_str(">")?; } } clean::PathParameters::Parenthesized { ref inputs, ref output } => { @@ -257,12 +319,19 @@ impl fmt::Display for clean::PathParameters { f.write_str(", ")?; } comma = true; - write!(f, "{}", *ty)?; + if f.alternate() { + write!(f, "{:#}", *ty)?; + } else { + write!(f, "{}", *ty)?; + } } f.write_str(")")?; if let Some(ref ty) = *output { - f.write_str(" -> ")?; - write!(f, "{}", ty)?; + if f.alternate() { + write!(f, " -> {:#}", ty)?; + } else { + write!(f, " -> {}", ty)?; + } } } } @@ -273,7 +342,11 @@ impl fmt::Display for clean::PathParameters { impl fmt::Display for clean::PathSegment { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 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 { f.write_str("::")? } - write!(f, "{}", seg)?; + if f.alternate() { + write!(f, "{:#}", seg)?; + } else { + write!(f, "{}", seg)?; + } } Ok(()) } @@ -349,7 +426,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path, match rel_root { Some(mut root) => { 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)?; } else { 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(()) } @@ -377,33 +458,35 @@ fn primitive_link(f: &mut fmt::Formatter, name: &str) -> fmt::Result { let m = cache(); let mut needs_termination = false; - match m.primitive_locations.get(&prim) { - Some(&LOCAL_CRATE) => { - let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); - let len = if len == 0 {0} else {len - 1}; - write!(f, "", - repeat("../").take(len).collect::(), - prim.to_url_str())?; - 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::())) - } - (_, render::Unknown) => None, - }; - if let Some((cname, root)) = loc { - write!(f, "", - root, - cname, + if !f.alternate() { + match m.primitive_locations.get(&prim) { + Some(&LOCAL_CRATE) => { + let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); + let len = if len == 0 {0} else {len - 1}; + write!(f, "", + repeat("../").take(len).collect::(), prim.to_url_str())?; 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::())) + } + (_, render::Unknown) => None, + }; + if let Some((cname, root)) = loc { + write!(f, "", + root, + cname, + prim.to_url_str())?; + needs_termination = true; + } + } + None => {} } - None => {} } write!(f, "{}", name)?; if needs_termination { @@ -419,7 +502,7 @@ fn tybounds(w: &mut fmt::Formatter, Some(ref params) => { for param in params { write!(w, " + ")?; - write!(w, "{}", *param)?; + fmt::Display::fmt(param, w)?; } Ok(()) } @@ -436,10 +519,12 @@ impl<'a> HRef<'a> { impl<'a> fmt::Display for HRef<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match href(self.did) { - Some((url, shortty, fqp)) => { + Some((url, shortty, fqp)) => if !f.alternate() { write!(f, "{}", shortty, url, fqp.join("::"), self.text) - } + } else { + write!(f, "{}", self.text) + }, _ => write!(f, "{}", self.text), } } @@ -459,49 +544,68 @@ impl fmt::Display for clean::Type { clean::Infer => write!(f, "_"), clean::Primitive(prim) => primitive_link(f, prim, prim.to_string()), clean::BareFunction(ref decl) => { - write!(f, "{}{}fn{}{}", - UnsafetySpace(decl.unsafety), - AbiSpace(decl.abi), - decl.generics, - decl.decl) + if f.alternate() { + write!(f, "{}{}fn{:#}{:#}", + UnsafetySpace(decl.unsafety), + AbiSpace(decl.abi), + decl.generics, + decl.decl) + } else { + write!(f, "{}{}fn{}{}", + UnsafetySpace(decl.unsafety), + AbiSpace(decl.abi), + decl.generics, + decl.decl) + } } clean::Tuple(ref typs) => { match &typs[..] { &[] => primitive_link(f, PrimitiveType::Tuple, "()"), &[ref one] => { primitive_link(f, PrimitiveType::Tuple, "(")?; - write!(f, "{},", one)?; + //carry f.alternate() into this display w/o branching manually + fmt::Display::fmt(one, f)?; primitive_link(f, PrimitiveType::Tuple, ")") } many => { primitive_link(f, PrimitiveType::Tuple, "(")?; - write!(f, "{}", CommaSep(&many))?; + fmt::Display::fmt(&CommaSep(&many), f)?; primitive_link(f, PrimitiveType::Tuple, ")") } } } clean::Vector(ref t) => { primitive_link(f, PrimitiveType::Slice, &format!("["))?; - write!(f, "{}", t)?; + fmt::Display::fmt(t, f)?; primitive_link(f, PrimitiveType::Slice, &format!("]")) } clean::FixedVector(ref t, ref s) => { primitive_link(f, PrimitiveType::Array, "[")?; - write!(f, "{}", t)?; - primitive_link(f, PrimitiveType::Array, - &format!("; {}]", Escape(s))) + fmt::Display::fmt(t, f)?; + if f.alternate() { + primitive_link(f, PrimitiveType::Array, + &format!("; {}]", s)) + } else { + primitive_link(f, PrimitiveType::Array, + &format!("; {}]", Escape(s))) + } } clean::Never => f.write_str("!"), clean::RawPointer(m, ref t) => { match **t { clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => { - primitive_link(f, clean::PrimitiveType::RawPointer, - &format!("*{}{}", RawMutableSpace(m), t)) + if f.alternate() { + 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, &format!("*{}", RawMutableSpace(m)))?; - write!(f, "{}", t) + fmt::Display::fmt(t, f) } } } @@ -515,18 +619,31 @@ impl fmt::Display for clean::Type { clean::Vector(ref bt) => { // BorrowedRef{ ... Vector(T) } is &[T] match **bt { clean::Generic(_) => - primitive_link(f, PrimitiveType::Slice, - &format!("&{}{}[{}]", lt, m, **bt)), + if f.alternate() { + primitive_link(f, PrimitiveType::Slice, + &format!("&{}{}[{:#}]", lt, m, **bt)) + } else { + primitive_link(f, PrimitiveType::Slice, + &format!("&{}{}[{}]", lt, m, **bt)) + }, _ => { primitive_link(f, PrimitiveType::Slice, &format!("&{}{}[", lt, m))?; - write!(f, "{}", **bt)?; + if f.alternate() { + write!(f, "{:#}", **bt)?; + } else { + write!(f, "{}", **bt)?; + } primitive_link(f, PrimitiveType::Slice, "]") } } } _ => { - write!(f, "&{}{}{}", lt, m, **ty) + if f.alternate() { + write!(f, "&{}{}{:#}", lt, m, **ty) + } else { + write!(f, "&{}{}{}", lt, m, **ty) + } } } } @@ -535,7 +652,11 @@ impl fmt::Display for clean::Type { if i != 0 { write!(f, " + ")?; } - write!(f, "{}", *bound)?; + if f.alternate() { + write!(f, "{:#}", *bound)?; + } else { + write!(f, "{}", *bound)?; + } } Ok(()) } @@ -545,7 +666,11 @@ impl fmt::Display for clean::Type { if i != 0 { write!(f, " + ")?; } - write!(f, "{}", *bound)?; + if f.alternate() { + write!(f, "{:#}", *bound)?; + } else { + write!(f, "{}", *bound)?; + } } Ok(()) } @@ -564,7 +689,11 @@ impl fmt::Display for clean::Type { ref self_type, 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()); resolved_path(f, did, &path, false)?; @@ -573,7 +702,11 @@ impl fmt::Display for clean::Type { Ok(()) } clean::QPath { ref name, ref self_type, ref trait_ } => { - write!(f, "<{} as {}>::{}", self_type, trait_, name) + if f.alternate() { + write!(f, "<{:#} as {:#}>::{}", self_type, trait_, name) + } else { + write!(f, "<{} as {}>::{}", self_type, trait_, name) + } } clean::Unique(..) => { panic!("should have been cleaned") @@ -583,24 +716,30 @@ impl fmt::Display for clean::Type { } 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_ { write!(f, "{}", if i.polarity == Some(clean::ImplPolarity::Negative) { "!" } else { "" })?; if link_trait { - write!(f, "{}", *ty)?; + fmt::Display::fmt(ty, f)?; } else { match *ty { clean::ResolvedPath{ typarams: None, ref path, is_generic: false, .. } => { 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!(), } } write!(f, " for ")?; } - write!(f, "{}{}", i.for_, WhereClause(&i.generics))?; + fmt::Display::fmt(&i.for_, f)?; + fmt::Display::fmt(&WhereClause(&i.generics), f)?; Ok(()) } @@ -622,7 +761,11 @@ impl fmt::Display for clean::Arguments { if !input.name.is_empty() { 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, ",")?; } } if !self.values.is_empty() { @@ -636,6 +779,7 @@ impl fmt::Display for clean::FunctionRetTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { 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, " -> {}", ty), clean::DefaultReturn => Ok(()), } @@ -645,9 +789,17 @@ impl fmt::Display for clean::FunctionRetTy { impl fmt::Display for clean::FnDecl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 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 { - 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) + } } } } @@ -655,34 +807,82 @@ impl fmt::Display for clean::FnDecl { impl<'a> fmt::Display for Method<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let decl = self.0; + let indent = self.1; + let amp = if f.alternate() { "&" } else { "&" }; let mut args = String::new(); + let mut args_plain = String::new(); for (i, input) in decl.inputs.values.iter().enumerate() { if let Some(selfty) = input.to_self() { 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) => { - args.push_str(&format!("&{} {}self", *lt, MutableSpace(mtbl))); + let arg = format!("{}{} {}self", amp, *lt, MutableSpace(mtbl)); + args.push_str(&arg); + args_plain.push_str(&arg); } clean::SelfBorrowed(None, mtbl) => { - args.push_str(&format!("&{}self", MutableSpace(mtbl))); + let arg = format!("{}{}self", amp, MutableSpace(mtbl)); + args.push_str(&arg); + args_plain.push_str(&arg); } 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 { - args.push_str("\n "); + if i > 0 { + args.push_str("\n "); + args_plain.push_str("\n "); + } if !input.name.is_empty() { 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(","); } - if i + 1 < decl.inputs.values.len() { args.push_str(","); } } - if let Some(None) = decl.inputs.values.iter().last().map(|val| val.to_self()) { - args.push_str("\n"); + + 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!("({})", args_plain); + } else { + output = format!("({args})\n{arrow}", args = args, arrow = arrow); + plain = format!("({args})\n{arrow}", args = args_plain, arrow = arrow_plain); } - write!(f, "({args}){arrow}", args = args, arrow = decl.output) + + if plain.replace("\n", "").len() > 80 { + let pad = format!("\n{}", indent); + output = output.replace("\n", &pad); + } else { + output = output.replace("\n", ""); + } + write!(f, "{}", output) } } @@ -776,7 +976,11 @@ impl fmt::Display for clean::ViewListIdent { impl fmt::Display for clean::TypeBinding { 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) + } } } @@ -800,10 +1004,11 @@ impl fmt::Display for RawMutableSpace { impl fmt::Display for AbiSpace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let quot = if f.alternate() { "\"" } else { """ }; match self.0 { Abi::Rust => Ok(()), Abi::C => write!(f, "extern "), - abi => write!(f, "extern "{}" ", abi.name()), + abi => write!(f, "extern {0}{1}{0} ", quot, abi.name()), } } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 03d772d1a6d..20eda9f1480 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1975,6 +1975,14 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, UnstableFeatures::Allow => f.constness, _ => hir::Constness::NotConst }; + let prefix = format!("{vis}{constness}{unsafety}{abi:#}fn {name}{generics:#}", + vis = VisSpace(&it.visibility), + constness = ConstnessSpace(vis_constness), + unsafety = UnsafetySpace(f.unsafety), + abi = AbiSpace(f.abi), + name = it.name.as_ref().unwrap(), + generics = f.generics)?; + let indent = repeat(" ").take(prefix.len()).collect::(); write!(w, "
{vis}{constness}{unsafety}{abi}fn \
                {name}{generics}{decl}{where_clause}
", vis = VisSpace(&it.visibility), @@ -2254,6 +2262,13 @@ fn render_assoc_item(w: &mut fmt::Formatter, UnstableFeatures::Allow => constness, _ => hir::Constness::NotConst }; + let prefix = format!("{}{}{:#}fn {}{:#}", + ConstnessSpace(vis_constness), + UnsafetySpace(unsafety), + AbiSpace(abi), + name, + *g); + let indent = repeat(" ").take(prefix.len()).collect::(); write!(w, "{}{}{}fn {name}\ {generics}{decl}{where_clause}", ConstnessSpace(vis_constness), @@ -2262,7 +2277,7 @@ fn render_assoc_item(w: &mut fmt::Formatter, href = href, name = name, generics = *g, - decl = Method(d), + decl = Method(d, &indent), where_clause = WhereClause(g)) } match item.inner { From fb442a7e271ec058908ad5d03c08bae655f9e654 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Mon, 26 Sep 2016 18:47:09 -0500 Subject: [PATCH 04/19] rustdoc: format bare functions like rustfmt see commit 2a274e72 for details --- src/librustdoc/html/format.rs | 53 +++++++++++++++++++---------------- src/librustdoc/html/render.rs | 16 +++++------ 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 84057fddf5a..7b21f37d215 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -621,17 +621,19 @@ impl fmt::Display for clean::Type { clean::Generic(_) => if f.alternate() { primitive_link(f, PrimitiveType::Slice, - &format!("&{}{}[{:#}]", lt, m, **bt)) + &format!("&{}{}[{:#}]", lt, m, **bt)) } else { primitive_link(f, PrimitiveType::Slice, &format!("&{}{}[{}]", lt, m, **bt)) }, _ => { - primitive_link(f, PrimitiveType::Slice, - &format!("&{}{}[", lt, m))?; if f.alternate() { + primitive_link(f, PrimitiveType::Slice, + &format!("&{}{}[", lt, m))?; write!(f, "{:#}", **bt)?; } else { + primitive_link(f, PrimitiveType::Slice, + &format!("&{}{}[", lt, m))?; write!(f, "{}", **bt)?; } primitive_link(f, PrimitiveType::Slice, "]") @@ -640,7 +642,7 @@ impl fmt::Display for clean::Type { } _ => { if f.alternate() { - write!(f, "&{}{}{:#}", lt, m, **ty) + write!(f, "&{}{}{:#}", lt, m, **ty) } else { write!(f, "&{}{}{}", lt, m, **ty) } @@ -757,7 +759,6 @@ pub fn fmt_impl_for_trait_page(i: &clean::Impl, f: &mut fmt::Formatter) -> fmt:: impl fmt::Display for clean::Arguments { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for (i, input) in self.values.iter().enumerate() { - write!(f, "\n ")?; if !input.name.is_empty() { write!(f, "{}: ", input.name)?; } @@ -766,10 +767,7 @@ impl fmt::Display for clean::Arguments { } else { write!(f, "{}", input.type_)?; } - if i + 1 < self.values.len() { write!(f, ",")?; } - } - if !self.values.is_empty() { - write!(f, "\n")?; + if i + 1 < self.values.len() { write!(f, ", ")?; } } Ok(()) } @@ -819,14 +817,12 @@ impl<'a> fmt::Display for Method<'a> { args_plain.push_str("self"); } clean::SelfBorrowed(Some(ref lt), mtbl) => { - let arg = format!("{}{} {}self", amp, *lt, MutableSpace(mtbl)); - args.push_str(&arg); - args_plain.push_str(&arg); + args.push_str(&format!("{}{} {}self", amp, *lt, MutableSpace(mtbl))); + args_plain.push_str(&format!("&{} {}self", *lt, MutableSpace(mtbl))); } clean::SelfBorrowed(None, mtbl) => { - let arg = format!("{}{}self", amp, MutableSpace(mtbl)); - args.push_str(&arg); - args_plain.push_str(&arg); + args.push_str(&format!("{}{}self", amp, MutableSpace(mtbl))); + args_plain.push_str(&format!("&{}self", MutableSpace(mtbl))); } clean::SelfExplicit(ref typ) => { if f.alternate() { @@ -839,13 +835,14 @@ impl<'a> fmt::Display for Method<'a> { } } else { if i > 0 { - args.push_str("\n "); - args_plain.push_str("\n "); + args.push_str("
"); + args_plain.push_str(" "); } if !input.name.is_empty() { args.push_str(&format!("{}: ", input.name)); args_plain.push_str(&format!("{}: ", input.name)); } + if f.alternate() { args.push_str(&format!("{:#}", input.type_)); } else { @@ -859,6 +856,11 @@ impl<'a> fmt::Display for Method<'a> { } } + if decl.variadic { + args.push_str(",
..."); + args_plain.push_str(", ..."); + } + let arrow_plain = format!("{:#}", decl.output); let arrow = if f.alternate() { format!("{:#}", decl.output) @@ -870,17 +872,20 @@ impl<'a> fmt::Display for Method<'a> { let plain: String; if arrow.is_empty() { output = format!("({})", args); - plain = format!("({})", args_plain); + plain = format!("{}({})", indent.replace(" ", " "), args_plain); } else { - output = format!("({args})\n{arrow}", args = args, arrow = arrow); - plain = format!("({args})\n{arrow}", args = args_plain, arrow = arrow_plain); + output = format!("({args})
{arrow}", args = args, arrow = arrow); + plain = format!("{indent}({args}){arrow}", + indent = indent.replace(" ", " "), + args = args_plain, + arrow = arrow_plain); } - if plain.replace("\n", "").len() > 80 { - let pad = format!("\n{}", indent); - output = output.replace("\n", &pad); + if plain.len() > 80 { + let pad = format!("
{}", indent); + output = output.replace("
", &pad); } else { - output = output.replace("\n", ""); + output = output.replace("
", ""); } write!(f, "{}", output) } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 20eda9f1480..c326b7d8b86 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1975,13 +1975,13 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, UnstableFeatures::Allow => f.constness, _ => hir::Constness::NotConst }; - let prefix = format!("{vis}{constness}{unsafety}{abi:#}fn {name}{generics:#}", - vis = VisSpace(&it.visibility), - constness = ConstnessSpace(vis_constness), - unsafety = UnsafetySpace(f.unsafety), - abi = AbiSpace(f.abi), - name = it.name.as_ref().unwrap(), - generics = f.generics)?; + 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(" ").take(prefix.len()).collect::(); write!(w, "
{vis}{constness}{unsafety}{abi}fn \
                {name}{generics}{decl}{where_clause}
", @@ -1992,7 +1992,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, name = it.name.as_ref().unwrap(), generics = f.generics, where_clause = WhereClause(&f.generics), - decl = f.decl)?; + decl = Method(&f.decl, &indent))?; document(w, cx, it) } From 2a7d495e650ebe4fd48c472ada8d5cfb06ff3edf Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Mon, 26 Sep 2016 19:36:48 -0500 Subject: [PATCH 05/19] rustdoc: fix regression when printing single-element tuples --- src/librustdoc/html/format.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 7b21f37d215..8221d1720e2 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -565,7 +565,7 @@ impl fmt::Display for clean::Type { primitive_link(f, PrimitiveType::Tuple, "(")?; //carry f.alternate() into this display w/o branching manually fmt::Display::fmt(one, f)?; - primitive_link(f, PrimitiveType::Tuple, ")") + primitive_link(f, PrimitiveType::Tuple, ",)") } many => { primitive_link(f, PrimitiveType::Tuple, "(")?; From 0c2b2581318f9473f4a49363869fab5ac25ebbc7 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 27 Sep 2016 09:39:43 -0500 Subject: [PATCH 06/19] add rustdoc test for adding line breaks --- src/test/rustdoc/line-breaks.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/rustdoc/line-breaks.rs diff --git a/src/test/rustdoc/line-breaks.rs b/src/test/rustdoc/line-breaks.rs new file mode 100644 index 00000000000..cc608a24475 --- /dev/null +++ b/src/test/rustdoc/line-breaks.rs @@ -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 or the MIT license +// , 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 { + Some(parameter_one + parameter_two) +} + +//@count foo/fn.short_name.html //pre/br 0 +pub fn short_name(param: i32) -> i32 { param + 1 } From 213063730183648cd84767f30503eb1697c6344b Mon Sep 17 00:00:00 2001 From: KillTheMule Date: Thu, 6 Oct 2016 10:47:55 +0200 Subject: [PATCH 07/19] Book: Be very explicit of lifetimes being descriptive ... no prescriptive. Pointed out in https://users.rust-lang.org/t/what-if-i-get-lifetimes-wrong/7535/4, which was a revelation to me and made me think this should be more clear in the book. --- src/doc/book/lifetimes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index f7d9c94bc45..9918c24e175 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -56,6 +56,8 @@ 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 lifetimes, which describe the scope that a reference is valid for. +*Note* It's important to understand that lifetimes are _descriptive_ not _prescriptive_. This means that the lifetimes of references are determined by the code, not by the lifetime annotations. The annotations, however, point out the lifetimes to the compiler in case it can't figure them out by itself. + When we have a function that takes an argument by reference, we can be implicit or explicit about the lifetime of the reference: From 7f02eb387d490932d45fa82ae755bceced94a698 Mon Sep 17 00:00:00 2001 From: KillTheMule Date: Thu, 6 Oct 2016 11:15:47 +0200 Subject: [PATCH 08/19] Distinguish lifetimes and their annotations Also, emphasize differently. --- src/doc/book/lifetimes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index 9918c24e175..da73c0c9ea2 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -56,7 +56,7 @@ 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 lifetimes, which describe the scope that a reference is valid for. -*Note* It's important to understand that lifetimes are _descriptive_ not _prescriptive_. This means that the lifetimes of references are determined by the code, not by the lifetime annotations. The annotations, however, point out the lifetimes to the compiler in case it can't figure them out by itself. +**Note** It's important to understand that lifetime annotations are _descriptive_ not _prescriptive_. This means that the lifetimes of references are determined by the code, not by the annotations. The annotations, however, point out the lifetimes to the compiler in case it can't figure them out by itself. When we have a function that takes an argument by reference, we can be implicit or explicit about the lifetime of the reference: From a54230239310ab5a20b1c23fd4341b938d0fd2a4 Mon Sep 17 00:00:00 2001 From: KillTheMule Date: Thu, 6 Oct 2016 11:52:30 +0200 Subject: [PATCH 09/19] Another shot at clarity --- src/doc/book/lifetimes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index da73c0c9ea2..9d30aa85f3f 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -56,7 +56,7 @@ 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 lifetimes, which describe the scope that a reference is valid for. -**Note** It's important to understand that lifetime annotations are _descriptive_ not _prescriptive_. This means that the lifetimes of references are determined by the code, not by the annotations. The annotations, however, point out the lifetimes to the compiler in case it can't figure them out by itself. +**Note** It's important to understand that lifetime annotations are _descriptive_ not _prescriptive_. This means that who long a reference is valid is determined by the code, not by the annotations. The annotations, however, point out this fact to the compiler in case it can't figure it out by itself. When we have a function that takes an argument by reference, we can be implicit or explicit about the lifetime of the reference: From 2a0bd6db856929315876b2b875e5fcf22832ff58 Mon Sep 17 00:00:00 2001 From: KillTheMule Date: Thu, 6 Oct 2016 11:53:53 +0200 Subject: [PATCH 10/19] Typos --- src/doc/book/lifetimes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index 9d30aa85f3f..652ed9d2f73 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -56,7 +56,7 @@ 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 lifetimes, which describe the scope that a reference is valid for. -**Note** It's important to understand that lifetime annotations are _descriptive_ not _prescriptive_. This means that who long a reference is valid is determined by the code, not by the annotations. The annotations, however, point out this fact to the compiler in case it can't figure it out by itself. +**Note** It's important to understand that lifetime annotations are _descriptive_, not _prescriptive_. This means that how long a reference is valid is determined by the code, not by the annotations. The annotations, however, point out this fact to the compiler in case it can't figure it out by itself. When we have a function that takes an argument by reference, we can be implicit or explicit about the lifetime of the reference: From 0d0cdb77dfe5efc9ded30e6ab8b175d602b07223 Mon Sep 17 00:00:00 2001 From: KillTheMule Date: Fri, 7 Oct 2016 08:48:19 +0200 Subject: [PATCH 11/19] Wrap & improve --- src/doc/book/lifetimes.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index 652ed9d2f73..e865609f217 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -56,10 +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 lifetimes, which describe the scope that a reference is valid for. -**Note** It's important to understand that lifetime annotations are _descriptive_, not _prescriptive_. This means that how long a reference is valid is determined by the code, not by the annotations. The annotations, however, point out this fact to the compiler in case it can't figure it out by itself. - -When we have a function that takes an argument by reference, we can be -implicit or explicit about the lifetime of the reference: +**Note** It's important to understand that lifetime annotations are +_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 // implicit From 5a30f0c728ec538312094b9fc3e9b7f6149b0286 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 8 Oct 2016 14:43:50 +0200 Subject: [PATCH 12/19] Add ICH test case for statics Fixes #37001. --- src/test/incremental/hashes/statics.rs | 185 +++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 src/test/incremental/hashes/statics.rs diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs new file mode 100644 index 00000000000..ac67e434901 --- /dev/null +++ b/src/test/incremental/hashes/statics.rs @@ -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 or the MIT license +// , 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 to Option --------------------------------- +#[cfg(cfail1)] +static STATIC_CHANGE_TYPE_2: Option = 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 = 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 = None; +} From eb07a6cfd04144bf76104226cd37647e9c35d9fa Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 8 Oct 2016 14:44:51 +0200 Subject: [PATCH 13/19] Add ICH test case for consts Fixes #37000. --- src/test/incremental/hashes/consts.rs | 132 ++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/test/incremental/hashes/consts.rs diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs new file mode 100644 index 00000000000..10c02d84b38 --- /dev/null +++ b/src/test/incremental/hashes/consts.rs @@ -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 or the MIT license +// , 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 to Option -------------------------------- +#[cfg(cfail1)] +const CONST_CHANGE_TYPE_2: Option = 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 = 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 = None; +} From 9d364267d665aa684c11fc525e90aa0b6c16eaf5 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sun, 9 Oct 2016 10:12:26 -0700 Subject: [PATCH 14/19] Update E0303 to new error format --- src/librustc_const_eval/check_match.rs | 6 ++++-- src/test/compile-fail/E0007.rs | 1 + src/test/compile-fail/E0303.rs | 8 ++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 2bd4a4d3029..9281d8aa44a 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -1238,8 +1238,10 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> { match pat.node { PatKind::Binding(.., ref subpat) => { if !self.bindings_allowed { - span_err!(self.cx.tcx.sess, pat.span, E0303, - "pattern bindings are not allowed after an `@`"); + struct_span_err!(self.cx.tcx.sess, pat.span, E0303, + "pattern bindings are not allowed after an `@`") + .span_label(pat.span, &format!("not allowed after `@`")) + .emit(); } if subpat.is_some() { diff --git a/src/test/compile-fail/E0007.rs b/src/test/compile-fail/E0007.rs index 4be115b8afd..b72b5e3b280 100644 --- a/src/test/compile-fail/E0007.rs +++ b/src/test/compile-fail/E0007.rs @@ -15,6 +15,7 @@ fn main() { //~^ ERROR E0007 //~| NOTE binds an already bound by-move value by moving it //~| ERROR E0303 + //~| NOTE not allowed after `@` None => {}, } } diff --git a/src/test/compile-fail/E0303.rs b/src/test/compile-fail/E0303.rs index 67947fd087c..e631fe2a8a7 100644 --- a/src/test/compile-fail/E0303.rs +++ b/src/test/compile-fail/E0303.rs @@ -10,8 +10,12 @@ fn main() { match Some("hi".to_string()) { - ref op_string_ref @ Some(s) => {}, //~ ERROR E0303 - //~^ ERROR E0009 + ref op_string_ref @ Some(s) => {}, + //~^ 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 => {}, } } From 67a54441832e335dd14d6987280a1bee4e9a4d76 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 7 Oct 2016 14:46:47 +1100 Subject: [PATCH 15/19] Merge `Printer::token` and `Printer::size`. Logically, it's a vector of pairs, so might as well represent it that way. The commit also changes `scan_stack` so that it is initialized with the default size, instead of the excessive `55 * linewidth` size, which it usually doesn't get even close to reaching. --- src/libsyntax/print/pp.rs | 69 ++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 32b66da4d96..792239e7219 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -125,9 +125,8 @@ impl fmt::Display for Token { } } -fn buf_str(toks: &[Token], szs: &[isize], left: usize, right: usize, lim: usize) -> String { - let n = toks.len(); - assert_eq!(n, szs.len()); +fn buf_str(buf: &[BufEntry], left: usize, right: usize, lim: usize) -> String { + let n = buf.len(); let mut i = left; let mut l = lim; 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 { s.push_str(", "); } - s.push_str(&format!("{}={}", szs[i], &toks[i])); + s.push_str(&format!("{}={}", buf[i].size, &buf[i].token)); i += 1; i %= n; } @@ -159,13 +158,9 @@ pub struct PrintStackElem { const SIZE_INFINITY: isize = 0xffff; pub fn mk_printer<'a>(out: Box, linewidth: usize) -> Printer<'a> { - // Yes 55, it makes the ring buffers big enough to never - // fall behind. + // Yes 55, it makes the ring buffers big enough to never fall behind. let n: usize = 55 * linewidth; debug!("mk_printer {}", linewidth); - let token = vec![Token::Eof; n]; - let size = vec![0; n]; - let scan_stack = VecDeque::with_capacity(n); Printer { out: out, buf_len: n, @@ -173,11 +168,10 @@ pub fn mk_printer<'a>(out: Box, linewidth: usize) -> Printer<'a> { space: linewidth as isize, left: 0, right: 0, - token: token, - size: size, + buf: vec![BufEntry { token: Token::Eof, size: 0 }; n], left_total: 0, right_total: 0, - scan_stack: scan_stack, + scan_stack: VecDeque::new(), print_stack: Vec::new(), pending_indentation: 0 } @@ -269,10 +263,8 @@ pub struct Printer<'a> { left: usize, /// Index of right side of input stream right: usize, - /// Ring-buffer stream goes through - token: Vec , - /// Ring-buffer of calculated sizes - size: Vec , + /// Ring-buffer of tokens and calculated sizes + buf: Vec, /// Running size of stream "...left" left_total: isize, /// 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 /// bottom as it becomes irrelevant due to the primary ring-buffer /// advancing. - scan_stack: VecDeque , + scan_stack: VecDeque, /// Stack of blocks-in-progress being flushed by print print_stack: Vec , /// Buffered indentation to avoid writing trailing whitespace pending_indentation: isize, } +#[derive(Clone)] +struct BufEntry { + token: Token, + size: isize, +} + impl<'a> Printer<'a> { pub fn last_token(&mut self) -> Token { - self.token[self.right].clone() + self.buf[self.right].token.clone() } // be very careful with this! 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<()> { debug!("pp Vec<{},{}>", self.left, self.right); @@ -318,8 +316,7 @@ impl<'a> Printer<'a> { } else { self.advance_right(); } debug!("pp Begin({})/buffer Vec<{},{}>", b.offset, self.left, self.right); - self.token[self.right] = token; - self.size[self.right] = -self.right_total; + self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; let right = self.right; self.scan_push(right); Ok(()) @@ -331,8 +328,7 @@ impl<'a> Printer<'a> { } else { debug!("pp End/buffer Vec<{},{}>", self.left, self.right); self.advance_right(); - self.token[self.right] = token; - self.size[self.right] = -1; + self.buf[self.right] = BufEntry { token: token, size: -1 }; let right = self.right; self.scan_push(right); Ok(()) @@ -350,8 +346,7 @@ impl<'a> Printer<'a> { self.check_stack(0); let right = self.right; self.scan_push(right); - self.token[self.right] = token; - self.size[self.right] = -self.right_total; + self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; self.right_total += b.blank_space; Ok(()) } @@ -364,8 +359,7 @@ impl<'a> Printer<'a> { debug!("pp String('{}')/buffer Vec<{},{}>", s, self.left, self.right); self.advance_right(); - self.token[self.right] = Token::String(s, len); - self.size[self.right] = len; + self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len }; self.right_total += len; self.check_stream() } @@ -381,7 +375,7 @@ impl<'a> Printer<'a> { if Some(&self.left) == self.scan_stack.back() { debug!("setting {} to infinity and popping", self.left); let scanned = self.scan_pop_bottom(); - self.size[scanned] = SIZE_INFINITY; + self.buf[scanned].size = SIZE_INFINITY; } self.advance_left()?; if self.left != self.right { @@ -410,12 +404,12 @@ impl<'a> Printer<'a> { } pub fn advance_left(&mut self) -> io::Result<()> { 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 { - let left = self.token[self.left].clone(); + let left = self.buf[self.left].token.clone(); let len = match left { Token::Break(b) => b.blank_space, @@ -437,7 +431,7 @@ impl<'a> Printer<'a> { self.left += 1; self.left %= self.buf_len; - left_size = self.size[self.left]; + left_size = self.buf[self.left].size; } Ok(()) @@ -445,23 +439,23 @@ impl<'a> Printer<'a> { pub fn check_stack(&mut self, k: isize) { if !self.scan_stack.is_empty() { let x = self.scan_top(); - match self.token[x] { + match self.buf[x].token { Token::Begin(_) => { if k > 0 { 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); } } Token::End => { // paper says + not =, but that makes no sense. let popped = self.scan_pop(); - self.size[popped] = 1; + self.buf[popped].size = 1; self.check_stack(k + 1); } _ => { 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 { self.check_stack(k); } @@ -499,8 +493,7 @@ impl<'a> Printer<'a> { pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> { debug!("print {} {} (remaining line space={})", token, l, self.space); - debug!("{}", buf_str(&self.token, - &self.size, + debug!("{}", buf_str(&self.buf, self.left, self.right, 6)); From f52723c3300f70ffe5c79620cb346251d7c236e4 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 10 Oct 2016 11:57:49 -0400 Subject: [PATCH 16/19] ICH: Enable some cases in trait definition hashing. --- src/test/incremental/hashes/trait_defs.rs | 170 +++++++++++----------- 1 file changed, 82 insertions(+), 88 deletions(-) diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index 58fbdabf872..937f053e320 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -46,16 +46,15 @@ pub trait TraitVisibility { } // Change trait unsafety ---------------------------------------------------------- -// FIXME: this should work but doesn't yet. -// #[cfg(cfail1)] -// trait TraitUnsafety { } +#[cfg(cfail1)] +trait TraitUnsafety { } -// #[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")] -// unsafe trait TraitUnsafety { } +#[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")] +unsafe trait TraitUnsafety { } @@ -178,20 +177,19 @@ trait TraitChangeMethodParameterType { // Change type of method parameter (&i32 => &mut i32) ----------------------------- -// FIXME: this should work but doesn't yet. -// #[cfg(cfail1)] -// trait TraitChangeMethodParameterTypeRef { -// fn method(a: &i32); -// } +#[cfg(cfail1)] +trait TraitChangeMethodParameterTypeRef { + fn method(a: &i32); +} -// #[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 TraitChangeMethodParameterTypeRef { -// fn method(a: &mut i32); -// } +#[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 TraitChangeMethodParameterTypeRef { + fn method(a: &mut i32); +} @@ -249,35 +247,35 @@ trait TraitChangeOrderOfMethods { // Change mode of self parameter -------------------------------------------------- -// FIXME: this should work but doesn't yet. -// #[cfg(cfail1)] -// trait TraitChangeModeSelfRefToMut { -// fn method(&self); -// } +#[cfg(cfail1)] +trait TraitChangeModeSelfRefToMut { + fn method(&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 TraitChangeModeSelfRefToMut { -// 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 TraitChangeModeSelfRefToMut { + 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")] -// #[rustc_clean(label="Hir", cfg="cfail3")] -// #[rustc_metadata_dirty(cfg="cfail2")] -// #[rustc_metadata_clean(cfg="cfail3")] -// trait TraitChangeModeSelfOwnToMut { -// fn method(mut self); -// } + +#[cfg(cfail1)] +trait TraitChangeModeSelfOwnToMut { + fn method(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 -------------------------------------------------- -// FIXME: this should work but doesn't yet. -// #[cfg(cfail1)] -// trait TraitAddUnsafeModifier { -// fn method(); -// } +#[cfg(cfail1)] +trait TraitAddUnsafeModifier { + fn method(); +} -// #[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 TraitAddUnsafeModifier { -// unsafe fn method(); -// } +#[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 TraitAddUnsafeModifier { + unsafe fn method(); +} // Add extern modifier to method -------------------------------------------------- -// FIXME: this should work but doesn't yet. -// #[cfg(cfail1)] -// trait TraitAddExternModifier { -// fn method(); -// } +#[cfg(cfail1)] +trait TraitAddExternModifier { + fn method(); +} -// #[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 TraitAddExternModifier { -// extern fn method(); -// } +#[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 TraitAddExternModifier { + extern fn method(); +} // Change extern "C" to extern "rust-intrinsic" ----------------------------------- -// FIXME: this should work but doesn't yet. -// #[cfg(cfail1)] -// trait TraitChangeExternCToRustIntrinsic { -// extern "C" fn method(); -// } +#[cfg(cfail1)] +trait TraitChangeExternCToRustIntrinsic { + extern "C" fn method(); +} -// #[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 TraitChangeExternCToRustIntrinsic { -// extern "rust-intrinsic" fn method(); -// } +#[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 TraitChangeExternCToRustIntrinsic { + extern "rust-intrinsic" fn method(); +} @@ -1118,4 +1113,3 @@ mod change_method_type_parameter_bound_indirectly_where { fn method(a: T); } } - From 3c66f96aacacee83bf52341cf349e24c768aa1f2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 10 Oct 2016 18:15:55 +0200 Subject: [PATCH 17/19] Add missing urls on String module --- src/libcollections/string.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 119828ea43c..7a61451b900 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -14,12 +14,11 @@ //! [`ToString`]s, and several error types that may result from working with //! [`String`]s. //! -//! [`String`]: struct.String.html //! [`ToString`]: trait.ToString.html //! //! # 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(); @@ -28,9 +27,11 @@ //! 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(); //! From 2b7222d3ececbdc9840a3d7bd34f6cca905b80ad Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Sat, 24 Sep 2016 19:35:24 +0200 Subject: [PATCH 18/19] Add method str::repeat(self, usize) -> String MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is relatively simple to repeat a string n times: `(0..n).map(|_| s).collect::()`. It becomes slightly more complicated to do it “right” (sizing the allocation up front), which warrants a method that does it for us. This method is useful in writing testcases, or when generating text. `format!()` can be used to repeat single characters, but not repeating strings like this. --- src/libcollections/str.rs | 20 ++++++++++++++++++++ src/libcollectionstest/lib.rs | 1 + src/libcollectionstest/str.rs | 7 +++++++ 3 files changed, 28 insertions(+) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 999c84ba705..eb3cbf59aa4 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -1746,4 +1746,24 @@ impl str { 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 + } } diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 32a07e3e7e6..ac5a1217b49 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -19,6 +19,7 @@ #![feature(enumset)] #![feature(pattern)] #![feature(rand)] +#![feature(repeat_str)] #![feature(step_by)] #![feature(str_escape)] #![feature(test)] diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index a61925cd3be..ebf3b017651 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -1272,6 +1272,13 @@ fn test_cow_from() { } } +#[test] +fn test_repeat() { + assert_eq!("".repeat(3), ""); + assert_eq!("abc".repeat(0), ""); + assert_eq!("α".repeat(3), "ααα"); +} + mod pattern { use std::str::pattern::Pattern; use std::str::pattern::{Searcher, ReverseSearcher}; From ee3de444e6c64083e4af84b701580d4084ac865c Mon Sep 17 00:00:00 2001 From: p512 Date: Tue, 11 Oct 2016 01:21:44 +0200 Subject: [PATCH 19/19] Changed 0 into '0' 0 is not a production rule but a literal --- src/libcollections/fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index b095b8131b6..883417e9f4e 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -327,7 +327,7 @@ //! format := '{' [ argument ] [ ':' format_spec ] '}' //! argument := integer | identifier //! -//! format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type] +//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type] //! fill := character //! align := '<' | '^' | '>' //! sign := '+' | '-'