Skip to content

Commit

Permalink
Auto merge of #50478 - pietroalbini:beta-backports, r=kennytm
Browse files Browse the repository at this point in the history
[beta] Process backports

* #50419: rustdoc: Resolve nested `impl Trait`s
* #50474: Fix ICE in assertion macro

r? @Mark-Simulacrum
  • Loading branch information
bors committed May 6, 2018
2 parents 1f200ac + efa8a29 commit 1ac15ac
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 89 deletions.
63 changes: 32 additions & 31 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1729,8 +1729,18 @@ pub struct Generics {

impl Clean<Generics> for hir::Generics {
fn clean(&self, cx: &DocContext) -> Generics {
let mut params = Vec::with_capacity(self.params.len());
for p in &self.params {
let p = p.clean(cx);
if let GenericParam::Type(ref tp) = p {
if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
cx.impl_trait_bounds.borrow_mut().insert(tp.did, tp.bounds.clone());
}
}
params.push(p);
}
let mut g = Generics {
params: self.params.clean(cx),
params,
where_predicates: self.where_clause.predicates.clean(cx)
};

Expand Down Expand Up @@ -1843,9 +1853,11 @@ pub struct Method {

impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) {
fn clean(&self, cx: &DocContext) -> Method {
let generics = self.1.clean(cx);
let (generics, decl) = enter_impl_trait(cx, || {
(self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))
});
Method {
decl: enter_impl_trait(cx, &generics.params, || (&*self.0.decl, self.2).clean(cx)),
decl,
generics,
unsafety: self.0.unsafety,
constness: self.0.constness,
Expand Down Expand Up @@ -1873,8 +1885,9 @@ pub struct Function {

impl Clean<Item> for doctree::Function {
fn clean(&self, cx: &DocContext) -> Item {
let generics = self.generics.clean(cx);
let decl = enter_impl_trait(cx, &generics.params, || (&self.decl, self.body).clean(cx));
let (generics, decl) = enter_impl_trait(cx, || {
(self.generics.clean(cx), (&self.decl, self.body).clean(cx))
});
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
Expand Down Expand Up @@ -2113,12 +2126,12 @@ impl Clean<Item> for hir::TraitItem {
MethodItem((sig, &self.generics, body).clean(cx))
}
hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
let generics = self.generics.clean(cx);
let (generics, decl) = enter_impl_trait(cx, || {
(self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
});
TyMethodItem(TyMethod {
unsafety: sig.unsafety.clone(),
decl: enter_impl_trait(cx, &generics.params, || {
(&*sig.decl, &names[..]).clean(cx)
}),
decl,
generics,
abi: sig.abi
})
Expand Down Expand Up @@ -3389,12 +3402,12 @@ pub struct BareFunctionDecl {

impl Clean<BareFunctionDecl> for hir::BareFnTy {
fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
let generic_params = self.generic_params.clean(cx);
let (generic_params, decl) = enter_impl_trait(cx, || {
(self.generic_params.clean(cx), (&*self.decl, &self.arg_names[..]).clean(cx))
});
BareFunctionDecl {
unsafety: self.unsafety,
decl: enter_impl_trait(cx, &generic_params, || {
(&*self.decl, &self.arg_names[..]).clean(cx)
}),
decl,
generic_params,
abi: self.abi,
}
Expand Down Expand Up @@ -3696,11 +3709,11 @@ impl Clean<Item> for hir::ForeignItem {
fn clean(&self, cx: &DocContext) -> Item {
let inner = match self.node {
hir::ForeignItemFn(ref decl, ref names, ref generics) => {
let generics = generics.clean(cx);
let (generics, decl) = enter_impl_trait(cx, || {
(generics.clean(cx), (&**decl, &names[..]).clean(cx))
});
ForeignFunctionItem(Function {
decl: enter_impl_trait(cx, &generics.params, || {
(&**decl, &names[..]).clean(cx)
}),
decl,
generics,
unsafety: hir::Unsafety::Unsafe,
abi: Abi::Rust,
Expand Down Expand Up @@ -4003,23 +4016,11 @@ pub fn def_id_to_path(cx: &DocContext, did: DefId, name: Option<String>) -> Vec<
once(crate_name).chain(relative).collect()
}

pub fn enter_impl_trait<F, R>(cx: &DocContext, gps: &[GenericParam], f: F) -> R
pub fn enter_impl_trait<F, R>(cx: &DocContext, f: F) -> R
where
F: FnOnce() -> R,
{
let bounds = gps.iter()
.filter_map(|p| {
if let GenericParam::Type(ref tp) = *p {
if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
return Some((tp.did, tp.bounds.clone()));
}
}

None
})
.collect::<FxHashMap<DefId, Vec<TyParamBound>>>();

let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), bounds);
let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), Default::default());
let r = f();
assert!(cx.impl_trait_bounds.borrow().is_empty());
*cx.impl_trait_bounds.borrow_mut() = old_bounds;
Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#![cfg_attr(stage0, feature(i128_type))]
#![feature(const_atomic_usize_new)]
#![feature(rustc_attrs)]
#![feature(str_escape)]

// See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
#[allow(unused_extern_crates)]
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ pub trait PrintState<'a> {
style: ast::StrStyle) -> io::Result<()> {
let st = match style {
ast::StrStyle::Cooked => {
(format!("\"{}\"", parse::escape_default(st)))
(format!("\"{}\"", st.escape_debug()))
}
ast::StrStyle::Raw(n) => {
(format!("r{delim}\"{string}\"{delim}",
Expand Down
61 changes: 4 additions & 57 deletions src/libsyntax_ext/assert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,13 @@ pub fn expand_assert<'cx>(
tts: if let Some(ts) = custom_msg_args {
ts.into()
} else {
// `expr_to_string` escapes the string literals with `.escape_default()`
// which escapes all non-ASCII characters with `\u`.
let escaped_expr = escape_format_string(&unescape_printable_unicode(
&pprust::expr_to_string(&cond_expr),
));

TokenStream::from(TokenTree::Token(
DUMMY_SP,
token::Literal(
token::Lit::Str_(Name::intern(&format!("assertion failed: {}", escaped_expr))),
token::Lit::Str_(Name::intern(&format!(
"assertion failed: {}",
pprust::expr_to_string(&cond_expr).escape_debug()
))),
None,
),
)).into()
Expand All @@ -70,53 +67,3 @@ pub fn expand_assert<'cx>(
);
MacEager::expr(if_expr)
}

/// Escapes a string for use as a formatting string.
fn escape_format_string(s: &str) -> String {
let mut res = String::with_capacity(s.len());
for c in s.chars() {
res.extend(c.escape_debug());
match c {
'{' | '}' => res.push(c),
_ => {}
}
}
res
}

#[test]
fn test_escape_format_string() {
assert!(escape_format_string(r"foo{}\") == r"foo{{}}\\");
}

/// Unescapes the escaped unicodes (`\u{...}`) that are printable.
fn unescape_printable_unicode(mut s: &str) -> String {
use std::{char, u32};

let mut res = String::with_capacity(s.len());

loop {
if let Some(start) = s.find(r"\u{") {
res.push_str(&s[0..start]);
s = &s[start..];
s.find('}')
.and_then(|end| {
let v = u32::from_str_radix(&s[3..end], 16).ok()?;
let c = char::from_u32(v)?;
// Escape unprintable characters.
res.extend(c.escape_debug());
s = &s[end + 1..];
Some(())
})
.expect("lexer should have rejected invalid escape sequences");
} else {
res.push_str(s);
return res;
}
}
}

#[test]
fn test_unescape_printable_unicode() {
assert!(unescape_printable_unicode(r"\u{2603}\n\u{0}") == r"☃\n\u{0}");
}
19 changes: 19 additions & 0 deletions src/test/compile-fail/issue-50471.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2018 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.

// must-compile-successfully

fn main() {
assert!({false});

assert!(r"\u{41}" == "A");

assert!(r"\u{".is_empty());
}
7 changes: 7 additions & 0 deletions src/test/rustdoc/universal-impl-trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#![feature(universal_impl_trait)]
#![crate_name = "foo"]

use std::io::Read;

// @has foo/fn.foo.html
// @has - //pre 'foo('
// @matches - '_x: impl <a class="trait" href="[^"]+/trait\.Clone\.html"'
Expand Down Expand Up @@ -39,6 +41,11 @@ impl<T> S<T> {
// @matches - '_baz:.+struct\.S\.html.+impl .+trait\.Clone\.html'
pub fn baz(_baz: S<impl Clone>) {
}

// @has - 'qux</a>('
// @matches - 'trait\.Read\.html'
pub fn qux(_qux: impl IntoIterator<Item = S<impl Read>>) {
}
}

// @has - 'method</a>('
Expand Down

0 comments on commit 1ac15ac

Please sign in to comment.