From f3733a2f82b0c98f53ed85425c9b00cf8093337b Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Wed, 1 Aug 2018 21:12:19 -0500 Subject: [PATCH 1/4] make `everybody_loops` keep item declarations --- src/librustc_driver/lib.rs | 1 + src/librustc_driver/pretty.rs | 94 ++++++++++++++++++++++++++--------- 2 files changed, 71 insertions(+), 24 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index df641b8fbc0fe..44fac8ae0a09a 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -20,6 +20,7 @@ #![feature(box_syntax)] #![cfg_attr(unix, feature(libc))] +#![feature(option_replace)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 6433a93a317a6..1e74ae10403a8 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -33,6 +33,7 @@ use syntax::fold::{self, Folder}; use syntax::print::{pprust}; use syntax::print::pprust::PrintState; use syntax::ptr::P; +use syntax::util::ThinVec; use syntax::util::small_vector::SmallVector; use syntax_pos::{self, FileName}; @@ -650,12 +651,17 @@ impl UserIdentifiedItem { // [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401 pub struct ReplaceBodyWithLoop<'a> { within_static_or_const: bool, + nested_blocks: Option>, sess: &'a Session, } impl<'a> ReplaceBodyWithLoop<'a> { pub fn new(sess: &'a Session) -> ReplaceBodyWithLoop<'a> { - ReplaceBodyWithLoop { within_static_or_const: false, sess } + ReplaceBodyWithLoop { + within_static_or_const: false, + nested_blocks: None, + sess + } } fn run R>(&mut self, is_const: bool, action: F) -> R { @@ -740,41 +746,81 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { } fn fold_block(&mut self, b: P) -> P { - fn expr_to_block(rules: ast::BlockCheckMode, + fn stmt_to_block(rules: ast::BlockCheckMode, recovered: bool, - e: Option>, - sess: &Session) -> P { - P(ast::Block { - stmts: e.map(|e| { - ast::Stmt { - id: sess.next_node_id(), - span: e.span, - node: ast::StmtKind::Expr(e), - } - }) - .into_iter() - .collect(), + s: Option, + sess: &Session) -> ast::Block { + ast::Block { + stmts: s.into_iter().collect(), rules, id: sess.next_node_id(), span: syntax_pos::DUMMY_SP, recovered, - }) + } } - if !self.within_static_or_const { - - let empty_block = expr_to_block(BlockCheckMode::Default, false, None, self.sess); - let loop_expr = P(ast::Expr { - node: ast::ExprKind::Loop(empty_block, None), - id: self.sess.next_node_id(), + fn block_to_stmt(b: ast::Block, sess: &Session) -> ast::Stmt { + let expr = P(ast::Expr { + id: sess.next_node_id(), + node: ast::ExprKind::Block(P(b), None), span: syntax_pos::DUMMY_SP, - attrs: ast::ThinVec::new(), + attrs: ThinVec::new(), }); - expr_to_block(b.rules, b.recovered, Some(loop_expr), self.sess) + ast::Stmt { + id: sess.next_node_id(), + node: ast::StmtKind::Expr(expr), + span: syntax_pos::DUMMY_SP, + } + } + + let empty_block = stmt_to_block(BlockCheckMode::Default, false, None, self.sess); + let loop_expr = P(ast::Expr { + node: ast::ExprKind::Loop(P(empty_block), None), + id: self.sess.next_node_id(), + span: syntax_pos::DUMMY_SP, + attrs: ast::ThinVec::new(), + }); + + let loop_stmt = ast::Stmt { + id: self.sess.next_node_id(), + span: syntax_pos::DUMMY_SP, + node: ast::StmtKind::Expr(loop_expr), + }; - } else { + if self.within_static_or_const { fold::noop_fold_block(b, self) + } else { + b.map(|b| { + let old_blocks = self.nested_blocks.replace(vec![]); + + let mut stmts = b.stmts.into_iter() + .flat_map(|s| self.fold_stmt(s)) + .filter(|s| s.is_item()) + .collect::>(); + + // we put a Some in there earlier with that replace(), so this is valid + let new_blocks = self.nested_blocks.take().unwrap(); + self.nested_blocks = old_blocks; + stmts.extend(new_blocks.into_iter().map(|b| block_to_stmt(b, &self.sess))); + + let mut new_block = ast::Block { + stmts, + ..b + }; + + if let Some(old_blocks) = self.nested_blocks.as_mut() { + //push our fresh block onto the cache and yield an empty block with `loop {}` + old_blocks.push(new_block); + + stmt_to_block(b.rules, b.recovered, Some(loop_stmt), self.sess) + } else { + //push `loop {}` onto the end of our fresh block and yield that + new_block.stmts.push(loop_stmt); + + new_block + } + }) } } From 8df498be1c08bb4a5c6317ef0a5802c362ba26ac Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 2 Aug 2018 15:30:57 -0500 Subject: [PATCH 2/4] more fixes for everybody_loops --- src/librustc_driver/pretty.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 1e74ae10403a8..2777593b6bd66 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -666,8 +666,10 @@ impl<'a> ReplaceBodyWithLoop<'a> { fn run R>(&mut self, is_const: bool, action: F) -> R { let old_const = mem::replace(&mut self.within_static_or_const, is_const); + let old_blocks = self.nested_blocks.take(); let ret = action(self); self.within_static_or_const = old_const; + self.nested_blocks = old_blocks; ret } @@ -745,6 +747,10 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { self.run(is_const, |s| fold::noop_fold_impl_item(i, s)) } + fn fold_anon_const(&mut self, c: ast::AnonConst) -> ast::AnonConst { + self.run(true, |s| fold::noop_fold_anon_const(c, s)) + } + fn fold_block(&mut self, b: P) -> P { fn stmt_to_block(rules: ast::BlockCheckMode, recovered: bool, @@ -811,7 +817,9 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { if let Some(old_blocks) = self.nested_blocks.as_mut() { //push our fresh block onto the cache and yield an empty block with `loop {}` - old_blocks.push(new_block); + if !new_block.stmts.is_empty() { + old_blocks.push(new_block); + } stmt_to_block(b.rules, b.recovered, Some(loop_stmt), self.sess) } else { From d6a7a3cab0b93b680802876ab490ce25b6b861f4 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 2 Aug 2018 15:42:02 -0500 Subject: [PATCH 3/4] add rustdoc test for `everybody_loops` fix --- src/test/rustdoc/traits-in-bodies.rs | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/test/rustdoc/traits-in-bodies.rs diff --git a/src/test/rustdoc/traits-in-bodies.rs b/src/test/rustdoc/traits-in-bodies.rs new file mode 100644 index 0000000000000..3acf4af5fd247 --- /dev/null +++ b/src/test/rustdoc/traits-in-bodies.rs @@ -0,0 +1,29 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//prior to fixing `everybody_loops` to preserve items, rustdoc would crash on this file, as it +//didn't see that `SomeStruct` implemented `Clone` + +//FIXME(misdreavus): whenever rustdoc shows traits impl'd inside bodies, make sure this test +//reflects that + +pub struct Bounded(T); + +pub struct SomeStruct; + +fn asdf() -> Bounded { + impl Clone for SomeStruct { + fn clone(&self) -> SomeStruct { + SomeStruct + } + } + + Bounded(SomeStruct) +} From 7e77d19905ebfcc76c19301587baf2c53acf2fd9 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 2 Aug 2018 16:24:20 -0500 Subject: [PATCH 4/4] preserve order if blocks are between items --- src/librustc_driver/pretty.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 2777593b6bd66..9135c9e179fca 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -798,17 +798,17 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { fold::noop_fold_block(b, self) } else { b.map(|b| { - let old_blocks = self.nested_blocks.replace(vec![]); + let mut stmts = vec![]; + for s in b.stmts { + let old_blocks = self.nested_blocks.replace(vec![]); - let mut stmts = b.stmts.into_iter() - .flat_map(|s| self.fold_stmt(s)) - .filter(|s| s.is_item()) - .collect::>(); + stmts.extend(self.fold_stmt(s).into_iter().filter(|s| s.is_item())); - // we put a Some in there earlier with that replace(), so this is valid - let new_blocks = self.nested_blocks.take().unwrap(); - self.nested_blocks = old_blocks; - stmts.extend(new_blocks.into_iter().map(|b| block_to_stmt(b, &self.sess))); + // we put a Some in there earlier with that replace(), so this is valid + let new_blocks = self.nested_blocks.take().unwrap(); + self.nested_blocks = old_blocks; + stmts.extend(new_blocks.into_iter().map(|b| block_to_stmt(b, &self.sess))); + } let mut new_block = ast::Block { stmts,